@@ -300,6 +300,9 @@ - (id)init
300300 [connection release ]; connection = nil ;
301301 }
302302
303+ // Register help search handler to support search Vim docs via the Help menu
304+ [NSApp registerUserInterfaceItemSearchHandler: self ];
305+
303306#if !DISABLE_SPARKLE
304307 // Sparkle is enabled (this is the default). Initialize it. It will
305308 // automatically check for update.
@@ -951,6 +954,9 @@ - (void)refreshMainMenu
951954
952955 NSMenu *windowsMenu = [mainMenu findWindowsMenu ];
953956 [NSApp setWindowsMenu: windowsMenu];
957+
958+ NSMenu *helpMenu = [mainMenu findHelpMenu ];
959+ [NSApp setHelpMenu: helpMenu];
954960}
955961
956962- (NSArray *)filterOpenFiles : (NSArray *)filenames
@@ -1150,10 +1156,11 @@ - (IBAction)fileOpen:(id)sender
11501156 NSInteger result = [panel runModal ];
11511157
11521158#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10)
1153- if (NSModalResponseOK == result) {
1159+ if (NSModalResponseOK == result)
11541160#else
1155- if (NSOKButton == result) {
1161+ if (NSOKButton == result)
11561162#endif
1163+ {
11571164 // NOTE: -[NSOpenPanel filenames] is deprecated on 10.7 so use
11581165 // -[NSOpenPanel URLs] instead. The downside is that we have to check
11591166 // that each URL is really a path first.
@@ -1234,15 +1241,20 @@ - (IBAction)openWebsite:(id)sender
12341241 [NSURL URLWithString: MMWebsiteString]];
12351242}
12361243
1237- - (IBAction )showVimHelp:(id )sender
1244+ - (IBAction )showVimHelp : (id )sender withCmd : ( NSString *) cmd
12381245{
12391246 ASLogDebug (@" Open window with Vim help" );
1240- // Open a new window with the help window maximized .
1247+ // Open a new window with only the help window shown .
12411248 [self launchVimProcessWithArguments: [NSArray arrayWithObjects:
1242- @" -c" , @" :h gui_mac " , @" -c" , @" :res " , nil ]
1249+ @" -c" , cmd , @" -c" , @" :only " , nil ]
12431250 workingDirectory: nil ];
12441251}
12451252
1253+ - (IBAction )showVimHelp : (id )sender
1254+ {
1255+ [self showVimHelp: sender withCmd: @" :h gui_mac" ];
1256+ }
1257+
12461258- (IBAction )checkForUpdates : (id )sender
12471259{
12481260#if !DISABLE_SPARKLE
@@ -1421,6 +1433,99 @@ - (NSArray *)serverList
14211433 return array;
14221434}
14231435
1436+ // Begin NSUserInterfaceItemSearching implementation
1437+ - (NSArray <NSString *> *)localizedTitlesForItem : (id )item
1438+ {
1439+ return item;
1440+ }
1441+
1442+ - (void )searchForItemsWithSearchString : (NSString *)searchString
1443+ resultLimit : (NSInteger )resultLimit
1444+ matchedItemHandler : (void (^)(NSArray *items))handleMatchedItems
1445+ {
1446+ // Search documentation tags and provide the results in a pair of (file
1447+ // name, tag name). Currently lazily parse the Vim's doc tags, and reuse
1448+ // that in future searches.
1449+ //
1450+ // Does not support plugins for now, as different Vim instances could have
1451+ // different plugins loaded. Theoretically it's possible to query the
1452+ // current Vim instance for what plugins are loaded and the tags associated
1453+ // with them but it's tricky especially since this function is not invoked
1454+ // on the main thread. Just providing Vim's builtin docs should be mostly
1455+ // good enough.
1456+
1457+ static BOOL parsed = NO ;
1458+ static NSMutableArray *parsedLineComponents = nil ;
1459+
1460+ @synchronized (self) {
1461+ if (!parsed) {
1462+ parsedLineComponents = [[NSMutableArray alloc ]init];
1463+
1464+ NSString *tagsFilePath = [[[NSBundle mainBundle ] resourcePath ]
1465+ stringByAppendingPathComponent: @" vim/runtime/doc/tags" ];
1466+ NSString *fileContent = [NSString stringWithContentsOfFile: tagsFilePath encoding: NSUTF8StringEncoding error: NULL ];
1467+ NSArray *lines = [fileContent componentsSeparatedByString: @" \n " ];
1468+
1469+ for (NSString *line in lines) {
1470+ NSArray <NSString *> *components = [line componentsSeparatedByString: @" \t " ];
1471+ if ([components count ] < 2 ) {
1472+ continue ;
1473+ }
1474+ [parsedLineComponents addObject: components];
1475+ }
1476+
1477+ parsed = YES ;
1478+ }
1479+ }
1480+
1481+ // Use a simple search algorithm where the string is split by whitespace and each word has to match
1482+ // substring in the tag. Don't do fuzzy matching or regex for simplicity for now.
1483+ NSArray <NSString *> *searchStrings = [searchString componentsSeparatedByString: @" " ];
1484+
1485+ NSMutableArray *ret = [[[NSMutableArray alloc ]init] autorelease ];
1486+ for (NSArray <NSString *> *line in parsedLineComponents) {
1487+ BOOL found = YES ;
1488+ for (NSString *curSearchString in searchStrings) {
1489+ if (![line[0 ] localizedCaseInsensitiveContainsString: curSearchString]) {
1490+ found = NO ;
1491+ break ;
1492+ }
1493+ }
1494+ if (found) {
1495+ // We flip the ordering because we want it to look like "file_name.txt > tag_name" in the results.
1496+ NSArray *foundObject = @[line[1 ], line[0 ]];
1497+
1498+ if ([searchStrings count ] == 1 && [searchString localizedCaseInsensitiveCompare: line[0 ]] == NSOrderedSame) {
1499+ // Exact match has highest priority.
1500+ [ret insertObject: foundObject atIndex: 0 ];
1501+ }
1502+ else {
1503+ // Don't do any other prioritization for now. May add more sophisticated sorting/heuristics
1504+ // in the future.
1505+ [ret addObject: foundObject];
1506+ }
1507+ }
1508+ }
1509+
1510+ // Return the results to callback.
1511+ handleMatchedItems (ret);
1512+ }
1513+
1514+ - (void )performActionForItem : (id )item
1515+ {
1516+ // When opening a help page, either open a new Vim instance, or reuse the
1517+ // existing one.
1518+ MMVimController *vimController = [self keyVimController ];
1519+ if (vimController == nil ) {
1520+ [self showVimHelp: self withCmd: [NSString stringWithFormat:
1521+ @" :help %@ " , item[1 ]]];
1522+ return ;
1523+ }
1524+ [vimController addVimInput: [NSString stringWithFormat:
1525+ @" <C-\\ ><C-N>:help %@ <CR>" , item[1 ]]];
1526+ }
1527+ // End NSUserInterfaceItemSearching
1528+
14241529@end // MMAppController
14251530
14261531
0 commit comments