From abf9a0da38ef77e7314f3079b6389baeaaeec14e Mon Sep 17 00:00:00 2001 From: IdanArye Date: Thu, 22 Nov 2012 12:53:53 +0200 Subject: [PATCH 1/6] Working --- editors/vim/README.md | 10 ++- editors/vim/autoload/dcomplete.vim | 103 +++++++++++++++++++++++++++++ editors/vim/ftplugin/d.vim | 1 + 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 editors/vim/autoload/dcomplete.vim create mode 100644 editors/vim/ftplugin/d.vim diff --git a/editors/vim/README.md b/editors/vim/README.md index 9c0c5da..3bfd251 100644 --- a/editors/vim/README.md +++ b/editors/vim/README.md @@ -1 +1,9 @@ -Nothing here yet. If you know vim, consider writing a module and creating a pull request. +A plugin for using dscanner with vim. + +Installation and Configuration +============================== +Put the autoload and ftplugin folders in your vim runtime path. + +Compile dscanner and put it in your path, or set the global variable g:dscanner\_path to where you put dscanner. + +If you need to use an include path, use the global variable g:dscanner\_includePath. diff --git a/editors/vim/autoload/dcomplete.vim b/editors/vim/autoload/dcomplete.vim new file mode 100644 index 0000000..7ee2812 --- /dev/null +++ b/editors/vim/autoload/dcomplete.vim @@ -0,0 +1,103 @@ +"The completion function +function! dcomplete#Complete(findstart,base) + if a:findstart + let prePos=searchpos('\W',"bn") + let preChar=getline(prePos[0])[prePos[1]-1] + if '.'==preChar + "Save the data for use in the dscanner call. + let b:dscanner_lastPos=prePos + let b:dscanner_type='.' + return prePos[1] + endif + "If we can't find a dot, we look for a paren. + let prePos=searchpos("(","bn",line('.')) + if prePos[0] + if getline('.')[prePos[1]:col('.')-2]=~'^\s*\w*$' + let b:dscanner_lastPos=prePos + let b:dscanner_type='(' + return prePos[1] + endif + endif + "If we can't find either, dscanner can't help us. + return -2 + else + "Run dscanner according to the preChar. + if b:dscanner_type=='.' + let scanResult=s:runDScanner('dotComplete') + else + let scanResult=s:runDScanner('parenComplete') + endif + "Split the result text to lines. + let resultLines=split(scanResult,"\n") + "If the last line is --------------, we have an error. + if resultLines[-1]=~'-\+' + return resultLines[-1] + end + + "Identify the type of result received + let b:dscanner_resultType=resultLines[0] + "Parse the result accoring to their type + if b:dscanner_resultType=='dotComplete' + return s:parsePairs(a:base,resultLines,'','') + elseif b:dscanner_resultType=='completions' + return s:parsePairs(a:base,resultLines,'',')') + elseif b:dscanner_resultType=='calltips' + return s:parseCalltips(a:base,resultLines) + endif + endif +endfunction + +"Run dscanner +function! s:runDScanner(scanCommand) + if exists('g:dscanner_path') + let l:dscannerCommand=g:dscanner_path + else + let l:dscannerCommand='dscanner' + endif + + if exists('g:dscanner_includePath') + let l:dscannerCommand=l:dscannerCommand.' -I'.g:dscanner_includePath + endif + + + let l:tmpFileName=tempname() + exec "write ".l:tmpFileName + let scanResult=system(l:dscannerCommand.' --'.a:scanCommand.' '.(line2byte('.')+col('.')-2).' <'.l:tmpFileName) + call delete(l:tmpFileName) + return scanResult +endfunction + +"Parse simple pair results +function! s:parsePairs(base,resultLines,addBefore,addAfter) + let result=[] + for resultLine in a:resultLines[1:] + if len(resultLine) + let lineParts=split(resultLine) + if lineParts[0]=~'^'.a:base + call add(result,{'word':a:addBefore.lineParts[0].a:addAfter,'kind':lineParts[1]}) + endif + end + endfor + return result +endfunction + +"Parse function calltips results +function! s:parseCalltips(base,resultLines) + let result=[a:base] + for resultLine in a:resultLines[1:] + if len(resultLine) + let funcArgs=[] + for funcArg in split(resultLine[match(resultLine,'(')+1:-2],',\\n\\t') + let argParts=split(funcArg) + if 1 Date: Thu, 22 Nov 2012 13:09:52 +0200 Subject: [PATCH 2/6] Wrote that it was testes on Linux. I'll test in on Windows when I get the chance. --- editors/vim/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/editors/vim/README.md b/editors/vim/README.md index 3bfd251..2a99c78 100644 --- a/editors/vim/README.md +++ b/editors/vim/README.md @@ -1,5 +1,7 @@ A plugin for using dscanner with vim. +Tested on Linux + Installation and Configuration ============================== Put the autoload and ftplugin folders in your vim runtime path. From 8475dc5dfd968034345487a51a5e4139b616004a Mon Sep 17 00:00:00 2001 From: IdanArye Date: Sun, 25 Nov 2012 17:15:01 +0200 Subject: [PATCH 3/6] Fixed a bug in s:parsePairs. Somtimes Dscanner writes extra data before the results, so we only show lines with a word, than space, than a single character. --- editors/vim/autoload/dcomplete.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editors/vim/autoload/dcomplete.vim b/editors/vim/autoload/dcomplete.vim index 7ee2812..3d99797 100644 --- a/editors/vim/autoload/dcomplete.vim +++ b/editors/vim/autoload/dcomplete.vim @@ -46,7 +46,7 @@ function! dcomplete#Complete(findstart,base) endif endif endfunction - +echo "hi" "Run dscanner function! s:runDScanner(scanCommand) if exists('g:dscanner_path') @@ -73,7 +73,7 @@ function! s:parsePairs(base,resultLines,addBefore,addAfter) for resultLine in a:resultLines[1:] if len(resultLine) let lineParts=split(resultLine) - if lineParts[0]=~'^'.a:base + if lineParts[0]=~'^'.a:base && 2==len(lineParts) && 1==len(lineParts[1]) call add(result,{'word':a:addBefore.lineParts[0].a:addAfter,'kind':lineParts[1]}) endif end From 0a0b7ff36e0bddf526a8b62db286fc13a2564589 Mon Sep 17 00:00:00 2001 From: IdanArye Date: Wed, 5 Dec 2012 01:17:31 +0200 Subject: [PATCH 4/6] Added some filtering to the dscanner results. --- editors/vim/autoload/dcomplete.vim | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/editors/vim/autoload/dcomplete.vim b/editors/vim/autoload/dcomplete.vim index 3d99797..82a29f3 100644 --- a/editors/vim/autoload/dcomplete.vim +++ b/editors/vim/autoload/dcomplete.vim @@ -34,19 +34,22 @@ function! dcomplete#Complete(findstart,base) return resultLines[-1] end - "Identify the type of result received - let b:dscanner_resultType=resultLines[0] - "Parse the result accoring to their type - if b:dscanner_resultType=='dotComplete' - return s:parsePairs(a:base,resultLines,'','') - elseif b:dscanner_resultType=='completions' - return s:parsePairs(a:base,resultLines,'',')') - elseif b:dscanner_resultType=='calltips' - return s:parseCalltips(a:base,resultLines) - endif + "Find the begining of the results. + while len(resultLines) + "Identify the type of result received + let b:dscanner_resultType=resultLines[0] + "Parse the result accoring to their type + if b:dscanner_resultType=='dotComplete' + return s:parsePairs(a:base,resultLines,'','') + elseif b:dscanner_resultType=='completions' + return s:parsePairs(a:base,resultLines,'',')') + elseif b:dscanner_resultType=='calltips' + return s:parseCalltips(a:base,resultLines) + endif + let resultLines=resultLines[1:] + endwhile endif endfunction -echo "hi" "Run dscanner function! s:runDScanner(scanCommand) if exists('g:dscanner_path') @@ -85,7 +88,7 @@ endfunction function! s:parseCalltips(base,resultLines) let result=[a:base] for resultLine in a:resultLines[1:] - if len(resultLine) + if 0<=match(resultLine,".*(.*)") let funcArgs=[] for funcArg in split(resultLine[match(resultLine,'(')+1:-2],',\\n\\t') let argParts=split(funcArg) From 15140e21c2721775bd3c6213c017ea7d2dcf7e9d Mon Sep 17 00:00:00 2001 From: IdanA Date: Sun, 9 Dec 2012 16:14:27 +0200 Subject: [PATCH 5/6] Fixed things for windows. --- editors/vim/README.md | 17 +++++++++++++++-- editors/vim/autoload/dcomplete.vim | 6 ++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/editors/vim/README.md b/editors/vim/README.md index 2a99c78..c7e1294 100644 --- a/editors/vim/README.md +++ b/editors/vim/README.md @@ -1,6 +1,6 @@ A plugin for using dscanner with vim. -Tested on Linux +Tested on Linux and Windows(see comment for windows) Installation and Configuration ============================== @@ -8,4 +8,17 @@ Put the autoload and ftplugin folders in your vim runtime path. Compile dscanner and put it in your path, or set the global variable g:dscanner\_path to where you put dscanner. -If you need to use an include path, use the global variable g:dscanner\_includePath. +If you need to use an include path, use the global variable g:dscanner\_includePath as a list of those paths. + +Using on Windows +================ +Under Linux, Dscanner can /etc/dmd.conf to get the default include paths. I've found no such file in the Windows distribution of dmd(it's probably in the registry), so you need to configure it manually. You need to \src\phobos and \src\druntime\import folders from where you installed dmd. For example, +``` +let g:dscanner_includePath=['C:\Program Files\dmd2\src\phobos','C:\Program Files\dmd2\src\druntime\import'] +``` + +Also, the Dscanner has a problem reading files in windows format, so use +``` +set fileformat=unix +``` +to make you files use unix format. diff --git a/editors/vim/autoload/dcomplete.vim b/editors/vim/autoload/dcomplete.vim index 82a29f3..5cd7bf5 100644 --- a/editors/vim/autoload/dcomplete.vim +++ b/editors/vim/autoload/dcomplete.vim @@ -59,13 +59,15 @@ function! s:runDScanner(scanCommand) endif if exists('g:dscanner_includePath') - let l:dscannerCommand=l:dscannerCommand.' -I'.g:dscanner_includePath + for l:includePath in g:dscanner_includePath + let l:dscannerCommand=l:dscannerCommand.' '.shellescape('-I'.l:includePath) + endfor endif let l:tmpFileName=tempname() exec "write ".l:tmpFileName - let scanResult=system(l:dscannerCommand.' --'.a:scanCommand.' '.(line2byte('.')+col('.')-2).' <'.l:tmpFileName) + let scanResult=system(l:dscannerCommand.' --'.a:scanCommand.' '.(line2byte('.')+col('.')-2).' <'.shellescape(l:tmpFileName)) call delete(l:tmpFileName) return scanResult endfunction From 23c1924dc6ae3f61a86d7136e1757eaf8cbff191 Mon Sep 17 00:00:00 2001 From: IdanA Date: Wed, 12 Dec 2012 17:03:39 +0200 Subject: [PATCH 6/6] Fixes for Windows: I'm now creating the temp file in Unix format. The problem was calculating the byte position in Windows format - and while it might be possible, it's much simpler to use Unix format for the temp file. Also updated the readme. --- editors/vim/README.md | 8 +------- editors/vim/autoload/dcomplete.vim | 7 ++++++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/editors/vim/README.md b/editors/vim/README.md index c7e1294..69e831e 100644 --- a/editors/vim/README.md +++ b/editors/vim/README.md @@ -12,13 +12,7 @@ If you need to use an include path, use the global variable g:dscanner\_includeP Using on Windows ================ -Under Linux, Dscanner can /etc/dmd.conf to get the default include paths. I've found no such file in the Windows distribution of dmd(it's probably in the registry), so you need to configure it manually. You need to \src\phobos and \src\druntime\import folders from where you installed dmd. For example, +Under Linux, Dscanner reads /etc/dmd.conf to get the default include paths. The equivalent file in Windows - 'sc.ini' - does not have a fixed location, so you need to configure the import paths manually. You need the \src\phobos and \src\druntime\import folders from where you installed dmd. For example, ``` let g:dscanner_includePath=['C:\Program Files\dmd2\src\phobos','C:\Program Files\dmd2\src\druntime\import'] ``` - -Also, the Dscanner has a problem reading files in windows format, so use -``` -set fileformat=unix -``` -to make you files use unix format. diff --git a/editors/vim/autoload/dcomplete.vim b/editors/vim/autoload/dcomplete.vim index 5cd7bf5..7dfa70c 100644 --- a/editors/vim/autoload/dcomplete.vim +++ b/editors/vim/autoload/dcomplete.vim @@ -66,8 +66,13 @@ function! s:runDScanner(scanCommand) let l:tmpFileName=tempname() + "Save the temp file in unix format for better reading of byte position. + let l:oldFileFormat=&fileformat + set fileformat=unix + let l:bytePosition=line2byte('.')+col('.')-2 exec "write ".l:tmpFileName - let scanResult=system(l:dscannerCommand.' --'.a:scanCommand.' '.(line2byte('.')+col('.')-2).' <'.shellescape(l:tmpFileName)) + let &fileformat=l:oldFileFormat + let scanResult=system(l:dscannerCommand.' --'.a:scanCommand.' '.l:bytePosition.' <'.shellescape(l:tmpFileName)) call delete(l:tmpFileName) return scanResult endfunction