├── .gitignore ├── .travis.yml ├── Agda Writer.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── Agda Writer.xccheckout │ └── xcuserdata │ │ └── markokoleznik.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── xcshareddata │ └── xcschemes │ │ └── Agda Writer.xcscheme └── xcuserdata │ └── markokoleznik.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── Agda Writer ├── AWAboutViewController.h ├── AWAboutViewController.m ├── AWAgdaActions.h ├── AWAgdaActions.m ├── AWAgdaBufferWindow.h ├── AWAgdaBufferWindow.m ├── AWAgdaParser.h ├── AWAgdaParser.m ├── AWColors.h ├── AWColors.m ├── AWCommunitacion.h ├── AWCommunitacion.m ├── AWContainerOutputTextView.h ├── AWContainerOutputTextView.m ├── AWContainerStatusTextView.h ├── AWContainerStatusTextView.m ├── AWGoalsTableController.h ├── AWGoalsTableController.m ├── AWHelper.h ├── AWHelper.m ├── AWHighlighting.h ├── AWHighlighting.m ├── AWInputViewController.h ├── AWInputViewController.m ├── AWInputViewController.xib ├── AWInputWindow.h ├── AWInputWindow.m ├── AWMainSplitView.h ├── AWMainSplitView.m ├── AWMainTextView.h ├── AWMainTextView.m ├── AWNotifications.h ├── AWNotifications.m ├── AWPopoverViewController.h ├── AWPopoverViewController.m ├── AWPopoverViewController.xib ├── AWStatusTextView.h ├── AWStatusTextView.m ├── AWToastWindow.h ├── AWToastWindow.m ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ └── Main.storyboard ├── CustomTokenCell.h ├── CustomTokenCell.m ├── Document.h ├── Document.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── icon_128x128.png │ │ ├── icon_128x128@2x.png │ │ ├── icon_16x16.png │ │ ├── icon_16x16@2x.png │ │ ├── icon_256x256.png │ │ ├── icon_256x256@2x.png │ │ ├── icon_32x32.png │ │ ├── icon_32x32@2x.png │ │ ├── icon_512x512.png │ │ └── icon_512x512@2x.png ├── Info.plist ├── Key Bindings.plist ├── MAAttachedWindow.h ├── MAAttachedWindow.m ├── MarkerLineNumberView.h ├── MarkerLineNumberView.m ├── NoodleLineNumberMarker.h ├── NoodleLineNumberMarker.m ├── NoodleLineNumberView.h ├── NoodleLineNumberView.m ├── PreferencesGeneralController.h ├── PreferencesGeneralController.m ├── PreferencesKeyBindingsController.h ├── PreferencesKeyBindingsController.m ├── ReadmeMarkdown │ ├── ex01.gif │ └── ex02.gif ├── TODO List ├── UnicodeTransformator.h ├── UnicodeTransformator.m ├── ViewController.h ├── ViewController.m ├── agda │ ├── Agda-2.4.2.2 │ │ └── lib │ │ │ └── prim │ │ │ └── Agda │ │ │ └── Primitive.agdai │ └── agda ├── defaults.plist └── main.m ├── Agda WriterTests ├── AgdaParserTests.m ├── AgdaWriterTests.m ├── Agda_WriterTests.m ├── Info.plist ├── check-mark.png ├── failed_default.png ├── icon_128x128.png ├── load_failed.png ├── load_successful.png ├── settings-general.png ├── settings-keybindings.png ├── successful_default.png └── x-mark.png ├── Agda WriterUITests ├── Agda_WriterUITests.m └── Info.plist ├── Licence.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | AgdaWriter.xcodeproj/xcuserdata/markokoleznik.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist 3 | 4 | AgdaWriter.xcodeproj/project.xcworkspace/xcuserdata/markokoleznik.xcuserdatad/UserInterfaceState.xcuserstate 5 | 6 | AgdaWriter.xcodeproj/project.xcworkspace/xcuserdata/markokoleznik.xcuserdatad/UserInterfaceState.xcuserstate 7 | 8 | AgdaWriter.xcodeproj/xcuserdata/markokoleznik.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist 9 | 10 | AgdaWriter.xcodeproj/project.xcworkspace/xcuserdata/markokoleznik.xcuserdatad/xcdebugger/Expressions.xcexplist 11 | 12 | *.agda 13 | 14 | *.xcbkptlist 15 | 16 | *.xcbkptlist 17 | 18 | Agda Writer/Base.lproj/.DS_Store 19 | 20 | Agda Writer/Images.xcassets/.DS_Store 21 | 22 | Agda Writer/Images.xcassets/AppIcon.appiconset/.DS_Store 23 | 24 | Agda WriterTests/.DS_Store 25 | 26 | Agda Writer/agda/.DS_Store 27 | 28 | Agda Writer/.DS_Store 29 | 30 | Agda Writer.xcodeproj/xcuserdata/markokoleznik.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist 31 | 32 | Agda Writer.xcodeproj/xcuserdata/markokoleznik.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist 33 | 34 | *.xcbkptlist 35 | 36 | .DS_Store 37 | 38 | *.xcuserstate 39 | 40 | *.xcbkptlist 41 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | xcode_project: Agda Writer.xcodeproj # path to your xcodeproj folder 3 | xcode_scheme: Agda Writer 4 | -------------------------------------------------------------------------------- /Agda Writer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Agda Writer.xcodeproj/project.xcworkspace/xcshareddata/Agda Writer.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 68B6DD37-40BD-4632-9E19-BC042DFAAA37 9 | IDESourceControlProjectName 10 | Agda Writer 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 61E9CB5882E67476C57707B878B82E48C7614C86 14 | github.com:markokoleznik/agda-writer.git 15 | 16 | IDESourceControlProjectPath 17 | Agda Writer.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 61E9CB5882E67476C57707B878B82E48C7614C86 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | github.com:markokoleznik/agda-writer.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 61E9CB5882E67476C57707B878B82E48C7614C86 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 61E9CB5882E67476C57707B878B82E48C7614C86 36 | IDESourceControlWCCName 37 | agda-writer 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Agda Writer.xcodeproj/project.xcworkspace/xcuserdata/markokoleznik.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer.xcodeproj/project.xcworkspace/xcuserdata/markokoleznik.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Agda Writer.xcodeproj/xcshareddata/xcschemes/Agda Writer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 57 | 63 | 64 | 65 | 66 | 67 | 73 | 74 | 75 | 76 | 77 | 78 | 88 | 90 | 96 | 97 | 98 | 99 | 100 | 101 | 107 | 109 | 115 | 116 | 117 | 118 | 120 | 121 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /Agda Writer.xcodeproj/xcuserdata/markokoleznik.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Agda Writer.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | D531F0FB1B55E580002E7E0F 16 | 17 | primary 18 | 19 | 20 | D531F1141B55E580002E7E0F 21 | 22 | primary 23 | 24 | 25 | D5E81AFF1BE225FC0027076D 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Agda Writer/AWAboutViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWAboutViewController.h 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 19. 08. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AWAboutViewController : NSViewController 12 | @property (strong) IBOutlet NSTextField *attributionForMattGemmell; 13 | @property (strong) IBOutlet NSTextField *attributionForAgda; 14 | 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Agda Writer/AWAboutViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWAboutViewController.m 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 19. 08. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWAboutViewController.h" 10 | 11 | @interface AWAboutViewController () 12 | 13 | @end 14 | 15 | @implementation AWAboutViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do view setup here. 20 | [self.attributionForMattGemmell setAllowsEditingTextAttributes: YES]; 21 | [self.attributionForMattGemmell setSelectable: YES]; 22 | NSMutableAttributedString * attribution = [[NSMutableAttributedString alloc] initWithString:@"Includes MAAttachedWindow code by "]; 23 | NSURL * url = [NSURL URLWithString:@"http://mattgemmell.com/"]; 24 | [attribution appendAttributedString:[self hyperlinkFromString:@"Matt Gemmell" withURL:url]]; 25 | [attribution appendAttributedString:[[NSAttributedString alloc] initWithString:@"."]]; 26 | [self.attributionForMattGemmell setAttributedStringValue:attribution]; 27 | 28 | // Includes Agda 2.4.2.2, avaliable here. 29 | [self.attributionForAgda setAllowsEditingTextAttributes: YES]; 30 | [self.attributionForAgda setSelectable: YES]; 31 | NSMutableAttributedString * attributionForAgdaString = [[NSMutableAttributedString alloc] initWithString:@"Includes Agda 2.4.2.2, avaliable "]; 32 | NSURL * urlToAgda = [NSURL URLWithString:@"http://wiki.portal.chalmers.se/agda/pmwiki.php"]; 33 | [attributionForAgdaString appendAttributedString:[self hyperlinkFromString:@"here" withURL:urlToAgda]]; 34 | [attributionForAgdaString appendAttributedString:[[NSAttributedString alloc] initWithString:@"."]]; 35 | [self.attributionForAgda setAttributedStringValue:attributionForAgdaString]; 36 | 37 | 38 | } 39 | 40 | -(id)hyperlinkFromString:(NSString*)inString withURL:(NSURL*)aURL 41 | { 42 | NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString: inString]; 43 | NSRange range = NSMakeRange(0, [attrString length]); 44 | 45 | [attrString beginEditing]; 46 | [attrString addAttribute:NSLinkAttributeName value:[aURL absoluteString] range:range]; 47 | 48 | // make the text appear in blue 49 | [attrString addAttribute:NSForegroundColorAttributeName value:[NSColor blueColor] range:range]; 50 | 51 | // next make the text appear with an underline 52 | [attrString addAttribute: 53 | NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:NSUnderlineStyleSingle] range:range]; 54 | 55 | [attrString endEditing]; 56 | 57 | return attrString; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /Agda Writer/AWAgdaActions.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWAgdaActions.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 20. 04. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AWMainTextView.h" 11 | 12 | typedef enum : NSUInteger { 13 | AWNormalisationLevelInstantiated, 14 | AWNormalisationLevelSimplified, 15 | AWNormalisationLevelNormalised, 16 | AWNormalisationLevelNone 17 | } AWNormalisationLevel; 18 | 19 | 20 | 21 | @interface AWAgdaActions : NSObject 22 | 23 | 24 | //********* Requests ********* 25 | #pragma mark - 26 | #pragma mark Agda requests 27 | 28 | // List of Interaction, thanks to banacorn! 29 | // https://github.com/banacorn/agda-mode/wiki/Conversations-between-Agda-&-agda-mode 30 | 31 | 32 | 33 | // Load 34 | +(NSString *)actionLoadWithFilePath:(NSString *)filePath; 35 | // Compile 36 | +(NSString *)actionCompileWithFilePath:(NSString *)filePath; 37 | // Give 38 | +(NSString *)actionGiveWithFilePath:(NSString *)filePath 39 | goal:(AgdaGoal *)goal; 40 | // Refine 41 | +(NSString *)actionRefineWithFilePath:(NSString *)filePath 42 | goal:(AgdaGoal *)goal; 43 | // Auto 44 | +(NSString *)actionAutoWithFilePath:(NSString *)filePath 45 | goal:(AgdaGoal *)goal; 46 | // Case 47 | +(NSString *)actionCaseWithFilePath:(NSString *)filePath 48 | goal:(AgdaGoal *)goal; 49 | 50 | +(NSString *)actionGoalTypeWithFilePath:(NSString *)filePath 51 | goal:(AgdaGoal *)goal 52 | normalisationLevel:(AWNormalisationLevel)level; 53 | 54 | +(NSString *)actionGoalTypeAndContextWithFilePath:(NSString *)filePath 55 | goal:(AgdaGoal *)goal 56 | normalisationLevel:(AWNormalisationLevel)level; 57 | 58 | +(NSString *)actionGoalTypeAndInfferedContextWithFilePath:(NSString *)filePath 59 | goal:(AgdaGoal *)goal 60 | normalisationLevel:(AWNormalisationLevel)level; 61 | 62 | +(NSString *)actionShowConstraintsWithFilePath:(NSString *)filePath; 63 | 64 | +(NSString *)actionShowMetasWithFilePath:(NSString *)filePath; 65 | 66 | +(NSString *)actionShowModuleContentsFilePath:(NSString *)filePath 67 | goal:(AgdaGoal *)goal 68 | normalisationLevel:(AWNormalisationLevel)level 69 | content:(NSString *)content; 70 | 71 | +(NSString *)actionImplicitArgumentsWithFilePath:(NSString *)filePath; 72 | 73 | +(NSString *)actionInferWithFilePath:(NSString *)filePath 74 | goal:(AgdaGoal *)goal 75 | normalisationLevel:(AWNormalisationLevel)level 76 | content:(NSString *)content; 77 | 78 | +(NSString *)actionComputeNormalFormWithFilePath:(NSString *)filePath 79 | goal:(AgdaGoal *)goal 80 | content:(NSString *)content; 81 | 82 | +(NSString *)actionToggleImplicitArgumentsWithFilePath:(NSString *)filePath; 83 | 84 | +(NSString *)actionSolveAllConstraints:(NSString *)filePath; 85 | 86 | +(NSString *)actionWhyInScopeWithFilePath:(NSString *)filePath 87 | goal:(AgdaGoal *)goal 88 | content:(NSString *)content; 89 | 90 | +(NSString *)actionContextWithFilePath:(NSString *)filePath 91 | goal:(AgdaGoal *)goal 92 | normalisationLevel:(AWNormalisationLevel)level; 93 | 94 | +(NSString *)actionShowVersionWithFilePath:(NSString *)filepath; 95 | 96 | 97 | #pragma mark - 98 | #pragma mark Agda Actions 99 | +(void)executeAction:(NSDictionary *)action sender:(id) sender; 100 | +(void)executeArrayOfActions:(NSArray *)actions sender:(id) sender; 101 | @end 102 | -------------------------------------------------------------------------------- /Agda Writer/AWAgdaBufferWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWAgdaBufferWindow.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 28. 04. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AWAgdaBufferWindow : NSViewController 12 | @property (unsafe_unretained) IBOutlet NSTextView *agdaTextView; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Agda Writer/AWAgdaBufferWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWAgdaBufferWindow.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 28. 04. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWAgdaBufferWindow.h" 10 | #import "AWNotifications.h" 11 | 12 | @implementation AWAgdaBufferWindow 13 | 14 | -(void)viewDidLoad 15 | { 16 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(agdaBufferDataAvaliable:) name:AWAgdaReplied object:nil]; 17 | } 18 | 19 | 20 | -(void)agdaBufferDataAvaliable:(NSNotification *)notification 21 | { 22 | if ([notification.object isKindOfClass:[NSString class]]) { 23 | NSString *reply = notification.object; 24 | [self.agdaTextView.textStorage beginEditing]; 25 | [[self.agdaTextView.textStorage mutableString] appendString:reply]; 26 | [self.agdaTextView.textStorage endEditing]; 27 | } 28 | } 29 | 30 | -(void)viewDidDisappear 31 | { 32 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Agda Writer/AWAgdaParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWAgdaParser.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 4. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #import "CustomTokenCell.h" 13 | 14 | @interface AWAgdaParser : NSObject 15 | 16 | -(void) parseResponse:(NSString *)response; 17 | +(NSDictionary *)parseAction:(NSString *) action; 18 | +(NSArray *)makeArrayOfActions:(NSString *)reply; 19 | +(NSArray *)makeArrayOfGoalsWithSuggestions:(NSString *)goals; 20 | +(NSArray *)makeArrayOfActionsAndDeleteActionFromString:(NSMutableString *)reply; 21 | +(NSDictionary *)goalIndexAndRange:(NSRange)currentSelection textStorage:(NSTextStorage *)textStorage; 22 | +(NSRange) goalAtIndex: (NSInteger) index textStorage:(NSTextStorage *)textStorage; 23 | +(NSArray *) allGoalsWithRanges:(NSTextStorage *) textStorage; 24 | +(NSArray *) caseSplitActions:(NSString *)reply; 25 | /** Parses highlighting. 26 | @param NSString Response from Agda (read from disk) 27 | @return NSArray Array contains objects of type NSDictionary. Form: @{type : @[range]} 28 | */ 29 | +(NSArray *) parseHighlighting:(NSString *)highlighting; 30 | + (NSRange) rangeFromLineNumber:(NSUInteger)lineNumber 31 | andLineRange:(NSRange) lineRange 32 | string:(NSString *)string; 33 | +(NSInteger) parseGotoAction:(NSString *)reply; 34 | + (NSDictionary *)parsedLineOfHighligting:(NSString *)line; 35 | 36 | + (NSMutableAttributedString *) parseRangesAndAddAttachments:(NSAttributedString *)reply parentViewController:(id)parentViewController; 37 | @end 38 | -------------------------------------------------------------------------------- /Agda Writer/AWAgdaParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWAgdaParser.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 4. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWAgdaParser.h" 10 | 11 | 12 | @implementation AWAgdaParser 13 | 14 | -(void) parseResponse:(NSString *)response 15 | { 16 | 17 | } 18 | 19 | /*! 20 | @method Parses actions from Agda response 21 | @param String action, which is response from Agda 22 | @return returns NSDictionary with key as string (operation to perform) and array of string with parameters of operation 23 | */ 24 | 25 | +(NSDictionary *)parseAction:(NSString *) action 26 | { 27 | // ((last . 2) . (agda2-make-case-action '("twice Z = ?" "twice (S x) = ?"))) 28 | 29 | // delete prefixes on weird responses, so for example 30 | // ((last . 1) . (agda2-goals-action '(0 1))) 31 | // should go to 32 | // (agda2-goals-action '(0 1)) 33 | 34 | if ([action hasPrefix:@"((last"]) { 35 | // delete last character and first two (( 36 | action = [action substringWithRange:NSMakeRange(5, action.length - 5 - 1)]; 37 | int i = 0; 38 | while (i < action.length) { 39 | if ([action characterAtIndex:i] == '(') { 40 | action = [action substringFromIndex:i]; 41 | break; 42 | } 43 | i++; 44 | } 45 | 46 | 47 | } 48 | 49 | NSDictionary * dict; 50 | if (![action hasPrefix:@"(agda2-"]) { 51 | return nil; 52 | } 53 | 54 | 55 | // We have agda action. 56 | action = [action substringWithRange:NSMakeRange(1, action.length - 2)]; 57 | 58 | NSArray * actions = [self executeParser:action]; 59 | if (actions.count > 0) { 60 | dict = @{actions[0]: [actions subarrayWithRange:NSMakeRange(1, actions.count - 1)]}; 61 | } 62 | return dict; 63 | } 64 | 65 | +(NSArray *) executeParser:(NSString *) action 66 | { 67 | NSMutableArray * actions = [[NSMutableArray alloc] init]; 68 | int i = 0; 69 | int j = 0; 70 | 71 | while (i < action.length) { 72 | j = i; 73 | if ([action characterAtIndex:i] == '"') { 74 | j++; 75 | while (j < action.length) { 76 | if ([action characterAtIndex:j] == '"') { 77 | // add substring between quotation marks to array "actions" 78 | [actions addObject:[action substringWithRange:NSMakeRange(i, j - i + 1)]]; 79 | break; 80 | } 81 | j++; 82 | } 83 | i = j + 2; 84 | } 85 | else if (i < action.length - 2 && [[action substringWithRange:NSMakeRange(i, 2)] isEqualToString:@"'("]) 86 | { 87 | NSInteger numberOfLeftParenthesis = 0; 88 | while (j < action.length) { 89 | if ([action characterAtIndex:j] == ')') { 90 | numberOfLeftParenthesis--; 91 | if (numberOfLeftParenthesis == 0) { 92 | // add lisp comments to "actions" 93 | [actions addObject:[action substringWithRange:NSMakeRange(i, j - i + 1)]]; 94 | } 95 | 96 | } 97 | else if ([action characterAtIndex:j] == '(') { 98 | numberOfLeftParenthesis++; 99 | } 100 | j++; 101 | } 102 | i = j + 2; 103 | } 104 | else 105 | { 106 | while (j < action.length) { 107 | if ([action characterAtIndex:j] == ' ' || j + 1 == action.length) { 108 | 109 | if (j + 1 == action.length) { 110 | [actions addObject:[action substringWithRange:NSMakeRange(i, j - i + 1)]]; 111 | break; 112 | } 113 | 114 | // add substring to "actions" 115 | [actions addObject:[action substringWithRange:NSMakeRange(i, j - i)]]; 116 | break; 117 | } 118 | j++; 119 | } 120 | i = j + 1; 121 | } 122 | } 123 | return actions; 124 | } 125 | 126 | +(NSArray *)makeArrayOfActions:(NSString *)reply 127 | { 128 | // Array contains NSDictionary objects with key as main action and array of strings as its parameters 129 | // Example: 130 | // (agda2-highlight-load-and-delete-action "/var/folders/c6/1rfd2v_n4f32q66rsjbfqb340000gn/T/agda2-mode2743") 131 | // @{@"agda2-highlight-load-and-delete-action" : @[@"/var/folders/c6/1rfd2v_n4f32q66rsjbfqb340000gn/T/agda2-mode2743"]} 132 | NSMutableArray * actionsWithDictionaries = [[NSMutableArray alloc] init]; 133 | reply = [reply stringByReplacingOccurrencesOfString:@"Agda2> " withString:@""]; 134 | NSArray * actions = [reply componentsSeparatedByString:@"\n"]; 135 | 136 | 137 | for (NSString * action in actions) { 138 | NSDictionary * dict = [self parseAction:action]; 139 | if (dict) { 140 | [actionsWithDictionaries addObject:dict]; 141 | } 142 | 143 | } 144 | return actionsWithDictionaries; 145 | } 146 | 147 | +(NSArray *)makeArrayOfActionsAndDeleteActionFromString:(NSMutableString *)reply 148 | { 149 | // 1.) step: make array of actions 150 | NSMutableArray * actionsWithDictionaries = [[NSMutableArray alloc] init]; 151 | NSMutableArray * actions = [[NSMutableArray alloc] init]; 152 | [reply replaceOccurrencesOfString:@"Agda2> " withString:@"" options:NSLiteralSearch range:NSMakeRange(0, reply.length)]; 153 | BOOL insideQuotes = NO; 154 | int numberOfLeftParenthesis = 0; 155 | int start = 0; 156 | int i = 0; 157 | while (i < reply.length) { 158 | if ([reply characterAtIndex:i] == '"') { 159 | if (insideQuotes) { 160 | insideQuotes = NO; 161 | } 162 | else { 163 | insideQuotes = YES; 164 | } 165 | } 166 | if ([reply characterAtIndex:i] == '(' && !insideQuotes) { 167 | if (numberOfLeftParenthesis == 0) { 168 | start = i; 169 | } 170 | numberOfLeftParenthesis ++; 171 | } 172 | else if ([reply characterAtIndex:i] == ')' && !insideQuotes) { 173 | numberOfLeftParenthesis --; 174 | if (numberOfLeftParenthesis == 0) { 175 | // End parsing 176 | NSRange rangeOfAction = NSMakeRange(start, i + 1 - start); 177 | [actions addObject:[reply substringWithRange:rangeOfAction]]; 178 | // delete that part of reply 179 | [reply deleteCharactersInRange:NSMakeRange(0, i + 1)]; 180 | i = 0; 181 | } 182 | } 183 | i++; 184 | } 185 | 186 | 187 | // 2.) step: create array of dictionaries {actionName: [arg1, arg2,...]} 188 | for (NSString * action in actions) { 189 | NSDictionary * dict = [self parseAction:action]; 190 | if (dict) { 191 | [actionsWithDictionaries addObject:dict]; 192 | } 193 | } 194 | 195 | return actionsWithDictionaries; 196 | 197 | } 198 | 199 | +(NSArray *)makeArrayOfGoalsWithSuggestions:(NSString *)goals 200 | { 201 | NSMutableArray * goalsMutable = [[NSMutableArray alloc] init]; 202 | goals = [goals stringByReplacingOccurrencesOfString:@"\"" withString:@""]; 203 | NSArray * goalsArray = [goals componentsSeparatedByString:@"\\n"]; 204 | for (NSString * goal in goalsArray) { 205 | NSArray * subGoalArray = [goal componentsSeparatedByString:@" : "]; 206 | if (subGoalArray.count >= 2) { 207 | NSString * goalIndex = subGoalArray[0]; 208 | if ([goalIndex characterAtIndex:0] == '?') { 209 | goalIndex = [goalIndex substringFromIndex:1]; 210 | NSDictionary * dict = @{@"goalIndex" : @([goalIndex integerValue]), 211 | @"goalType" : goal}; 212 | [goalsMutable addObject:dict]; 213 | } 214 | else { 215 | NSDictionary * dict = @{@"goalIndex" : @"nil", 216 | @"goalType" : goal}; 217 | [goalsMutable addObject:dict]; 218 | } 219 | 220 | } 221 | } 222 | return goalsMutable; 223 | } 224 | 225 | // Regex to find all the goals: 226 | // (?=(\{!(?:[^!]|\{![^!]*!\})*!\})) 227 | // By stribizhev 228 | // http://stackoverflow.com/questions/30574174/find-range-of-goals-that-arent-in-comments-with-regex 229 | 230 | +(NSDictionary *)goalIndexAndRange:(NSRange)currentSelection textStorage:(NSTextStorage *)textStorage 231 | { 232 | NSDictionary * dict; 233 | NSString * regexPattern = @"(?=(\\{!(?:[^!]|\\{![^!]*!\\})*!\\}))"; 234 | NSError * error; 235 | NSRegularExpression * regex = [[NSRegularExpression alloc] initWithPattern:regexPattern options:NSRegularExpressionAnchorsMatchLines error:&error]; 236 | NSRange fullRange = NSMakeRange(0, textStorage.string.length); 237 | NSArray * matches = [regex matchesInString:textStorage.string options:0 range:fullRange]; 238 | NSInteger goalIndex = 0; 239 | for (NSTextCheckingResult * result in matches) { 240 | if (currentSelection.location > [result rangeAtIndex:1].location && (currentSelection.location + currentSelection.length) < ([result rangeAtIndex:1].location + [result rangeAtIndex:1].length)) { 241 | // we found appropriate result 242 | // Convert NSRange to string 243 | 244 | dict = @{@"goalIndex" : @(goalIndex), 245 | @"foundRange" : NSStringFromRange([result rangeAtIndex:1])}; 246 | return dict; 247 | } 248 | goalIndex ++; 249 | } 250 | return dict; 251 | } 252 | 253 | +(NSArray *) allGoalsWithRanges:(NSTextStorage *) textStorage 254 | { 255 | NSMutableArray * goals; 256 | NSString * regexPattern = @"(?=(\\{!(?:[^!]|\\{![^!]*!\\})*!\\}))"; 257 | NSError * error; 258 | NSRegularExpression * regex = [[NSRegularExpression alloc] initWithPattern:regexPattern options:NSRegularExpressionAnchorsMatchLines error:&error]; 259 | NSRange fullRange = NSMakeRange(0, textStorage.string.length); 260 | NSArray * matches = [regex matchesInString:textStorage.string options:0 range:fullRange]; 261 | if (matches) { 262 | goals = [[NSMutableArray alloc] initWithCapacity:matches.count]; 263 | } 264 | for (NSTextCheckingResult * result in matches) { 265 | [goals addObject:NSStringFromRange([result rangeAtIndex:1])]; 266 | } 267 | return goals; 268 | } 269 | 270 | 271 | +(NSRange) goalAtIndex: (NSInteger) index textStorage:(NSTextStorage *)textStorage 272 | { 273 | NSRange foundRange = NSMakeRange(NSNotFound, 0); 274 | // We'll use Regular Expressions to find goals range. 275 | NSString * regexPattern = @"(?=(\\{!(?:[^!]|\\{![^!]*!\\})*!\\}))"; 276 | NSError * error; 277 | NSRegularExpression * regex = [[NSRegularExpression alloc] initWithPattern:regexPattern options:NSRegularExpressionAnchorsMatchLines error:&error]; 278 | NSArray * matches = [regex matchesInString:textStorage.string options:0 range:NSMakeRange(0, textStorage.length)]; 279 | 280 | if (matches.count > index) { 281 | NSTextCheckingResult * result = [matches objectAtIndex:index]; 282 | foundRange = [result rangeAtIndex:1]; 283 | } 284 | 285 | return foundRange; 286 | } 287 | 288 | +(NSArray *) caseSplitActions:(NSString *)reply 289 | { 290 | NSMutableArray * actions = [[NSMutableArray alloc] init]; 291 | if ([reply hasPrefix:@"'("] && [reply hasSuffix:@")"]) { 292 | reply = [reply substringWithRange:NSMakeRange(2, reply.length - 3)]; 293 | // NSLog(@"substring: %@", reply); 294 | NSArray * actionsWithQuotes = [reply componentsSeparatedByString:@"\" \""]; 295 | for (NSString * action in actionsWithQuotes) { 296 | NSString * parsedAction = action; 297 | if ([action hasPrefix:@"\""]) { 298 | parsedAction = [parsedAction substringFromIndex:1]; 299 | } 300 | if ([action hasSuffix:@"\""]) { 301 | parsedAction = [parsedAction substringToIndex:parsedAction.length - 1]; 302 | } 303 | 304 | // parsedAction = [parsedAction stringByAppendingString:@"\n"]; 305 | 306 | [actions addObject:parsedAction]; 307 | } 308 | 309 | } 310 | return actions; 311 | } 312 | 313 | +(NSArray *)parseDirectHighligting:(NSArray *)highlighting 314 | { 315 | return @[]; 316 | } 317 | 318 | 319 | +(NSArray *) parseHighlighting:(NSString *)highlighting 320 | { 321 | /* 322 | We receive "highlighting" in this form: 323 | ((si1 ei1 (type1) nil path) (si2 ei2 (type2) path) ...) 324 | where: 325 | siN start of range N 326 | eiN end of range N 327 | typeN type, for exaple "word", "symbol", "operator" ... 328 | path is the path of a file 329 | */ 330 | 331 | // ditch first two and the last two parenthesis 332 | if ([highlighting hasPrefix:@"(("] && [highlighting hasSuffix:@"))"]) { 333 | highlighting = [highlighting substringWithRange:NSMakeRange(2, highlighting.length - 4)]; 334 | } 335 | NSMutableArray * result = [[NSMutableArray alloc] init]; 336 | // create array of 337 | // siK eiK (typeK) path 338 | // note: those are now without parenthesis 339 | NSArray * matches = [highlighting componentsSeparatedByString:@") ("]; 340 | 341 | 342 | for (NSString * line in matches) { 343 | 344 | NSDictionary * dict = [self parsedLineOfHighligting:line]; 345 | if (dict) { 346 | [result addObject:dict]; 347 | } 348 | } 349 | 350 | return result; 351 | } 352 | 353 | + (NSDictionary *)parsedLineOfHighligting:(NSString *)line 354 | { 355 | NSDictionary * dict; 356 | 357 | // first find a type 358 | NSRange rangeOfType = NSMakeRange(NSNotFound, 0); 359 | for (NSInteger i = 1; i < line.length; i++) { 360 | if ([line characterAtIndex:i] == '(') { 361 | rangeOfType.location = i + 1; 362 | } 363 | else if ([line characterAtIndex:i] == ')') { 364 | rangeOfType.length = i - rangeOfType.location; 365 | break; 366 | } 367 | } 368 | NSString * typeName; 369 | if (rangeOfType.location == NSNotFound) { 370 | // fall back if range isn't found... Just in case! :) 371 | return nil; 372 | } 373 | typeName = [line substringWithRange:rangeOfType]; 374 | // delete that type from string 375 | NSString const * lineCopy = [NSString stringWithFormat:@"%@%@", [line substringToIndex:rangeOfType.location - 2], [line substringFromIndex:rangeOfType.location + rangeOfType.length + 1]]; 376 | 377 | // get those components: 378 | // @[siK, eik, path] 379 | NSArray * components = [lineCopy componentsSeparatedByString:@" "]; 380 | if (components.count > 2) { 381 | NSNumberFormatter *f = [[NSNumberFormatter alloc] init]; 382 | f.numberStyle = NSNumberFormatterDecimalStyle; 383 | NSNumber *startNumber = [f numberFromString:components[0]]; 384 | NSNumber *endNumber = [f numberFromString:components[1]]; 385 | NSRange range = NSMakeRange([startNumber integerValue], [endNumber integerValue] - [startNumber integerValue]); 386 | 387 | dict = @{typeName : @[NSStringFromRange(range)]}; 388 | 389 | } 390 | 391 | return dict; 392 | } 393 | 394 | + (NSRange) rangeFromLineNumber:(NSUInteger)lineNumber 395 | andLineRange:(NSRange) lineRange 396 | string:(NSString *)string { 397 | NSRange range = NSMakeRange(NSNotFound, 0); 398 | 399 | NSInteger numberOfChars = 0; 400 | NSArray * lines = [string componentsSeparatedByString:@"\n"]; 401 | NSInteger i = 0; 402 | for (NSString * line in lines) { 403 | if (i + 1 == lineNumber) { 404 | range = NSMakeRange(numberOfChars + lineRange.location - 1, lineRange.length); 405 | return range; 406 | } 407 | numberOfChars += line.length + 1; 408 | i++; 409 | } 410 | 411 | return range; 412 | } 413 | 414 | +(NSInteger) parseGotoAction:(NSString *)reply { 415 | 416 | if ([reply hasSuffix:@")"]) { 417 | NSArray * components = [reply componentsSeparatedByString:@" . "]; 418 | NSString * lastComponent = components[components.count - 1]; 419 | lastComponent = [lastComponent substringToIndex:lastComponent.length - 1]; 420 | return [lastComponent integerValue]; 421 | } 422 | 423 | return 0; 424 | } 425 | 426 | + (NSMutableAttributedString *)parseRangesAndAddAttachments:(NSAttributedString *)reply parentViewController:(id)parentViewController; 427 | { 428 | NSMutableAttributedString * attrString = [[NSMutableAttributedString alloc] initWithAttributedString:reply]; 429 | 430 | 431 | NSString * regexPattern = @"[0-9]*,[0-9]*-[0-9]*"; 432 | NSError * error; 433 | NSRegularExpression * regex = [[NSRegularExpression alloc] initWithPattern:regexPattern options:NSRegularExpressionAnchorsMatchLines error:&error]; 434 | NSArray * matches = [regex matchesInString:[reply string] options:0 range:NSMakeRange(0, reply.length)]; 435 | 436 | // replace all "ranges" with cell attachments. 437 | 438 | for (NSTextCheckingResult * result in [matches reverseObjectEnumerator]) { 439 | 440 | NSTextAttachment * attachment = [[NSTextAttachment alloc] initWithFileWrapper:nil]; 441 | NSMutableAttributedString * text = [NSMutableAttributedString new]; 442 | [text appendAttributedString:[[NSAttributedString alloc] initWithString:@" "]]; 443 | CustomTokenCell * tokenCell = [[CustomTokenCell alloc] init]; 444 | tokenCell.parentViewController = parentViewController; 445 | NSString * substringOfRange = [[reply attributedSubstringFromRange:result.range] string]; 446 | [tokenCell setTitle:substringOfRange]; 447 | [attachment setAttachmentCell:tokenCell]; 448 | [text appendAttributedString:[NSAttributedString attributedStringWithAttachment:attachment]]; 449 | [text appendAttributedString:[[NSAttributedString alloc] initWithString:@" "]]; 450 | 451 | [attrString replaceCharactersInRange:result.range withAttributedString:text]; 452 | 453 | } 454 | 455 | 456 | return attrString; 457 | } 458 | 459 | @end 460 | -------------------------------------------------------------------------------- /Agda Writer/AWColors.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWColors.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 6. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | 14 | @interface AWColors : NSObject 15 | 16 | + (CGColorRef) defaultBackgroundColor; 17 | + (CGColorRef) defaultSeparatorColor; 18 | + (NSColor *) unselectedTokenColor; 19 | + (NSColor *) borderTokenColor; 20 | + (NSColor *) highlightColorForType:(NSString *)type; 21 | @end 22 | -------------------------------------------------------------------------------- /Agda Writer/AWColors.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWColors.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 6. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #define COLOR_MAX_VALUE 255.0 10 | 11 | #import "AWColors.h" 12 | 13 | 14 | // All types are here: 15 | // https://github.com/agda/agda/blob/master/src/data/emacs-mode/agda2-highlight.el#L385 16 | 17 | //`bound' Bound variables. 18 | //`coinductiveconstructor' Coinductive constructors. 19 | //`datatype' Data types. 20 | //`dotted' Dotted patterns. 21 | //`error' Errors. 22 | //`field' Record fields. 23 | //`function' Functions. 24 | //`incompletepattern' Incomplete patterns. 25 | //`inductiveconstructor' Inductive constructors. 26 | //`keyword' Keywords. 27 | //`module' Module names. 28 | //`number' Numbers. 29 | //`operator' Operators. 30 | //`postulate' Postulates. 31 | //`primitive' Primitive functions. 32 | //`primitivetype' Primitive types (like Set and Prop). 33 | //`macro' Macros. 34 | //`record' Record types. 35 | //`string' Strings. 36 | //`symbol' Symbols like forall, =, ->, etc. 37 | //`terminationproblem' Termination problems. 38 | //`typechecks' Code which is being type-checked. 39 | //`unsolvedconstraint' Unsolved constraints, not connected to meta 40 | //variables. 41 | //`unsolvedmeta' Unsolved meta variables. 42 | //`comment' Comments.") 43 | 44 | 45 | 46 | //https://github.com/agda/agda/blob/e49365f6e45442618010069c2dcc5917d0272083/src/data/Agda.css 47 | ///* Aspects. */ 48 | //.Comment { color: #B22222 } R: 178 G: 34 B: 34 49 | //.Keyword { color: #CD6600 } 205,102,0 50 | //.String { color: #B22222 } 178,34,34 ! 51 | //.Number { color: #A020F0 } 160,32,240 52 | //.Symbol { color: #404040 } 64,64,64 53 | //.PrimitiveType { color: #0000CD } 0,0,205 54 | //.Operator {} 55 | // 56 | ///* NameKinds. */ 57 | //.Bound { color: black } 58 | //.InductiveConstructor { color: #008B00 } 0,139,0 59 | //.CoinductiveConstructor { color: #8B7500 } 139,117,0 60 | //.Datatype { color: #0000CD } 0,0,205 ! 61 | //.Field { color: #EE1289 } 238,18,137 62 | //.Function { color: #0000CD } 0,0,205 ! 63 | //.Module { color: #A020F0 } 160,32,240 ! 64 | //.Postulate { color: #0000CD } ! 65 | //.Primitive { color: #0000CD } ! 66 | //.Record { color: #0000CD } ! 67 | // 68 | ///* OtherAspects. */ 69 | //.DottedPattern {} 70 | //.UnsolvedMeta { color: black; background: yellow } 71 | //.UnsolvedConstraint { color: black; background: yellow } 72 | //.TerminationProblem { color: black; background: #FFA07A } 255,160,122 73 | //.IncompletePattern { color: black; background: #F5DEB3 } 245,222,179 74 | //.Error { color: red; text-decoration: underline } 75 | //.TypeChecks { color: black; background: #ADD8E6 } 173,216,230 76 | // 77 | ///* Standard attributes. */ 78 | //a { text-decoration: none } 79 | //a[href]:hover { background-color: #B4EEB4 } 80 | 81 | 82 | #define darkRedColor [NSColor colorWithRed:178.0/COLOR_MAX_VALUE green:34.0/COLOR_MAX_VALUE blue:34.0/COLOR_MAX_VALUE alpha:1.0] 83 | #define orangeColor [NSColor colorWithRed:205.0/COLOR_MAX_VALUE green:102.0/COLOR_MAX_VALUE blue:0.0/COLOR_MAX_VALUE alpha:1.0] 84 | #define purpleColor [NSColor colorWithRed:172.0/COLOR_MAX_VALUE green:2.0/COLOR_MAX_VALUE blue:128.0/COLOR_MAX_VALUE alpha:1.0] 85 | #define blueColor [NSColor colorWithRed:0.0/COLOR_MAX_VALUE green:1.0/COLOR_MAX_VALUE blue:193.0/COLOR_MAX_VALUE alpha:1.0] 86 | #define darkGreyColor [NSColor colorWithRed:49.0/COLOR_MAX_VALUE green:49.0/COLOR_MAX_VALUE blue:49.0/COLOR_MAX_VALUE alpha:1.0] 87 | #define greenColor [NSColor colorWithRed:20.0/COLOR_MAX_VALUE green:124.0/COLOR_MAX_VALUE blue:0.0/COLOR_MAX_VALUE alpha:1.0] 88 | #define errorColor [NSColor redColor] 89 | #define defaultColor [NSColor darkGrayColor] 90 | #define pinkColor [NSColor colorWithRed:231.0/COLOR_MAX_VALUE green:0.0/COLOR_MAX_VALUE blue:118.0/COLOR_MAX_VALUE alpha:1.0] 91 | #define yellowColor [NSColor yellowColor] 92 | 93 | NSString * const AWbound = @"bound"; 94 | NSString * const AWcoinductiveconstructor = @"coinductiveconstructor"; 95 | NSString * const AWdatatype = @"datatype"; 96 | NSString * const AWdotted = @"dotted"; 97 | NSString * const AWerror = @"error"; 98 | NSString * const AWfield = @"field"; 99 | NSString * const AWfunction = @"function"; 100 | NSString * const AWincompletepattern = @"incompletepattern"; 101 | NSString * const AWinductiveconstructor = @"inductiveconstructor"; 102 | NSString * const AWkeyword = @"keyword"; 103 | NSString * const AWmodule = @"module"; 104 | NSString * const AWnumber = @"number"; 105 | NSString * const AWpostulate = @"postulate"; 106 | NSString * const AWprimitive = @"primitive"; 107 | NSString * const AWprimitivetype = @"primitivetype"; 108 | NSString * const AWmacro = @"macro"; 109 | NSString * const AWrecord = @"record"; 110 | NSString * const AWstring = @"string"; 111 | NSString * const AWsymbol = @"symbol"; 112 | NSString * const AWterminationproblem = @"terminationproblem"; 113 | NSString * const AWtypechecks = @"typechecks"; 114 | NSString * const AWunsolvedconstraint = @"unsolvedconstraint"; 115 | NSString * const AWunsolvedmeta = @"unsolvedmeta"; 116 | NSString * const AWcomment = @"comment"; 117 | 118 | NSString * const AWdatatypeOperator = @"datatype operator"; 119 | NSString * const AWfunctionOperator = @"function operator"; 120 | NSString * const AWinductiveconstructorOperator = @"inductiveconstructor operator"; 121 | 122 | @implementation AWColors 123 | 124 | + (CGColorRef) defaultBackgroundColor 125 | { 126 | return CGColorCreateGenericRGB(239.0/255.0, 239.0/255.0, 239.0/255.0, 1); 127 | } 128 | 129 | + (CGColorRef) defaultSeparatorColor 130 | { 131 | return CGColorCreateGenericRGB(176.0/255.0, 176.0/255.0, 176.0/255.0, 1); 132 | } 133 | 134 | + (NSColor *) unselectedTokenColor 135 | { 136 | return [NSColor colorWithCalibratedRed:0/COLOR_MAX_VALUE green:64.0/COLOR_MAX_VALUE blue:153.0/COLOR_MAX_VALUE alpha:1.0]; 137 | } 138 | 139 | + (NSColor *) borderTokenColor 140 | { 141 | return [NSColor colorWithCalibratedRed:110.f/255.f green:116.f/255.f blue:114.f/255.f alpha:1.f]; 142 | } 143 | 144 | + (NSColor *) highlightColorForType:(NSString *)type 145 | { 146 | 147 | NSColor * color; 148 | 149 | if ([type isEqualToString:AWcomment]) { 150 | color = darkRedColor; 151 | } 152 | else if ([type isEqualToString:AWbound]) { 153 | color = darkGreyColor; 154 | } 155 | else if ([type isEqualToString:AWcoinductiveconstructor]) { 156 | color = defaultColor; 157 | } 158 | else if ([type isEqualToString:AWdatatype]) { 159 | color = blueColor; 160 | } 161 | else if ([type isEqualToString:AWdatatypeOperator]) { 162 | color = blueColor; 163 | } 164 | else if ([type isEqualToString:AWdotted]) { 165 | color = defaultColor; 166 | } 167 | else if ([type isEqualToString:AWerror]) { 168 | color = errorColor; 169 | } 170 | else if ([type isEqualToString:AWfield]) { 171 | color = pinkColor; 172 | } 173 | else if ([type isEqualToString:AWfunction]) { 174 | color = blueColor; 175 | } 176 | else if ([type isEqualToString:AWfunctionOperator]) { 177 | color = blueColor; 178 | } 179 | else if ([type isEqualToString:AWincompletepattern]) { 180 | color = defaultColor; 181 | } 182 | else if ([type isEqualToString:AWinductiveconstructor]) { 183 | color = greenColor; 184 | } 185 | else if ([type isEqualToString:AWinductiveconstructorOperator]) { 186 | color = greenColor; 187 | } 188 | else if ([type isEqualToString:AWkeyword]) { 189 | color = orangeColor; 190 | } 191 | else if ([type isEqualToString:AWmacro]) { 192 | color = defaultColor; 193 | } 194 | else if ([type isEqualToString:AWmodule]) { 195 | color = purpleColor; 196 | } 197 | else if ([type isEqualToString:AWnumber]) { 198 | color = purpleColor; 199 | } 200 | else if ([type isEqualToString:AWpostulate]) { 201 | color = blueColor; 202 | } 203 | else if ([type isEqualToString:AWprimitive]) { 204 | color = defaultColor; 205 | } 206 | else if ([type isEqualToString:AWprimitivetype]) { 207 | color = blueColor; 208 | } 209 | else if ([type isEqualToString:AWrecord]) { 210 | color = blueColor; 211 | } 212 | else if ([type isEqualToString:AWstring]) { 213 | color = darkRedColor; 214 | } 215 | else if ([type isEqualToString:AWsymbol]) { 216 | color = [NSColor darkGrayColor]; 217 | } 218 | else if ([type isEqualToString:AWterminationproblem]) { 219 | color = defaultColor; 220 | } 221 | else if ([type isEqualToString:AWtypechecks]) { 222 | color = defaultColor; 223 | } 224 | else if ([type isEqualToString:AWunsolvedconstraint]) { 225 | color = defaultColor; 226 | } 227 | else if ([type isEqualToString:AWunsolvedmeta]) { 228 | color = darkGreyColor; 229 | } 230 | else { 231 | NSLog(@"AWColors.m : TYPE NOT FOUND!\n%@", type); 232 | color = defaultColor; 233 | } 234 | 235 | return color; 236 | } 237 | 238 | @end 239 | -------------------------------------------------------------------------------- /Agda Writer/AWCommunitacion.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWCommunitacion.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 3. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | @interface AWCommunitacion : NSObject { 14 | 15 | NSPipe * inputPipe; 16 | NSPipe * outputPipe; 17 | 18 | NSFileHandle * fileReading; 19 | NSFileHandle * fileWriting; 20 | 21 | NSTask * task; 22 | 23 | dispatch_queue_t agdaQueue; 24 | 25 | NSMutableString * partialAgdaResponse; 26 | 27 | } 28 | 29 | @property BOOL searchingForAgda; 30 | @property int numberOfNotificationHits; 31 | @property BOOL hasOpenConnectionToAgda; 32 | 33 | @property NSViewController * activeViewController; 34 | 35 | 36 | #pragma mark Init methods 37 | - (id) init; 38 | - (id) initForCommunicatingWithAgda; 39 | 40 | #pragma mark Communication methods 41 | - (void) writeData: (NSString * ) message; 42 | - (void) writeDataToAgda:(NSString *) message sender:(NSViewController *)sender; 43 | - (void) searchForAgda; 44 | - (BOOL) isAgdaAvaliableAtPath:(NSString *)path; 45 | - (void) closeConnectionToAgda; 46 | - (void) quitAndRestartConnectionToAgda; 47 | - (void) clearPartialResponse; 48 | - (void) openConnectionToAgda; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Agda Writer/AWCommunitacion.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWCommunitacion.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 3. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWCommunitacion.h" 10 | #import "AWNotifications.h" 11 | #import "AWAgdaParser.h" 12 | #import "AWAgdaActions.h" 13 | #import "AWHelper.h" 14 | 15 | @implementation AWCommunitacion 16 | 17 | 18 | -(id) init 19 | { 20 | self = [super init]; 21 | if (self) { 22 | 23 | 24 | [self openPipes]; 25 | [[NSNotificationCenter defaultCenter] addObserver:self 26 | selector:@selector(dataAvailabe:) 27 | name:NSFileHandleReadToEndOfFileCompletionNotification 28 | object:nil]; 29 | 30 | self.searchingForAgda = NO; 31 | self.numberOfNotificationHits = 0; 32 | 33 | } 34 | return self; 35 | } 36 | 37 | -(id) initForCommunicatingWithAgda 38 | { 39 | self = [super init]; 40 | if (self) { 41 | 42 | // Create new thread 43 | agdaQueue = dispatch_queue_create("net.koleznik.agdaQueue", NULL); 44 | 45 | // Initialize mutable string 46 | partialAgdaResponse = [[NSMutableString alloc] init]; 47 | 48 | self.hasOpenConnectionToAgda = NO; 49 | } 50 | return self; 51 | } 52 | 53 | - (BOOL) isAgdaAvaliableAtPath:(NSString *)path 54 | { 55 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 56 | task = [NSTask new]; 57 | task.launchPath = path; 58 | task.arguments = @[@"--interaction"]; 59 | task.standardInput = outputPipe; 60 | task.standardOutput = inputPipe; 61 | 62 | // Potentialy unsafe code. Wrap it around try/catch block 63 | @try { 64 | [task launch]; 65 | // NSTask didn't throw exception. Return YES; 66 | return YES; 67 | } 68 | @catch (NSException *exception) { 69 | // Exception was thrown. Return NO; 70 | NSLog(@"Failed to load Agda. Reason: %@", exception.reason); 71 | return NO; 72 | } 73 | @finally { 74 | // Pass. 75 | } 76 | 77 | } 78 | 79 | 80 | - (void) dataAvailabe:(NSNotification *) notification { 81 | 82 | NSData *data = [[notification userInfo] objectForKey:NSFileHandleNotificationDataItem]; 83 | NSString * reply = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 84 | NSArray * actions = [AWAgdaParser makeArrayOfActionsAndDeleteActionFromString:[[NSMutableString alloc] initWithString:reply]]; 85 | [AWNotifications notifyExecuteActions:actions sender:self.activeViewController]; 86 | } 87 | 88 | 89 | - (void) stopTask 90 | { 91 | [task terminate]; 92 | } 93 | 94 | 95 | 96 | - (void) startTask 97 | { 98 | 99 | 100 | task = [NSTask new]; 101 | // PATH TO AGDA 102 | task.launchPath = [AWNotifications agdaLaunchPath]; 103 | NSLog(@"launch path: %@", task.launchPath); 104 | task.arguments = @[@"--interaction"]; 105 | task.standardInput = outputPipe; 106 | task.standardOutput = inputPipe; 107 | BOOL exists = [[NSFileManager defaultManager] isExecutableFileAtPath:[task launchPath]]; 108 | if (exists) { 109 | @try { 110 | [task launch]; 111 | } 112 | @catch (NSException *exception) { 113 | NSLog(@"Exception: %@", exception.reason); 114 | NSAlert * alert = [[NSAlert alloc] init]; 115 | [alert addButtonWithTitle:@"OK"]; 116 | [alert setMessageText:@"Task can't be launched!\nCheck your path in Settings."]; 117 | [alert setAlertStyle:NSWarningAlertStyle]; 118 | if ([alert runModal] == NSAlertFirstButtonReturn) { 119 | // NSLog(@"Open preferences"); 120 | [AWNotifications notifyOpenPreferences]; 121 | } 122 | } 123 | @finally { 124 | 125 | } 126 | 127 | } 128 | else 129 | { 130 | // File can't be lauched! 131 | NSLog(@"File can't be launched!\nLaunch path not accessible."); 132 | NSAlert * alert = [[NSAlert alloc] init]; 133 | [alert addButtonWithTitle:@"OK"]; 134 | [alert setMessageText:@"Task can't be launched!\nCheck your path in Settings."]; 135 | [alert setAlertStyle:NSWarningAlertStyle]; 136 | if ([alert runModal] == NSAlertFirstButtonReturn) { 137 | // NSLog(@"Open preferences"); 138 | [AWNotifications notifyOpenPreferences]; 139 | } 140 | } 141 | 142 | } 143 | 144 | -(void) searchForAgda 145 | { 146 | [self openPipes]; 147 | task = [NSTask new]; 148 | // PATH TO AGDA 149 | task.launchPath = @"/usr/bin/find"; 150 | NSLog(@"launch path: %@", task.launchPath); 151 | task.arguments = @[NSHomeDirectory(), @"-name", @"agda"]; 152 | task.standardInput = outputPipe; 153 | task.standardOutput = inputPipe; 154 | 155 | @try { 156 | [task launch]; 157 | self.searchingForAgda = YES; 158 | } 159 | @catch (NSException *exception) { 160 | NSLog(@"exception: %@", exception.description); 161 | } 162 | @finally { 163 | 164 | } 165 | 166 | 167 | 168 | } 169 | 170 | 171 | 172 | - (void) openPipes 173 | { 174 | inputPipe = [NSPipe pipe]; 175 | outputPipe = [NSPipe pipe]; 176 | 177 | fileReading = inputPipe.fileHandleForReading; 178 | [fileReading readToEndOfFileInBackgroundAndNotify]; 179 | fileWriting = outputPipe.fileHandleForWriting; 180 | } 181 | 182 | - (void) closePipes 183 | { 184 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 185 | if ([task isRunning]) { 186 | [task terminate]; 187 | } 188 | } 189 | 190 | - (void) openConnectionToAgda 191 | { 192 | // spawn task in a custom thread 193 | dispatch_queue_t taskQueue = dispatch_queue_create("net.koleznik.AgdaQueue", NULL); 194 | dispatch_async(taskQueue, ^{ 195 | task = [[NSTask alloc] init]; 196 | // set standard input, output and error. Error outputs will be in our outputs. 197 | [task setStandardOutput: [NSPipe pipe]]; 198 | [task setStandardInput: [NSPipe pipe]]; 199 | [task setStandardError: [task standardOutput]]; 200 | BOOL useBundledAgda = [[NSUserDefaults standardUserDefaults] boolForKey:@"useBundledAgda"]; 201 | if (useBundledAgda) { 202 | NSDictionary * environmentDictionary = @{ 203 | @"Agda_datadir" : [AWHelper pathToBundledAgdaPrimitive], 204 | @"DYLD_FALLBACK_LIBRARY_PATH" : [AWHelper pathToBundledAgda] 205 | }; 206 | [task setLaunchPath:[AWHelper pathToBundledAgda]]; 207 | [task setEnvironment:environmentDictionary]; 208 | } 209 | else { 210 | [task setLaunchPath:[AWNotifications agdaLaunchPath]]; 211 | } 212 | // [task setEnvironment:@{@"Agda_datadir" : @"/Users/andrej/Documents/agda-writer/agda/Agda-2.4.0.2", 213 | // @"DYLD_FALLBACK_LIBRARY_PATH" : @"/Users/andrej/Documents/agda-writer/agda"}]; 214 | 215 | 216 | [task setArguments:@[@"--interaction"]]; 217 | 218 | NSLog(@"Agda launch path:\n%@", task.launchPath); 219 | 220 | [[[task standardOutput] fileHandleForReading] waitForDataInBackgroundAndNotify]; 221 | 222 | // Add observer 223 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAgdaResponse:) name:NSFileHandleDataAvailableNotification object:nil]; 224 | 225 | // when everything is set, launch task 226 | 227 | @try { 228 | [task launch]; 229 | self.hasOpenConnectionToAgda = YES; 230 | // Wait until exit; this would block the main thread, but we are on our own thread. 231 | [task waitUntilExit]; 232 | } 233 | @catch (NSException *exception) { 234 | NSLog(@"Exeption launching the task, reason: %@", exception.reason); 235 | // Open preferences 236 | dispatch_sync(dispatch_get_main_queue(), ^{ 237 | NSAlert * alert = [[NSAlert alloc] init]; 238 | [alert addButtonWithTitle:@"OK"]; 239 | [alert setMessageText:@"Task can't be launched!\nCheck your path in Settings."]; 240 | [alert setAlertStyle:NSWarningAlertStyle]; 241 | if ([alert runModal] == NSAlertFirstButtonReturn) { 242 | NSLog(@"Open preferences"); 243 | [AWNotifications notifyOpenPreferences]; 244 | } 245 | }); 246 | 247 | } 248 | @finally { 249 | 250 | } 251 | 252 | 253 | 254 | 255 | }); 256 | 257 | } 258 | 259 | - (void) closeConnectionToAgda 260 | { 261 | [self closePipes]; 262 | fileReading = nil; 263 | fileWriting = nil; 264 | } 265 | 266 | -(void)quitAndRestartConnectionToAgda { 267 | // Close stuff 268 | [self closePipes]; 269 | fileReading = nil; 270 | fileWriting = nil; 271 | task = nil; 272 | 273 | // Open new connection 274 | [self openConnectionToAgda]; 275 | 276 | } 277 | 278 | - (void) handleAgdaResponse:(NSNotification *) notification 279 | { 280 | NSData * avaliableData = [[[task standardOutput] fileHandleForReading] availableData]; 281 | NSString * avaliableString = [[NSString alloc] initWithData:avaliableData encoding:NSUTF8StringEncoding]; 282 | dispatch_sync(dispatch_get_main_queue(), ^{ 283 | // Handle avaliable data on main thread 284 | // NSLog(@"%@", avaliableString); 285 | // Append partial string and perform action if possible 286 | // if possible, cut this part of the string. 287 | if (avaliableString) { 288 | [partialAgdaResponse appendString:avaliableString]; 289 | [AWNotifications notifyAgdaReplied:avaliableString sender:self.activeViewController]; 290 | NSArray * actions = [AWAgdaParser makeArrayOfActionsAndDeleteActionFromString:partialAgdaResponse]; 291 | if (actions.count > 0) { 292 | [AWNotifications notifyExecuteActions:actions sender:self.activeViewController]; 293 | } 294 | 295 | } 296 | 297 | 298 | 299 | }); 300 | // we need to register for notifications everytime notification is recieved 301 | [[[task standardOutput] fileHandleForReading] waitForDataInBackgroundAndNotify]; 302 | } 303 | 304 | 305 | - (void) writeDataToAgda:(NSString *) message sender:(NSViewController *)sender; 306 | { 307 | // Don't forget to append newline character at the end of message (if it has none) 308 | // \n aka newline reacts as hitting enter in terminal. It flushes all the writing buffer. No need for closing the pipes. 309 | // All messages to agda should end with '\n', since we are in interactive mode! 310 | 311 | if (![message hasSuffix:@"\n"]) { 312 | message = [message stringByAppendingString:@"\n"]; 313 | } 314 | if (!self.hasOpenConnectionToAgda) { 315 | [self openConnectionToAgda]; 316 | } 317 | // Add output to buffer! 318 | // NSLog(@"%@", message); 319 | [AWNotifications notifyAgdaReplied:message sender:sender]; 320 | 321 | self.activeViewController = sender; 322 | 323 | [[[task standardInput] fileHandleForWriting] writeData:[message dataUsingEncoding:NSUTF8StringEncoding]]; 324 | } 325 | 326 | - (void) writeData: (NSString * ) message 327 | { 328 | [self openPipes]; 329 | [self startTask]; 330 | [fileWriting writeData:[message dataUsingEncoding:NSUTF8StringEncoding]]; 331 | [fileWriting closeFile]; 332 | } 333 | 334 | 335 | - (void) clearPartialResponse { 336 | partialAgdaResponse = [[NSMutableString alloc] init]; 337 | } 338 | 339 | 340 | #pragma mark - 341 | 342 | -(void)dealloc 343 | { 344 | // Remove self as observer and terminate task if it's still running 345 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 346 | if ([task isRunning]) { 347 | [task terminate]; 348 | } 349 | } 350 | 351 | 352 | 353 | @end 354 | -------------------------------------------------------------------------------- /Agda Writer/AWContainerOutputTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWContainerOutputTextView.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 6. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AWContainerOutputTextView : NSView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Agda Writer/AWContainerOutputTextView.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWContainerOutputTextView.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 6. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWContainerOutputTextView.h" 10 | #import "AWColors.h" 11 | 12 | @implementation AWContainerOutputTextView 13 | 14 | - (void)awakeFromNib 15 | { 16 | [self setWantsLayer:YES]; 17 | self.layer.masksToBounds = YES; 18 | self.layer.borderWidth = 1.0f ; 19 | 20 | 21 | [self.layer setBackgroundColor:[AWColors defaultBackgroundColor]]; 22 | 23 | [self.layer setBorderColor:[AWColors defaultSeparatorColor]]; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Agda Writer/AWContainerStatusTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWContainerStatusTextView.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 6. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AWContainerStatusTextView : NSView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Agda Writer/AWContainerStatusTextView.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWContainerStatusTextView.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 6. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWContainerStatusTextView.h" 10 | #import "AWColors.h" 11 | #import "AWNotifications.h" 12 | 13 | @implementation AWContainerStatusTextView 14 | 15 | - (void)awakeFromNib 16 | { 17 | [self setWantsLayer:YES]; 18 | self.layer.masksToBounds = YES; 19 | self.layer.borderWidth = 1.0f ; 20 | 21 | [self.layer setBackgroundColor:[AWColors defaultBackgroundColor]]; 22 | 23 | [self.layer setBorderColor:[AWColors defaultSeparatorColor]]; 24 | 25 | } 26 | 27 | 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Agda Writer/AWGoalsTableController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWGoalsTableController.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 1. 06. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AWMainTextView.h" 11 | 12 | @interface AWGoalsTableController : NSObject 13 | 14 | @property (weak) IBOutlet NSTableView *goalsTable; 15 | @property (unsafe_unretained) IBOutlet AWMainTextView *mainTextView; 16 | 17 | @property (nonatomic) id parentViewController; 18 | 19 | -(void)selectRow:(NSInteger)row highlightGoal:(BOOL)highlight; 20 | 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Agda Writer/AWGoalsTableController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWGoalsTableController.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 1. 06. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWGoalsTableController.h" 10 | #import "AWNotifications.h" 11 | #import "AWAgdaParser.h" 12 | 13 | @implementation AWGoalsTableController { 14 | NSMutableArray * items; 15 | NSMutableArray * goalIndexes; 16 | NSArray * goals; 17 | 18 | BOOL shouldHighlightText; 19 | } 20 | 21 | -(void)awakeFromNib 22 | { 23 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(allGoalsAction:) name:AWAllGoals object:nil]; 24 | shouldHighlightText = YES; 25 | 26 | } 27 | 28 | - (void)allGoalsAction:(NSNotification *)notification 29 | { 30 | if (notification.object != self.parentViewController) { 31 | return; 32 | } 33 | // Create array of goals 34 | items = [[NSMutableArray alloc] init]; 35 | goalIndexes = [[NSMutableArray alloc] init]; 36 | NSArray * arrayOfDicts = [AWAgdaParser makeArrayOfGoalsWithSuggestions:notification.userInfo[@"goals"]]; 37 | for (NSDictionary * dict in arrayOfDicts) { 38 | [items addObject:dict[@"goalType"]]; 39 | [goalIndexes addObject:dict[@"goalIndex"]]; 40 | } 41 | [self.goalsTable reloadData]; 42 | } 43 | 44 | -(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView 45 | { 46 | return items.count; 47 | } 48 | 49 | - (NSView *)tableView:(NSTableView *)tableView 50 | viewForTableColumn:(NSTableColumn *)tableColumn 51 | row:(NSInteger)row { 52 | 53 | if ([tableColumn.identifier isEqualToString:@"GoalType"]) { 54 | NSTableCellView *result = [tableView makeViewWithIdentifier:@"GoalType" owner:self]; 55 | result.textField.stringValue = [items objectAtIndex:row]; 56 | 57 | return result; 58 | } 59 | else if ([tableColumn.identifier isEqualToString:@"GoalNumber"]) 60 | { 61 | NSTableCellView *result = [tableView makeViewWithIdentifier:@"GoalNumber" owner:self]; 62 | result.textField.stringValue = [goalIndexes objectAtIndex:row]; 63 | 64 | return result; 65 | } 66 | return nil; 67 | 68 | } 69 | 70 | 71 | -(void)selectRow:(NSInteger)row highlightGoal:(BOOL)highlight 72 | { 73 | shouldHighlightText = highlight; 74 | [self.goalsTable scrollRowToVisible:row]; 75 | [self.goalsTable selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO]; 76 | } 77 | 78 | 79 | - (void)tableViewSelectionDidChange:(NSNotification *)notification { 80 | NSTableView * tableView = notification.object; 81 | if (items.count > tableView.selectedRow) { 82 | // NSLog(@"User pressed goal number: %li, name: %@", tableView.selectedRow, items[tableView.selectedRow]); 83 | 84 | // Find all goals (ranges of goals) and show pressed goal. 85 | NSRange selectedGoal = [AWAgdaParser goalAtIndex:tableView.selectedRow textStorage:self.mainTextView.textStorage]; 86 | // Show pressed goal 87 | if (selectedGoal.location != NSNotFound) { 88 | if (shouldHighlightText) { 89 | [self.mainTextView scrollRangeToVisible:selectedGoal]; 90 | [self.mainTextView showFindIndicatorForRange:selectedGoal]; 91 | if (3 <= (selectedGoal.length - 3)) { 92 | [self.mainTextView setSelectedRange:NSMakeRange(selectedGoal.location + 3, selectedGoal.length - 6)]; 93 | } 94 | else { 95 | [self.mainTextView setSelectedRange:NSMakeRange(selectedGoal.location + 2, selectedGoal.length - 4)]; 96 | } 97 | 98 | 99 | } 100 | } 101 | else { 102 | NSString * content = items[tableView.selectedRow]; 103 | NSString * regexPattern = @"[0-9]*,[0-9]*-[0-9]*"; 104 | NSError * error; 105 | NSRegularExpression * regex = [[NSRegularExpression alloc] initWithPattern:regexPattern options:NSRegularExpressionAnchorsMatchLines error:&error]; 106 | NSArray * matches = [regex matchesInString:content options:0 range:NSMakeRange(0, content.length)]; 107 | if (matches.count == 1) { 108 | NSTextCheckingResult * result = matches[0]; 109 | 110 | NSString * substring = [content substringWithRange:result.range]; 111 | NSArray * components = [substring componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@",-"]]; 112 | if (components.count == 3) { 113 | NSInteger lineNumber = [components[0] integerValue]; 114 | NSInteger startRange = [components[1] integerValue]; 115 | NSInteger endRange = [components[2] integerValue]; 116 | 117 | NSRange lineRange = NSMakeRange(startRange, endRange - startRange); 118 | NSRange actualRange = [AWAgdaParser rangeFromLineNumber:lineNumber andLineRange:lineRange string:self.mainTextView.string]; 119 | if (actualRange.location != NSNotFound) { 120 | [self.mainTextView scrollRangeToVisible:actualRange]; 121 | [self.mainTextView showFindIndicatorForRange:actualRange]; 122 | [self.mainTextView setSelectedRange:actualRange]; 123 | } 124 | } 125 | } 126 | } 127 | shouldHighlightText = YES; 128 | 129 | [self.mainTextView.window makeFirstResponder:self.mainTextView]; 130 | } 131 | else 132 | { 133 | // NSLog(@"Index %li out of bounds for array of length %li",tableView.selectedRow, items.count); 134 | } 135 | 136 | 137 | } 138 | 139 | @end 140 | -------------------------------------------------------------------------------- /Agda Writer/AWHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWHelper.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 6. 05. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AWHelper : NSObject 13 | 14 | + (NSFont *)defaultFontInAgda; 15 | + (void) saveDefaultFont:(NSFont *)font; 16 | + (void) setUserDefaults; 17 | + (BOOL) isShowingNotifications; 18 | + (void) setShowingNotifications:(BOOL)isShowing; 19 | + (NSDictionary *) keyBindings; 20 | + (void) saveKeyBindings: (NSDictionary *)keyBindings; 21 | + (void) savePathToLibraries: (NSString *)path; 22 | + (NSString *)pathToLibraries; 23 | + (NSString *)pathToLibrariesToAgda; 24 | + (CGFloat) delayForAutocomplete; 25 | 26 | + (NSString *) helpForExternalLibraries; 27 | 28 | + (NSString *) pathToBundledAgda; 29 | + (NSString *) pathToBundledAgdaPrimitive; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Agda Writer/AWHelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWHelper.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 6. 05. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWHelper.h" 10 | #import "AWNotifications.h" 11 | 12 | @implementation AWHelper 13 | 14 | + (NSFont *)defaultFontInAgda 15 | { 16 | NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; 17 | NSString * fontName = [ud objectForKey:FONT_FAMILY_KEY]; 18 | NSNumber * fontSize = [ud objectForKey:FONT_SIZE_KEY]; 19 | if (fontName && fontSize) { 20 | NSFont * defaultFont = [NSFont fontWithName:fontName size:[fontSize floatValue]]; 21 | return defaultFont; 22 | } 23 | else 24 | { 25 | // Load font from plist 26 | NSDictionary * defaults = [AWNotifications dictionaryOfDefaults]; 27 | NSDictionary * font = [defaults objectForKey:@"defaultFont"]; 28 | NSString * name = [font objectForKey:@"name"]; 29 | NSNumber * fontSize = (NSNumber *)[font objectForKey:@"size"]; 30 | NSFont * fontRet = [NSFont fontWithName:name size:[fontSize floatValue]]; 31 | return fontRet; 32 | } 33 | 34 | return nil; 35 | } 36 | 37 | + (void) saveDefaultFont:(NSFont *)font 38 | { 39 | NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; 40 | [ud setObject:font.fontName forKey:FONT_FAMILY_KEY]; 41 | [ud setObject:[NSNumber numberWithFloat:font.pointSize] forKey:FONT_SIZE_KEY]; 42 | [ud synchronize]; 43 | } 44 | 45 | + (void) setUserDefaults { 46 | NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; 47 | // [ud removeObjectForKey:@"KeyBindings"]; 48 | NSDictionary * keyBindings = [ud objectForKey:@"KeyBindings"]; 49 | if (!keyBindings) { 50 | NSURL * keyBindingsUrl = [[NSBundle mainBundle] URLForResource:@"Key Bindings" withExtension:@"plist"]; 51 | [ud setObject:[NSDictionary dictionaryWithContentsOfURL:keyBindingsUrl] forKey:@"KeyBindings"]; 52 | } 53 | NSNumber * showNotifications = [ud objectForKey:@"showNotifications"]; 54 | if (!showNotifications) { 55 | [ud setObject:[NSNumber numberWithBool:YES] forKey:@"showNotifications"]; 56 | } 57 | NSNumber * delayForAutocomplete = [ud objectForKey:@"delayForAutocomplete"]; 58 | if (!delayForAutocomplete) { 59 | [ud setObject:[NSNumber numberWithFloat:0.5f] forKey:@"delayForAutocomplete"]; 60 | } 61 | NSNumber * numberOfSpacesRepresentingTab = [ud objectForKey:@"numberOfSpacesRepresentingTab"]; 62 | if (!numberOfSpacesRepresentingTab) { 63 | [ud setInteger:2 forKey:@"numberOfSpacesRepresentingTab"]; 64 | } 65 | // [ud removeObjectForKey:@"numberOfSpacesRepresentingTab"]; 66 | [ud synchronize]; 67 | 68 | } 69 | 70 | + (NSDictionary *)keyBindings { 71 | NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; 72 | NSDictionary * keyBindings = [ud objectForKey:@"KeyBindings"]; 73 | return keyBindings; 74 | } 75 | 76 | + (void)saveKeyBindings: (NSDictionary *)keyBindings { 77 | NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; 78 | [ud setObject:keyBindings forKey:@"KeyBindings"]; 79 | [ud synchronize]; 80 | } 81 | 82 | + (BOOL)isShowingNotifications { 83 | NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; 84 | NSNumber * showNotifications = [ud objectForKey:@"showNotifications"]; 85 | return [showNotifications boolValue]; 86 | } 87 | 88 | + (void)setShowingNotifications:(BOOL)isShowing { 89 | NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; 90 | [ud setObject:[NSNumber numberWithBool:isShowing] forKey:@"showNotifications"]; 91 | [ud synchronize]; 92 | } 93 | 94 | + (void) savePathToLibraries: (NSString *)path 95 | { 96 | NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; 97 | [ud setObject:path forKey:@"pathToLibraries"]; 98 | [ud synchronize]; 99 | } 100 | + (NSString *)pathToLibraries 101 | { 102 | NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; 103 | NSString * pathToLibraries = [ud objectForKey:@"pathToLibraries"]; 104 | if (pathToLibraries) { 105 | return pathToLibraries; 106 | } 107 | else { 108 | return @""; 109 | } 110 | } 111 | 112 | + (NSString *)pathToLibrariesToAgda 113 | { 114 | NSString * pathToLibraries = [self pathToLibraries]; 115 | NSArray * arrayOfPaths = [[pathToLibraries copy] componentsSeparatedByString:@", "]; 116 | NSString * pathString = @""; 117 | for (NSString * path in arrayOfPaths) { 118 | pathString = [pathString stringByAppendingFormat:@"%@\", \"", path]; 119 | } 120 | pathString = [pathString substringToIndex:pathString.length - 4]; 121 | return pathString; 122 | } 123 | 124 | +(CGFloat)delayForAutocomplete { 125 | NSUserDefaults * ud = [NSUserDefaults standardUserDefaults]; 126 | return [[ud objectForKey:@"delayForAutocomplete"] floatValue]; 127 | } 128 | 129 | + (NSString *) helpForExternalLibraries { 130 | return @"Explanation: Libraries, which you can import when loading a file, for example stdlib. If you want to use multiple libraries, separate them with comma (,)\n\nUsage: You should put full path, ~ stands for relative to current work path.\n\nExample:\n/Users/username/AgdaLibs\n/Users/libs/lib1, /Users/agda/lib2"; 131 | } 132 | 133 | + (NSString *) pathToBundledAgda { 134 | return [[NSBundle mainBundle] pathForResource:@"agda" ofType:@""]; 135 | } 136 | + (NSString *) pathToBundledAgdaPrimitive { 137 | NSString * pathToAgdaDirectory = [NSString stringWithFormat:@"%@%@", [[NSBundle mainBundle] resourcePath], @"/Agda-2.4.2.2"];; 138 | return pathToAgdaDirectory; 139 | } 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /Agda Writer/AWHighlighting.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWHighlighting.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 12. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AWHighlighting : NSObject 13 | 14 | 15 | + (void) highlightCodeAtRange:(NSRange) range actionName: (NSString *) actionName textView: (NSTextView *)textView; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Agda Writer/AWHighlighting.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWHighlighting.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 12. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWHighlighting.h" 10 | #import "AWColors.h" 11 | 12 | 13 | @implementation AWHighlighting 14 | 15 | + (void) highlightCodeAtRange:(NSRange) range actionName: (NSString *) actionName textView: (NSTextView *)textView 16 | { 17 | range = NSMakeRange(range.location - 1, range.length); 18 | NSColor * color = [AWColors highlightColorForType:actionName]; 19 | if (color) { 20 | [textView.layoutManager addTemporaryAttributes:[NSDictionary dictionaryWithObject:color forKey:NSForegroundColorAttributeName] forCharacterRange:range]; 21 | } 22 | 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Agda Writer/AWInputViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWInputViewController.h 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 21. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MAAttachedWindow.h" 11 | #import "AWAgdaActions.h" 12 | 13 | 14 | typedef enum : NSUInteger { 15 | AWInputViewTypeShowModuleContents, 16 | AWInputViewTypeInfer, 17 | AWInputViewTypeComputeNormalForm, 18 | AWInputViewTypeWhyInScope 19 | } AWInputViewType; 20 | 21 | @protocol AWInputDelegate 22 | @required 23 | -(void)inputDidEndEditing:(NSString *)content withType:(AWInputViewType)type normalisationLevel:(AWNormalisationLevel)level; 24 | 25 | @optional 26 | -(void)closeWindow; 27 | 28 | @end 29 | 30 | @interface AWInputViewController : NSViewController 31 | 32 | - (id)initWithInputType: (AWInputViewType)inputType global: (BOOL)isGlobal rect:(NSRect)rect; 33 | 34 | @property (weak) IBOutlet NSTextField *inputTitle; 35 | @property (weak) IBOutlet NSTextField *inputTextField; 36 | @property (nonatomic) id delegate; 37 | @property AWNormalisationLevel normalisationLevel; 38 | @property NSPoint point; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Agda Writer/AWInputViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWInputViewController.m 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 21. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWInputViewController.h" 10 | #import "UnicodeTransformator.h" 11 | #import "AWHelper.h" 12 | 13 | @interface AWInputViewController () 14 | 15 | @end 16 | 17 | @class MAAttachedWindow; 18 | 19 | @implementation AWInputViewController { 20 | AWInputViewType _type; 21 | BOOL _isGlobal; 22 | NSRect _rect; 23 | BOOL _autoCompleteTriggered; 24 | 25 | } 26 | 27 | - (void)viewDidLoad { 28 | [super viewDidLoad]; 29 | 30 | self.inputTextField.delegate = self; 31 | [self.inputTextField setFont:[AWHelper defaultFontInAgda]]; 32 | 33 | _autoCompleteTriggered = NO; 34 | 35 | 36 | if (_isGlobal) { 37 | self.point = NSMakePoint(200, 220); 38 | 39 | switch (_type) { 40 | case AWInputViewTypeComputeNormalForm: 41 | [self.inputTitle setStringValue:@"Compute normal form (global):"]; 42 | break; 43 | case AWInputViewTypeInfer: 44 | [self.inputTitle setStringValue:@"Infer (global):"]; 45 | break; 46 | case AWInputViewTypeShowModuleContents: 47 | [self.inputTitle setStringValue:@"Show Module Contents (global):"]; 48 | break; 49 | case AWInputViewTypeWhyInScope: 50 | [self.inputTitle setStringValue:@"Why in scope? (global):"]; 51 | break; 52 | default: 53 | break; 54 | } 55 | } 56 | else { 57 | 58 | 59 | NSPoint point = NSMakePoint(_rect.origin.x + _rect.size.width/2, _rect.origin.y + _rect.size.height/2); 60 | self.point = point; 61 | NSRect frame = self.view.frame; 62 | [self.view setFrame:NSMakeRect(frame.origin.x, frame.origin.y, frame.size.width*2/3, frame.size.width*1/3)]; 63 | switch (_type) { 64 | case AWInputViewTypeComputeNormalForm: 65 | [self.inputTitle setStringValue:@"Compute normal form (goal specific):"]; 66 | break; 67 | case AWInputViewTypeInfer: 68 | [self.inputTitle setStringValue:@"Infer (goal specific):"]; 69 | break; 70 | case AWInputViewTypeShowModuleContents: 71 | [self.inputTitle setStringValue:@"Show Module Contents (goal specific):"]; 72 | break; 73 | case AWInputViewTypeWhyInScope: 74 | [self.inputTitle setStringValue:@"Why in scope? (goal specific):"]; 75 | break; 76 | 77 | default: 78 | break; 79 | } 80 | } 81 | 82 | 83 | 84 | // Do view setup here. 85 | } 86 | 87 | - (id)initWithInputType: (AWInputViewType)inputType global: (BOOL)isGlobal rect:(NSRect)rect; 88 | { 89 | self = [self initWithNibName:@"AWInputViewController" bundle:nil]; 90 | if (self) { 91 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidResignKey:) name: 92 | @"NSWindowDidResignKeyNotification" object:nil]; 93 | 94 | 95 | 96 | _type = inputType; 97 | _isGlobal = isGlobal; 98 | _rect = rect; 99 | 100 | 101 | 102 | 103 | } 104 | return self; 105 | } 106 | 107 | -(void)controlTextDidChange:(NSNotification *)obj 108 | { 109 | if (_autoCompleteTriggered) { 110 | return; 111 | } 112 | else { 113 | _autoCompleteTriggered = YES; 114 | [[[obj userInfo] objectForKey:@"NSFieldEditor"] complete:nil]; 115 | 116 | } 117 | 118 | } 119 | 120 | 121 | 122 | -(void)keyUp:(NSEvent *)theEvent 123 | { 124 | [super keyUp:theEvent]; 125 | 126 | if (_autoCompleteTriggered) { 127 | _autoCompleteTriggered = NO; 128 | } 129 | if (theEvent.keyCode == 53) { 130 | // escape pressed, close window 131 | [self.delegate closeWindow]; 132 | } 133 | else if (theEvent.keyCode == 49) { 134 | // space was pressed 135 | NSString * unicodeText = [UnicodeTransformator transformToUnicode:self.inputTextField.stringValue]; 136 | if (![unicodeText isEqualToString:self.inputTextField.stringValue]) { 137 | self.inputTextField.stringValue = unicodeText; 138 | } 139 | } 140 | } 141 | 142 | 143 | -(NSArray *)control:(NSControl *)control textView:(NSTextView *)textView completions:(NSArray *)words forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(NSInteger *)index 144 | { 145 | NSString * partialWord = [self.inputTextField.stringValue substringWithRange:charRange]; 146 | if (charRange.location == 0) { 147 | return @[]; 148 | } 149 | // Don't harass user if he writes '=' 150 | if ([partialWord isEqualToString:@"="] || 151 | [partialWord isEqualToString:@"_"]) { 152 | return @[]; 153 | } 154 | NSDictionary * keyBindings = [AWHelper keyBindings]; 155 | 156 | 157 | NSMutableArray * mutableArray = [[NSMutableArray alloc] init]; 158 | NSArray * filteredArray = [keyBindings.allKeys filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { 159 | NSString * name = (NSString *)evaluatedObject; 160 | if ([name hasPrefix:@"\\"]) { 161 | name = [name substringFromIndex:1]; 162 | } 163 | return [name hasPrefix:partialWord]; 164 | }]]; 165 | 166 | for (NSString * name in filteredArray) { 167 | if ([name hasPrefix:@"\\"]) { 168 | [mutableArray addObject:[name substringFromIndex:1]]; 169 | } 170 | else { 171 | [mutableArray addObject:name]; 172 | } 173 | } 174 | 175 | [mutableArray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { 176 | NSString * name1 = (NSString *)obj1; 177 | NSString * name2 = (NSString *)obj2; 178 | if ([name1 hasPrefix:@"\\"]) { 179 | name1 = [name1 substringFromIndex:1]; 180 | } 181 | if ([name2 hasPrefix:@"\\"]) { 182 | name2 = [name2 substringFromIndex:1]; 183 | } 184 | return [name1 compare:name2]; 185 | }]; 186 | 187 | if (filteredArray.count == 1 && [filteredArray[0] isEqualToString:partialWord]) { 188 | return @[]; 189 | } 190 | return mutableArray; 191 | } 192 | 193 | 194 | -(void)windowDidResignKey:(NSNotification *)notification 195 | { 196 | if ([notification.object isKindOfClass:[MAAttachedWindow class]]) { 197 | [self.delegate closeWindow]; 198 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 199 | } 200 | } 201 | 202 | 203 | -(void)controlTextDidEndEditing:(NSNotification *)obj 204 | { 205 | [self.delegate inputDidEndEditing:self.inputTextField.stringValue withType:_type normalisationLevel:self.normalisationLevel]; 206 | 207 | } 208 | 209 | 210 | @end 211 | -------------------------------------------------------------------------------- /Agda Writer/AWInputViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /Agda Writer/AWInputWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWInputWindow.h 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 21. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AWInputWindow : NSWindow 12 | -(id)init; 13 | -(void)show; 14 | @end 15 | -------------------------------------------------------------------------------- /Agda Writer/AWInputWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWInputWindow.m 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 21. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWInputWindow.h" 10 | 11 | @implementation AWInputWindow 12 | -(id)init { 13 | NSRect frame = NSMakeRect(0, 0, 400, 200); 14 | // Prepare borderless window 15 | self = [super initWithContentRect:frame styleMask:NSBorderlessWindowMask backing:NSBackingStoreRetained defer:NO]; 16 | if (self) { 17 | 18 | [self setOpaque:NO]; 19 | [self setMovableByWindowBackground:YES]; 20 | [self setBackgroundColor:[NSColor clearColor]]; 21 | [self setAlphaValue:1.0]; 22 | // Ensure that Toast always stays in front of every window 23 | // [self setLevel:kCGOverlayWindowLevelKey]; 24 | 25 | // Prepare content view 26 | NSView * contentView = [[NSView alloc] initWithFrame:frame]; 27 | [contentView setWantsLayer:YES]; 28 | [contentView.layer setCornerRadius:20]; 29 | NSColor * backgroundColor = [NSColor colorWithWhite:0.3 alpha:0.7]; 30 | [contentView.layer setBackgroundColor:backgroundColor.CGColor]; 31 | 32 | NSTextField * textField = [[NSTextField alloc] initWithFrame:NSMakeRect(frame.origin.x, frame.origin.y + 20, frame.size.width, 100)]; 33 | [textField setBezeled:YES]; 34 | [textField setDrawsBackground:NO]; 35 | [textField setEditable:YES]; 36 | [textField setSelectable:YES]; 37 | [textField setPlaceholderString:@"Normalize..."]; 38 | [contentView addSubview:textField]; 39 | 40 | 41 | [self setContentView:contentView]; 42 | [self center]; 43 | } 44 | 45 | return self; 46 | } 47 | 48 | -(void)show { 49 | [self makeKeyAndOrderFront:NSApp]; 50 | // [self ] 51 | } 52 | 53 | -(void)close { 54 | 55 | } 56 | @end 57 | -------------------------------------------------------------------------------- /Agda Writer/AWMainSplitView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWMainSplitView.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 6. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol NSSplitViewAnimatableDelegate 12 | /** Inform delegate about the status of the animation (if set). 13 | @param splitView target splitview 14 | @param animating YES if animating is started, NO if animation is ended 15 | */ 16 | - (void) splitView:(NSSplitView *)splitView splitViewIsAnimating:(BOOL)animating; 17 | @end 18 | 19 | /** This is an extension of NSSplitView category. It allows to animate divider position (one at time or more than one at time). It also provide a simple method to get an n-th divider position. */ 20 | 21 | @interface AWMainSplitView : NSSplitView { 22 | BOOL collapsed; 23 | CGFloat defaultWidth; 24 | } 25 | 26 | 27 | - (IBAction)collapse:(id)sender; 28 | 29 | /** Set the new position of a divider at index. 30 | @param position the new divider position 31 | @param dividerIndex target divider index in this splitview 32 | @param animated use animated transitions? 33 | @return YES if you can animate your transitions 34 | */ 35 | - (BOOL) setPosition:(CGFloat)position ofDividerAtIndex:(NSInteger)dividerIndex animated:(BOOL) animated; 36 | 37 | /** Set more than one divider position at the same time using animated transitions 38 | @param newPositions an array of the new divider positions (pass it as NSNumber) 39 | @param dividerIndexes divider indexes array (set of NSNumber) 40 | @return YES if you can animate your transitions 41 | */ 42 | - (BOOL) setPositions:(NSArray *)newPositions ofDividersAtIndexes:(NSArray *)dividerIndexes; 43 | 44 | /** Set the new position of a divider at index. 45 | @param position the new divider position 46 | @param dividerIndex target divider index in this splitview 47 | @return target divider position 48 | */ 49 | - (CGFloat) positionOfDividerAtIndex:(NSInteger)dividerIndex; 50 | 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Agda Writer/AWMainSplitView.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWMainSplitView.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 6. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWMainSplitView.h" 10 | #import 11 | 12 | @implementation AWMainSplitView 13 | 14 | -(void)awakeFromNib 15 | { 16 | collapsed = NO; 17 | defaultWidth = [self positionOfDividerAtIndex:0]; 18 | 19 | } 20 | 21 | - (IBAction)collapse:(id)sender 22 | { 23 | // if (collapsed) { 24 | // [self setPosition:defaultWidth ofDividerAtIndex:0 animated:YES]; 25 | // collapsed = NO; 26 | // } 27 | // else 28 | // { 29 | // defaultWidth = [self positionOfDividerAtIndex:0]; 30 | // [self setPosition:[self maxPossiblePositionOfDividerAtIndex:0] ofDividerAtIndex:0 animated:YES]; 31 | // collapsed = YES; 32 | // } 33 | } 34 | 35 | 36 | - (CGFloat)positionOfDividerAtIndex:(NSInteger)dividerIndex { 37 | // It looks like NSSplitView relies on its subviews being ordered left->right or top->bottom so we can too. 38 | // It also raises w/ array bounds exception if you use its API with dividerIndex > count of subviews. 39 | while (dividerIndex >= 0 && [self isSubviewCollapsed:[[self subviews] objectAtIndex:dividerIndex]]) 40 | dividerIndex--; 41 | if (dividerIndex < 0) 42 | return 0.0f; 43 | 44 | NSRect priorViewFrame = [[[self subviews] objectAtIndex:dividerIndex] frame]; 45 | return [self isVertical] ? NSMaxX(priorViewFrame) : NSMaxY(priorViewFrame); 46 | } 47 | 48 | 49 | //- (void)animateDividerToPosition:(CGFloat)dividerPosition 50 | //{ 51 | // NSView *view0 = [[self subviews] objectAtIndex:0]; 52 | // NSView *view1 = [[self subviews] objectAtIndex:1]; 53 | // NSRect view0Rect = [view0 frame]; 54 | // NSRect view1Rect = [view1 frame]; 55 | // NSRect overalRect = [self frame]; 56 | // CGFloat dividerThickness = [self dividerThickness]; 57 | // 58 | // if ([self isVertical]) { 59 | // view0Rect.size.width = dividerPosition; 60 | // view1Rect.origin.x = dividerPosition + dividerThickness; 61 | // view1Rect.size.width = overalRect.size.width - view0Rect.size.width - dividerThickness; 62 | // } else { 63 | // view0Rect.size.height = dividerPosition; 64 | // view1Rect.origin.y = dividerPosition + dividerThickness; 65 | // view1Rect.size.height = overalRect.size.height - view0Rect.size.height - dividerThickness; 66 | // } 67 | // 68 | // [NSAnimationContext beginGrouping]; 69 | // [[NSAnimationContext currentContext] setDuration:2.3]; 70 | // [[view0 animator] setFrame: view0Rect]; 71 | // [[view1 animator] setFrame: view1Rect]; 72 | // [NSAnimationContext endGrouping]; 73 | //} 74 | 75 | - (BOOL) setPositions:(NSArray *)newPositions ofDividersAtIndexes:(NSArray *)indexes { 76 | NSUInteger numberOfSubviews = self.subviews.count; 77 | 78 | // indexes and newPositions arrays must have the same object count 79 | if (indexes.count == newPositions.count == NO) return NO; 80 | // trying to move too many dividers 81 | if (indexes.count < numberOfSubviews == NO) return NO; 82 | 83 | NSRect newRect[numberOfSubviews]; 84 | 85 | for (NSUInteger i = 0; i < numberOfSubviews; i++) 86 | newRect[i] = [[self.subviews objectAtIndex:i] frame]; 87 | 88 | for (NSNumber *indexObject in indexes) { 89 | NSInteger index = [indexObject integerValue]; 90 | CGFloat newPosition = [[newPositions objectAtIndex:[indexes indexOfObject:indexObject]] doubleValue]; 91 | if (self.isVertical) { 92 | CGFloat oldMaxXOfRightHandView = NSMaxX(newRect[index + 1]); 93 | newRect[index].size.width = newPosition - NSMinX(newRect[index]); 94 | CGFloat dividerAdjustment = (newPosition < NSWidth(self.bounds)) ? self.dividerThickness : 0.0; 95 | newRect[index + 1].origin.x = newPosition + dividerAdjustment; 96 | newRect[index + 1].size.width = oldMaxXOfRightHandView - newPosition - dividerAdjustment; 97 | } else { 98 | CGFloat oldMaxYOfBottomView = NSMaxY(newRect[index + 1]); 99 | newRect[index].size.height = newPosition - NSMinY(newRect[index]); 100 | CGFloat dividerAdjustment = (newPosition < NSHeight(self.bounds)) ? self.dividerThickness : 0.0; 101 | newRect[index + 1].origin.y = newPosition + dividerAdjustment; 102 | newRect[index + 1].size.height = oldMaxYOfBottomView - newPosition - dividerAdjustment; 103 | } 104 | } 105 | 106 | if ([self.delegate respondsToSelector:@selector(splitView:splitViewIsAnimating:)]) 107 | [((id )self.delegate) splitView:self splitViewIsAnimating:YES]; 108 | 109 | [CATransaction begin]; { 110 | [CATransaction setAnimationDuration:0.40]; // was 0.25 111 | [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; 112 | [CATransaction setCompletionBlock:^{ 113 | 114 | if ([self.delegate respondsToSelector:@selector(splitView:splitViewIsAnimating:)]) 115 | [((id )self.delegate) splitView:self splitViewIsAnimating:NO]; 116 | 117 | }]; 118 | 119 | for (NSUInteger i = 0; i < numberOfSubviews; i++) { 120 | [[[self.subviews objectAtIndex:i] animator] setFrame:newRect[i]]; 121 | } 122 | } [CATransaction commit]; 123 | return YES; 124 | } 125 | 126 | - (BOOL) setPosition:(CGFloat)position ofDividerAtIndex:(NSInteger)dividerIndex animated:(BOOL) animated { 127 | if (!animated) [self setPosition:position ofDividerAtIndex:dividerIndex]; 128 | else { 129 | NSUInteger numberOfSubviews = self.subviews.count; 130 | if (dividerIndex >= numberOfSubviews) return NO; 131 | [self setPositions:@[@(position)] ofDividersAtIndexes:@[@(dividerIndex)]]; 132 | } 133 | return YES; 134 | } 135 | 136 | 137 | // [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) { 138 | // context.duration = 5.0f; 139 | // CGFloat maxPosition = [self maxPossiblePositionOfDividerAtIndex:0]; 140 | // [[self animator] setPosition:maxPosition ofDividerAtIndex:0]; 141 | // } completionHandler:^{ 142 | // [[self animator] setPosition:[self minPossiblePositionOfDividerAtIndex:0] + 100 ofDividerAtIndex:0]; 143 | // }]; 144 | 145 | 146 | @end 147 | -------------------------------------------------------------------------------- /Agda Writer/AWMainTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWMainTextView.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 29. 01. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //goalIndex: index of the goal 12 | //startCharIndex: character index of the starting position 13 | //startRow: row of the starting position 14 | //startColumn: column of the starting position 15 | //endCharIndex: character index of the ending position 16 | //endRow: row of the ending position 17 | //endColumn: column of the ending position 18 | //content: contents you wanna give 19 | 20 | 21 | @interface AgdaGoal : NSObject 22 | 23 | @property NSInteger agdaGoalIndex; 24 | @property NSInteger goalIndex; 25 | @property NSInteger startCharIndex; 26 | @property NSInteger startRow; 27 | @property NSInteger startColumn; 28 | @property NSInteger endCharIndex; 29 | @property NSInteger endRow; 30 | @property NSInteger endColumn; 31 | @property NSInteger numberOfEmptySpaces; 32 | @property NSRange rangeOfCurrentLine; 33 | @property NSRange rangeOfContent; 34 | @property NSString * content; 35 | 36 | @end 37 | 38 | @protocol MainTextViewDelegate 39 | 40 | @required 41 | - (void)highlightSelectedGoalAtRow:(NSInteger)row; 42 | - (void)reloadFile; 43 | 44 | @end 45 | 46 | @interface AWMainTextView : NSTextView { 47 | BOOL initialize; 48 | NSDictionary * defaultAttributes; 49 | NSDictionary * goalsAttributes; 50 | NSMutableAttributedString * mutableAttributedString; 51 | NSArray * goalsIndexesArray; 52 | 53 | NSMutableSet * mutableSetOfActionNames; 54 | 55 | } 56 | 57 | 58 | @property (nonatomic) AgdaGoal * selectedGoal; 59 | @property (nonatomic) AgdaGoal * lastSelectedGoal; 60 | 61 | @property (nonatomic) id mainTextViewDelegate; 62 | @property (nonatomic) id parentViewController; 63 | 64 | -(void) applyUnicodeTransformation; 65 | - (void) clearHighligting; 66 | 67 | 68 | 69 | 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /Agda Writer/AWNotifications.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWNotifications.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 24. 01. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | extern NSString * const fontSizeChanged; 13 | extern NSString * const fontFamilyChanged; 14 | extern NSString * const FONT_SIZE_KEY; 15 | extern NSString * const FONT_FAMILY_KEY; 16 | extern NSString * const KEY_ON_TABLE_PRESSED; 17 | extern NSString * const REMOVE_CONTROLLER; 18 | extern NSString * const AWAgdaReplied; 19 | extern NSString * const AWExecuteActions; 20 | extern NSString * const AWAgdaBufferDataAvaliable; 21 | extern NSString * const AWAgdaVersionAvaliable; 22 | extern NSString * const AWOpenPreferences; 23 | extern NSString * const AWAllGoals; 24 | extern NSString * const AWPossibleAgdaPathFound; 25 | extern NSString * const AWPlaceInsertionPointAtCharIndex; 26 | extern NSString * const AWAgdaGaveAction; 27 | extern NSString * const AWAgdaMakeCaseAction; 28 | extern NSString * const AWAgdaHighlightCode; 29 | extern NSString * const AWAgdaClearHighlighting; 30 | extern NSString * const AWAgdaGoto; 31 | extern NSString * const AWSelectAgdaRange; 32 | 33 | typedef NS_ENUM(NSInteger, KeyPressed) { 34 | AWEnterPressed, 35 | AWEscapePressed 36 | }; 37 | 38 | @interface AWNotifications : NSObject 39 | 40 | + (void) notifyFontSizeChanged: (NSNumber *) fontSize; 41 | + (void) notifyFontFamilyChanged: (NSString *) fontFamily; 42 | + (void) notifyKeyReturnPressed: (NSInteger) key; 43 | + (void) notifyRemoveViewController: (NSViewController *) viewController; 44 | + (void) notifyTextChangedInRange: (NSRange) affectedRange replacementString: (NSString *) replacementString; 45 | + (void) notifyAgdaReplied:(NSString *)reply sender:(id)sender; 46 | + (void) notifyExecuteActions:(NSArray *)actions sender:(NSViewController *)sender; 47 | + (void) notifyAgdaBufferDataAvaliable:(NSAttributedString *)buffer sender:(id)sender; 48 | + (void) notifyAgdaVersion:(NSString *)version; 49 | + (void) notifyAllGoals: (NSString *)allGoals sender:(id)sender; 50 | + (void) notifyPossibleAgdaPathFound: (NSString *)agdaPaths; 51 | + (void) notifyAgdaGaveAction:(NSInteger)goalIndex content:(NSString *)content sender:(id)sender; 52 | + (void) notifyMakeCaseAction:(NSString *)makeCaseActions sender:(id)sender; 53 | + (void) notifyHighlightCode:(NSArray *)array sender:(id)sender; 54 | + (void) notifyClearHighlightingWithSender:(id)sender; 55 | + (void) notifyAgdaGotoIndex:(NSInteger)index sender:(id)sender; 56 | 57 | + (void) notifyPlaceInsertionPointAtCharIndex:(NSUInteger) charIndex; 58 | 59 | + (void) notifyOpenPreferences; 60 | 61 | + (void) notifySelectAgdaRange:(NSString *)agdaRange sender:(id)sender; 62 | 63 | + (NSDictionary *) dictionaryOfDefaults; 64 | + (NSString *) agdaLaunchPath; 65 | + (void) setAgdaLaunchPath:(NSString *)path; 66 | 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /Agda Writer/AWNotifications.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWNotifications.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 24. 01. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWNotifications.h" 10 | 11 | NSString * const fontSizeChanged = @"net.koleznik.fontSizeChanged"; 12 | NSString * const fontFamilyChanged = @"net.koleznik.fontFamilyChanged"; 13 | NSString * const FONT_SIZE_KEY = @"fontSize"; 14 | NSString * const FONT_FAMILY_KEY = @"fontFamily"; 15 | NSString * const KEY_ON_TABLE_PRESSED = @"net.koleznik.keyReturnPressed"; 16 | NSString * const REMOVE_CONTROLLER = @"net.koleznik.removeController"; 17 | NSString * const AWAgdaReplied = @"net.koleznik.agdaReplied"; 18 | NSString * const AWExecuteActions = @"net.koleznik.executeActions"; 19 | NSString * const AWAgdaBufferDataAvaliable = @"net.koleznik.agdaBufferDataAvaliable"; 20 | NSString * const AWAgdaVersionAvaliable = @"net.koleznik.agdaVersionAvaliable"; 21 | NSString * const AWOpenPreferences = @"net.koleznik.openPreferences"; 22 | NSString * const AWAllGoals = @"net.koleznik.allGoals"; 23 | NSString * const AWPossibleAgdaPathFound = @"net.koleznik.possibleAgdaPathFound"; 24 | NSString * const AWPlaceInsertionPointAtCharIndex = @"net.koleznik.placeInsertionPointAtCharIndex"; 25 | NSString * const AWAgdaGaveAction = @"net.koleznik.AgdaGaveAction"; 26 | NSString * const AWAgdaMakeCaseAction = @"net.koleznik.AgdaMakeCaseAction"; 27 | NSString * const AWAgdaHighlightCode = @"net.koleznik.AgdaHighlightCode"; 28 | NSString * const AWAgdaClearHighlighting = @"net.koleznik.AgdaClearHighlighting"; 29 | NSString * const AWAgdaGoto = @"net.koleznik.AgdaGoto"; 30 | NSString * const AWSelectAgdaRange = @"net.koleznik.SelectAgdaRange"; 31 | 32 | 33 | 34 | @implementation AWNotifications 35 | 36 | + (void) notifyClearHighlightingWithSender:(id)sender 37 | { 38 | [[NSNotificationCenter defaultCenter] postNotificationName:AWAgdaClearHighlighting object:sender]; 39 | } 40 | + (void) notifyHighlightCode:(NSArray *)array sender:(id)sender 41 | { 42 | [[NSNotificationCenter defaultCenter] postNotificationName:AWAgdaHighlightCode object:sender userInfo:@{@"actions" : array}]; 43 | } 44 | 45 | + (void) notifyFontSizeChanged: (NSNumber *) fontSize 46 | { 47 | [[NSNotificationCenter defaultCenter] postNotificationName:fontSizeChanged object:fontSize]; 48 | } 49 | 50 | + (void) notifyFontFamilyChanged: (NSString *) fontFamily 51 | { 52 | [[NSNotificationCenter defaultCenter] postNotificationName:fontFamilyChanged object:fontFamily]; 53 | } 54 | 55 | + (void) notifyKeyReturnPressed: (NSInteger) key; 56 | { 57 | [[NSNotificationCenter defaultCenter] postNotificationName:KEY_ON_TABLE_PRESSED object:[NSNumber numberWithInteger:key]]; 58 | } 59 | 60 | + (void) notifyRemoveViewController:(NSViewController *)viewController 61 | { 62 | [[NSNotificationCenter defaultCenter] postNotificationName:REMOVE_CONTROLLER object:viewController]; 63 | } 64 | 65 | + (void) notifyTextChangedInRange: (NSRange) affectedRange replacementString: (NSString *) replacementString 66 | { 67 | [[NSNotificationCenter defaultCenter] postNotificationName:@"textChangedInRangeWithReplacementString" object:@{@"range":[NSValue valueWithRange:affectedRange], @"replacementString":replacementString}]; 68 | } 69 | 70 | + (void) notifyAgdaReplied:(NSString *)reply sender:(id)sender 71 | { 72 | [[NSNotificationCenter defaultCenter] postNotificationName:AWAgdaReplied object:reply]; 73 | } 74 | 75 | + (void) notifyAgdaGaveAction:(NSInteger)goalIndex content:(NSString *)content sender:(id)sender 76 | { 77 | NSDictionary * action = @{@"goalIndex" : @(goalIndex), @"content": content}; 78 | [[NSNotificationCenter defaultCenter] postNotificationName:AWAgdaGaveAction object:sender userInfo:@{@"action" : action}]; 79 | } 80 | 81 | + (NSURL *) defaultUrl 82 | { 83 | return [[NSBundle mainBundle] URLForResource:@"defaults" withExtension:@"plist"]; 84 | } 85 | 86 | + (NSDictionary *) dictionaryOfDefaults 87 | { 88 | NSDictionary *plistContent = [NSDictionary dictionaryWithContentsOfURL: [self defaultUrl]]; 89 | 90 | return plistContent; 91 | } 92 | 93 | + (void) setAgdaLaunchPath:(NSString *)path 94 | { 95 | NSDictionary *plistContent = [self dictionaryOfDefaults]; 96 | [plistContent setValue:path forKey:@"agdaLaunchPath"]; 97 | [plistContent writeToURL:[self defaultUrl] atomically:YES]; 98 | } 99 | 100 | + (NSString *) agdaLaunchPath 101 | { 102 | NSDictionary *plistContent = [self dictionaryOfDefaults]; 103 | return [plistContent objectForKey:@"agdaLaunchPath"]; 104 | 105 | } 106 | 107 | + (void) notifyExecuteActions:(NSArray *)actions sender:(NSViewController *)sender; 108 | { 109 | [[NSNotificationCenter defaultCenter] postNotificationName:AWExecuteActions object:sender userInfo:@{@"actions" : actions}]; 110 | } 111 | 112 | + (void) notifyAgdaBufferDataAvaliable:(NSAttributedString *)buffer sender:(id)sender 113 | { 114 | [[NSNotificationCenter defaultCenter] postNotificationName:AWAgdaBufferDataAvaliable object:sender userInfo:@{@"buffer" : buffer}]; 115 | } 116 | 117 | + (void)notifyAgdaVersion:(NSString *)version 118 | { 119 | [[NSNotificationCenter defaultCenter] postNotificationName:AWAgdaVersionAvaliable object:version]; 120 | } 121 | 122 | + (void) notifyOpenPreferences { 123 | [[NSNotificationCenter defaultCenter] postNotificationName:AWOpenPreferences object:nil]; 124 | } 125 | 126 | + (void) notifyAllGoals: (NSString *)allGoals sender:(id)sender{ 127 | [[NSNotificationCenter defaultCenter] postNotificationName:AWAllGoals object:sender userInfo:@{@"goals" : allGoals}]; 128 | } 129 | 130 | + (void) notifyPossibleAgdaPathFound:(NSString *)agdaPaths 131 | { 132 | [[NSNotificationCenter defaultCenter] postNotificationName:AWPossibleAgdaPathFound object:agdaPaths]; 133 | } 134 | 135 | + (void) notifyPlaceInsertionPointAtCharIndex:(NSUInteger) charIndex 136 | { 137 | [[NSNotificationCenter defaultCenter] postNotificationName:AWPlaceInsertionPointAtCharIndex object:[NSNumber numberWithUnsignedInteger:charIndex]]; 138 | } 139 | 140 | +(void) notifyMakeCaseAction:(NSString *)makeCaseActions sender:(id)sender; 141 | { 142 | [[NSNotificationCenter defaultCenter] postNotificationName:AWAgdaMakeCaseAction object:sender userInfo:@{@"action" : makeCaseActions}]; 143 | } 144 | +(void)notifyAgdaGotoIndex:(NSInteger)index sender:(id)sender { 145 | [[NSNotificationCenter defaultCenter] postNotificationName:AWAgdaGoto object:sender userInfo:@{@"index" : [NSNumber numberWithInteger:index]}]; 146 | } 147 | 148 | + (void)notifySelectAgdaRange:(NSString *)agdaRange sender:(id)sender 149 | { 150 | [[NSNotificationCenter defaultCenter] postNotificationName:AWSelectAgdaRange object:sender userInfo:@{@"agdaRange" : agdaRange}]; 151 | } 152 | 153 | 154 | @end 155 | -------------------------------------------------------------------------------- /Agda Writer/AWPopoverViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWPopoverViewController.h 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 10. 08. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AWPopoverViewController : NSViewController 12 | 13 | @property (strong) IBOutlet NSTextField *contentTextField; 14 | 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Agda Writer/AWPopoverViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWPopoverViewController.m 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 10. 08. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWPopoverViewController.h" 10 | 11 | @interface AWPopoverViewController () 12 | 13 | @end 14 | 15 | @implementation AWPopoverViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do view setup here. 20 | 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Agda Writer/AWPopoverViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Agda Writer/AWStatusTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWStatusTextView.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 3. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AWStatusTextView : NSTextView 12 | 13 | - (IBAction)clearContet:(id)sender; 14 | 15 | @property (nonatomic) id parentViewController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Agda Writer/AWStatusTextView.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWStatusTextView.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 3. 02. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWStatusTextView.h" 10 | #import "AWNotifications.h" 11 | #import "AWAgdaParser.h" 12 | #import "AWHelper.h" 13 | 14 | @implementation AWStatusTextView 15 | 16 | 17 | -(void)awakeFromNib 18 | { 19 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(agdaBuffer:) name:AWAgdaBufferDataAvaliable object:nil]; 20 | 21 | [self setFont:[NSFont systemFontOfSize:25.0]]; 22 | [self.textStorage setFont:[AWHelper defaultFontInAgda]]; 23 | 24 | } 25 | 26 | 27 | -(void)agdaBuffer:(NSNotification *)notification 28 | { 29 | if (self.font.pointSize != 13.0) { 30 | [self setFont:[NSFont systemFontOfSize:13]]; 31 | } 32 | 33 | if (notification.object == self.parentViewController) { 34 | // NSString *reply = notification.userInfo[@"buffer"]; 35 | // reply = [reply substringWithRange:NSMakeRange(1, reply.length - 2)]; 36 | // reply = [reply stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"]; 37 | // if (![reply hasSuffix:@"\n"]) { 38 | // reply = [reply stringByAppendingString:@"\n"]; 39 | // } 40 | NSAttributedString *reply = notification.userInfo[@"buffer"]; 41 | NSMutableAttributedString * mutableReply = [[NSMutableAttributedString alloc] initWithAttributedString:reply]; 42 | 43 | // reply = [mutableReply attributedSubstringFromRange:NSMakeRange(1, mutableReply.length - 2)]; 44 | [mutableReply.mutableString replaceOccurrencesOfString:@"\"" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, mutableReply.length)]; 45 | [mutableReply.mutableString replaceOccurrencesOfString:@"\\n" withString:@"\n" options:NSCaseInsensitiveSearch range:NSMakeRange(0, mutableReply.length)]; 46 | 47 | if ([mutableReply.mutableString hasSuffix:@"\n\n"]) { 48 | } 49 | else if ([mutableReply.mutableString hasSuffix:@"\n"]) { 50 | [mutableReply appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n"]]; 51 | } 52 | else { 53 | [mutableReply appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n\n"]]; 54 | } 55 | 56 | // parse ranges and return string with attachments 57 | 58 | NSMutableAttributedString * attrReply = [AWAgdaParser parseRangesAndAddAttachments:mutableReply parentViewController:self.parentViewController]; 59 | [attrReply addAttributes:@{NSFontAttributeName : [AWHelper defaultFontInAgda]} range:NSMakeRange(0, attrReply.length)]; 60 | 61 | 62 | [self.textStorage beginEditing]; 63 | [self.textStorage appendAttributedString:attrReply]; 64 | [self.textStorage endEditing]; 65 | [self scrollToEndOfDocument:nil]; 66 | } 67 | } 68 | 69 | - (IBAction)clearContet:(id)sender 70 | { 71 | [self setString:@""]; 72 | } 73 | 74 | -(void)dealloc 75 | { 76 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /Agda Writer/AWToastWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // AWToastWindow.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 23. 05. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum : NSUInteger { 12 | ToastTypeLoadSuccessful, 13 | ToastTypeLoadFailed, 14 | ToastTypeSuccess, 15 | ToastTypeFailed 16 | } ToastType; 17 | 18 | 19 | @interface AWToastWindow : NSWindow 20 | 21 | - (id)initWithToastType:(ToastType)toastType; 22 | - (void)show; 23 | @end 24 | -------------------------------------------------------------------------------- /Agda Writer/AWToastWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // AWToastWindow.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 23. 05. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AWToastWindow.h" 10 | #import "AWHelper.h" 11 | 12 | #define VISIBLE_TIME 0.8 // in seconds 13 | #define FADING_TIME 0.4 // -- || -- 14 | #define WINDOW_SIZE 150 15 | 16 | @implementation AWToastWindow 17 | - (id) initWithToastType:(ToastType)toastType 18 | { 19 | NSRect frame = NSMakeRect(0, 0, WINDOW_SIZE, WINDOW_SIZE); 20 | // Prepare borderless window 21 | self = [super initWithContentRect:frame styleMask:NSBorderlessWindowMask backing:NSBackingStoreRetained defer:NO]; 22 | if (self) { 23 | [self setOpaque:NO]; 24 | [self setMovableByWindowBackground:YES]; 25 | [self setBackgroundColor:[NSColor clearColor]]; 26 | [self setAlphaValue:0.0]; 27 | // Ensure that Toast always stays in front of every window 28 | [self setLevel:kCGOverlayWindowLevelKey]; 29 | 30 | // Prepare content view 31 | NSView * contentView = [[NSView alloc] initWithFrame:frame]; 32 | [contentView setWantsLayer:YES]; 33 | [contentView.layer setCornerRadius:20]; 34 | NSColor * backgroundColor = [NSColor colorWithWhite:0.3 alpha:0.7]; 35 | [contentView.layer setBackgroundColor:backgroundColor.CGColor]; 36 | 37 | NSImageView * imageView = [[NSImageView alloc] initWithFrame:frame]; 38 | 39 | // Prepare image 40 | NSString * imageName; 41 | switch (toastType) { 42 | case ToastTypeLoadSuccessful: 43 | imageName = @"load_successful"; 44 | break; 45 | case ToastTypeLoadFailed: 46 | imageName = @"load_failed"; 47 | break; 48 | case ToastTypeFailed: 49 | imageName = @"failed_default"; 50 | break; 51 | case ToastTypeSuccess: 52 | imageName = @"successful_default"; 53 | default: 54 | break; 55 | } 56 | 57 | [imageView setImage:[NSImage imageNamed:imageName]]; 58 | 59 | [contentView addSubview:imageView]; 60 | [self setContentView:contentView]; 61 | [self center]; 62 | } 63 | 64 | return self; 65 | 66 | } 67 | 68 | - (void)show 69 | { 70 | if ([AWHelper isShowingNotifications]) { 71 | [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) { 72 | [self makeKeyAndOrderFront:NSApp]; 73 | [context setDuration:0.1]; 74 | [self.animator setAlphaValue:1.0]; 75 | } completionHandler:^{ 76 | [self performSelector:@selector(closeToast) withObject:nil afterDelay:VISIBLE_TIME]; 77 | }]; 78 | } 79 | 80 | } 81 | 82 | - (void) closeToast 83 | { 84 | [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) { 85 | [context setDuration:FADING_TIME]; 86 | [self.animator setAlphaValue:0.0]; 87 | } completionHandler:^{ 88 | 89 | }]; 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /Agda Writer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 15. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AWCommunitacion.h" 11 | 12 | @interface AppDelegate : NSObject 13 | 14 | @property (strong) AWCommunitacion * communicator; 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /Agda Writer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 15. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "AWHelper.h" 11 | #import "AWNotifications.h" 12 | 13 | 14 | @interface AppDelegate () 15 | 16 | @end 17 | 18 | @implementation AppDelegate 19 | 20 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 21 | // Insert code here to initialize your application 22 | 23 | // check for agda! 24 | if ([[AWNotifications agdaLaunchPath] isEqualToString:@""]) { 25 | // agda path is not yet set 26 | 27 | BOOL isPathToAgdaSet = NO; 28 | 29 | NSArray * reasonablePlacesForAgda = 30 | @[ 31 | @"~/.cabal/bin/agda", 32 | @"~/Library/Haskell/bin/agda", 33 | @"/Library/Haskell/bin/agda" 34 | ]; 35 | for (NSString * path in reasonablePlacesForAgda) { 36 | 37 | if ([self isAgdaAvaliableAtPath:path]) { 38 | [AWNotifications setAgdaLaunchPath:path]; 39 | isPathToAgdaSet = YES; 40 | [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:NO] forKey:@"useBundledAgda"]; 41 | break; 42 | } 43 | } 44 | 45 | 46 | if (!isPathToAgdaSet) { 47 | // If everything fails, load agda from Agda Writer's folder. 48 | // Don't forget to use custom dictionary with appropriate arguments (dictionary). 49 | [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"useBundledAgda"]; 50 | } 51 | } 52 | 53 | 54 | 55 | self.communicator = [[AWCommunitacion alloc] initForCommunicatingWithAgda]; 56 | [self.communicator openConnectionToAgda]; 57 | [AWHelper setUserDefaults]; 58 | } 59 | 60 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 61 | // Insert code here to tear down your application 62 | [self.communicator closeConnectionToAgda]; 63 | } 64 | 65 | #pragma mark - 66 | -(BOOL)isAgdaAvaliableAtPath:(NSString *)path 67 | { 68 | AWCommunitacion * agdaComm = [[AWCommunitacion alloc] init]; 69 | return [agdaComm isAgdaAvaliableAtPath:path]; 70 | 71 | } 72 | 73 | - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication { 74 | return YES; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /Agda Writer/CustomTokenCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // CustomTokenCell.h 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 2. 05. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CustomTokenCell : NSTextAttachmentCell 12 | { 13 | BOOL highlighted; 14 | NSFont * defaultFont; 15 | } 16 | -(id)init; 17 | -(id) initWithParentViewController: (id)parentViewController; 18 | -(void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView; 19 | @property NSRange whereToGoRange; 20 | @property id parentViewController; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Agda Writer/CustomTokenCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // CustomTokenCell.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 2. 05. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "CustomTokenCell.h" 10 | #import "AWNotifications.h" 11 | #import "AWHelper.h" 12 | #import "AWColors.h" 13 | 14 | @implementation CustomTokenCell 15 | 16 | #define FONT_SCALAR 0.8 17 | 18 | -(id)init 19 | { 20 | self = [super init]; 21 | if (self) { 22 | defaultFont = [AWHelper defaultFontInAgda]; 23 | // make font smaller by some arbitrary factor 24 | if (defaultFont) { 25 | defaultFont = [[NSFontManager sharedFontManager] convertFont:defaultFont toSize:defaultFont.pointSize * FONT_SCALAR]; 26 | 27 | } 28 | 29 | } 30 | return self; 31 | } 32 | 33 | - (id) initWithParentViewController:(id)parentViewController 34 | { 35 | self = [self init]; 36 | if (self) { 37 | self.parentViewController = parentViewController; 38 | } 39 | 40 | return self; 41 | } 42 | 43 | 44 | #pragma mark - NSTextAttachmentCell Overrides 45 | 46 | - (NSSize)cellSize 47 | { 48 | // font name and font size: 49 | // defaultFont.fontName 50 | // defaultFont.pointSize 51 | return NSMakeSize([[self stringValue] sizeWithAttributes:@{NSFontAttributeName:defaultFont}].width + 13.f, 52 | [[self stringValue] sizeWithAttributes:@{NSFontAttributeName:defaultFont}].height); 53 | } 54 | 55 | - (NSPoint)cellBaselineOffset 56 | { 57 | return NSMakePoint(-1.f, -1.f); 58 | } 59 | 60 | - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView 61 | { 62 | // [self drawWithFrame:cellFrame inView:controlView characterIndex:NSNotFound layoutManager:nil]; 63 | } 64 | 65 | - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView characterIndex:(NSUInteger)charIndex 66 | { 67 | // [self drawWithFrame:cellFrame inView:controlView characterIndex:charIndex layoutManager:nil]; 68 | } 69 | 70 | - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView characterIndex:(NSUInteger)charIndex layoutManager:(NSLayoutManager *)layoutManager 71 | { 72 | NSColor* bgColor = [AWColors unselectedTokenColor]; 73 | NSColor* borderColor = [AWColors borderTokenColor]; 74 | 75 | NSRect frame = cellFrame; 76 | CGFloat radius = ceilf([self cellSize].height / 2.f); 77 | NSBezierPath* roundedRectanglePath = [NSBezierPath bezierPathWithRoundedRect: NSMakeRect(NSMinX(frame) + 0.5, NSMinY(frame) + 3.5, NSWidth(frame) - 1, NSHeight(frame) - 1) xRadius: radius yRadius: radius]; 78 | // [(highlighted ? [NSColor blueColor] : bgColor) setFill]; 79 | [bgColor setFill]; 80 | [roundedRectanglePath fill]; 81 | [borderColor setStroke]; 82 | [roundedRectanglePath setLineWidth: 1]; 83 | [roundedRectanglePath stroke]; 84 | 85 | 86 | 87 | CGSize size = [[self stringValue] sizeWithAttributes:@{NSFontAttributeName:defaultFont}]; 88 | CGRect textFrame = CGRectMake(cellFrame.origin.x + (cellFrame.size.width - size.width)/2, 89 | cellFrame.origin.y + 2.f, 90 | size.width, 91 | size.height); 92 | 93 | [self setUsesSingleLineMode:YES]; 94 | [[self stringValue] drawInRect:textFrame withAttributes:@{NSFontAttributeName:defaultFont, NSForegroundColorAttributeName:[NSColor whiteColor]}]; 95 | } 96 | 97 | - (void)highlight:(BOOL)flag withFrame:(NSRect)cellFrame inView:(NSView *)controlView 98 | { 99 | highlighted = flag; 100 | [controlView setNeedsDisplayInRect:cellFrame]; 101 | } 102 | 103 | - (BOOL)wantsToTrackMouse 104 | { 105 | return YES; 106 | } 107 | 108 | - (BOOL)wantsToTrackMouseForEvent:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView atCharacterIndex:(NSUInteger)charIndex 109 | { 110 | // Hover 111 | return YES; 112 | } 113 | 114 | - (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)flag 115 | { 116 | return [self trackMouse:theEvent inRect:cellFrame ofView:controlView atCharacterIndex:NSNotFound untilMouseUp:flag]; 117 | } 118 | 119 | - (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView atCharacterIndex:(NSUInteger)charIndex untilMouseUp:(BOOL)flag 120 | { 121 | [self highlight:flag withFrame:cellFrame inView:controlView]; 122 | [AWNotifications notifySelectAgdaRange:self.title sender:self.parentViewController]; 123 | return YES; 124 | } 125 | 126 | @end 127 | -------------------------------------------------------------------------------- /Agda Writer/Document.h: -------------------------------------------------------------------------------- 1 | // 2 | // Document.h 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 15. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Document : NSDocument 12 | 13 | @property (strong) NSTextView * mainTextView; 14 | @property NSString * contentString; 15 | @property NSURL * filePath; 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /Agda Writer/Document.m: -------------------------------------------------------------------------------- 1 | // 2 | // Document.m 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 15. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "Document.h" 10 | 11 | @interface Document () 12 | 13 | @end 14 | 15 | @implementation Document 16 | 17 | - (instancetype)init { 18 | self = [super init]; 19 | if (self) { 20 | // Add your subclass-specific initialization here. 21 | } 22 | return self; 23 | } 24 | 25 | - (void)windowControllerDidLoadNib:(NSWindowController *)aController { 26 | [super windowControllerDidLoadNib:aController]; 27 | // Add any code here that needs to be executed once the windowController has loaded the document's window. 28 | } 29 | 30 | + (BOOL)autosavesInPlace { 31 | return NO; 32 | } 33 | 34 | - (void)makeWindowControllers { 35 | // Override to return the Storyboard file name of the document. 36 | NSWindowController * windowController = [[NSStoryboard storyboardWithName:@"Main" bundle:nil] instantiateControllerWithIdentifier:@"Document Window Controller"]; 37 | 38 | // Set represented object, so we can access this class in window controller. 39 | windowController.contentViewController.representedObject = self; 40 | [self addWindowController:windowController]; 41 | } 42 | 43 | -(void)saveDocument:(id)sender 44 | { 45 | [super saveDocument:sender]; 46 | } 47 | 48 | -(void)saveToURL:(NSURL *)url ofType:(NSString *)typeName forSaveOperation:(NSSaveOperationType)saveOperation delegate:(id)delegate didSaveSelector:(SEL)didSaveSelector contextInfo:(void *)contextInfo 49 | { 50 | // NSLog(@"URL: %@", url); 51 | self.filePath = url; 52 | 53 | [super saveToURL:url ofType:typeName forSaveOperation:saveOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo]; 54 | } 55 | 56 | 57 | -(BOOL)writeToURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError 58 | { 59 | // NSLog(@"%@", [self.mainTextView string]); 60 | // NSLog(@"URL: %@", url); 61 | 62 | NSError * error; 63 | BOOL success = [self.mainTextView.string writeToURL:url atomically:NO encoding:NSUTF8StringEncoding error:&error]; 64 | if (error) { 65 | NSLog(@"Error saving file, reason: %@", error.description); 66 | } 67 | return success; 68 | } 69 | 70 | 71 | -(BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError 72 | { 73 | 74 | NSLog(@"reading from: %@", url); 75 | self.filePath = url; 76 | return [super readFromURL:url ofType:typeName error:outError]; 77 | } 78 | 79 | - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError { 80 | 81 | if (data) { 82 | self.contentString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 83 | 84 | if (self.contentString) { 85 | return YES; 86 | } 87 | } 88 | 89 | return NO; 90 | 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /Agda Writer/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "icon_16x16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "icon_16x16@2x.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "icon_32x32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "icon_32x32@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "icon_128x128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "icon_128x128@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "icon_256x256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "icon_256x256@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "icon_512x512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "icon_512x512@2x.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /Agda Writer/Images.xcassets/AppIcon.appiconset/icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/Images.xcassets/AppIcon.appiconset/icon_128x128.png -------------------------------------------------------------------------------- /Agda Writer/Images.xcassets/AppIcon.appiconset/icon_128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/Images.xcassets/AppIcon.appiconset/icon_128x128@2x.png -------------------------------------------------------------------------------- /Agda Writer/Images.xcassets/AppIcon.appiconset/icon_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/Images.xcassets/AppIcon.appiconset/icon_16x16.png -------------------------------------------------------------------------------- /Agda Writer/Images.xcassets/AppIcon.appiconset/icon_16x16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/Images.xcassets/AppIcon.appiconset/icon_16x16@2x.png -------------------------------------------------------------------------------- /Agda Writer/Images.xcassets/AppIcon.appiconset/icon_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/Images.xcassets/AppIcon.appiconset/icon_256x256.png -------------------------------------------------------------------------------- /Agda Writer/Images.xcassets/AppIcon.appiconset/icon_256x256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/Images.xcassets/AppIcon.appiconset/icon_256x256@2x.png -------------------------------------------------------------------------------- /Agda Writer/Images.xcassets/AppIcon.appiconset/icon_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/Images.xcassets/AppIcon.appiconset/icon_32x32.png -------------------------------------------------------------------------------- /Agda Writer/Images.xcassets/AppIcon.appiconset/icon_32x32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/Images.xcassets/AppIcon.appiconset/icon_32x32@2x.png -------------------------------------------------------------------------------- /Agda Writer/Images.xcassets/AppIcon.appiconset/icon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/Images.xcassets/AppIcon.appiconset/icon_512x512.png -------------------------------------------------------------------------------- /Agda Writer/Images.xcassets/AppIcon.appiconset/icon_512x512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/Images.xcassets/AppIcon.appiconset/icon_512x512@2x.png -------------------------------------------------------------------------------- /Agda Writer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDocumentTypes 8 | 9 | 10 | CFBundleTypeExtensions 11 | 12 | agda 13 | 14 | CFBundleTypeIconFile 15 | icon_128x128 16 | CFBundleTypeMIMETypes 17 | 18 | text/plain 19 | 20 | CFBundleTypeName 21 | Agda Document 22 | CFBundleTypeOSTypes 23 | 24 | ???? 25 | 26 | CFBundleTypeRole 27 | Editor 28 | LSItemContentTypes 29 | 30 | net.koleznik.Agda-Writer 31 | 32 | LSTypeIsPackage 33 | 1 34 | NSDocumentClass 35 | Document 36 | 37 | 38 | CFBundleExecutable 39 | $(EXECUTABLE_NAME) 40 | CFBundleIconFile 41 | icon_128x128 42 | CFBundleIdentifier 43 | $(PRODUCT_BUNDLE_IDENTIFIER) 44 | CFBundleInfoDictionaryVersion 45 | 6.0 46 | CFBundleName 47 | $(PRODUCT_NAME) 48 | CFBundlePackageType 49 | APPL 50 | CFBundleShortVersionString 51 | 1.2.3 52 | CFBundleSignature 53 | ???? 54 | CFBundleVersion 55 | 9 56 | LSApplicationCategoryType 57 | public.app-category.developer-tools 58 | LSMinimumSystemVersion 59 | $(MACOSX_DEPLOYMENT_TARGET) 60 | NSHumanReadableCopyright 61 | Copyright © 2015 koleznik.net. All rights reserved. 62 | NSMainStoryboardFile 63 | Main 64 | NSPrincipalClass 65 | NSApplication 66 | UTExportedTypeDeclarations 67 | 68 | 69 | UTTypeConformsTo 70 | 71 | public.text 72 | 73 | UTTypeDescription 74 | Agda Doument 75 | UTTypeIconFile 76 | icon_128x128 77 | UTTypeIdentifier 78 | net.koleznik.Agda-Writer 79 | UTTypeTagSpecification 80 | 81 | public.filename-extension 82 | 83 | agda 84 | 85 | public.mime-type 86 | 87 | text/plain 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /Agda Writer/Key Bindings.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -> 6 | 7 | \to 8 | 9 | <=> 10 | 11 | => 12 | 13 | <= 14 | 15 | <-> 16 | 17 | <- 18 | 19 | \bn 20 | 21 | \le 22 | 23 | \ge 24 | 25 | \neq 26 | 27 | \approx 28 | 29 | \napprox 30 | 31 | \simeq 32 | 33 | \cong 34 | 35 | \equiv 36 | 37 | \nequiv 38 | 39 | \pm 40 | ± 41 | \mp 42 | 43 | \times 44 | × 45 | \div 46 | ÷ 47 | \cdot 48 | 49 | \circ 50 | 51 | \emptyset 52 | 53 | \in 54 | 55 | \notin 56 | 57 | \ni 58 | 59 | \notni 60 | 61 | \subset 62 | 63 | \subseteq 64 | 65 | \notsubset 66 | 67 | \notsubseteq 68 | 69 | \subsetneq 70 | 71 | \supsetneq 72 | 73 | \supset 74 | 75 | \supseteq 76 | 77 | \cup 78 | 79 | \cap 80 | 81 | \bigcup 82 | 83 | \bigcap 84 | 85 | \aleph 86 | 87 | \beth 88 | 89 | \neg 90 | ¬ 91 | \wedge 92 | 93 | \vee 94 | 95 | \veebar 96 | 97 | \forall 98 | 99 | \exists 100 | 101 | \top 102 | 103 | \bot 104 | 105 | \therefore 106 | 107 | \vdash 108 | 109 | \models 110 | 111 | \Box 112 | 113 | \angle 114 | 115 | \triangle 116 | 117 | \perp 118 | 119 | \parallel 120 | 121 | \sim 122 | 123 | \infty 124 | 125 | \Delta 126 | Δ 127 | \nabla 128 | 129 | \partial 130 | 131 | \sum 132 | 133 | \prod 134 | 135 | \int 136 | 137 | \iint 138 | 139 | \iiint 140 | 141 | \iiiint 142 | 143 | \oint 144 | 145 | \Re 146 | 147 | \Im 148 | 149 | \wp 150 | 151 | \lfloor 152 | 153 | \rfloor 154 | 155 | \lceil 156 | 157 | \rceil 158 | 159 | \| 160 | 161 | \langle 162 | 163 | \rangle 164 | 165 | \' 166 | 167 | \'' 168 | 169 | \''' 170 | 171 | \oplus 172 | 173 | \otimes 174 | 175 | \triangleleft 176 | 177 | \unlhd 178 | 179 | \rtimes 180 | 181 | \bigoplus 182 | 183 | \bigotimes 184 | 185 | \rightarrow 186 | 187 | \leftarrow 188 | 189 | \uparrow 190 | 191 | \downarrow 192 | 193 | \nwarrow 194 | 195 | \searrow 196 | 197 | \mapsto 198 | 199 | \leftrightarrow 200 | 201 | \rightarrowtail 202 | 203 | \twoheadrightarrow 204 | 205 | \hookrightarrow 206 | 207 | \Rightarrow 208 | 209 | \Leftarrow 210 | 211 | \Uparrow 212 | 213 | \Downarrow 214 | 215 | \nearrow 216 | 217 | \swarrow 218 | 219 | \Leftrightarrow 220 | 221 | \cdots 222 | 223 | \ddots 224 | 225 | \ldots 226 | 227 | \vdots 228 | 229 | \alpha 230 | α 231 | \beta 232 | β 233 | \gamma 234 | γ 235 | \delta 236 | δ 237 | \epsilon 238 | ϵ 239 | \zeta 240 | ζ 241 | \eta 242 | η 243 | \theta 244 | θ 245 | \kappa 246 | κ 247 | \lambda 248 | λ 249 | \mu 250 | μ 251 | \nu 252 | ν 253 | \xi 254 | ξ 255 | \omicron 256 | ο 257 | \pi 258 | π 259 | \rho 260 | ρ 261 | \sigma 262 | σ 263 | \tau 264 | τ 265 | \upsilon 266 | υ 267 | \phi 268 | ϕ 269 | \chi 270 | χ 271 | \psi 272 | ψ 273 | \omega 274 | ω 275 | \Alpha 276 | Α 277 | \Beta 278 | Β 279 | \Gama 280 | Γ 281 | \Epsilon 282 | Ε 283 | \Zeta 284 | Ζ 285 | \Eta 286 | Η 287 | \Theta 288 | Θ 289 | \Kappa 290 | Κ 291 | \Lambda 292 | Λ 293 | \Mu 294 | Μ 295 | \Nu 296 | Ν 297 | \Xi 298 | Ξ 299 | \Omicron 300 | Ο 301 | \Pi 302 | Π 303 | \Rho 304 | Ρ 305 | \Sigma 306 | Σ 307 | \Tau 308 | Τ 309 | \Upsilon 310 | Υ 311 | \Phi 312 | Φ 313 | \Chi 314 | Χ 315 | \Psi 316 | Ψ 317 | \Omega 318 | Ω 319 | \varepsilon 320 | ε 321 | \varkappa 322 | ϰ 323 | \varphi 324 | φ 325 | \varpi 326 | ϖ 327 | \varrho 328 | ϱ 329 | \varsigma 330 | ς 331 | \vartheta 332 | ϑ 333 | _0 334 | 335 | _1 336 | 337 | _2 338 | 339 | _3 340 | 341 | _4 342 | 343 | _5 344 | 345 | _6 346 | 347 | _7 348 | 349 | _8 350 | 351 | _9 352 | 353 | ^0 354 | 355 | ^1 356 | ¹ 357 | ^2 358 | ² 359 | ^3 360 | ³ 361 | ^4 362 | 363 | ^5 364 | 365 | ^6 366 | 367 | ^7 368 | 369 | ^8 370 | 371 | ^9 372 | 373 | 374 | 375 | -------------------------------------------------------------------------------- /Agda Writer/MAAttachedWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // MAAttachedWindow.h 3 | // 4 | // Created by Matt Gemmell on 27/09/2007. 5 | // Copyright 2007 Magic Aubergine. 6 | // 7 | 8 | #import 9 | 10 | /* 11 | Below are the positions the attached window can be displayed at. 12 | 13 | Note that these positions are relative to the point passed to the constructor, 14 | e.g. MAPositionBottomRight will put the window below the point and towards the right, 15 | MAPositionTop will horizontally center the window above the point, 16 | MAPositionRightTop will put the window to the right and above the point, 17 | and so on. 18 | 19 | You can also pass MAPositionAutomatic (or use an initializer which omits the 'onSide:' 20 | argument) and the attached window will try to position itself sensibly, based on 21 | available screen-space. 22 | 23 | Notes regarding automatically-positioned attached windows: 24 | 25 | (a) The window prefers to position itself horizontally centered below the specified point. 26 | This gives a certain enhanced visual sense of an attachment/relationship. 27 | 28 | (b) The window will try to align itself with its parent window (if any); i.e. it will 29 | attempt to stay within its parent window's frame if it can. 30 | 31 | (c) The algorithm isn't perfect. :) If in doubt, do your own calculations and then 32 | explicitly request that the window attach itself to a particular side. 33 | */ 34 | 35 | typedef enum _MAWindowPosition { 36 | // The four primary sides are compatible with the preferredEdge of NSDrawer. 37 | MAPositionLeft = NSMinXEdge, // 0 38 | MAPositionRight = NSMaxXEdge, // 2 39 | MAPositionTop = NSMaxYEdge, // 3 40 | MAPositionBottom = NSMinYEdge, // 1 41 | MAPositionLeftTop = 4, 42 | MAPositionLeftBottom = 5, 43 | MAPositionRightTop = 6, 44 | MAPositionRightBottom = 7, 45 | MAPositionTopLeft = 8, 46 | MAPositionTopRight = 9, 47 | MAPositionBottomLeft = 10, 48 | MAPositionBottomRight = 11, 49 | MAPositionAutomatic = 12 50 | } MAWindowPosition; 51 | 52 | @interface MAAttachedWindow : NSWindow { 53 | NSColor *borderColor; 54 | float borderWidth; 55 | float viewMargin; 56 | float arrowBaseWidth; 57 | float arrowHeight; 58 | BOOL hasArrow; 59 | float cornerRadius; 60 | BOOL drawsRoundCornerBesideArrow; 61 | 62 | @private 63 | NSColor *_MABackgroundColor; 64 | __weak NSView *_view; 65 | __weak NSWindow *_window; 66 | NSPoint _point; 67 | MAWindowPosition _side; 68 | float _distance; 69 | NSRect _viewFrame; 70 | BOOL _resizing; 71 | } 72 | 73 | /* 74 | Initialization methods 75 | 76 | Parameters: 77 | 78 | view The view to display in the attached window. Must not be nil. 79 | 80 | point The point to which the attached window should be attached. If you 81 | are also specifying a parent window, the point should be in the 82 | coordinate system of that parent window. If you are not specifying 83 | a window, the point should be in the screen's coordinate space. 84 | This value is required. 85 | 86 | window The parent window to attach this one to. Note that no actual 87 | relationship is created (particularly, this window is not made 88 | a childWindow of the parent window). 89 | Default: nil. 90 | 91 | side The side of the specified point on which to attach this window. 92 | Default: MAPositionAutomatic. 93 | 94 | distance How far from the specified point this window should be. 95 | Default: 0. 96 | */ 97 | 98 | - (MAAttachedWindow *)initWithView:(NSView *)view // designated initializer 99 | attachedToPoint:(NSPoint)point 100 | inWindow:(NSWindow *)window 101 | onSide:(MAWindowPosition)side 102 | atDistance:(float)distance; 103 | 104 | - (MAAttachedWindow *)initWithView:(NSView *)view 105 | attachedToPoint:(NSPoint)point 106 | inWindow:(NSWindow *)window 107 | atDistance:(float)distance; 108 | 109 | - (MAAttachedWindow *)initWithView:(NSView *)view 110 | attachedToPoint:(NSPoint)point 111 | onSide:(MAWindowPosition)side 112 | atDistance:(float)distance; 113 | 114 | - (MAAttachedWindow *)initWithView:(NSView *)view 115 | attachedToPoint:(NSPoint)point 116 | atDistance:(float)distance; 117 | 118 | - (MAAttachedWindow *)initWithView:(NSView *)view 119 | attachedToPoint:(NSPoint)point 120 | inWindow:(NSWindow *)window; 121 | 122 | - (MAAttachedWindow *)initWithView:(NSView *)view 123 | attachedToPoint:(NSPoint)point 124 | onSide:(MAWindowPosition)side; 125 | 126 | - (MAAttachedWindow *)initWithView:(NSView *)view 127 | attachedToPoint:(NSPoint)point; 128 | 129 | // Accessor methods 130 | - (void)setPoint:(NSPoint)point side:(MAWindowPosition)side; 131 | - (NSColor *)borderColor; 132 | - (void)setBorderColor:(NSColor *)value; 133 | - (float)borderWidth; 134 | - (void)setBorderWidth:(float)value; // See note 1 below. 135 | - (float)viewMargin; 136 | - (void)setViewMargin:(float)value; // See note 2 below. 137 | - (float)arrowBaseWidth; 138 | - (void)setArrowBaseWidth:(float)value; // See note 2 below. 139 | - (float)arrowHeight; 140 | - (void)setArrowHeight:(float)value; // See note 2 below. 141 | - (float)hasArrow; 142 | - (void)setHasArrow:(float)value; 143 | - (float)cornerRadius; 144 | - (void)setCornerRadius:(float)value; // See note 2 below. 145 | - (float)drawsRoundCornerBesideArrow; // See note 3 below. 146 | - (void)setDrawsRoundCornerBesideArrow:(float)value; // See note 2 below. 147 | - (void)setBackgroundImage:(NSImage *)value; 148 | - (NSColor *)windowBackgroundColor; // See note 4 below. 149 | - (void)setBackgroundColor:(NSColor *)value; 150 | 151 | /* 152 | Notes regarding accessor methods: 153 | 154 | 1. The border is drawn inside the viewMargin area, expanding inwards; it does not 155 | increase the width/height of the window. You can use the -setBorderWidth: and 156 | -setViewMargin: methods together to achieve the exact look/geometry you want. 157 | (viewMargin is the distance between the edge of the view and the window edge.) 158 | 159 | 2. The specified setter methods are primarily intended to be used _before_ the window 160 | is first shown. If you use them while the window is already visible, be aware 161 | that they may cause the window to move and/or resize, in order to stay anchored 162 | to the point specified in the initializer. They may also cause the view to move 163 | within the window, in order to remain centered there. 164 | 165 | Note that the -setHasArrow: method can safely be used at any time, and will not 166 | cause moving/resizing of the window. This is for convenience, in case you want 167 | to add or remove the arrow in response to user interaction. For example, you 168 | could make the attached window movable by its background, and if the user dragged 169 | it away from its initial point, the arrow could be removed. This would duplicate 170 | how Aperture's attached windows behave. 171 | 172 | 3. drawsRoundCornerBesideArrow takes effect when the arrow is being drawn at a corner, 173 | i.e. when it's not at one of the four primary compass directions. In this situation, 174 | if drawsRoundCornerBesideArrow is YES (the default), then that corner of the window 175 | will be rounded just like the other three corners, thus the arrow will be inset 176 | slightly from the edge of the window to allow room for the rounded corner. If this 177 | value is NO, the corner beside the arrow will be a square corner, and the other 178 | three corners will be rounded. 179 | 180 | This is useful when you want to attach a window very near the edge of another window, 181 | and don't want the attached window's edge to be visually outside the frame of the 182 | parent window. 183 | 184 | 4. Note that to retrieve the background color of the window, you should use the 185 | -windowBackgroundColor method, instead of -backgroundColor. This is because we draw 186 | the entire background of the window (rounded path, arrow, etc) in an NSColor pattern 187 | image, and set it as the backgroundColor of the window. 188 | */ 189 | 190 | @end 191 | -------------------------------------------------------------------------------- /Agda Writer/MarkerLineNumberView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MarkerTextView.h 3 | // Line View Test 4 | // 5 | // Created by Paul Kim on 10/4/08. 6 | // Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person 9 | // obtaining a copy of this software and associated documentation 10 | // files (the "Software"), to deal in the Software without 11 | // restriction, including without limitation the rights to use, 12 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the 14 | // Software is furnished to do so, subject to the following 15 | // conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be 18 | // included in all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | // OTHER DEALINGS IN THE SOFTWARE. 28 | // 29 | 30 | #import 31 | #import "NoodleLineNumberView.h" 32 | 33 | @interface MarkerLineNumberView : NoodleLineNumberView 34 | { 35 | NSImage *markerImage; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Agda Writer/MarkerLineNumberView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MarkerTextView.m 3 | // Line View Test 4 | // 5 | // Created by Paul Kim on 10/4/08. 6 | // Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person 9 | // obtaining a copy of this software and associated documentation 10 | // files (the "Software"), to deal in the Software without 11 | // restriction, including without limitation the rights to use, 12 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the 14 | // Software is furnished to do so, subject to the following 15 | // conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be 18 | // included in all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | // OTHER DEALINGS IN THE SOFTWARE. 28 | // 29 | 30 | #import "MarkerLineNumberView.h" 31 | #import "NoodleLineNumberMarker.h" 32 | 33 | #define CORNER_RADIUS 3.0 34 | #define MARKER_HEIGHT 13.0 35 | 36 | @implementation MarkerLineNumberView 37 | 38 | - (void)dealloc 39 | { 40 | 41 | } 42 | 43 | - (void)setRuleThickness:(CGFloat)thickness 44 | { 45 | [super setRuleThickness:thickness]; 46 | 47 | // Overridden to reset the size of the marker image forcing it to redraw with the new width. 48 | // If doing this in a non-subclass of NoodleLineNumberView, you can set it to post frame 49 | // notifications and listen for them. 50 | [markerImage setSize:NSMakeSize(thickness, MARKER_HEIGHT)]; 51 | } 52 | 53 | - (void)drawMarkerImageIntoRep:(id)rep 54 | { 55 | NSBezierPath *path; 56 | NSRect rect; 57 | 58 | rect = NSMakeRect(1.0, 2.0, [rep size].width - 2.0, [rep size].height - 3.0); 59 | 60 | path = [NSBezierPath bezierPath]; 61 | [path moveToPoint:NSMakePoint(NSMaxX(rect), NSMinY(rect) + NSHeight(rect) / 2)]; 62 | [path lineToPoint:NSMakePoint(NSMaxX(rect) - 5.0, NSMaxY(rect))]; 63 | 64 | [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(rect) + CORNER_RADIUS, NSMaxY(rect) - CORNER_RADIUS) radius:CORNER_RADIUS startAngle:90 endAngle:180]; 65 | 66 | [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(rect) + CORNER_RADIUS, NSMinY(rect) + CORNER_RADIUS) radius:CORNER_RADIUS startAngle:180 endAngle:270]; 67 | [path lineToPoint:NSMakePoint(NSMaxX(rect) - 5.0, NSMinY(rect))]; 68 | [path closePath]; 69 | 70 | [[NSColor colorWithCalibratedRed:0.003 green:0.56 blue:0.85 alpha:1.0] set]; 71 | [path fill]; 72 | 73 | [[NSColor colorWithCalibratedRed:0 green:0.44 blue:0.8 alpha:1.0] set]; 74 | 75 | [path setLineWidth:2.0]; 76 | [path stroke]; 77 | } 78 | 79 | - (NSImage *)markerImageWithSize:(NSSize)size 80 | { 81 | if (markerImage == nil) 82 | { 83 | NSCustomImageRep *rep; 84 | 85 | markerImage = [[NSImage alloc] initWithSize:size]; 86 | rep = [[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawMarkerImageIntoRep:) delegate:self]; 87 | [rep setSize:size]; 88 | [markerImage addRepresentation:rep]; 89 | } 90 | return markerImage; 91 | } 92 | 93 | - (void)mouseDown:(NSEvent *)theEvent 94 | { 95 | NSPoint location; 96 | NSInteger line; 97 | 98 | location = [self convertPoint:[theEvent locationInWindow] fromView:nil]; 99 | line = [self lineNumberForLocation:location.y]; 100 | 101 | if (line != NSNotFound) 102 | { 103 | NoodleLineNumberMarker *marker; 104 | 105 | marker = [self markerAtLine:line]; 106 | 107 | if (marker != nil) 108 | { 109 | [self removeMarker:marker]; 110 | } 111 | else 112 | { 113 | marker = [[NoodleLineNumberMarker alloc] initWithRulerView:self 114 | lineNumber:line 115 | image:[self markerImageWithSize:NSMakeSize([self ruleThickness], MARKER_HEIGHT)] 116 | imageOrigin:NSMakePoint(0, MARKER_HEIGHT / 2)]; 117 | [self addMarker:marker]; 118 | } 119 | [self setNeedsDisplay:YES]; 120 | } 121 | } 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /Agda Writer/NoodleLineNumberMarker.h: -------------------------------------------------------------------------------- 1 | // 2 | // NoodleLineNumberMarker.h 3 | // NoodleKit 4 | // 5 | // Created by Paul Kim on 9/30/08. 6 | // Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person 9 | // obtaining a copy of this software and associated documentation 10 | // files (the "Software"), to deal in the Software without 11 | // restriction, including without limitation the rights to use, 12 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the 14 | // Software is furnished to do so, subject to the following 15 | // conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be 18 | // included in all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | // OTHER DEALINGS IN THE SOFTWARE. 28 | // 29 | 30 | #import 31 | 32 | /* 33 | Marker for NoodleLineNumberView. 34 | 35 | For more details, see the related blog post at: http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/ 36 | */ 37 | 38 | @interface NoodleLineNumberMarker : NSRulerMarker 39 | { 40 | NSUInteger _lineNumber; 41 | } 42 | 43 | - (id)initWithRulerView:(NSRulerView *)aRulerView lineNumber:(CGFloat)line image:(NSImage *)anImage imageOrigin:(NSPoint)imageOrigin; 44 | 45 | - (void)setLineNumber:(NSUInteger)line; 46 | - (NSUInteger)lineNumber; 47 | 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Agda Writer/NoodleLineNumberMarker.m: -------------------------------------------------------------------------------- 1 | // 2 | // NoodleLineNumberMarker.m 3 | // NoodleKit 4 | // 5 | // Created by Paul Kim on 9/30/08. 6 | // Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person 9 | // obtaining a copy of this software and associated documentation 10 | // files (the "Software"), to deal in the Software without 11 | // restriction, including without limitation the rights to use, 12 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the 14 | // Software is furnished to do so, subject to the following 15 | // conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be 18 | // included in all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | // OTHER DEALINGS IN THE SOFTWARE. 28 | // 29 | 30 | #import "NoodleLineNumberMarker.h" 31 | 32 | 33 | @implementation NoodleLineNumberMarker 34 | 35 | - (id)initWithRulerView:(NSRulerView *)aRulerView lineNumber:(CGFloat)line image:(NSImage *)anImage imageOrigin:(NSPoint)imageOrigin 36 | { 37 | if ((self = [super initWithRulerView:aRulerView markerLocation:0.0 image:anImage imageOrigin:imageOrigin]) != nil) 38 | { 39 | _lineNumber = line; 40 | } 41 | return self; 42 | } 43 | 44 | - (void)setLineNumber:(NSUInteger)line 45 | { 46 | _lineNumber = line; 47 | } 48 | 49 | - (NSUInteger)lineNumber 50 | { 51 | return _lineNumber; 52 | } 53 | 54 | #pragma mark NSCoding methods 55 | 56 | #define NOODLE_LINE_CODING_KEY @"line" 57 | 58 | - (id)initWithCoder:(NSCoder *)decoder 59 | { 60 | if ((self = [super initWithCoder:decoder]) != nil) 61 | { 62 | if ([decoder allowsKeyedCoding]) 63 | { 64 | _lineNumber = [[decoder decodeObjectForKey:NOODLE_LINE_CODING_KEY] unsignedIntegerValue]; 65 | } 66 | else 67 | { 68 | _lineNumber = [[decoder decodeObject] unsignedIntegerValue]; 69 | } 70 | } 71 | return self; 72 | } 73 | 74 | - (void)encodeWithCoder:(NSCoder *)encoder 75 | { 76 | [super encodeWithCoder:encoder]; 77 | 78 | if ([encoder allowsKeyedCoding]) 79 | { 80 | [encoder encodeObject:[NSNumber numberWithUnsignedInteger:_lineNumber] forKey:NOODLE_LINE_CODING_KEY]; 81 | } 82 | else 83 | { 84 | [encoder encodeObject:[NSNumber numberWithUnsignedInteger:_lineNumber]]; 85 | } 86 | } 87 | 88 | 89 | #pragma mark NSCopying methods 90 | 91 | - (id)copyWithZone:(NSZone *)zone 92 | { 93 | id copy; 94 | 95 | copy = [super copyWithZone:zone]; 96 | [copy setLineNumber:_lineNumber]; 97 | 98 | return copy; 99 | } 100 | 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /Agda Writer/NoodleLineNumberView.h: -------------------------------------------------------------------------------- 1 | // 2 | // NoodleLineNumberView.h 3 | // NoodleKit 4 | // 5 | // Created by Paul Kim on 9/28/08. 6 | // Copyright (c) 2008-2012 Noodlesoft, LLC. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person 9 | // obtaining a copy of this software and associated documentation 10 | // files (the "Software"), to deal in the Software without 11 | // restriction, including without limitation the rights to use, 12 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the 14 | // Software is furnished to do so, subject to the following 15 | // conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be 18 | // included in all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | // OTHER DEALINGS IN THE SOFTWARE. 28 | // 29 | 30 | #import 31 | 32 | /* 33 | Displays line numbers for an NSTextView. 34 | 35 | For more details, see the related blog post at: http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/ 36 | */ 37 | 38 | @class NoodleLineNumberMarker; 39 | 40 | @interface NoodleLineNumberView : NSRulerView 41 | { 42 | // Array of character indices for the beginning of each line 43 | NSMutableArray *_lineIndices; 44 | // When text is edited, this is the start of the editing region. All line calculations after this point are invalid 45 | // and need to be recalculated. 46 | NSUInteger _invalidCharacterIndex; 47 | 48 | // Maps line numbers to markers 49 | NSMutableDictionary *_linesToMarkers; 50 | 51 | NSFont *_font; 52 | NSColor *_textColor; 53 | NSColor *_alternateTextColor; 54 | NSColor *_backgroundColor; 55 | } 56 | 57 | @property (readwrite, retain) NSFont *font; 58 | @property (readwrite, retain) NSColor *textColor; 59 | @property (readwrite, retain) NSColor *alternateTextColor; 60 | @property (readwrite, retain) NSColor *backgroundColor; 61 | 62 | - (id)initWithScrollView:(NSScrollView *)aScrollView; 63 | 64 | - (NSUInteger)lineNumberForLocation:(CGFloat)location; 65 | - (NoodleLineNumberMarker *)markerAtLine:(NSUInteger)line; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /Agda Writer/PreferencesGeneralController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PreferencesGeneralController.h 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 25. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PreferencesGeneralController : NSViewController 12 | @property (weak) IBOutlet NSTextField *agdaPathTextField; 13 | @property (weak) IBOutlet NSImageView *okImage; 14 | @property (weak) IBOutlet NSImageView *closeImage; 15 | - (IBAction)pathSelected:(id)sender; 16 | @property (weak) IBOutlet NSPopUpButton *fontFamilyPopupButton; 17 | @property (weak) IBOutlet NSPopUpButton *fontSizePopupButton; 18 | @property (weak) IBOutlet NSButton *showsNotifications; 19 | 20 | - (IBAction)showNotificationChanged:(id)sender; 21 | - (IBAction)fontFamilyChanged:(NSPopUpButton *)sender; 22 | 23 | - (IBAction)fontSizeChanged:(NSPopUpButton *)sender; 24 | @property (weak) IBOutlet NSTextField *pathToLibraries; 25 | - (IBAction)pathToLibrariesAction:(NSTextField *)sender; 26 | 27 | - (IBAction)browseAction:(NSButton *)sender; 28 | - (IBAction)delayForAutocompleteChanged:(NSTextField *)sender; 29 | - (IBAction)showHelpForExternalLibraries:(NSButton *)sender; 30 | 31 | 32 | @property (weak) IBOutlet NSTextField *delayForAutocompleteTextField; 33 | @property CGFloat delayForAutocomplete; 34 | @end 35 | -------------------------------------------------------------------------------- /Agda Writer/PreferencesGeneralController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PreferencesGeneralController.m 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 25. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "PreferencesGeneralController.h" 10 | #import "AWCommunitacion.h" 11 | #import "AWNotifications.h" 12 | #import "AWHelper.h" 13 | #import "AWPopoverViewController.h" 14 | 15 | @interface PreferencesGeneralController () 16 | 17 | @end 18 | 19 | @implementation PreferencesGeneralController { 20 | NSFont * selectedFont; 21 | AWPopoverViewController * _popoverViewController; 22 | NSPopover * _popover; 23 | 24 | } 25 | 26 | - (void)viewDidLoad { 27 | [super viewDidLoad]; 28 | 29 | 30 | 31 | // Do view setup here. 32 | 33 | [self.agdaPathTextField setStringValue:[AWNotifications agdaLaunchPath]]; 34 | [self setImagesFoundPath:[self isAgdaAvaliableAtPath:[AWNotifications agdaLaunchPath]]]; 35 | 36 | if ([AWHelper isShowingNotifications]) { 37 | [self.showsNotifications setState:NSOnState]; 38 | } 39 | else { 40 | [self.showsNotifications setState:NSOffState]; 41 | } 42 | [self.pathToLibraries setStringValue:[AWHelper pathToLibraries]]; 43 | selectedFont = [AWHelper defaultFontInAgda]; 44 | self.pathToLibraries.delegate = self; 45 | self.delayForAutocompleteTextField.delegate = self; 46 | 47 | _popover = [[NSPopover alloc] init]; 48 | _popoverViewController = [[AWPopoverViewController alloc] initWithNibName:@"AWPopoverViewController" bundle:nil]; 49 | [_popover setBehavior:NSPopoverBehaviorTransient]; 50 | [_popover setContentViewController:_popoverViewController]; 51 | [_popover setAnimates:YES]; 52 | 53 | [self fillFontFamilies]; 54 | [self fillFontSizes]; 55 | 56 | } 57 | 58 | - (void) fillFontSizes 59 | { 60 | for (int i = 8; i <= 25; i++) { 61 | [self.fontSizePopupButton addItemWithTitle:[NSString stringWithFormat:@"%i",i]]; 62 | } 63 | 64 | [self.fontSizePopupButton selectItemWithTitle:[NSString stringWithFormat:@"%li", (long)[selectedFont pointSize]]]; 65 | } 66 | 67 | - (void) fillFontFamilies 68 | { 69 | NSArray *fontFamilies = [[NSFontManager sharedFontManager] availableFontFamilies]; 70 | 71 | for (NSString * fontFamily in fontFamilies) { 72 | [self.fontFamilyPopupButton addItemWithTitle:fontFamily]; 73 | } 74 | [self.fontFamilyPopupButton selectItemWithTitle:selectedFont.familyName]; 75 | } 76 | 77 | - (void) setImagesFoundPath:(BOOL)found 78 | { 79 | [self.okImage setHidden:NO]; 80 | [self.closeImage setHidden:NO]; 81 | [self.okImage setWantsLayer:YES]; 82 | [self.closeImage setWantsLayer:YES]; 83 | [self.okImage setAlphaValue:0.0]; 84 | [self.closeImage setAlphaValue:1.0]; 85 | if (found) { 86 | [self.okImage setAlphaValue:1.0]; 87 | [self.closeImage setAlphaValue:0.0]; 88 | } 89 | } 90 | 91 | 92 | -(BOOL)isAgdaAvaliableAtPath:(NSString *)path 93 | { 94 | AWCommunitacion * agdaComm = [[AWCommunitacion alloc] init]; 95 | return [agdaComm isAgdaAvaliableAtPath:path]; 96 | 97 | } 98 | 99 | - (IBAction)pathSelected:(id)sender { 100 | if ([sender isKindOfClass:[NSTextField class]]) { 101 | NSTextField * tf = (NSTextField *)sender; 102 | if ([self isAgdaAvaliableAtPath:tf.stringValue]) { 103 | [self.agdaPathTextField setStringValue:tf.stringValue]; 104 | [AWNotifications setAgdaLaunchPath:tf.stringValue]; 105 | 106 | [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) { 107 | [context setDuration:0.5f]; 108 | [self.closeImage.animator setAlphaValue:0.0]; 109 | [self.okImage.animator setAlphaValue:1.0]; 110 | } completionHandler:^{ 111 | }]; 112 | 113 | } 114 | else { 115 | [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) { 116 | [context setDuration:0.5f]; 117 | [self.okImage.animator setAlphaValue:0.0]; 118 | [self.closeImage.animator setAlphaValue:1.0]; 119 | } completionHandler:^{ 120 | 121 | }]; 122 | 123 | 124 | } 125 | } 126 | } 127 | 128 | - (IBAction)showNotificationChanged:(id)sender { 129 | NSButton * button = sender; 130 | if ([button state] == NSOnState) { 131 | [AWHelper setShowingNotifications:YES]; 132 | } 133 | else { 134 | [AWHelper setShowingNotifications:NO]; 135 | 136 | } 137 | } 138 | 139 | - (IBAction)fontFamilyChanged:(NSPopUpButton *)sender { 140 | [AWNotifications notifyFontFamilyChanged:sender.titleOfSelectedItem]; 141 | } 142 | 143 | - (IBAction)fontSizeChanged:(NSPopUpButton *)sender { 144 | NSNumber * newFontSize = [[NSNumberFormatter new] numberFromString:sender.titleOfSelectedItem]; 145 | [AWNotifications notifyFontSizeChanged:newFontSize]; 146 | } 147 | 148 | - (IBAction)pathToLibrariesAction:(NSTextField *)sender { 149 | [AWHelper savePathToLibraries:sender.stringValue]; 150 | } 151 | 152 | 153 | - (IBAction)browseAction:(NSButton *)sender { 154 | 155 | NSOpenPanel * panel = [NSOpenPanel openPanel]; 156 | [panel setAllowsMultipleSelection:NO]; 157 | [panel setCanChooseDirectories:NO]; 158 | [panel setCanChooseFiles:YES]; 159 | [panel setShowsHiddenFiles:YES]; 160 | [panel setAllowedFileTypes:@[@""]]; 161 | if ([panel runModal] != NSFileHandlingPanelOKButton) { 162 | return; 163 | } 164 | NSURL * selectedFileURL = [[panel URLs] lastObject]; 165 | // NSLog(@"Selected File Path: %@", [selectedFileURL path]); 166 | if ([self isAgdaAvaliableAtPath:[selectedFileURL path]]) { 167 | [self.agdaPathTextField setStringValue:[selectedFileURL path]]; 168 | [AWNotifications setAgdaLaunchPath:[selectedFileURL path]]; 169 | 170 | [self setImagesFoundPath:YES]; 171 | } 172 | else { 173 | [self setImagesFoundPath:NO]; 174 | } 175 | 176 | } 177 | 178 | -(NSArray *)control:(NSControl *)control textView:(NSTextView *)textView completions:(NSArray *)words forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(NSInteger *)index 179 | { 180 | return @[]; 181 | } 182 | 183 | 184 | -(void)setNilValueForKey:(NSString *)key 185 | { 186 | if ([key isEqualToString:@"delayForAutocomplete"]) { 187 | self.delayForAutocomplete = 0; 188 | [self.delayForAutocompleteTextField setStringValue:@"0"]; 189 | } 190 | } 191 | 192 | 193 | - (IBAction)delayForAutocompleteChanged:(NSTextField *)sender { 194 | NSLog(@"input changed"); 195 | } 196 | 197 | - (IBAction)showHelpForExternalLibraries:(NSButton *)sender { 198 | [_popover showRelativeToRect:sender.bounds ofView:sender preferredEdge:NSMaxXEdge]; 199 | // Text can be changed AFTER UI elements has been loaded! 200 | [_popoverViewController.contentTextField setStringValue:[AWHelper helpForExternalLibraries]]; 201 | } 202 | 203 | 204 | 205 | @end 206 | -------------------------------------------------------------------------------- /Agda Writer/PreferencesKeyBindingsController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PreferencesKeyBindingsController.h 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 25. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PreferencesKeyBindingsController : NSViewController 12 | @property (weak) IBOutlet NSTableView *keyBindingsTableView; 13 | - (IBAction)addBinding:(id)sender; 14 | 15 | - (IBAction)removeBinding:(id)sender; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Agda Writer/PreferencesKeyBindingsController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PreferencesKeyBindingsController.m 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 25. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "PreferencesKeyBindingsController.h" 10 | #import "AWHelper.h" 11 | 12 | @interface PreferencesKeyBindingsController () 13 | 14 | @end 15 | 16 | @implementation PreferencesKeyBindingsController { 17 | NSMutableDictionary * items; 18 | NSMutableArray * sortedKeys; 19 | } 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | // Do view setup here. 24 | 25 | // Load items from Key Bindings.plist 26 | 27 | items = [[NSMutableDictionary alloc] initWithDictionary:[AWHelper keyBindings]]; 28 | // [items enumerateKeysAndObjectsWithOptions: usingBlock:^(id key, id obj, BOOL *stop) { 29 | // 30 | // }]; 31 | 32 | [self sortDictionaryByKeys]; 33 | 34 | 35 | 36 | } 37 | 38 | - (IBAction)addBinding:(id)sender { 39 | [sortedKeys addObject:@""]; 40 | [self.keyBindingsTableView reloadData]; 41 | // [self.keyBindingsTableView scrollToEndOfDocument:nil]; 42 | [self.keyBindingsTableView editColumn:0 row:sortedKeys.count - 1 withEvent:nil select:YES]; 43 | } 44 | 45 | - (IBAction)removeBinding:(id)sender { 46 | 47 | NSInteger selectedRow = [self.keyBindingsTableView selectedRow]; 48 | if (selectedRow != -1) { 49 | NSString * key = sortedKeys[selectedRow]; 50 | [sortedKeys removeObjectAtIndex:selectedRow]; 51 | [items removeObjectForKey:key]; 52 | [AWHelper saveKeyBindings:items]; 53 | [self.keyBindingsTableView reloadData]; 54 | if (selectedRow > 0) { 55 | NSIndexSet * indexSet = [NSIndexSet indexSetWithIndex:selectedRow - 1]; 56 | [self.keyBindingsTableView selectRowIndexes:indexSet byExtendingSelection:NO]; 57 | } 58 | 59 | } 60 | 61 | } 62 | 63 | - (void) sortDictionaryByKeys { 64 | 65 | sortedKeys = [[NSMutableArray alloc] initWithArray:[items.allKeys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 66 | NSString * name1 = (NSString *)obj1; 67 | NSString * name2 = (NSString *)obj2; 68 | if ([name1 hasPrefix:@"\\"]) { 69 | name1 = [name1 substringFromIndex:1]; 70 | } 71 | if ([name2 hasPrefix:@"\\"]) { 72 | name2 = [name2 substringFromIndex:1]; 73 | } 74 | return [name1 compare:name2]; 75 | }]]; 76 | 77 | } 78 | 79 | 80 | -(id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row 81 | { 82 | NSString * key = sortedKeys[row]; 83 | if (!key) { 84 | if ([tableColumn.identifier isEqualToString:@"columnKey"]) { 85 | return @""; 86 | } 87 | else if ([tableColumn.identifier isEqualToString:@"columnValue"]) { 88 | return @""; 89 | } 90 | } 91 | if ([tableColumn.identifier isEqualToString:@"columnKey"]) { 92 | 93 | 94 | return key; 95 | } 96 | else if ([tableColumn.identifier isEqualToString:@"columnValue"]) 97 | { 98 | 99 | return items[key]; 100 | 101 | } 102 | 103 | return nil; 104 | 105 | } 106 | 107 | -(void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row 108 | { 109 | if ([tableColumn.identifier isEqualToString:@"columnKey"]) { 110 | if (items[object] && ![object isEqualToString:@""]) { 111 | // Key already exist, show warning! 112 | NSAlert * alert = [[NSAlert alloc] init]; 113 | [alert addButtonWithTitle:@"Done"]; 114 | [alert setMessageText:@"Key already exists!\nPlease set unique key."]; 115 | [alert setAlertStyle:NSWarningAlertStyle]; 116 | if ([alert runModal] == NSAlertFirstButtonReturn) { 117 | } 118 | } 119 | else { 120 | if (items[sortedKeys[row]]) { 121 | //change, first save new value 122 | NSString * oldValue = items[sortedKeys[row]]; 123 | [items removeObjectForKey:sortedKeys[row]]; 124 | [items setObject:oldValue forKey:object]; 125 | [AWHelper saveKeyBindings:items]; 126 | 127 | } 128 | [sortedKeys replaceObjectAtIndex:row withObject:object]; 129 | 130 | } 131 | 132 | 133 | 134 | } 135 | else if ([tableColumn.identifier isEqualToString:@"columnValue"]) { 136 | if (![sortedKeys[row] isEqualToString:@""]) { 137 | // key is set, ok 138 | if (![object isEqualToString:@""]) { 139 | [items setObject:object forKey:sortedKeys[row]]; 140 | [AWHelper saveKeyBindings:items]; 141 | } 142 | else { 143 | NSAlert * alert = [[NSAlert alloc] init]; 144 | [alert addButtonWithTitle:@"Done"]; 145 | [alert setMessageText:@"Value can't be empty."]; 146 | [alert setAlertStyle:NSWarningAlertStyle]; 147 | if ([alert runModal] == NSAlertFirstButtonReturn) { 148 | } 149 | } 150 | 151 | 152 | } 153 | else { 154 | NSAlert * alert = [[NSAlert alloc] init]; 155 | [alert addButtonWithTitle:@"Done"]; 156 | [alert setMessageText:@"Please set unique key first."]; 157 | [alert setAlertStyle:NSWarningAlertStyle]; 158 | if ([alert runModal] == NSAlertFirstButtonReturn) { 159 | } 160 | } 161 | } 162 | } 163 | 164 | -(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView 165 | { 166 | return sortedKeys.count; 167 | 168 | } 169 | 170 | 171 | @end 172 | -------------------------------------------------------------------------------- /Agda Writer/ReadmeMarkdown/ex01.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/ReadmeMarkdown/ex01.gif -------------------------------------------------------------------------------- /Agda Writer/ReadmeMarkdown/ex02.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/ReadmeMarkdown/ex02.gif -------------------------------------------------------------------------------- /Agda Writer/TODO List: -------------------------------------------------------------------------------- 1 | - Change icon in preferences (Completed) 2 | - Add question button with explanation to external libraries (Completed) 3 | - Implement About 4 | - Add attribution for MAAtachedWindow (with html link) 5 | - Say thanks for NoodleLineNumberView 6 | - Remove Help 7 | -------------------------------------------------------------------------------- /Agda Writer/UnicodeTransformator.h: -------------------------------------------------------------------------------- 1 | // 2 | // UnicodeTransformator.h 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 24. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UnicodeTransformator : NSObject 12 | 13 | + (NSString *)transformToUnicode:(NSString *)input; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Agda Writer/UnicodeTransformator.m: -------------------------------------------------------------------------------- 1 | // 2 | // UnicodeTransformator.m 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 24. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import "UnicodeTransformator.h" 10 | #import "AWHelper.h" 11 | 12 | @implementation UnicodeTransformator 13 | 14 | + (NSString *)transformToUnicode:(NSString *)input 15 | { 16 | NSCharacterSet * characterSet = [NSCharacterSet characterSetWithCharactersInString:@"\n\t ()"]; 17 | NSArray * components = [input componentsSeparatedByCharactersInSet:characterSet]; 18 | NSDictionary * keyBindings = [AWHelper keyBindings]; 19 | for (NSString * token in components) { 20 | NSString * replacementString = [keyBindings objectForKey:token]; 21 | if (replacementString) { 22 | input = [input stringByReplacingOccurrencesOfString:token withString:replacementString]; 23 | } 24 | } 25 | 26 | return input; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Agda Writer/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 15. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | #import "AWCommunitacion.h" 12 | #import "AWAgdaActions.h" 13 | #import "AWToastWindow.h" 14 | #import "AWMainTextView.h" 15 | #import "Document.h" 16 | #import "AWGoalsTableController.h" 17 | #import "AWStatusTextView.h" 18 | #import "AWInputWindow.h" 19 | #import "MAAttachedWindow.h" 20 | #import "AWInputViewController.h" 21 | 22 | 23 | @class AgdaGoal, NoodleLineNumberView; 24 | 25 | @interface ViewController : NSViewController 26 | { 27 | Document * document; 28 | } 29 | 30 | @property (unsafe_unretained) IBOutlet AWMainTextView *mainTextView; 31 | 32 | @property (strong) IBOutlet AWGoalsTableController *goalsTableController; 33 | 34 | @property (unsafe_unretained) IBOutlet AWStatusTextView *statusTextView; 35 | 36 | 37 | 38 | @property IBOutlet NSTextView *lineNumbersView; 39 | @property AWToastWindow * toastView; 40 | @property MAAttachedWindow * inputWindow; 41 | @property AWInputViewController * inputViewController; 42 | @property (weak) IBOutlet NSTextField *lastStatusTextField; 43 | 44 | #pragma mark - 45 | #pragma mark Global actions 46 | 47 | // Global actions 48 | - (IBAction)actionLoad:(id)sender; 49 | - (IBAction)actionQuitAndRestartAgda:(NSMenuItem *)sender; 50 | - (IBAction)actionCompile:(id)sender; 51 | - (IBAction)actionQuit:(NSMenuItem *)sender; 52 | // Goal specific actions 53 | #pragma mark Goal specific actions 54 | - (IBAction)actionGive:(NSMenuItem *)sender; 55 | - (IBAction)actionRefine:(id)sender; 56 | - (IBAction)actionAuto:(NSMenuItem *)sender; 57 | - (IBAction)actionCase:(NSMenuItem *)sender; 58 | 59 | // Goal 60 | // Type 61 | - (IBAction)actionGoalTypeSimplified:(id)sender; 62 | - (IBAction)actionGoalTypeNormalised:(id)sender; 63 | - (IBAction)actionGoalTypeInstantiated:(id)sender; 64 | // Type and Context 65 | - (IBAction)actionGoalTypeAndContextSimplified:(id)sender; 66 | - (IBAction)actionGoalTypeAndContextNormalised:(id)sender; 67 | - (IBAction)actionGoalTypeAndContextInstantiated:(id)sender; 68 | // Type and Inffered Context 69 | - (IBAction)actionGoalTypeAndInfferedContextSimplified:(id)sender; 70 | - (IBAction)actionGoalTypeAndInfferedContextNormalised:(id)sender; 71 | - (IBAction)actionGoalTypeAndInfferedContextInstantiated:(id)sender; 72 | 73 | // Show 74 | // Constraints 75 | - (IBAction)actionShowConstraints:(id)sender; 76 | - (IBAction)actionShowMetas:(id)sender; 77 | // Module Contents 78 | - (IBAction)actionShowModuleContentsSimplified:(id)sender; 79 | - (IBAction)actionShowModuleContentsNormalised:(id)sender; 80 | - (IBAction)actionShowModuleContentsInstantiated:(id)sender; 81 | // Implicit Arguments 82 | - (IBAction)actionImplicitArguments:(id)sender; 83 | 84 | // Infer 85 | - (IBAction)actionInferSimplified:(id)sender; 86 | - (IBAction)actionInferNormalised:(id)sender; 87 | - (IBAction)actionInferInstantiated:(id)sender; 88 | 89 | // Togle Implicit Arguments 90 | - (IBAction)actionToggleImplicitArguments:(id)sender; 91 | 92 | // Solve All Constraints 93 | - (IBAction)actionSolveAllConstraints:(id)sender; 94 | 95 | // Why in Scope? 96 | - (IBAction)actionWhyInScope:(id)sender; 97 | 98 | // Context 99 | - (IBAction)actionContextSimplified:(id)sender; 100 | - (IBAction)actionContextNormalised:(id)sender; 101 | - (IBAction)actionContextInstantiated:(id)sender; 102 | 103 | // Show Version 104 | - (IBAction)actionShowVersion:(id)sender; 105 | 106 | //- (IBAction)actionGoalType:(NSMenuItem *)sender; 107 | //- (IBAction)actionContextEnvironment:(NSMenuItem *)sender; 108 | //- (IBAction)actionGoalTypeAndContext:(NSMenuItem *)sender; 109 | //- (IBAction)actionGoalTypeAndInferredType:(NSMenuItem *)sender; 110 | //- (IBAction)actionComputeNormalForm:(NSMenuItem *)sender; 111 | //- (IBAction)actionNormalize:(id)sender; 112 | //- (IBAction)actionNormalizeGoal:(id)sender; 113 | 114 | #pragma mark - 115 | - (IBAction)applyUnicodeTransformation:(id)sender; 116 | - (IBAction)biggerText:(id)sender; 117 | - (IBAction)smallerText:(id)sender; 118 | 119 | - (void)saveDocument:(id)sender; 120 | 121 | @property (weak) IBOutlet NSTableView *lineNumberTableView; 122 | 123 | @property NoodleLineNumberView * lineNumberView; 124 | 125 | @property (weak) IBOutlet NSScrollView *mainScrollView; 126 | 127 | 128 | @end 129 | 130 | -------------------------------------------------------------------------------- /Agda Writer/agda/Agda-2.4.2.2/lib/prim/Agda/Primitive.agdai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/agda/Agda-2.4.2.2/lib/prim/Agda/Primitive.agdai -------------------------------------------------------------------------------- /Agda Writer/agda/agda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda Writer/agda/agda -------------------------------------------------------------------------------- /Agda Writer/defaults.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | defaultFont 6 | 7 | name 8 | Menlo 9 | size 10 | 14 11 | 12 | agdaLaunchPath 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Agda Writer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Agda Writer 4 | // 5 | // Created by Marko Koležnik on 15. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /Agda WriterTests/AgdaParserTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AgdaParserTests.m 3 | // AgdaWriter 4 | // 5 | // Created by Marko Koležnik on 20. 04. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "AWAgdaParser.h" 12 | 13 | @interface AgdaParserTests : XCTestCase 14 | @property NSString * testPassedDescription; 15 | @property NSString * testFailedDescription; 16 | @property NSString * dictionariesNotEqualDescription; 17 | @end 18 | 19 | 20 | @implementation AgdaParserTests 21 | 22 | - (void)setUp { 23 | [super setUp]; 24 | // Put setup code here. This method is called before the invocation of each test method in the class. 25 | self.testPassedDescription = @"Test passed."; 26 | self.testFailedDescription = @"Test failed. Reason: "; 27 | self.dictionariesNotEqualDescription = @"Dictionaries are not equal!"; 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | #pragma mark- 36 | #pragma mark Responses 37 | 38 | - (void) testAgdaResponse9 { 39 | NSString * agdaResponse = @"(agda2-info-action \"*Agda Version*\" \"Agda version 2.4.2.2\" nil)"; 40 | NSDictionary * parsedObj = [AWAgdaParser parseAction:agdaResponse]; 41 | NSDictionary * expectedObj = @{@"agda2-info-action" : @[@"\"*Agda Version*\"", @"\"Agda version 2.4.2.2\"", @"nil"]}; 42 | 43 | [parsedObj isEqualToDictionary:expectedObj] ? XCTAssertTrue(self.testPassedDescription) : XCTAssertFalse([self.testFailedDescription stringByAppendingString:self.dictionariesNotEqualDescription]); 44 | } 45 | 46 | - (void) testAgdaResponse1 { 47 | NSString * agdaResponse = @"(agda2-status-action \"\")"; 48 | NSDictionary * parsedObj = [AWAgdaParser parseAction:agdaResponse]; 49 | NSDictionary * expectedObj = @{@"agda2-status-action" : @[@"\"\""]}; 50 | 51 | // Check for equal dictionaries (have dictionaries same keys and corresponding values? 52 | 53 | [parsedObj isEqualToDictionary:expectedObj] ? XCTAssertTrue(self.testPassedDescription) : XCTAssertFalse([self.testFailedDescription stringByAppendingString:self.dictionariesNotEqualDescription]); 54 | } 55 | - (void) testAgdaResponse2 { 56 | NSString * agdaResponse = @"(agda2-info-action \"*Type-checking*\" \"\" nil)"; 57 | NSDictionary * parsedObj = [AWAgdaParser parseAction:agdaResponse]; 58 | NSDictionary * expectedObj = @{@"agda2-info-action" : @[@"\"*Type-checking*\"", @"\"\"", @"nil"]}; 59 | 60 | [parsedObj isEqualToDictionary:expectedObj] ? XCTAssertTrue(self.testPassedDescription) : XCTAssertFalse([self.testFailedDescription stringByAppendingString:self.dictionariesNotEqualDescription]); 61 | } 62 | - (void) testAgdaResponse3 { 63 | NSString * agdaResponse = @"(agda2-info-action \"*Type-checking*\" \"Finished Foo.\n\" t)"; 64 | NSDictionary * parsedObj = [AWAgdaParser parseAction:agdaResponse]; 65 | NSDictionary * expectedObj = @{@"agda2-info-action" : @[@"\"*Type-checking*\"", @"\"Finished Foo.\n\"", @"t"]}; 66 | 67 | [parsedObj isEqualToDictionary:expectedObj] ? XCTAssertTrue(self.testPassedDescription) : XCTAssertFalse([self.testFailedDescription stringByAppendingString:self.dictionariesNotEqualDescription]); 68 | } 69 | - (void) testAgdaResponse4 { 70 | NSString * agdaResponse = @"(agda2-status-action \"\")"; 71 | NSDictionary * parsedObj = [AWAgdaParser parseAction:agdaResponse]; 72 | NSDictionary * expectedObj = @{@"agda2-status-action" : @[@"\"\""]}; 73 | 74 | [parsedObj isEqualToDictionary:expectedObj] ? XCTAssertTrue(self.testPassedDescription) : XCTAssertFalse([self.testFailedDescription stringByAppendingString:self.dictionariesNotEqualDescription]); 75 | } 76 | - (void) testAgdaResponse5 { 77 | NSString * agdaResponse = @"(agda2-info-action \"*All Goals*\" \"?0 : bool\n?1 : bool\n\" nil)"; 78 | NSDictionary * parsedObj = [AWAgdaParser parseAction:agdaResponse]; 79 | NSDictionary * expectedObj = @{@"agda2-info-action" : @[@"\"*All Goals*\"", @"\"?0 : bool\n?1 : bool\n\"", @"nil"]}; 80 | 81 | [parsedObj isEqualToDictionary:expectedObj] ? XCTAssertTrue(self.testPassedDescription) : XCTAssertFalse([self.testFailedDescription stringByAppendingString:self.dictionariesNotEqualDescription]); 82 | } 83 | - (void) testAgdaResponse6 { 84 | NSString * agdaResponse = @"((last . 1) . (agda2-goals-action '(0 1)))"; 85 | NSDictionary * parsedObj = [AWAgdaParser parseAction:agdaResponse]; 86 | NSDictionary * expectedObj = @{@"agda2-goals-action" : @[@"'(0 1)"]}; 87 | 88 | [parsedObj isEqualToDictionary:expectedObj] ? XCTAssertTrue(self.testPassedDescription) : XCTAssertFalse([self.testFailedDescription stringByAppendingString:self.dictionariesNotEqualDescription]); 89 | } 90 | - (void) testAgdaResponse7 { 91 | NSString * agdaResponse = @"(agda2-highlight-clear)"; 92 | NSDictionary * parsedObj = [AWAgdaParser parseAction:agdaResponse]; 93 | NSDictionary * expectedObj = @{@"agda2-highlight-clear" : @[]}; 94 | 95 | [parsedObj isEqualToDictionary:expectedObj] ? XCTAssertTrue(self.testPassedDescription) : XCTAssertFalse([self.testFailedDescription stringByAppendingString:self.dictionariesNotEqualDescription]); 96 | } 97 | - (void) testAgdaResponse8 { 98 | NSString * agdaResponse = @"(agda2-info-action \"*Type-checking*\" \"Checking Foo (/Users/markokoleznik/Documents/os_x_development/agda-writer/foo.agda).\n\" t)"; 99 | NSDictionary * parsedObj = [AWAgdaParser parseAction:agdaResponse]; 100 | NSDictionary * expectedObj = @{@"agda2-info-action" : @[@"\"*Type-checking*\"", @"\"Checking Foo (/Users/markokoleznik/Documents/os_x_development/agda-writer/foo.agda).\n\"", @"t"]}; 101 | 102 | [parsedObj isEqualToDictionary:expectedObj] ? XCTAssertTrue(self.testPassedDescription) : XCTAssertFalse([self.testFailedDescription stringByAppendingString:self.dictionariesNotEqualDescription]); 103 | } 104 | 105 | - (void) testAgdaResponse10 { 106 | NSString * agdaResponse = @"(agda2-give-action 0 \"x\")"; 107 | NSDictionary * parsedObj = [AWAgdaParser parseAction:agdaResponse]; 108 | NSDictionary * expectedObj = @{@"agda2-give-action" : @[@"0", @"\"x\""]}; 109 | 110 | [parsedObj isEqualToDictionary:expectedObj] ? XCTAssertTrue(self.testPassedDescription) : XCTAssertFalse([self.testFailedDescription stringByAppendingString:self.dictionariesNotEqualDescription]); 111 | } 112 | 113 | // (agda2-info-action "*Normal Form*" "\"hi!\"" nil) 114 | 115 | - (void) testAgdaResponse11 { 116 | NSString * agdaResponse = @"(agda2-info-action \"*Normal Form*\" \"\"hi!\"\" nil)"; 117 | NSDictionary * parsedObj = [AWAgdaParser parseAction:agdaResponse]; 118 | NSDictionary * expectedObj = @{@"agda2-info-action" : @[@"*Normal Form*", @"\"hi!\"", @"nil"]}; 119 | [parsedObj isEqualToDictionary:expectedObj] ? XCTAssertTrue(self.testPassedDescription) : XCTAssertFalse([self.testFailedDescription stringByAppendingString:self.dictionariesNotEqualDescription]); 120 | } 121 | 122 | 123 | //(agda2-give-action 0 "x") 124 | //(agda2-info-action "*Agda Version*" "Agda version 2.4.2.2" nil) 125 | 126 | 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /Agda WriterTests/AgdaWriterTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AgdaWriterTests.m 3 | // AgdaWriterTests 4 | // 5 | // Created by Marko Koležnik on 15. 10. 14. 6 | // Copyright (c) 2014 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AgdaWriterTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation AgdaWriterTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testAgdaParser { 34 | 35 | } 36 | 37 | - (void)testPerformanceExample { 38 | // This is an example of a performance test case. 39 | [self measureBlock:^{ 40 | // Put the code you want to measure the time of here. 41 | }]; 42 | } 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /Agda WriterTests/Agda_WriterTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // Agda_WriterTests.m 3 | // Agda WriterTests 4 | // 5 | // Created by Marko Koležnik on 15. 07. 15. 6 | // Copyright (c) 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface Agda_WriterTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation Agda_WriterTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Agda WriterTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Agda WriterTests/check-mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda WriterTests/check-mark.png -------------------------------------------------------------------------------- /Agda WriterTests/failed_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda WriterTests/failed_default.png -------------------------------------------------------------------------------- /Agda WriterTests/icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda WriterTests/icon_128x128.png -------------------------------------------------------------------------------- /Agda WriterTests/load_failed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda WriterTests/load_failed.png -------------------------------------------------------------------------------- /Agda WriterTests/load_successful.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda WriterTests/load_successful.png -------------------------------------------------------------------------------- /Agda WriterTests/settings-general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda WriterTests/settings-general.png -------------------------------------------------------------------------------- /Agda WriterTests/settings-keybindings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda WriterTests/settings-keybindings.png -------------------------------------------------------------------------------- /Agda WriterTests/successful_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda WriterTests/successful_default.png -------------------------------------------------------------------------------- /Agda WriterTests/x-mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markokoleznik/agda-writer/d70246fc98536e7babd1116a189fbf6e710d39af/Agda WriterTests/x-mark.png -------------------------------------------------------------------------------- /Agda WriterUITests/Agda_WriterUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // Agda_WriterUITests.m 3 | // Agda WriterUITests 4 | // 5 | // Created by Marko Koležnik on 29. 10. 15. 6 | // Copyright © 2015 koleznik.net. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Agda_WriterUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation Agda_WriterUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Agda WriterUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Licence.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Marko Koleznik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- 24 | 25 | The Agda software bundled with Agda Writer is licenced as follows: 26 | 27 | Copyright (c) 2005-2015 Ulf Norell, Andreas Abel, Nils Anders 28 | Danielsson, Andrés Sicard-Ramírez, Dominique Devriese, Péter 29 | Divianszki, Francesco Mazzoli, Stevan Andjelkovic, Daniel Gustafsson, 30 | Alan Jeffrey, Makoto Takeyama, Andrea Vezzosi, Nicolas Pouillard, 31 | James Chapman, Jean-Philippe Bernardy, Fredrik Lindblad, Nobuo 32 | Yamashita, Fredrik Nordvall Forsberg, Patrik Jansson, Guilhem Moulin, 33 | Stefan Monnier, Marcin Benke, Olle Fredriksson, Darin Morrison, Jesper 34 | Cockx, Wolfram Kahl, Catarina Coquand 35 | 36 | Permission is hereby granted, free of charge, to any person obtaining 37 | a copy of this software and associated documentation files (the 38 | "Software"), to deal in the Software without restriction, including 39 | without limitation the rights to use, copy, modify, merge, publish, 40 | distribute, sublicense, and/or sell copies of the Software, and to 41 | permit persons to whom the Software is furnished to do so, subject to 42 | the following conditions: 43 | 44 | The above copyright notice and this permission notice shall be 45 | included in all copies or substantial portions of the Software. 46 | 47 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 48 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 49 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 50 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 51 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 52 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 53 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 54 | 55 | -------------------------------------------------------------------------------- 56 | 57 | The file `src/full/Agda/Utils/Parser/ReadP.hs` from the Agda source code is 58 | Copyright (c) The University of Glasgow 2002 and is licensed under a 59 | BSD-like license as follows: 60 | 61 | Redistribution and use in source and binary forms, with or without 62 | modification, are permitted provided that the following conditions are met: 63 | 64 | - Redistributions of source code must retain the above copyright notice, 65 | this list of conditions and the following disclaimer. 66 | 67 | - Redistributions in binary form must reproduce the above copyright notice, 68 | this list of conditions and the following disclaimer in the documentation 69 | and/or other materials provided with the distribution. 70 | 71 | - Neither name of the University nor the names of its contributors may be 72 | used to endorse or promote products derived from this software without 73 | specific prior written permission. 74 | 75 | THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF 76 | GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 77 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 78 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 79 | UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE 80 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 81 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 82 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 83 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 84 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 85 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 86 | DAMAGE. 87 | 88 | -------------------------------------------------------------------------------- 89 | 90 | The file `src/full/Agda/Utils/Maybe/Strict.hs` from the Agda source code 91 | uses the following license: 92 | 93 | Copyright (c) Roman Leshchinskiy 2006-2007 94 | 95 | Redistribution and use in source and binary forms, with or without 96 | modification, are permitted provided that the following conditions 97 | are met: 98 | 99 | 1. Redistributions of source code must retain the above copyright 100 | notice, this list of conditions and the following disclaimer. 101 | 2. Redistributions in binary form must reproduce the above copyright 102 | notice, this list of conditions and the following disclaimer in the 103 | documentation and/or other materials provided with the distribution. 104 | 3. Neither the name of the author nor the names of his contributors 105 | may be used to endorse or promote products derived from this software 106 | without specific prior written permission. 107 | 108 | THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND 109 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 110 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 111 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 112 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 113 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 114 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 115 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 116 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 117 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 118 | SUCH DAMAGE. 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Agda Writer 2 | A Graphical User Interface for Agda for OS X Systems. 3 | Works with OS X 10.10 (Yosemite) or later. 4 | 5 | # Installation 6 | You can find compiled program under Releases (.zip attachment). Just unzip it, move it to desired folder (ie. Applications) and run the program. 7 | 8 | # Agda Writer in Action 9 | ## Loading a File 10 | ![Alt Text](https://github.com/markokoleznik/agda-writer/blob/master/Agda%20Writer/ReadmeMarkdown/ex01.gif) 11 | 12 | ## Normalizing an expression 13 | ![Alt Text](https://github.com/markokoleznik/agda-writer/blob/master/Agda%20Writer/ReadmeMarkdown/ex02.gif) 14 | 15 | # Features 16 | - Handy shortcuts for actions 17 | - Customizable Unicode (Latex-like) input with autocompletion 18 | - Same color palette as in Emacs 19 | - Independent Buffer window, so you can always know what is going on 20 | - ... 21 | - Well, it's not Emacs :D 22 | 23 | # Awesome Features 24 | It works without downloading & compiling Agda first. Just run the program and you are ready. 25 | 26 | # License 27 | Agda Writer is Licensed under MIT License Agreement. 28 | See Licence.md for more details. 29 | --------------------------------------------------------------------------------