hookapp 0.0.7 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGELOG.md +14 -0
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +2 -2
  6. data/LICENSE.md +31 -0
  7. data/OVERVIEW.md +80 -0
  8. data/README.md +282 -21
  9. data/Rakefile +1 -1
  10. data/bin/hook +127 -10
  11. data/buildnotes.md +29 -0
  12. data/hook.rdoc +63 -4
  13. data/hookapp.gemspec +9 -8
  14. data/html/App.html +119 -0
  15. data/html/GLI.html +99 -0
  16. data/html/GLI/Commands.html +99 -0
  17. data/html/GLI/Commands/Doc.html +99 -0
  18. data/html/GLI/Commands/MarkdownDocumentListener.html +717 -0
  19. data/html/Hook.html +113 -0
  20. data/html/HookApp.html +1222 -0
  21. data/html/Hooker.html +119 -0
  22. data/html/README_rdoc.html +328 -0
  23. data/html/String.html +427 -0
  24. data/html/created.rid +9 -0
  25. data/html/css/fonts.css +167 -0
  26. data/html/css/rdoc.css +619 -0
  27. data/html/fonts/Lato-Light.ttf +0 -0
  28. data/html/fonts/Lato-LightItalic.ttf +0 -0
  29. data/html/fonts/Lato-Regular.ttf +0 -0
  30. data/html/fonts/Lato-RegularItalic.ttf +0 -0
  31. data/html/fonts/SourceCodePro-Bold.ttf +0 -0
  32. data/html/fonts/SourceCodePro-Regular.ttf +0 -0
  33. data/html/images/add.png +0 -0
  34. data/html/images/arrow_up.png +0 -0
  35. data/html/images/brick.png +0 -0
  36. data/html/images/brick_link.png +0 -0
  37. data/html/images/bug.png +0 -0
  38. data/html/images/bullet_black.png +0 -0
  39. data/html/images/bullet_toggle_minus.png +0 -0
  40. data/html/images/bullet_toggle_plus.png +0 -0
  41. data/html/images/date.png +0 -0
  42. data/html/images/delete.png +0 -0
  43. data/html/images/find.png +0 -0
  44. data/html/images/loadingAnimation.gif +0 -0
  45. data/html/images/macFFBgHack.png +0 -0
  46. data/html/images/package.png +0 -0
  47. data/html/images/page_green.png +0 -0
  48. data/html/images/page_white_text.png +0 -0
  49. data/html/images/page_white_width.png +0 -0
  50. data/html/images/plugin.png +0 -0
  51. data/html/images/ruby.png +0 -0
  52. data/html/images/tag_blue.png +0 -0
  53. data/html/images/tag_green.png +0 -0
  54. data/html/images/transparent.png +0 -0
  55. data/html/images/wrench.png +0 -0
  56. data/html/images/wrench_orange.png +0 -0
  57. data/html/images/zoom.png +0 -0
  58. data/html/index.html +308 -0
  59. data/html/js/darkfish.js +84 -0
  60. data/html/js/navigation.js +105 -0
  61. data/html/js/navigation.js.gz +0 -0
  62. data/html/js/search.js +110 -0
  63. data/html/js/search_index.js +1 -0
  64. data/html/js/search_index.js.gz +0 -0
  65. data/html/js/searcher.js +229 -0
  66. data/html/js/searcher.js.gz +0 -0
  67. data/html/table_of_contents.html +409 -0
  68. data/lib/completion/hook_completion.bash +22 -0
  69. data/lib/completion/hook_completion.fish +31 -0
  70. data/lib/completion/hook_completion.zsh +22 -0
  71. data/lib/helpers/fuzzyfilefinder +0 -0
  72. data/lib/hook.rb +5 -1
  73. data/lib/hook/hookapp.rb +489 -0
  74. data/lib/hook/hooker.rb +1 -344
  75. data/lib/hook/markdown_document_listener.rb +164 -0
  76. data/lib/hook/string.rb +60 -0
  77. data/lib/hook/version.rb +3 -1
  78. metadata +76 -12
