Merge branch 'master' of https://github.com/Hackerpilot/DCD
This commit is contained in:
commit
204ab386eb
|
@ -1 +1,46 @@
|
||||||
#VIM Integration
|
A plugin for using DCD with vim.
|
||||||
|
|
||||||
|
Tested on Linux(and a bit on Windows)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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. `DCDstartServer` can
|
||||||
|
receive import path(s) as arguments.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
"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
|
||||||
|
|
||||||
|
"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(copy(g:dcd_importPath))
|
||||||
|
else
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
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<len(argParts)
|
||||||
|
call add(funcArgs,argParts[-1])
|
||||||
|
else
|
||||||
|
call add(funcArgs,'')
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
let funcArgsString=join(funcArgs,', ').')'
|
||||||
|
call add(result,{'word':funcArgsString,'abbr':substitute(resultLine,'\\n\\t','','g'),'dup':1})
|
||||||
|
end
|
||||||
|
endfor
|
||||||
|
return result
|
||||||
|
endfunction
|
|
@ -0,0 +1,13 @@
|
||||||
|
setlocal omnifunc=dcomplete#Complete
|
||||||
|
|
||||||
|
if has('win32')
|
||||||
|
command! -buffer -nargs=* -complete=dir DCDstartServer execute '!start '.dcomplete#DCDserver().' '.dcomplete#initImportPath().
|
||||||
|
\ ' '.dcomplete#globImportPath([<f-args>])
|
||||||
|
else
|
||||||
|
command! -buffer -nargs=* -complete=dir DCDstartServer execute '!'.dcomplete#DCDserver().' '.dcomplete#initImportPath().
|
||||||
|
\ ' '.dcomplete#globImportPath([<f-args>]).' > /dev/null &'
|
||||||
|
endif
|
||||||
|
command! -buffer -nargs=? DCD execute '!'.dcomplete#DCDclient().' '.<q-args>
|
||||||
|
command! -buffer DCDstopServer DCD --shutdown
|
||||||
|
command! -buffer -nargs=+ -complete=dir DCDaddPath execute 'DCD '.dcomplete#globImportPath([<f-args>])
|
||||||
|
command! -buffer DCDclearCache DCD --clearCache
|
Loading…
Reference in New Issue