├── Flavorfile.lock ├── Gemfile ├── plugin └── dasht.vim ├── Gemfile.lock ├── README.md ├── autoload └── dasht.vim └── t └── dasht_test.vim /Flavorfile.lock: -------------------------------------------------------------------------------- 1 | kana/vim-vspec (1.9.0) 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem 'vim-flavor', '~> 4.0' 3 | -------------------------------------------------------------------------------- /plugin/dasht.vim: -------------------------------------------------------------------------------- 1 | command! -nargs=* -complete=tag -bang Dasht call Dasht(, '') 2 | 3 | " Searches for the given pattern in docsets configured for current filetype 4 | " unless the second argument is `!`, in which case it searches all docsets. 5 | function! Dasht(pattern, ...) abort 6 | let filetypes = a:0 == 1 && a:1 == '!' ? [] : split(&filetype, '\.') 7 | call dasht#search(a:pattern, filetypes) 8 | endfunction 9 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | parslet (2.0.0) 5 | pastel (0.8.0) 6 | tty-color (~> 0.5) 7 | thor (1.2.1) 8 | tty-color (0.6.0) 9 | vim-flavor (4.0.2) 10 | parslet (>= 1.8, < 3.0) 11 | pastel (~> 0.7) 12 | thor (>= 0.20, < 2.0) 13 | 14 | PLATFORMS 15 | ruby 16 | 17 | DEPENDENCIES 18 | vim-flavor (~> 4.0) 19 | 20 | BUNDLED WITH 21 | 2.3.25 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dasht.vim 2 | 3 | A (Neo)Vim plugin for [dasht]( https://github.com/sunaku/dasht ) integration: 4 | 5 | * Search docsets for something you type: 6 | 7 | ```vim 8 | " search related docsets 9 | nnoremap k :Dasht 10 | 11 | " search ALL the docsets 12 | nnoremap k :Dasht! 13 | ``` 14 | 15 | * Search docsets for words under cursor: 16 | 17 | ```vim 18 | " search related docsets 19 | nnoremap K :call Dasht(dasht#cursor_search_terms()) 20 | 21 | " search ALL the docsets 22 | nnoremap K :call Dasht(dasht#cursor_search_terms(), '!') 23 | ``` 24 | 25 | * Search docsets for your selected text: 26 | 27 | ```vim 28 | " search related docsets 29 | vnoremap K y:call Dasht(getreg(0)) 30 | 31 | " search ALL the docsets 32 | vnoremap K y:call Dasht(getreg(0), '!') 33 | ``` 34 | 35 | * Specify related docsets for searching: 36 | 37 | ```vim 38 | let g:dasht_filetype_docsets = {} " filetype => list of docset name regexp 39 | 40 | " For example: {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ 41 | 42 | " When in Elixir, also search Erlang: 43 | let g:dasht_filetype_docsets['elixir'] = ['elixir', 'erlang'] 44 | 45 | " When in C++, also search C, Boost, and OpenGL: 46 | let g:dasht_filetype_docsets['cpp'] = ['cpp', '^c$', 'boost', 'OpenGL'] 47 | 48 | " When in Python, also search NumPy, SciPy, and Pandas: 49 | let g:dasht_filetype_docsets['python'] = ['python', '(num|sci)py', 'pandas'] 50 | 51 | " When in HTML, also search CSS, JavaScript, Bootstrap, and jQuery: 52 | let g:dasht_filetype_docsets['html'] = ['html', 'css', 'js', 'bootstrap'] 53 | 54 | " When in Java, search Java SE11, but not JavaScript: 55 | let g:dasht_filetype_docsets['java'] = ['java_se11'] 56 | 57 | " and so on... }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} 58 | ``` 59 | 60 | * Configure where results are displayed: 61 | 62 | ```vim 63 | " create window below current one (default) 64 | let g:dasht_results_window = 'new' 65 | 66 | " create window beside current one 67 | let g:dasht_results_window = 'vnew' 68 | 69 | " use current window to show results 70 | let g:dasht_results_window = 'enew' 71 | 72 | " create panel at left-most edge 73 | let g:dasht_results_window = 'topleft vnew' 74 | 75 | " create panel at right-most edge 76 | let g:dasht_results_window = 'botright vnew' 77 | 78 | " create new tab beside current one 79 | let g:dasht_results_window = 'tabnew' 80 | ``` 81 | 82 | ## Testing 83 | 84 | Developers can run the [vim-vspec]( https://github.com/kana/vim-vspec ) tests: 85 | 86 | ```sh 87 | gem install bundler # first time 88 | bundle install # first time 89 | bundle exec vim-flavor test # every time 90 | ``` 91 | 92 | ## License 93 | 94 | [Spare A Life]: https://sunaku.github.io/vegan-for-life.html 95 | > Like my work? 👍 Please [spare a life] today as thanks! 🐄🐖🐑🐔🐣🐟✨🙊✌ 96 | > Why? For 💕 ethics, the 🌎 environment, and 💪 health; see link above. 🙇 97 | 98 | Copyright 2016 Suraj N. Kurapati 99 | 100 | Distributed under the same terms as Vim itself. 101 | -------------------------------------------------------------------------------- /autoload/dasht.vim: -------------------------------------------------------------------------------- 1 | " Searches for the given pattern (which may be a list) in the given docsets 2 | " (which may be a list or a filetype resolved by `g:dasht_filetype_docsets`). 3 | function! dasht#search(pattern, docsets) abort 4 | let title = type(a:pattern) == type([]) ? a:pattern[0] : a:pattern 5 | call dasht#execute(dasht#command(a:pattern, a:docsets), title) 6 | endfunction 7 | 8 | " Runs the given shell command. If it exits with a nonzero status, waits for 9 | " the user to press any key before clearing the given shell command's output. 10 | " Under NeoVim, the terminal's title is overriden to reflect the given value. 11 | function! dasht#execute(command, title) abort 12 | if has('terminal') 13 | call s:open_dasht_window() 14 | call term_start(['sh', '-c', a:command], { 15 | \ 'curwin': 1, 16 | \ 'term_name': a:title, 17 | \ 'exit_cb': function('s:handle_dasht_exit') 18 | \ }) 19 | elseif has('nvim') 20 | call s:open_dasht_window() 21 | call termopen(a:command, {'on_exit': function('s:handle_dasht_exit')}) 22 | " change tab title; see `:help :file_f` 23 | silent! execute 'file' shellescape(a:title, 1) 24 | startinsert 25 | else 26 | " stty and dd below emulate getch(3) 27 | " as answered by Diego Torres Milano 28 | " http://stackoverflow.com/a/8732057 29 | let command = 'clear ; '. a:command 30 | \ .' || {' 31 | \ .' stty raw -echo ;' 32 | \ .' dd bs=1 count=1 ;' 33 | \ .' stty -raw echo ;' 34 | \ .' } >/dev/null 2>&1' 35 | 36 | " gvim has no terminal emulation, so 37 | " launch an actual terminal emulator 38 | if has('gui') && has('gui_running') 39 | let command = 'xterm' 40 | \ .' -T '. shellescape(a:title) 41 | \ .' -e '. shellescape(command) 42 | \ .' &' 43 | endif 44 | 45 | silent execute '!' command 46 | redraw! 47 | endif 48 | endfunction 49 | 50 | function! s:open_dasht_window() abort 51 | execute get(g:, 'dasht_results_window', 'new') 52 | endfunction 53 | 54 | function! s:handle_dasht_exit(job_id, exit_status, ...) abort 55 | if a:exit_status == 0 56 | bdelete! 57 | elseif has('nvim') 58 | " Vim's :terminal exits insert mode when job is terminated, 59 | " whereas NeoVim's :terminal still remains in insert mode 60 | " and waits for any keypress before auto-closing itself. 61 | " This overrides NeoVim's :terminal to behave like Vim. 62 | call feedkeys("\\", 'n') 63 | endif 64 | endfunction 65 | 66 | " Builds a shell command that searches for the given pattern (which may be a 67 | " list) in the given docsets (which may be a list or the name of a filetype). 68 | function! dasht#command(pattern, docsets) abort 69 | let patterns = dasht#resolve_pattern(a:pattern) 70 | let patterns = empty(patterns) ? [''] : patterns 71 | return dasht#resolve_command(patterns, dasht#resolve_docsets(a:docsets)) 72 | endfunction 73 | 74 | " Resolves the given pattern (which may be a list) into a list of patterns: 75 | " the first one is the original and the second one is a forgiving fallback, 76 | " where all non-word characters are replaced by spaces (wildcards in dasht). 77 | " Duplicate values are removed from this list before it is returned to you. 78 | function! dasht#resolve_pattern(pattern) abort 79 | if type(a:pattern) == type([]) 80 | let result = [] 81 | call map(a:pattern, 'extend(result, dasht#resolve_pattern(v:val))') 82 | return dasht#unique(result) 83 | else 84 | let funcalls = split(a:pattern, '[(,)]\+') 85 | let wildcard = substitute(a:pattern, '\W\+', ' ', 'g') 86 | let patterns = map([a:pattern, wildcard] + funcalls, 87 | \ 'substitute(v:val, "^\\s\\+\\|\\s\\+$", "", "g")') 88 | return dasht#unique(filter(patterns, 'match(v:val, "\\S") != -1')) 89 | endif 90 | endfunction 91 | 92 | " Removes duplicate items, even if they are not adjacent, from the given list. 93 | function! dasht#unique(list) abort 94 | let new = {} 95 | return filter(a:list, 'get(new, v:val, 1) && len(extend(new, {v:val : 0}))') 96 | endfunction 97 | 98 | " Builds a shell command that searches for the given pattern (which may be a 99 | " list) in the given docsets (which may be a list or the name of a filetype). 100 | function! dasht#resolve_command(pattern, docsets) abort 101 | if type(a:pattern) == type([]) 102 | return join(map(a:pattern, 'dasht#resolve_command(v:val, a:docsets)'), ' || ') 103 | else 104 | let arguments = map([a:pattern] + a:docsets, 'shellescape(v:val, 1)') 105 | return join(['dasht'] + arguments, ' ') 106 | endif 107 | endfunction 108 | 109 | " Resolves the given docsets (which may be a list or the name of a filetype, 110 | " which is resolved through lookup in `g:dasht_filetype_docsets` dictionary: 111 | " the first one is original and the rest are from the dictionary definition). 112 | function! dasht#resolve_docsets(docsets) abort 113 | let resolved = [] 114 | let unresolved = type(a:docsets) == v:t_list ? a:docsets : [a:docsets] 115 | call map(unresolved, 'extend(resolved, s:resolve_single_docset(v:val))') 116 | return resolved 117 | endfunction 118 | 119 | function! s:resolve_single_docset(key) abort 120 | return get(get(g:, 'dasht_filetype_docsets', {}), a:key, [a:key]) 121 | endfunction 122 | 123 | let s:function_call_delimiters = '[()[:space:]]\+' 124 | let s:word_boundary_delimiters = '\W\+' 125 | 126 | " Finds search terms in the given haystack of text at the given column number. 127 | function! dasht#find_search_terms(haystack, cursor_column) abort 128 | if a:haystack !~ '\S' 129 | return [] 130 | endif 131 | 132 | let terms = split(a:haystack, s:function_call_delimiters .'\zs') 133 | let [terms_cursor_index, terms_cursor_column] = s:find_cursor_term(terms, a:cursor_column) 134 | if terms_cursor_index < 0 135 | return [] 136 | endif 137 | 138 | " use subword under cursor as the secondary fallback search term 139 | let cursor_term = terms[terms_cursor_index] 140 | let cursor_words = split(cursor_term, s:word_boundary_delimiters .'\zs') 141 | let cursor_term_column = a:cursor_column - terms_cursor_column 142 | let [cursor_words_index, _] = s:find_cursor_term(cursor_words, cursor_term_column) 143 | if cursor_words_index >= 0 144 | let cursor_term_word = cursor_words[cursor_words_index] 145 | let cursor_term_word = substitute(cursor_term_word, s:word_boundary_delimiters, '', 'g') 146 | endif 147 | 148 | " assemble results, adding cursor subword as secondary fallback 149 | let results = reverse(terms[0:terms_cursor_index]) 150 | let results = map(results, 'substitute(v:val, ",", "", "g")') 151 | let results = insert(results, cursor_term_word, 1) 152 | let results = map(results, 'substitute(v:val, s:function_call_delimiters, "", "g")') 153 | let results = uniq(results) " cursor_term_word may be duplicate 154 | 155 | " don't go back further than comma nearest to word under cursor 156 | let results_comma_index = index(results, "") 157 | if results_comma_index > 0 158 | let results = results[0:results_comma_index-1] 159 | endif 160 | 161 | return results 162 | endfunction 163 | 164 | function! s:find_cursor_term(terms, cursor_column) abort 165 | let index = 0 166 | let column = 0 167 | for term in a:terms 168 | let width = len(term) 169 | if column < a:cursor_column && column + width >= a:cursor_column 170 | return [index, column] 171 | endif 172 | let index += 1 173 | let column += width 174 | endfor 175 | return [-1, -1] 176 | endfunction 177 | 178 | " Finds search terms at the cursor position. This is a more intelligent form 179 | " of the expression "[expand(''), expand('')]" because it breaks 180 | " complex s containing multiple function calls (e.g. "foo(bar(baz))") 181 | " into pieces and focuses your search on the piece directly under the cursor. 182 | function! dasht#cursor_search_terms() abort 183 | return dasht#find_search_terms(getline('.'), col('.')) 184 | endfunction 185 | -------------------------------------------------------------------------------- /t/dasht_test.vim: -------------------------------------------------------------------------------- 1 | describe 'dasht#command' 2 | it 'runs dasht with blank argument when no/blank pattern is given' 3 | Expect dasht#command('', []) == "dasht ''" 4 | Expect dasht#command(' ', []) == "dasht ''" 5 | Expect dasht#command([''], []) == "dasht ''" 6 | Expect dasht#command([], []) == "dasht ''" 7 | end 8 | 9 | it 'runs dasht with argument when pattern is given' 10 | Expect dasht#command('foo', []) == "dasht 'foo'" 11 | Expect dasht#command(['foo'], []) == "dasht 'foo'" 12 | end 13 | 14 | it 'joins commands with || when fallback patterns are given' 15 | Expect dasht#command(['foo', 'bar'], []) == "dasht 'foo' || dasht 'bar'" 16 | end 17 | 18 | it 'joins commands with || when pattern expands into forgiving fallback' 19 | Expect dasht#command('foo!', []) == "dasht 'foo\\!' || dasht 'foo'" 20 | Expect dasht#command(['foo!'], []) == "dasht 'foo\\!' || dasht 'foo'" 21 | end 22 | 23 | it 'ignores duplicate patterns and instead only operates on unique ones' 24 | Expect dasht#command(['foo', 'foo'], []) == "dasht 'foo'" 25 | end 26 | end 27 | 28 | describe 'dasht#resolve_command' 29 | it 'blindly maps pattern to commands that run them with dasht' 30 | Expect dasht#resolve_command('', []) == "dasht ''" 31 | Expect dasht#resolve_command(' ', []) == "dasht ' '" 32 | Expect dasht#resolve_command('foo', []) == "dasht 'foo'" 33 | Expect dasht#resolve_command([], []) == '' 34 | Expect dasht#resolve_command([''], []) == "dasht ''" 35 | Expect dasht#resolve_command([' '], []) == "dasht ' '" 36 | Expect dasht#resolve_command(['foo'], []) == "dasht 'foo'" 37 | end 38 | 39 | it 'joins commands with || when fallback patterns are given' 40 | Expect dasht#resolve_command(['foo', 'bar'], []) == "dasht 'foo' || dasht 'bar'" 41 | end 42 | end 43 | 44 | describe 'dasht#resolve_pattern' 45 | it 'filters out blank (only containing whitespace) patterns' 46 | Expect dasht#resolve_pattern('') == [] 47 | Expect dasht#resolve_pattern(' ') == [] 48 | Expect dasht#resolve_pattern("\t") == [] 49 | Expect dasht#resolve_pattern(" \t ") == [] 50 | Expect dasht#resolve_pattern("\t \t") == [] 51 | end 52 | 53 | it 'strips leading and trailing whitespace from patterns' 54 | Expect dasht#resolve_pattern('foo ') == ['foo'] 55 | Expect dasht#resolve_pattern(' foo') == ['foo'] 56 | Expect dasht#resolve_pattern(' foo ') == ['foo'] 57 | Expect dasht#resolve_pattern("foo\t") == ['foo'] 58 | Expect dasht#resolve_pattern("\tfoo") == ['foo'] 59 | Expect dasht#resolve_pattern("\tfoo\t") == ['foo'] 60 | end 61 | 62 | it 'returns original version of pattern when it only contains word-chars' 63 | Expect dasht#resolve_pattern('foo') == ['foo'] 64 | end 65 | 66 | it 'returns forgiving version of pattern when it contains non-word chars' 67 | Expect dasht#resolve_pattern('foo!') == ['foo!', 'foo'] 68 | end 69 | 70 | it 'when given a list as argument, does all of the above for each member' 71 | Expect dasht#resolve_pattern([]) == [] 72 | Expect dasht#resolve_pattern(['']) == [] 73 | Expect dasht#resolve_pattern([' ']) == [] 74 | Expect dasht#resolve_pattern(["\t"]) == [] 75 | Expect dasht#resolve_pattern(['foo']) == ['foo'] 76 | Expect dasht#resolve_pattern(['foo', '']) == ['foo'] 77 | Expect dasht#resolve_pattern(['foo', ' ']) == ['foo'] 78 | Expect dasht#resolve_pattern(['foo', "\t"]) == ['foo'] 79 | Expect dasht#resolve_pattern(['foo!']) == ['foo!', 'foo'] 80 | Expect dasht#resolve_pattern(['foo', 'bar']) == ['foo', 'bar'] 81 | Expect dasht#resolve_pattern(['foo!', 'bar']) == ['foo!', 'foo', 'bar'] 82 | Expect dasht#resolve_pattern(['foo', 'bar!']) == ['foo', 'bar!', 'bar'] 83 | Expect dasht#resolve_pattern(['foo!', 'bar!']) == ['foo!', 'foo', 'bar!', 'bar'] 84 | end 85 | 86 | it 'removes duplicate patterns from the final list of patterns it returns' 87 | Expect dasht#resolve_pattern(['foo', 'foo']) == ['foo'] 88 | Expect dasht#resolve_pattern(['foo', 'foo!']) == ['foo', 'foo!'] 89 | Expect dasht#resolve_pattern(['foo', 'foo!', 'foo']) == ['foo', 'foo!'] 90 | end 91 | 92 | it 'resolves function calls() into separate patterns to be more forgiving' 93 | Expect dasht#resolve_pattern('a()') == ['a()', 'a'] 94 | Expect dasht#resolve_pattern('a()b()') == ['a()b()', 'a b', 'a', 'b'] 95 | Expect dasht#resolve_pattern('a(b())') == ['a(b())', 'a b', 'a', 'b'] 96 | Expect dasht#resolve_pattern('a(b(c))') == ['a(b(c))', 'a b c', 'a', 'b', 'c'] 97 | Expect dasht#resolve_pattern('a(b())c()') == ['a(b())c()', 'a b c', 'a', 'b', 'c'] 98 | Expect dasht#resolve_pattern('a(b(c,d))') == ['a(b(c,d))', 'a b c d', 'a', 'b', 'c', 'd'] 99 | Expect dasht#resolve_pattern('a( b( c, d ) )') == ['a( b( c, d ) )', 'a b c d', 'a', 'b', 'c', 'd'] 100 | end 101 | end 102 | 103 | describe 'dasht#resolve_docsets' 104 | it 'resolves filetype to itself when not found in dictionary' 105 | let g:dasht_filetype_docsets = {} 106 | Expect dasht#resolve_docsets('foo') == ['foo'] 107 | 108 | unlet g:dasht_filetype_docsets 109 | Expect dasht#resolve_docsets('foo') == ['foo'] 110 | end 111 | 112 | it 'resolves filetype to definition in dictionary' 113 | let g:dasht_filetype_docsets = {'foo': []} 114 | Expect dasht#resolve_docsets('foo') == [] 115 | 116 | let g:dasht_filetype_docsets = {'foo': ['bar']} 117 | Expect dasht#resolve_docsets('foo') == ['bar'] 118 | 119 | let g:dasht_filetype_docsets = {'foo': ['bar', 'qux']} 120 | Expect dasht#resolve_docsets('foo') == ['bar', 'qux'] 121 | end 122 | 123 | it 'resolves filetype for multiple docsets if list is given' 124 | Expect dasht#resolve_docsets([]) == [] 125 | 126 | unlet g:dasht_filetype_docsets 127 | Expect dasht#resolve_docsets(['foo']) == ['foo'] 128 | Expect dasht#resolve_docsets(['foo', 'bar']) == ['foo', 'bar'] 129 | 130 | let g:dasht_filetype_docsets = {'foo': ['hoge'], 'bar': ['piyo']} 131 | Expect dasht#resolve_docsets(['foo', 'bar']) == ['hoge', 'piyo'] 132 | end 133 | end 134 | 135 | describe 'dasht#unique' 136 | it 'does nothing when there are no duplicates' 137 | Expect dasht#unique([]) == [] 138 | Expect dasht#unique(['foo']) == ['foo'] 139 | Expect dasht#unique(['foo', 'bar']) == ['foo', 'bar'] 140 | end 141 | 142 | it 'retains first copy of adjacent duplicates' 143 | Expect dasht#unique(['foo', 'foo']) == ['foo'] 144 | Expect dasht#unique(['foo', 'foo', 'bar']) == ['foo', 'bar'] 145 | Expect dasht#unique(['foo', 'bar', 'bar']) == ['foo', 'bar'] 146 | Expect dasht#unique(['qux', 'foo', 'foo', 'bar']) == ['qux', 'foo', 'bar'] 147 | end 148 | 149 | it 'retains first copy of nonadjacent duplicates' 150 | Expect dasht#unique(['foo', 'bar', 'foo']) == ['foo', 'bar'] 151 | Expect dasht#unique(['foo', 'bar', 'bar', 'foo']) == ['foo', 'bar'] 152 | Expect dasht#unique(['foo', 'foo', 'bar', 'foo']) == ['foo', 'bar'] 153 | Expect dasht#unique(['foo', 'foo', 'bar', 'bar', 'foo']) == ['foo', 'bar'] 154 | end 155 | end 156 | 157 | describe 'dasht#find_search_terms' 158 | it 'empty line' 159 | Expect dasht#find_search_terms('', 1) == [] 160 | end 161 | 162 | it 'blank line' 163 | Expect dasht#find_search_terms(' ', 1) == [] 164 | end 165 | 166 | it 'single word' 167 | Expect dasht#find_search_terms('foo', 1) == ['foo'] 168 | end 169 | 170 | it 'single word with surrounding whitespace' 171 | Expect dasht#find_search_terms('foo ', 1) == ['foo'] 172 | Expect dasht#find_search_terms(' foo', 2) == ['foo'] 173 | Expect dasht#find_search_terms(' foo ', 2) == ['foo'] 174 | end 175 | 176 | it 'single word of multiple subwords: cursor on first subword' 177 | Expect dasht#find_search_terms('foo.bar', 1) == ['foo.bar', 'foo'] 178 | end 179 | 180 | it 'single word of multiple subwords: cursor at end of first subword' 181 | Expect dasht#find_search_terms('foo.bar', 4) == ['foo.bar', 'foo'] 182 | end 183 | 184 | it 'single word of multiple subwords: cursor on second subword' 185 | Expect dasht#find_search_terms('foo.bar', 5) == ['foo.bar', 'bar'] 186 | end 187 | 188 | it 'single word of multiple subwords: cursor on second subword' 189 | Expect dasht#find_search_terms('foo.bar.baz', 9) == ['foo.bar.baz', 'baz'] 190 | end 191 | 192 | it 'multiple words: cursor on first word' 193 | Expect dasht#find_search_terms('foo bar', 1) == ['foo'] 194 | Expect dasht#find_search_terms('foo(bar', 1) == ['foo'] 195 | end 196 | 197 | it 'multiple words: cursor at end of first word' 198 | Expect dasht#find_search_terms('foo bar', 4) == ['foo'] 199 | Expect dasht#find_search_terms('foo(bar', 4) == ['foo'] 200 | end 201 | 202 | it 'multiple words: cursor on second word' 203 | Expect dasht#find_search_terms('foo bar', 5) == ['bar', 'foo'] 204 | Expect dasht#find_search_terms('foo(bar', 5) == ['bar', 'foo'] 205 | end 206 | end 207 | 208 | describe 'dasht#cursor_search_terms' 209 | before 210 | call setline('.', 'Outer.outerFun(Inner.innerFun(innerArg, innerArg2), outerArg)') 211 | end 212 | 213 | it 'outer function call' 214 | normal ^t( 215 | Expect dasht#cursor_search_terms() == ['Outer.outerFun', 'outerFun'] 216 | end 217 | 218 | it 'opening parenthesis is considered part of function call' 219 | normal ^f( 220 | Expect dasht#cursor_search_terms() == ['Outer.outerFun', 'outerFun'] 221 | end 222 | 223 | it 'inner function call includes outer function call' 224 | normal ^2t( 225 | Expect dasht#cursor_search_terms() == ['Inner.innerFun', 'innerFun', 'Outer.outerFun'] 226 | end 227 | 228 | it 'inner function call argument includes function calls' 229 | call search('innerArg') 230 | Expect dasht#cursor_search_terms() == ['innerArg', 'Inner.innerFun', 'Outer.outerFun'] 231 | end 232 | 233 | it 'outer function call argument excludes function calls (stops at comma)' 234 | call search('outerArg') 235 | Expect dasht#cursor_search_terms() == ['outerArg'] 236 | end 237 | end 238 | --------------------------------------------------------------------------------