@@ -0,0 +1,105 @@
1
+ /*
2
+ * Navigation allows movement using the arrow keys through the search results.
3
+ *
4
+ * When using this library you will need to set scrollIntoView to the
5
+ * appropriate function for your layout. Use scrollInWindow if the container
6
+ * is not scrollable and scrollInElement if the container is a separate
7
+ * scrolling region.
8
+ */
9
+ Navigation = new function() {
10
+ this.initNavigation = function() {
11
+ var _this = this;
12
+
13
+ document.addEventListener('keydown', function(e) {
14
+ _this.onkeydown(e);
15
+ });
16
+
17
+ this.navigationActive = true;
18
+ }
19
+
20
+ this.setNavigationActive = function(state) {
21
+ this.navigationActive = state;
22
+ }
23
+
24
+ this.onkeydown = function(e) {
25
+ if (!this.navigationActive) return;
26
+ switch(e.keyCode) {
27
+ case 37: //Event.KEY_LEFT:
28
+ if (this.moveLeft()) e.preventDefault();
29
+ break;
30
+ case 38: //Event.KEY_UP:
31
+ if (e.keyCode == 38 || e.ctrlKey) {
32
+ if (this.moveUp()) e.preventDefault();
33
+ }
34
+ break;
35
+ case 39: //Event.KEY_RIGHT:
36
+ if (this.moveRight()) e.preventDefault();
37
+ break;
38
+ case 40: //Event.KEY_DOWN:
39
+ if (e.keyCode == 40 || e.ctrlKey) {
40
+ if (this.moveDown()) e.preventDefault();
41
+ }
42
+ break;
43
+ case 13: //Event.KEY_RETURN:
44
+ if (this.current) e.preventDefault();
45
+ this.select(this.current);
46
+ break;
47
+ }
48
+ if (e.ctrlKey && e.shiftKey) this.select(this.current);
49
+ }
50
+
51
+ this.moveRight = function() {
52
+ }
53
+
54
+ this.moveLeft = function() {
55
+ }
56
+
57
+ this.move = function(isDown) {
58
+ }
59
+
60
+ this.moveUp = function() {
61
+ return this.move(false);
62
+ }
63
+
64
+ this.moveDown = function() {
65
+ return this.move(true);
66
+ }
67
+
68
+ /*
69
+ * Scrolls to the given element in the scrollable element view.
70
+ */
71
+ this.scrollInElement = function(element, view) {
72
+ var offset, viewHeight, viewScroll, height;
73
+ offset = element.offsetTop;
74
+ height = element.offsetHeight;
75
+ viewHeight = view.offsetHeight;
76
+ viewScroll = view.scrollTop;
77
+
78
+ if (offset - viewScroll + height > viewHeight) {
79
+ view.scrollTop = offset - viewHeight + height;
80
+ }
81
+ if (offset < viewScroll) {
82
+ view.scrollTop = offset;
83
+ }
84
+ }
85
+
86
+ /*
87
+ * Scrolls to the given element in the window. The second argument is
88
+ * ignored
89
+ */
90
+ this.scrollInWindow = function(element, ignored) {
91
+ var offset, viewHeight, viewScroll, height;
92
+ offset = element.offsetTop;
93
+ height = element.offsetHeight;
94
+ viewHeight = window.innerHeight;
95
+ viewScroll = window.scrollY;
96
+
97
+ if (offset - viewScroll + height > viewHeight) {
98
+ window.scrollTo(window.scrollX, offset - viewHeight + height);
99
+ }
100
+ if (offset < viewScroll) {
101
+ window.scrollTo(window.scrollX, offset);
102
+ }
103
+ }
104
+ }
105
+
Binary file
@@ -0,0 +1,110 @@
1
+ Search = function(data, input, result) {
2
+ this.data = data;
3
+ this.input = input;
4
+ this.result = result;
5
+
6
+ this.current = null;
7
+ this.view = this.result.parentNode;
8
+ this.searcher = new Searcher(data.index);
9
+ this.init();
10
+ }
11
+
12
+ Search.prototype = Object.assign({}, Navigation, new function() {
13
+ var suid = 1;
14
+
15
+ this.init = function() {
16
+ var _this = this;
17
+ var observer = function(e) {
18
+ switch(e.keyCode) {
19
+ case 38: // Event.KEY_UP
20
+ case 40: // Event.KEY_DOWN
21
+ return;
22
+ }
23
+ _this.search(_this.input.value);
24
+ };
25
+ this.input.addEventListener('keyup', observer);
26
+ this.input.addEventListener('click', observer); // mac's clear field
27
+
28
+ this.searcher.ready(function(results, isLast) {
29
+ _this.addResults(results, isLast);
30
+ })
31
+
32
+ this.initNavigation();
33
+ this.setNavigationActive(false);
34
+ }
35
+
36
+ this.search = function(value, selectFirstMatch) {
37
+ value = value.trim().toLowerCase();
38
+ if (value) {
39
+ this.setNavigationActive(true);
40
+ } else {
41
+ this.setNavigationActive(false);
42
+ }
43
+
44
+ if (value == '') {
45
+ this.lastQuery = value;
46
+ this.result.innerHTML = '';
47
+ this.result.setAttribute('aria-expanded', 'false');
48
+ this.setNavigationActive(false);
49
+ } else if (value != this.lastQuery) {
50
+ this.lastQuery = value;
51
+ this.result.setAttribute('aria-busy', 'true');
52
+ this.result.setAttribute('aria-expanded', 'true');
53
+ this.firstRun = true;
54
+ this.searcher.find(value);
55
+ }
56
+ }
57
+
58
+ this.addResults = function(results, isLast) {
59
+ var target = this.result;
60
+ if (this.firstRun && (results.length > 0 || isLast)) {
61
+ this.current = null;
62
+ this.result.innerHTML = '';
63
+ }
64
+
65
+ for (var i=0, l = results.length; i < l; i++) {
66
+ var item = this.renderItem.call(this, results[i]);
67
+ item.setAttribute('id', 'search-result-' + target.childElementCount);
68
+ target.appendChild(item);
69
+ };
70
+
71
+ if (this.firstRun && results.length > 0) {
72
+ this.firstRun = false;
73
+ this.current = target.firstChild;
74
+ this.current.classList.add('search-selected');
75
+ }
76
+ //TODO: ECMAScript
77
+ //if (jQuery.browser.msie) this.$element[0].className += '';
78
+
79
+ if (isLast) this.result.setAttribute('aria-busy', 'false');
80
+ }
81
+
82
+ this.move = function(isDown) {
83
+ if (!this.current) return;
84
+ var next = isDown ? this.current.nextElementSibling : this.current.previousElementSibling;
85
+ if (next) {
86
+ this.current.classList.remove('search-selected');
87
+ next.classList.add('search-selected');
88
+ this.input.setAttribute('aria-activedescendant', next.getAttribute('id'));
89
+ this.scrollIntoView(next, this.view);
90
+ this.current = next;
91
+ this.input.value = next.firstChild.firstChild.text;
92
+ this.input.select();
93
+ }
94
+ return true;
95
+ }
96
+
97
+ this.hlt = function(html) {
98
+ return this.escapeHTML(html).
99
+ replace(/\u0001/g, '<em>').
100
+ replace(/\u0002/g, '</em>');
101
+ }
102
+
103
+ this.escapeHTML = function(html) {
104
+ return html.replace(/[&<>]/g, function(c) {
105
+ return '&#' + c.charCodeAt(0) + ';';
106
+ });
107
+ }
108
+
109
+ });
110
+
@@ -0,0 +1 @@
1
+ var search_data = {"index":{"searchIndex":["app","gli","commands","doc","markdowndocumentlistener","hook","hookapp","hooker","string","all_bookmarks()","beginning()","bookmark_for()","bookmark_from_app()","cap()","cap!()","clip()","clip_bookmark()","clone_hooks()","command()","commands()","copy_bookmark()","default_command()","delete_all_hooks()","delete_hooks()","end_command()","end_commands()","end_options()","ending()","flag()","format_regex()","get_hooks()","link_all()","link_files()","linked_bookmarks()","new()","nil_if_missing()","open_gui()","open_linked()","options()","output_array()","program_desc()","program_long_desc()","search_bookmarks()","search_name()","search_path_or_address()","select_hook()","split_hook()","split_hooks()","switch()","valid_hook()","valid_hook!()","validate_format()","version()","readme"],"longSearchIndex":["app","gli","gli::commands","gli::commands::doc","gli::commands::markdowndocumentlistener","hook","hookapp","hooker","string","hookapp#all_bookmarks()","gli::commands::markdowndocumentlistener#beginning()","hookapp#bookmark_for()","hookapp#bookmark_from_app()","string#cap()","string#cap!()","string#clip()","hookapp#clip_bookmark()","hookapp#clone_hooks()","gli::commands::markdowndocumentlistener#command()","gli::commands::markdowndocumentlistener#commands()","hookapp#copy_bookmark()","gli::commands::markdowndocumentlistener#default_command()","hookapp#delete_all_hooks()","hookapp#delete_hooks()","gli::commands::markdowndocumentlistener#end_command()","gli::commands::markdowndocumentlistener#end_commands()","gli::commands::markdowndocumentlistener#end_options()","gli::commands::markdowndocumentlistener#ending()","gli::commands::markdowndocumentlistener#flag()","hookapp#format_regex()","hookapp#get_hooks()","hookapp#link_all()","hookapp#link_files()","hookapp#linked_bookmarks()","gli::commands::markdowndocumentlistener::new()","string#nil_if_missing()","hookapp#open_gui()","hookapp#open_linked()","gli::commands::markdowndocumentlistener#options()","hookapp#output_array()","gli::commands::markdowndocumentlistener#program_desc()","gli::commands::markdowndocumentlistener#program_long_desc()","hookapp#search_bookmarks()","hookapp#search_name()","hookapp#search_path_or_address()","hookapp#select_hook()","string#split_hook()","string#split_hooks()","gli::commands::markdowndocumentlistener#switch()","string#valid_hook()","string#valid_hook!()","hookapp#validate_format()","gli::commands::markdowndocumentlistener#version()",""],"info":[["App","","App.html","","<p>Main class for GLI app\n"],["GLI","","GLI.html","",""],["GLI::Commands","","GLI/Commands.html","",""],["GLI::Commands::Doc","","GLI/Commands/Doc.html","",""],["GLI::Commands::MarkdownDocumentListener","","GLI/Commands/MarkdownDocumentListener.html","","<p>DocumentListener class for GLI documentation generator\n"],["Hook","","Hook.html","",""],["HookApp","","HookApp.html","","<p>Hook.app functions\n"],["Hooker","","Hooker.html","","<p>Hook.app CLI interface\n"],["String","","String.html","","<p>String helpers\n"],["all_bookmarks","HookApp","HookApp.html#method-i-all_bookmarks","()","<p>Get all known bookmarks. Return array of bookmark hashes.\n"],["beginning","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-beginning","()",""],["bookmark_for","HookApp","HookApp.html#method-i-bookmark_for","(url)","<p>Get a Hook bookmark for file or URL. Return bookmark hash.\n"],["bookmark_from_app","HookApp","HookApp.html#method-i-bookmark_from_app","(app, opts)","<p>Get a bookmark from the foreground document of specified app.\n"],["cap","String","String.html#method-i-cap","()","<p>Capitalize only if no uppercase\n"],["cap!","String","String.html#method-i-cap-21","()",""],["clip","String","String.html#method-i-clip","()",""],["clip_bookmark","HookApp","HookApp.html#method-i-clip_bookmark","(url, opts)","<p>Create a bookmark for specified file/url and copy to the clipboard.\n"],["clone_hooks","HookApp","HookApp.html#method-i-clone_hooks","(args)","<p>Copy all hooks from source file to target file\n"],["command","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-command","(name, aliases, desc, long_desc, arg_name, arg_options)","<p>Gives you a command in the current context and creates a new context of this command\n"],["commands","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-commands","()",""],["copy_bookmark","HookApp","HookApp.html#method-i-copy_bookmark","(title, url, opts)","<p>Create a bookmark from specified title and url and copy to the clipboard.\n"],["default_command","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-default_command","(name)","<p>Gives you the name of the current command in the current context\n"],["delete_all_hooks","HookApp","HookApp.html#method-i-delete_all_hooks","(url)","<p>Delete all hooked files/urls from target file\n"],["delete_hooks","HookApp","HookApp.html#method-i-delete_hooks","(args, opts)","<p>Delete hooks between two files/urls\n"],["end_command","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-end_command","(_name)","<p>Ends a command, and “pops” you back up one context\n"],["end_commands","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-end_commands","()",""],["end_options","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-end_options","()",""],["ending","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-ending","()","<p>Called when processing has completed\n"],["flag","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-flag","(name, aliases, desc, long_desc, default_value, arg_name, must_match, _type)","<p>Gives you a flag in the current context\n"],["format_regex","HookApp","HookApp.html#method-i-format_regex","(options)","<p>Create a single regex for validation of an array by first char or full match.\n"],["get_hooks","HookApp","HookApp.html#method-i-get_hooks","(url)","<p>Get bookmarks hooked to file or URL. Return array of bookmark hashes.\n"],["link_all","HookApp","HookApp.html#method-i-link_all","(args)","<p>Create bi-directional links between every file/url in the list of arguments\n"],["link_files","HookApp","HookApp.html#method-i-link_files","(args)","<p>Link 2 or more files/urls with bi-directional hooks.\n"],["linked_bookmarks","HookApp","HookApp.html#method-i-linked_bookmarks","(args, opts)","<p>Get a list of all hooks on a file/url.\n"],["new","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-c-new","(_global_options, _options, _arguments, app)",""],["nil_if_missing","String","String.html#method-i-nil_if_missing","()",""],["open_gui","HookApp","HookApp.html#method-i-open_gui","(url)","<p>Open the Hook GUI for browsing/performing actions on a file or url\n"],["open_linked","HookApp","HookApp.html#method-i-open_linked","(url)","<p>Select from a menu of available hooks and open using macOS `open`.\n"],["options","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-options","()",""],["output_array","HookApp","HookApp.html#method-i-output_array","(hooks_arr, opts)","<p>Output an array of hooks in the given format.\n"],["program_desc","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-program_desc","(desc)","<p>Gives you the program description\n"],["program_long_desc","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-program_long_desc","(desc)",""],["search_bookmarks","HookApp","HookApp.html#method-i-search_bookmarks","(search, opts)","<p>Search bookmarks, using both names and addresses unless options contain “:names_only”. Return …\n"],["search_name","HookApp","HookApp.html#method-i-search_name","(search)","<p>Search boomark names/titles. Return array of bookmark hashes.\n"],["search_path_or_address","HookApp","HookApp.html#method-i-search_path_or_address","(search)","<p>Search bookmark paths and addresses. Return array of bookmark hashes.\n"],["select_hook","HookApp","HookApp.html#method-i-select_hook","(marks)","<p>Generate a menu of available hooks for selecting one or more hooks to operate on. Revamped to use `fzf`, …\n"],["split_hook","String","String.html#method-i-split_hook","()",""],["split_hooks","String","String.html#method-i-split_hooks","()",""],["switch","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-switch","(name, aliases, desc, long_desc, negatable)","<p>Gives you a switch in the current context\n"],["valid_hook","String","String.html#method-i-valid_hook","()",""],["valid_hook!","String","String.html#method-i-valid_hook-21","()",""],["validate_format","HookApp","HookApp.html#method-i-validate_format","(fmt, options)","<p>Check if format fully matches or matches the first character of available options. Return full valid …\n"],["version","GLI::Commands::MarkdownDocumentListener","GLI/Commands/MarkdownDocumentListener.html#method-i-version","(version)","<p>Gives you the program version\n"],["README","","README_rdoc.html","","<p>hookapp\n<p>A CLI for Hook.app on macOS.\n<p>hook - CLI interface for Hook.app (macOS)\n"]]}}
@@ -0,0 +1,229 @@
1
+ Searcher = function(data) {
2
+ this.data = data;
3
+ this.handlers = [];
4
+ }
5
+
6
+ Searcher.prototype = new function() {
7
+ // search is performed in chunks of 1000 for non-blocking user input
8
+ var CHUNK_SIZE = 1000;
9
+ // do not try to find more than 100 results
10
+ var MAX_RESULTS = 100;
11
+ var huid = 1;
12
+ var suid = 1;
13
+ var runs = 0;
14
+
15
+ this.find = function(query) {
16
+ var queries = splitQuery(query);
17
+ var regexps = buildRegexps(queries);
18
+ var highlighters = buildHilighters(queries);
19
+ var state = { from: 0, pass: 0, limit: MAX_RESULTS, n: suid++};
20
+ var _this = this;
21
+
22
+ this.currentSuid = state.n;
23
+
24
+ if (!query) return;
25
+
26
+ var run = function() {
27
+ // stop current search thread if new search started
28
+ if (state.n != _this.currentSuid) return;
29
+
30
+ var results =
31
+ performSearch(_this.data, regexps, queries, highlighters, state);
32
+ var hasMore = (state.limit > 0 && state.pass < 4);
33
+
34
+ triggerResults.call(_this, results, !hasMore);
35
+ if (hasMore) {
36
+ setTimeout(run, 2);
37
+ }
38
+ runs++;
39
+ };
40
+ runs = 0;
41
+
42
+ // start search thread
43
+ run();
44
+ }
45
+
46
+ /* ----- Events ------ */
47
+ this.ready = function(fn) {
48
+ fn.huid = huid;
49
+ this.handlers.push(fn);
50
+ }
51
+
52
+ /* ----- Utilities ------ */
53
+ function splitQuery(query) {
54
+ return query.split(/(\s+|::?|\(\)?)/).filter(function(string) {
55
+ return string.match(/\S/);
56
+ });
57
+ }
58
+
59
+ function buildRegexps(queries) {
60
+ return queries.map(function(query) {
61
+ return new RegExp(query.replace(/(.)/g, '([$1])([^$1]*?)'), 'i');
62
+ });
63
+ }
64
+
65
+ function buildHilighters(queries) {
66
+ return queries.map(function(query) {
67
+ return query.split('').map(function(l, i) {
68
+ return '\u0001$' + (i*2+1) + '\u0002$' + (i*2+2);
69
+ }).join('');
70
+ });
71
+ }
72
+
73
+ // function longMatchRegexp(index, longIndex, regexps) {
74
+ // for (var i = regexps.length - 1; i >= 0; i--){
75
+ // if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
76
+ // };
77
+ // return true;
78
+ // }
79
+
80
+
81
+ /* ----- Mathchers ------ */
82
+
83
+ /*
84
+ * This record matches if the index starts with queries[0] and the record
85
+ * matches all of the regexps
86
+ */
87
+ function matchPassBeginning(index, longIndex, queries, regexps) {
88
+ if (index.indexOf(queries[0]) != 0) return false;
89
+ for (var i=1, l = regexps.length; i < l; i++) {
90
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
91
+ return false;
92
+ };
93
+ return true;
94
+ }
95
+
96
+ /*
97
+ * This record matches if the longIndex starts with queries[0] and the
98
+ * longIndex matches all of the regexps
99
+ */
100
+ function matchPassLongIndex(index, longIndex, queries, regexps) {
101
+ if (longIndex.indexOf(queries[0]) != 0) return false;
102
+ for (var i=1, l = regexps.length; i < l; i++) {
103
+ if (!longIndex.match(regexps[i]))
104
+ return false;
105
+ };
106
+ return true;
107
+ }
108
+
109
+ /*
110
+ * This record matches if the index contains queries[0] and the record
111
+ * matches all of the regexps
112
+ */
113
+ function matchPassContains(index, longIndex, queries, regexps) {
114
+ if (index.indexOf(queries[0]) == -1) return false;
115
+ for (var i=1, l = regexps.length; i < l; i++) {
116
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
117
+ return false;
118
+ };
119
+ return true;
120
+ }
121
+
122
+ /*
123
+ * This record matches if regexps[0] matches the index and the record
124
+ * matches all of the regexps
125
+ */
126
+ function matchPassRegexp(index, longIndex, queries, regexps) {
127
+ if (!index.match(regexps[0])) return false;
128
+ for (var i=1, l = regexps.length; i < l; i++) {
129
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
130
+ return false;
131
+ };
132
+ return true;
133
+ }
134
+
135
+
136
+ /* ----- Highlighters ------ */
137
+ function highlightRegexp(info, queries, regexps, highlighters) {
138
+ var result = createResult(info);
139
+ for (var i=0, l = regexps.length; i < l; i++) {
140
+ result.title = result.title.replace(regexps[i], highlighters[i]);
141
+ result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
142
+ };
143
+ return result;
144
+ }
145
+
146
+ function hltSubstring(string, pos, length) {
147
+ return string.substring(0, pos) + '\u0001' + string.substring(pos, pos + length) + '\u0002' + string.substring(pos + length);
148
+ }
149
+
150
+ function highlightQuery(info, queries, regexps, highlighters) {
151
+ var result = createResult(info);
152
+ var pos = 0;
153
+ var lcTitle = result.title.toLowerCase();
154
+
155
+ pos = lcTitle.indexOf(queries[0]);
156
+ if (pos != -1) {
157
+ result.title = hltSubstring(result.title, pos, queries[0].length);
158
+ }
159
+
160
+ result.namespace = result.namespace.replace(regexps[0], highlighters[0]);
161
+ for (var i=1, l = regexps.length; i < l; i++) {
162
+ result.title = result.title.replace(regexps[i], highlighters[i]);
163
+ result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
164
+ };
165
+ return result;
166
+ }
167
+
168
+ function createResult(info) {
169
+ var result = {};
170
+ result.title = info[0];
171
+ result.namespace = info[1];
172
+ result.path = info[2];
173
+ result.params = info[3];
174
+ result.snippet = info[4];
175
+ result.badge = info[6];
176
+ return result;
177
+ }
178
+
179
+ /* ----- Searching ------ */
180
+ function performSearch(data, regexps, queries, highlighters, state) {
181
+ var searchIndex = data.searchIndex;
182
+ var longSearchIndex = data.longSearchIndex;
183
+ var info = data.info;
184
+ var result = [];
185
+ var i = state.from;
186
+ var l = searchIndex.length;
187
+ var togo = CHUNK_SIZE;
188
+ var matchFunc, hltFunc;
189
+
190
+ while (state.pass < 4 && state.limit > 0 && togo > 0) {
191
+ if (state.pass == 0) {
192
+ matchFunc = matchPassBeginning;
193
+ hltFunc = highlightQuery;
194
+ } else if (state.pass == 1) {
195
+ matchFunc = matchPassLongIndex;
196
+ hltFunc = highlightQuery;
197
+ } else if (state.pass == 2) {
198
+ matchFunc = matchPassContains;
199
+ hltFunc = highlightQuery;
200
+ } else if (state.pass == 3) {
201
+ matchFunc = matchPassRegexp;
202
+ hltFunc = highlightRegexp;
203
+ }
204
+
205
+ for (; togo > 0 && i < l && state.limit > 0; i++, togo--) {
206
+ if (info[i].n == state.n) continue;
207
+ if (matchFunc(searchIndex[i], longSearchIndex[i], queries, regexps)) {
208
+ info[i].n = state.n;
209
+ result.push(hltFunc(info[i], queries, regexps, highlighters));
210
+ state.limit--;
211
+ }
212
+ };
213
+ if (searchIndex.length <= i) {
214
+ state.pass++;
215
+ i = state.from = 0;
216
+ } else {
217
+ state.from = i;
218
+ }
219
+ }
220
+ return result;
221
+ }
222
+
223
+ function triggerResults(results, isLast) {
224
+ this.handlers.forEach(function(fn) {
225
+ fn.call(this, results, isLast)
226
+ });
227
+ }
228
+ }
229
+