From 7fc2737ce36039d57ee8f370c3358d99a1bb1bef Mon Sep 17 00:00:00 2001 From: IdanArye Date: Wed, 28 Aug 2013 22:47:21 +0300 Subject: [PATCH 1/5] Vim plugin completed and tested on Linux --- editors/vim/README.md | 25 ++++++- editors/vim/autoload/dcomplete.vim | 111 +++++++++++++++++++++++++++++ editors/vim/ftplugin/d.vim | 6 ++ 3 files changed, 141 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 106acc3..315fe16 100644 --- a/editors/vim/README.md +++ b/editors/vim/README.md @@ -1 +1,24 @@ -#VIM Integration +A plugin for using DCD with vim. + +Tested on Linux + +Installation and Configuration +============================== +Put the autoload and ftplugin folders in your vim runtime path. + +Compile DCD and put both dcd-client and dcd-server in your path, or set the +global variable `g:dcd\_path` to where you put DCD. + +Usage +=================== +When the filetype is D, use the `DCDstartServer` command to start the server +and the `DCDstopServer` command to stop the server. + +Use the `DCDaddPath` command to add an import path to the server. Make sure you +escape spaces! + +Use the `DCD` command to send arbitary commands to the server via the client. +The syntax is the same as with `dcd-client`, so you can use it without +arguments to print the help message. + +When the server is running, use `CTRL`+`x` `CTRL`+`o` to use DCD completion. diff --git a/editors/vim/autoload/dcomplete.vim b/editors/vim/autoload/dcomplete.vim new file mode 100644 index 0000000..f8f5307 --- /dev/null +++ b/editors/vim/autoload/dcomplete.vim @@ -0,0 +1,111 @@ +"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 + let b:completionColumn=prePos[1]+1 + return prePos[1] + endif + "If we can't find a dot, we look for a paren. + let parenPos=searchpos("(","bn",line('.')) + if parenPos[0] + if getline('.')[parenPos[1]:col('.')-2]=~'^\s*\w*$' + let b:completionColumn=parenPos[1]+1 + return parenPos[1] + endif + endif + "If we can't find either, look for the beginning of the word + if line('.')==prePos[0] && getline(prePos[0])[prePos[1]]=~'\w' + return prePos[1] + endif + "If we can't find any of the above, DCD can't help us. + return -2 + else + "Run DCD + let scanResult=s:runDCDToGetAutocompletion() + "Split the result text to lines. + let resultLines=split(scanResult,"\n") + + "if we have less than one line - something wen wrong + if empty(resultLines) + return 'bad...' + endif + "identify completion type via the first line. + if resultLines[0]=='identifiers' + return s:parsePairs(a:base,resultLines[1:],'','') + elseif resultLines[0]=='calltips' + return s:parseCalltips(a:base,resultLines[1:]) + endif + return [] + endif +endfunction + +"Get the DCD server command path +function! dcomplete#DCDserver() + if exists('g:dcd_path') + return shellescape(g:dcd_path).(has('win32') ? '\' : '/').'dcd-server' + else + return 'dcd-server' + end +endfunction + +"Get the DCD client command path +function! dcomplete#DCDclient() + if exists('g:dcd_path') + return shellescape(g:dcd_path).(has('win32') ? '\' : '/').'dcd-client' + else + return 'dcd-client' + end +endfunction + +"Run DCD to get autocompletion results +function! s:runDCDToGetAutocompletion() + + 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('.')+b:completionColumn-2 + exec "write ".l:tmpFileName + let &fileformat=l:oldFileFormat + let scanResult=system(dcomplete#DCDclient().' --cursorPos '.l:bytePosition.' <'.shellescape(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 + if len(resultLine) + let lineParts=split(resultLine) + 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 + endfor + return result +endfunction + +"Parse function calltips results +function! s:parseCalltips(base,resultLines) + let result=[a:base] + for resultLine in a:resultLines + if 0<=match(resultLine,".*(.*)") + let funcArgs=[] + for funcArg in split(resultLine[match(resultLine,'(')+1:-2],', ') + let argParts=split(funcArg) + if 1 /dev/null &' +command! -buffer -nargs=? DCD execute '!'.dcomplete#DCDclient().' '. +command! -buffer DCDstopServer DCD --shutdown +command! -buffer -nargs=1 -complete=dir DCDaddPath DCD -I From 3dca325f6ea48e8213c9ab7c504960fbf782d94a Mon Sep 17 00:00:00 2001 From: IdanArye Date: Thu, 29 Aug 2013 21:03:25 +0300 Subject: [PATCH 2/5] Vim plugin working on Windows and Linux, and support default import paths. --- editors/vim/README.md | 16 ++++++++++++++-- editors/vim/autoload/dcomplete.vim | 23 +++++++++++++++++++++-- editors/vim/ftplugin/d.vim | 8 ++++++-- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/editors/vim/README.md b/editors/vim/README.md index 315fe16..49b9be1 100644 --- a/editors/vim/README.md +++ b/editors/vim/README.md @@ -1,6 +1,6 @@ A plugin for using DCD with vim. -Tested on Linux +Tested on Linux(and a bit on Windows) Installation and Configuration ============================== @@ -9,13 +9,25 @@ Put the autoload and ftplugin folders in your vim runtime path. Compile DCD and put both dcd-client and dcd-server in your path, or set the global variable `g:dcd\_path` to where you put DCD. +You can set `g:dcd\_importPath` to an import path(or list of import paths) to +use when starting the server. You should do so for Phobos and DRuntime - since +DCD does not add them for you. On Linux it should be: + +```vim +let g:dcd_importPath=['/usr/include/d','/usr/include/d/druntime/import'] +``` + +On windows you need to look for the path in dmd's installation. + +Import paths are globbed with Vim's globbing function. + Usage =================== When the filetype is D, use the `DCDstartServer` command to start the server and the `DCDstopServer` command to stop the server. Use the `DCDaddPath` command to add an import path to the server. Make sure you -escape spaces! +escape spaces! Import paths are globbed with Vim's globbing function. Use the `DCD` command to send arbitary commands to the server via the client. The syntax is the same as with `dcd-client`, so you can use it without diff --git a/editors/vim/autoload/dcomplete.vim b/editors/vim/autoload/dcomplete.vim index f8f5307..1cabb34 100644 --- a/editors/vim/autoload/dcomplete.vim +++ b/editors/vim/autoload/dcomplete.vim @@ -44,7 +44,7 @@ endfunction "Get the DCD server command path function! dcomplete#DCDserver() if exists('g:dcd_path') - return shellescape(g:dcd_path).(has('win32') ? '\' : '/').'dcd-server' + return shellescape(g:dcd_path.(has('win32') ? '\' : '/').'dcd-server') else return 'dcd-server' end @@ -53,12 +53,31 @@ endfunction "Get the DCD client command path function! dcomplete#DCDclient() if exists('g:dcd_path') - return shellescape(g:dcd_path).(has('win32') ? '\' : '/').'dcd-client' + return shellescape(g:dcd_path.(has('win32') ? '\' : '/').'dcd-client') else return 'dcd-client' end endfunction +"Use Vim's globbing on a path pattern or a list of patterns and translate them +"to DCD's syntax. +function! dcomplete#globImportPath(pattern) + if(type(a:pattern)==type([])) + return join(map(a:pattern,'dcomplete#globImportPath(v:val)'),' ') + else + return join(map(glob(a:pattern,0,1),'"-I".shellescape(v:val)'),' ') + endif +endfunction + +"Get the default import path when starting a server and translate them to +"DCD's syntax. +function! dcomplete#initImportPath() + if exists('g:dcd_importPath') + return dcomplete#globImportPath(g:dcd_importPath) + endif + return '' +endfunction + "Run DCD to get autocompletion results function! s:runDCDToGetAutocompletion() diff --git a/editors/vim/ftplugin/d.vim b/editors/vim/ftplugin/d.vim index 830245a..176c9c6 100644 --- a/editors/vim/ftplugin/d.vim +++ b/editors/vim/ftplugin/d.vim @@ -1,6 +1,10 @@ setlocal omnifunc=dcomplete#Complete -command! -buffer DCDstartServer execute '!'.dcomplete#DCDserver().' > /dev/null &' +if has('win32') + command! -buffer DCDstartServer execute '!start '.dcomplete#DCDserver().' '.dcomplete#initImportPath() +else + command! -buffer DCDstartServer execute '!'.dcomplete#DCDserver().' '.dcomplete#initImportPath().' > /dev/null &' +endif command! -buffer -nargs=? DCD execute '!'.dcomplete#DCDclient().' '. command! -buffer DCDstopServer DCD --shutdown -command! -buffer -nargs=1 -complete=dir DCDaddPath DCD -I +command! -buffer -nargs=+ -complete=dir DCDaddPath execute 'DCD '.dcomplete#globImportPath([]) From 066c1d60589ea116be697657435d5596c09471e8 Mon Sep 17 00:00:00 2001 From: IdanArye Date: Fri, 30 Aug 2013 03:46:55 +0300 Subject: [PATCH 3/5] Added a Vim plugin option to add import paths as arguments to DCDstartServer --- editors/vim/README.md | 8 +++++--- editors/vim/autoload/dcomplete.vim | 5 +++-- editors/vim/ftplugin/d.vim | 6 ++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/editors/vim/README.md b/editors/vim/README.md index 49b9be1..2788f24 100644 --- a/editors/vim/README.md +++ b/editors/vim/README.md @@ -24,13 +24,15 @@ Import paths are globbed with Vim's globbing function. Usage =================== When the filetype is D, use the `DCDstartServer` command to start the server -and the `DCDstopServer` command to stop the server. +and the `DCDstopServer` command to stop the server. `DCDstartServer` can +receive import path(s) as arguments. -Use the `DCDaddPath` command to add an import path to the server. Make sure you +Use the `DCDaddPath` command to add a import path(s) to the server. Make sure you escape spaces! Import paths are globbed with Vim's globbing function. Use the `DCD` command to send arbitary commands to the server via the client. The syntax is the same as with `dcd-client`, so you can use it without arguments to print the help message. -When the server is running, use `CTRL`+`x` `CTRL`+`o` to use DCD completion. +When the server is running, use `CTRL`+`x` `CTRL`+`o` in a D buffer to use DCD +completion. diff --git a/editors/vim/autoload/dcomplete.vim b/editors/vim/autoload/dcomplete.vim index 1cabb34..6e13d6f 100644 --- a/editors/vim/autoload/dcomplete.vim +++ b/editors/vim/autoload/dcomplete.vim @@ -73,9 +73,10 @@ endfunction "DCD's syntax. function! dcomplete#initImportPath() if exists('g:dcd_importPath') - return dcomplete#globImportPath(g:dcd_importPath) + return dcomplete#globImportPath(copy(g:dcd_importPath)) + else + return '' endif - return '' endfunction "Run DCD to get autocompletion results diff --git a/editors/vim/ftplugin/d.vim b/editors/vim/ftplugin/d.vim index 176c9c6..d87b45e 100644 --- a/editors/vim/ftplugin/d.vim +++ b/editors/vim/ftplugin/d.vim @@ -1,9 +1,11 @@ setlocal omnifunc=dcomplete#Complete if has('win32') - command! -buffer DCDstartServer execute '!start '.dcomplete#DCDserver().' '.dcomplete#initImportPath() + command! -buffer -nargs=* -complete=dir DCDstartServer execute '!start '.dcomplete#DCDserver().' '.dcomplete#initImportPath(). + \ ' '.dcomplete#globImportPath([]) else - command! -buffer DCDstartServer execute '!'.dcomplete#DCDserver().' '.dcomplete#initImportPath().' > /dev/null &' + command! -buffer -nargs=* -complete=dir DCDstartServer execute '!'.dcomplete#DCDserver().' '.dcomplete#initImportPath(). + \ ' '.dcomplete#globImportPath([]).' > /dev/null &' endif command! -buffer -nargs=? DCD execute '!'.dcomplete#DCDclient().' '. command! -buffer DCDstopServer DCD --shutdown From 94e43ada352e9d92ca63a853cf1d0845f6cb4865 Mon Sep 17 00:00:00 2001 From: IdanArye Date: Fri, 30 Aug 2013 03:50:48 +0300 Subject: [PATCH 4/5] Added the clearCache command --- editors/vim/README.md | 2 ++ editors/vim/ftplugin/d.vim | 1 + 2 files changed, 3 insertions(+) diff --git a/editors/vim/README.md b/editors/vim/README.md index 2788f24..344f645 100644 --- a/editors/vim/README.md +++ b/editors/vim/README.md @@ -34,5 +34,7 @@ Use the `DCD` command to send arbitary commands to the server via the client. The syntax is the same as with `dcd-client`, so you can use it without arguments to print the help message. +Use `DCDclearCache` to clear the DCD server cache. + When the server is running, use `CTRL`+`x` `CTRL`+`o` in a D buffer to use DCD completion. diff --git a/editors/vim/ftplugin/d.vim b/editors/vim/ftplugin/d.vim index d87b45e..ba5bc2e 100644 --- a/editors/vim/ftplugin/d.vim +++ b/editors/vim/ftplugin/d.vim @@ -10,3 +10,4 @@ endif command! -buffer -nargs=? DCD execute '!'.dcomplete#DCDclient().' '. command! -buffer DCDstopServer DCD --shutdown command! -buffer -nargs=+ -complete=dir DCDaddPath execute 'DCD '.dcomplete#globImportPath([]) +command! -buffer DCDclearCache DCD --clearCache From e07f437a9c1505de1362bd33178891f40941c730 Mon Sep 17 00:00:00 2001 From: IdanArye Date: Fri, 30 Aug 2013 03:57:39 +0300 Subject: [PATCH 5/5] Added a warning about a conflict between the Vim plugins of DCD and DScanner --- editors/vim/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/editors/vim/README.md b/editors/vim/README.md index 344f645..de5448b 100644 --- a/editors/vim/README.md +++ b/editors/vim/README.md @@ -22,7 +22,7 @@ On windows you need to look for the path in dmd's installation. Import paths are globbed with Vim's globbing function. Usage -=================== +===== When the filetype is D, use the `DCDstartServer` command to start the server and the `DCDstopServer` command to stop the server. `DCDstartServer` can receive import path(s) as arguments. @@ -38,3 +38,9 @@ Use `DCDclearCache` to clear the DCD server cache. When the server is running, use `CTRL`+`x` `CTRL`+`o` in a D buffer to use DCD completion. + +Conflicts +========= +This plugin conflicts with the DScanner plugin, as both use the `dcomplete` +autoload namespace and the `dcomplete#Complete` function - as per Vim's +conventions.