From 294963d925fe96bcacab053ef96e906536b73a16 Mon Sep 17 00:00:00 2001 From: Daniel Trstenjak Date: Thu, 26 Dec 2013 12:21:46 +0100 Subject: [PATCH 1/9] Add hdevtools command 'findsymbol' --- autoload/hdevtools.vim | 30 ++++++++++++++++++++++++++++++ ftplugin/haskell/hdevtools.vim | 4 +++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/autoload/hdevtools.vim b/autoload/hdevtools.vim index ba8ab2b..32d39b6 100644 --- a/autoload/hdevtools.vim +++ b/autoload/hdevtools.vim @@ -120,6 +120,36 @@ function! hdevtools#info(identifier) highlight link HdevtoolsInfoLink Underlined endfunction +function! hdevtools#findsymbol(identifier) + let l:identifier = a:identifier + + " No identifier argument given, probably called from a keyboard shortcut + if l:identifier ==# '' + " Get the identifier under the cursor + let l:identifier = s:extract_identifier(getline("."), col(".")) + endif + + if l:identifier ==# '' + echo '-- No Identifier Under Cursor' + return [] + endif + + let l:cmd = hdevtools#build_command('findsymbol', shellescape(l:identifier)) + let l:output = system(l:cmd) + let l:lines = split(l:output, '\n') + + " Check if the call to hdevtools info succeeded + if v:shell_error != 0 + for l:line in l:lines + call hdevtools#print_error(l:line) + endfor + else + return l:lines + endif + + return [] +endfunction + function! s:extract_identifier(line_text, col) if a:col > len(a:line_text) return '' diff --git a/ftplugin/haskell/hdevtools.vim b/ftplugin/haskell/hdevtools.vim index 1b2f241..fcdd8a1 100644 --- a/ftplugin/haskell/hdevtools.vim +++ b/ftplugin/haskell/hdevtools.vim @@ -32,10 +32,12 @@ nnoremap :call hdevtools#go_file("sp") command! -buffer -nargs=0 HdevtoolsType echo hdevtools#type()[1] command! -buffer -nargs=0 HdevtoolsClear call hdevtools#type_clear() command! -buffer -nargs=? HdevtoolsInfo call hdevtools#info() +command! -buffer -nargs=? HdevtoolsFindsymbol call hdevtools#findsymbol() let b:undo_ftplugin .= join(map([ \ 'HdevtoolsType', \ 'HdevtoolsClear', - \ 'HdevtoolsInfo' + \ 'HdevtoolsInfo', + \ 'HdevtoolsFindsymbol' \ ], '"delcommand " . v:val'), ' | ') let b:undo_ftplugin .= ' | unlet b:did_ftplugin_hdevtools' From a0b53319e55984e8cf9ccd227fab3934f64290d2 Mon Sep 17 00:00:00 2001 From: Daniel Trstenjak Date: Thu, 26 Dec 2013 15:29:15 +0100 Subject: [PATCH 2/9] Make function extract_identifier public available --- autoload/hdevtools.vim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/hdevtools.vim b/autoload/hdevtools.vim index 32d39b6..ffe30be 100644 --- a/autoload/hdevtools.vim +++ b/autoload/hdevtools.vim @@ -61,7 +61,7 @@ function! hdevtools#info(identifier) endif " Get the identifier under the cursor - let l:identifier = s:extract_identifier(getline("."), col(".")) + let l:identifier = hdevtools#extract_identifier(getline("."), col(".")) endif if l:identifier ==# '' @@ -126,7 +126,7 @@ function! hdevtools#findsymbol(identifier) " No identifier argument given, probably called from a keyboard shortcut if l:identifier ==# '' " Get the identifier under the cursor - let l:identifier = s:extract_identifier(getline("."), col(".")) + let l:identifier = hdevtools#extract_identifier(getline("."), col(".")) endif if l:identifier ==# '' @@ -150,7 +150,7 @@ function! hdevtools#findsymbol(identifier) return [] endfunction -function! s:extract_identifier(line_text, col) +function! hdevtools#extract_identifier(line_text, col) if a:col > len(a:line_text) return '' endif @@ -268,7 +268,7 @@ function! hdevtools#test_extract_identifier() let l:start_index = match(l:test, '#') + 1 let l:end_index = match(l:test, '\%>' . l:start_index . 'c#') - 1 for l:i in range(l:start_index, l:end_index) - let l:result = s:extract_identifier(l:input, l:i) + let l:result = hdevtools#extract_identifier(l:input, l:i) if l:expected !=# l:result call hdevtools#print_error("TEST FAILED expected: (" . l:expected . ") got: (" . l:result . ") for column " . l:i . " of: " . l:input) endif From e97860209d8c981527b0a30c0c9c35367503c2d7 Mon Sep 17 00:00:00 2001 From: Daniel Trstenjak Date: Wed, 1 Jan 2014 18:24:44 +0100 Subject: [PATCH 3/9] findsymbol with sourcefile --- autoload/hdevtools.vim | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/autoload/hdevtools.vim b/autoload/hdevtools.vim index ffe30be..bc743de 100644 --- a/autoload/hdevtools.vim +++ b/autoload/hdevtools.vim @@ -134,7 +134,13 @@ function! hdevtools#findsymbol(identifier) return [] endif - let l:cmd = hdevtools#build_command('findsymbol', shellescape(l:identifier)) + let l:file = expand('%') + if l:file ==# '' + call hdevtools#print_warning("current version of hdevtools.vim doesn't support running on an unnamed buffer.") + return + endif + + let l:cmd = hdevtools#build_command('findsymbol', shellescape(l:identifier) . ' ' . shellescape(l:file)) let l:output = system(l:cmd) let l:lines = split(l:output, '\n') From e4b9178f4aefe3e81c4c632d82c1436bc6c167e6 Mon Sep 17 00:00:00 2001 From: Daniel Trstenjak Date: Sat, 4 Jan 2014 13:20:21 +0100 Subject: [PATCH 4/9] Add variable hdevtools_src_dir --- autoload/hdevtools.vim | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/autoload/hdevtools.vim b/autoload/hdevtools.vim index bc743de..77f6c01 100644 --- a/autoload/hdevtools.vim +++ b/autoload/hdevtools.vim @@ -517,6 +517,10 @@ function! hdevtools#build_command(command, args) let l:cmd = l:cmd . ' ' . a:command . ' ' let l:cmd = l:cmd . get(g:, 'hdevtools_options', '') . ' ' + if exists('g:hdevtools_src_dir') + let l:cmd .= ' -g-i' . g:hdevtools_src_dir . ' ' + endif + let l:cmd = l:cmd . a:args return l:cmd endfunction From 11e6346ab7393a3318b76e096dddc97e1f6977f8 Mon Sep 17 00:00:00 2001 From: Daniel Trstenjak Date: Sat, 4 Jan 2014 13:22:06 +0100 Subject: [PATCH 5/9] Give 'findsymbol' the source files which export the desired symbol To be able to extend the import list also by modules of the current project, 'findsymbol' needs to get the source files, where it should search for the desired symbol. A project might contain a lot of source files, so we can't just take every source file, because the loading of each file with GHC might take some time. Currently a quite simple heuristic is used to find the source files, by using 'grep' and having a regex, which should match if the symbol is explicitely exported from the module. Currently the regex matches only export lists of the form: module Blub ( symbol1 , symbol2 ) where --- autoload/hdevtools.vim | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/autoload/hdevtools.vim b/autoload/hdevtools.vim index 77f6c01..d29b5c9 100644 --- a/autoload/hdevtools.vim +++ b/autoload/hdevtools.vim @@ -134,13 +134,33 @@ function! hdevtools#findsymbol(identifier) return [] endif - let l:file = expand('%') - if l:file ==# '' - call hdevtools#print_warning("current version of hdevtools.vim doesn't support running on an unnamed buffer.") - return + let l:escapedIdent = shellescape(l:identifier) + let l:srcFiles = [] + if exists('g:hdevtools_src_dir') + " only consider the source files that contain the identifier in the export list, currently + " only export lists are supported that look something like: + " + " module Blub + " ( identifier1 + " , identifier2 + " ) where + " + let l:regex = "'^ *[(,].*" . l:escapedIdent . ".*$'" + let l:grpcmd = 'grep --exclude=.hdevtools.sock -Rl -e ' . l:regex . ' ' . g:hdevtools_src_dir + let l:grepOutput = system(l:grpcmd) + let l:srcFiles = split(l:grepOutput, '\n') endif - let l:cmd = hdevtools#build_command('findsymbol', shellescape(l:identifier) . ' ' . shellescape(l:file)) + let l:srcParam = '' + let l:curFile = fnamemodify(expand('%'), ':p') + for l:srcFile in l:srcFiles + let l:absSrcFile = fnamemodify(l:srcFile, ':p') + if l:absSrcFile !=# l:curFile + let l:srcParam .= ' ' . shellescape(l:absSrcFile) + endif + endfor + + let l:cmd = hdevtools#build_command('findsymbol', l:escapedIdent . ' ' . l:srcParam) let l:output = system(l:cmd) let l:lines = split(l:output, '\n') From 5f8a979c0bd2b083509d64cbd19ae3a12aba4d6f Mon Sep 17 00:00:00 2001 From: Daniel Trstenjak Date: Sun, 5 Jan 2014 15:13:12 +0100 Subject: [PATCH 6/9] Make source files for 'findsymbol' an explicit argument of the function Remove the mostly application specific part of retrieving the source files for the 'findsymbol' command. --- autoload/hdevtools.vim | 29 ++++------------------------- ftplugin/haskell/hdevtools.vim | 2 +- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/autoload/hdevtools.vim b/autoload/hdevtools.vim index d29b5c9..9b2639d 100644 --- a/autoload/hdevtools.vim +++ b/autoload/hdevtools.vim @@ -120,7 +120,7 @@ function! hdevtools#info(identifier) highlight link HdevtoolsInfoLink Underlined endfunction -function! hdevtools#findsymbol(identifier) +function! hdevtools#findsymbol(identifier, srcFiles) let l:identifier = a:identifier " No identifier argument given, probably called from a keyboard shortcut @@ -134,33 +134,12 @@ function! hdevtools#findsymbol(identifier) return [] endif - let l:escapedIdent = shellescape(l:identifier) - let l:srcFiles = [] - if exists('g:hdevtools_src_dir') - " only consider the source files that contain the identifier in the export list, currently - " only export lists are supported that look something like: - " - " module Blub - " ( identifier1 - " , identifier2 - " ) where - " - let l:regex = "'^ *[(,].*" . l:escapedIdent . ".*$'" - let l:grpcmd = 'grep --exclude=.hdevtools.sock -Rl -e ' . l:regex . ' ' . g:hdevtools_src_dir - let l:grepOutput = system(l:grpcmd) - let l:srcFiles = split(l:grepOutput, '\n') - endif - let l:srcParam = '' - let l:curFile = fnamemodify(expand('%'), ':p') - for l:srcFile in l:srcFiles - let l:absSrcFile = fnamemodify(l:srcFile, ':p') - if l:absSrcFile !=# l:curFile - let l:srcParam .= ' ' . shellescape(l:absSrcFile) - endif + for l:srcFile in a:srcFiles + let l:srcParam .= ' ' . shellescape(l:srcFile) endfor - let l:cmd = hdevtools#build_command('findsymbol', l:escapedIdent . ' ' . l:srcParam) + let l:cmd = hdevtools#build_command('findsymbol', shellescape(l:identifier) . ' ' . l:srcParam) let l:output = system(l:cmd) let l:lines = split(l:output, '\n') diff --git a/ftplugin/haskell/hdevtools.vim b/ftplugin/haskell/hdevtools.vim index fcdd8a1..d1a6bcb 100644 --- a/ftplugin/haskell/hdevtools.vim +++ b/ftplugin/haskell/hdevtools.vim @@ -32,7 +32,7 @@ nnoremap :call hdevtools#go_file("sp") command! -buffer -nargs=0 HdevtoolsType echo hdevtools#type()[1] command! -buffer -nargs=0 HdevtoolsClear call hdevtools#type_clear() command! -buffer -nargs=? HdevtoolsInfo call hdevtools#info() -command! -buffer -nargs=? HdevtoolsFindsymbol call hdevtools#findsymbol() +command! -buffer -nargs=1 HdevtoolsFindsymbol call hdevtools#findsymbol(, []) let b:undo_ftplugin .= join(map([ \ 'HdevtoolsType', From 4d2acd37d4c3a507486aaeece1c3a40d85d8b394 Mon Sep 17 00:00:00 2001 From: Daniel Trstenjak Date: Tue, 7 Jan 2014 18:28:07 +0100 Subject: [PATCH 7/9] Support hdevtools options per buffer This makes it possible to have multiple haskell projects loaded inside one vim instance and a working hdevtools for each project. --- autoload/hdevtools.vim | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/autoload/hdevtools.vim b/autoload/hdevtools.vim index 9b2639d..96095cd 100644 --- a/autoload/hdevtools.vim +++ b/autoload/hdevtools.vim @@ -512,15 +512,16 @@ function! s:on_leave() endfunction function! hdevtools#build_command(command, args) - let l:cmd = 'hdevtools' - let l:cmd = l:cmd . ' ' . a:command . ' ' + let l:cmd = 'hdevtools' + let l:cmd .= ' ' . a:command + let l:cmd .= ' ' . hdevtools#options() - let l:cmd = l:cmd . get(g:, 'hdevtools_options', '') . ' ' - if exists('g:hdevtools_src_dir') - let l:cmd .= ' -g-i' . g:hdevtools_src_dir . ' ' + let l:srcDir = hdevtools#src_dir() + if l:srcDir !=# '' + let l:cmd .= ' -g-i' . l:srcDir endif - let l:cmd = l:cmd . a:args + let l:cmd .= ' ' . a:args return l:cmd endfunction @@ -597,6 +598,24 @@ function! hdevtools#type() return l:ret endfunction +function! hdevtools#options() + return s:get_buffer_or_global_var('hdevtools_options', '') +endfunction + +function! hdevtools#src_dir() + return s:get_buffer_or_global_var('hdevtools_src_dir', '') +endfunction + +function! s:get_buffer_or_global_var(varName, defaultValue) + let l:var = a:defaultValue + if exists('b:' . a:varName) + let l:var = get(b:, a:varName, '') + elseif exists('g:' . a:varName) + let l:var = get(g:, a:varName, '') + endif + return l:var +endfunction + function! hdevtools#type_clear() if exists('b:hdevtools_type') call hdevtools#clear_highlight() From 633080be14088df59f1b36504009c2025cc0c12a Mon Sep 17 00:00:00 2001 From: Daniel Trstenjak Date: Thu, 6 Mar 2014 21:21:03 +0100 Subject: [PATCH 8/9] Revert "Support hdevtools options per buffer" This reverts commit 4d2acd37d4c3a507486aaeece1c3a40d85d8b394. Buffer local options don't harmonize very well with other vim plugins like syntastic, which looks only after the global options. --- autoload/hdevtools.vim | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/autoload/hdevtools.vim b/autoload/hdevtools.vim index 96095cd..9b2639d 100644 --- a/autoload/hdevtools.vim +++ b/autoload/hdevtools.vim @@ -512,16 +512,15 @@ function! s:on_leave() endfunction function! hdevtools#build_command(command, args) - let l:cmd = 'hdevtools' - let l:cmd .= ' ' . a:command - let l:cmd .= ' ' . hdevtools#options() + let l:cmd = 'hdevtools' + let l:cmd = l:cmd . ' ' . a:command . ' ' - let l:srcDir = hdevtools#src_dir() - if l:srcDir !=# '' - let l:cmd .= ' -g-i' . l:srcDir + let l:cmd = l:cmd . get(g:, 'hdevtools_options', '') . ' ' + if exists('g:hdevtools_src_dir') + let l:cmd .= ' -g-i' . g:hdevtools_src_dir . ' ' endif - let l:cmd .= ' ' . a:args + let l:cmd = l:cmd . a:args return l:cmd endfunction @@ -598,24 +597,6 @@ function! hdevtools#type() return l:ret endfunction -function! hdevtools#options() - return s:get_buffer_or_global_var('hdevtools_options', '') -endfunction - -function! hdevtools#src_dir() - return s:get_buffer_or_global_var('hdevtools_src_dir', '') -endfunction - -function! s:get_buffer_or_global_var(varName, defaultValue) - let l:var = a:defaultValue - if exists('b:' . a:varName) - let l:var = get(b:, a:varName, '') - elseif exists('g:' . a:varName) - let l:var = get(g:, a:varName, '') - endif - return l:var -endfunction - function! hdevtools#type_clear() if exists('b:hdevtools_type') call hdevtools#clear_highlight() From cdf2ce1a5d36c4a6eb01d841416a122f44baed4c Mon Sep 17 00:00:00 2001 From: Daniel Trstenjak Date: Thu, 6 Mar 2014 21:26:21 +0100 Subject: [PATCH 9/9] Revert "Add variable hdevtools_src_dir" This reverts commit e4b9178f4aefe3e81c4c632d82c1436bc6c167e6. vim plugins like Syntastic don't use the hdevtools vim functions, they just call the hdevtools binary and use the g:hdevtools_options variable, so the separate option g:hdevtools_src_dir isn't considered. So it's better to add the source dir to the g:hdevtools_options, that it's also considered by Syntastic. --- autoload/hdevtools.vim | 4 ---- 1 file changed, 4 deletions(-) diff --git a/autoload/hdevtools.vim b/autoload/hdevtools.vim index 9b2639d..fe04f56 100644 --- a/autoload/hdevtools.vim +++ b/autoload/hdevtools.vim @@ -516,10 +516,6 @@ function! hdevtools#build_command(command, args) let l:cmd = l:cmd . ' ' . a:command . ' ' let l:cmd = l:cmd . get(g:, 'hdevtools_options', '') . ' ' - if exists('g:hdevtools_src_dir') - let l:cmd .= ' -g-i' . g:hdevtools_src_dir . ' ' - endif - let l:cmd = l:cmd . a:args return l:cmd endfunction