Autocompleiton and friends

This commit is contained in:
baabelfish 2016-02-01 09:16:57 +02:00
commit d07c351677
13 changed files with 167 additions and 79 deletions

View file

@ -12,13 +12,13 @@ Nim support for Neovim
- [x] Keywords
- [x] Operator precedence different colors
- [x] Numbers
- [ ] String
- [x] String
- [ ] Multiline comments
- [ ] Highlight variable names semantically
- [ ] Indendation
- [ ] Compiler support
- [x] Omnicomplete
- [ ] Make for errors
- [ ] Omnicomplete
- [x] Nimsuggest
- [x] Usages
- [x] Jump to definition
@ -34,14 +34,16 @@ Nim support for Neovim
- [x] NimRenameSymbol
- [ ] NimRenameSymbolProject
- [ ] IDE features
- [ ] Parse proc parameter types for parameter completion
- [ ] Auto complete modules
- [x] Neomake
- [x] Autocompletion with ycm
- [ ] Search and view online documentation
- [ ] Usages with unite
- [ ] Outline with unite
- [ ] Outline with a proper tagbar
- [ ] Usages with unite
- [ ] Autocompletion with ycm
- [ ] Autocompletion with deoplete
- [ ] Auto complete modules
- [ ] Parse proc parameter types for parameter completion
- [ ] REPL interaction
- [ ] Airline integration
- [ ] Add tests
- [x] CI integration
- [x] Test nimsuggest for surprises
@ -61,9 +63,9 @@ Nim support for Neovim
# TASKS
- [x] Sync version communicating with nimsuggest
- [ ] Test the user's versions
- [ ] Test dependency versions
- [ ] Add roadmap
# BUGS
- [ ] Not all lines are read from stdin for some reason with job-control
- [x] Not all lines are read from stdin for some reason with job-control

View file

@ -18,6 +18,7 @@ endfunction
function! features#definition#run()
call suggest#New("def", 0, s:DefinitionImpl)
call suggest#New("def", 1, 0, s:DefinitionImpl)
endfunction

View file

@ -6,66 +6,38 @@ let s:loaded = 1
let s:InfoImpl = {}
let s:idtypes = {
\ 'skProc': "Function",
\ 'skTemplate': "Template",
\ 'skType': "Type",
\ 'skMacro': "Macro",
\ 'skMethod': "Method",
\ 'skField': "Field",
\ 'skAlias': "Alias",
\ 'skConditional': "Conditional",
\ 'skConst': "Constant",
\ 'skConverter': "Converter",
\ 'skDynLib': "Dynamic library",
\ 'skEnumField': "Enum field",
\ 'skForVar': "Loop variable",
\ 'skGenericParam': "Generic parameter",
\ 'skGlobalVar': "Global variable",
\ 'skGlobalLet': "Global constant",
\ 'skIterator': "Iterator",
\ 'skLabel': "Label",
\ 'skLet': "Runtime constant",
\ 'skModule': "Module",
\ 'skPackage': "Package",
\ 'skParam': "Parameter",
\ 'skResult': "Result",
\ 'skStub': "Stub",
\ 'skTemp': "Temporary",
\ 'skUnknown': "Unknown",
\ 'skVar': "Variable"
\ }
function! s:InfoImpl.run(data)
if len(a:data.lines) == 0
echo "No information found"
else
let res = util#ParseV1(a:data.lines[0])
echohl None
let [_, ctype, name, type, filename, l, c, doc] = split(a:data.lines[0], "\\t")
let path = join(split(name, '\.')[0:-2], ".")
let module = split(name, '\.')[0]
let name = split(name, '\.')[-1]
let node_type = s:idtypes[ctype]
echohl Function | echon name
echohl Function | echon res.lname
echohl Comment | echon "\n » "
echohl Type | echon node_type
echohl Type | echon res.kindstr
if len(type) > 0 && name != type
if len(res.name) > 0 && res.lname != res.name
echon "\n"
echohl Comment | echon " » "
echohl Typedef | echon type
echohl Typedef | echon res.name
end
echohl Comment | echon "\n » "
echohl Include | echon path
echohl Include | echon res.location
echohl Comment | echon " ("
echohl String | echon filename
echohl String | echon res.file
echohl Comment | echon ")"
if res.doc != "\"\""
echohl Comment | echon "\n » "
echohl Normal | echon res.doc
endif
endif
endfunction
function! features#info#run()
call suggest#New("def", 0, s:InfoImpl)
call suggest#New("def", 1, 0, s:InfoImpl)
endfunction

View file

@ -27,5 +27,6 @@ endfunction
function! features#outline#run()
cclose
call setqflist([])
call suggest#New("outline", 1, s:OutlineImpl)
call suggest#New("outline", 1, 1, s:OutlineImpl)
endfunction

View file

@ -37,5 +37,6 @@ endfunction
function! features#rename#run(inProject)
let s:findInProject = a:inProject
call suggest#New("use", 1, s:RenameImpl)
call suggest#New("use", 1, 1, s:RenameImpl)
endfunction

View file

@ -46,13 +46,15 @@ endfunction
let s:UsagesDefinitionImpl = {}
function! s:UsagesDefinitionImpl.run(data)
let res = util#ParseV1(a:data.lines[0])
call suggest#NewKnown("use", 1, res.file, res.line, res.col + 1, s:UsagesImpl)
" let res = util#ParseV1(a:data.lines[0])
" call suggest#NewKnown("use", 1, res.file, res.line, res.col + 1, s:UsagesImpl)
call suggest#New("use", 1, 1, s:UsagesImpl)
endfunction
function! features#usages#run(findInProject)
cclose
call setqflist([])
let s:findInProject = a:findInProject
call suggest#New("def", 0, s:UsagesDefinitionImpl)
call suggest#New("def", 1, 0, s:UsagesDefinitionImpl)
endfunction

40
autoload/omni.vim Normal file
View file

@ -0,0 +1,40 @@
" if exists("s:loaded")
" finish
" endif
" let s:loaded = 1
function! omni#item(parsed)
return {
\ 'word': a:parsed.lname,
\ 'menu': a:parsed.module,
\ 'kind': a:parsed.kindshort . " » " . a:parsed.type,
\ 'info': a:parsed.doc,
\ }
endfunction
function! omni#nim(findstart, base)
if a:findstart && empty(a:base)
return col('.')
else
let file = expand("%:p")
let tempfile = file . ".temp"
let l = line(".")
let c = col(".")
call writefile(getline(1, '$'), tempfile)
let query = "sug " . file . ";" . tempfile . ":" . l . ":" . c
let jobcmdstr = g:nvim_nim_exec_nimsuggest . " --v2 --stdin " . file
let fullcmd = 'echo -e ' . shellescape(query, 1) . '|' . jobcmdstr
let completions_raw = split(system(fullcmd), "\n")[4:-2]
let completions = []
for line in completions_raw
call add(completions, omni#item(util#ParseV2(line)))
endfor
return {
\ 'words': completions,
\ 'refresh': 'always' }
endfunction

View file

@ -5,29 +5,44 @@ let s:loaded = 1
let s:findInProject = 1
let s:NimSuggestServer = {}
function! s:NimSuggestServer.on_stdout(job, chunk)
" echoerr join(a:chunk, "\n")
endfunction
function! s:NimSuggestServer.on_stderr(job, chunk)
" echoerr join(a:chunk, "\n")
endfunction
function! s:NimSuggestServer.on_exit()
" call jobstop(self.job_server)
endfunction
" NimSuggest
let s:NimSuggest = {}
function! s:NimSuggest.on_stdout(job, chunk)
if len(a:chunk[0]) != 0 && !(a:chunk[0] =~ "^usage")
call extend(self.lines, a:chunk)
endif
call extend(self.lines, a:chunk)
endfunction
function! s:NimSuggest.on_stderr()
function! s:NimSuggest.on_stderr(job, chunk)
endfunction
function! s:NimSuggest.on_exit()
if self.isAsync
let self.lines = self.lines[5:-1]
else
let self.lines = self.lines[4:-1]
endif
if len(self.lines) > 0
call self.handler.run(self)
else
" Clear cli
echo ""
echo ""
endif
endfunction
function! suggest#NewKnown(command, useV2, file, line, col, handler)
function! suggest#NewKnown(command, sync, useV2, file, line, col, handler)
let result = copy(s:NimSuggest)
let result.lines = []
let result.file = a:file
@ -35,28 +50,35 @@ function! suggest#NewKnown(command, useV2, file, line, col, handler)
let result.line = a:line
let result.col = a:col
let result.handler = a:handler
let result.isAsync = has("nvim") && !a:sync && g:nvim_nim_enable_async
" if a:useTempFile
" call writefile(getline(1, '$'), result.tempfile)
" endif
" let nimcom = completion . " " . file . (a:useTempFile ? (";" . result.tempfile) : "") . ":" . line . ":" . col
let jobcmd = [g:nvim_nim_exec_nimsuggest, (a:useV2 ? '--v2' : ''), '--stdin', result.file]
let jobcmdstr = g:nvim_nim_exec_nimsuggest . " " . (a:useV2 ? '--v2' : '') . " " . '--stdin' . " " . result.file
let jobstdin = a:command . " " . result.file . ":" . result.line . ":" . result.col
let query = a:command . " " . result.file . ":" . result.line . ":" . result.col
if !g:nvim_nim_enable_async || !has("nvim")
let fullcmd = 'echo -e ' . shellescape(jobstdin, 1) . '|' . jobcmdstr
if !result.isAsync
let jobcmdstr = g:nvim_nim_exec_nimsuggest . " " . (a:useV2 ? '--v2' : '') . " " . '--stdin' . " " . result.file
let fullcmd = 'echo -e ' . shellescape(query, 1) . '|' . jobcmdstr
let result.lines = split(system(fullcmd), "\n")[4:-2]
call a:handler.run(result)
else
call util#StartQuery()
let result.job = jobstart([g:nvim_nim_exec_nimsuggest, (a:useV2 ? '--v2' : ''), '--stdin', result.file], result)
call jobsend(result.job, jobcmd)
let result.job_server = jobstart([g:nvim_nim_exec_nimsuggest, '--port:5999', '--address:localhost', (a:useV2 ? '--v2' : ''), result.file], s:NimSuggestServer)
if result.job_server < 1
echoerr "Unable to start server"
else
" FIXME: Telnet is not possibly the best way to communicate :S
let result.job_suggest = jobstart(['telnet', 'localhost', '5999'], result)
call jobsend(result.job_suggest, query . "\n")
endif
endif
return result
endfunction
function! suggest#New(command, useV2, handler)
return suggest#NewKnown(a:command, a:useV2, expand("%:p"), line("."), col("."), a:handler)
function! suggest#New(command, sync, useV2, handler)
return suggest#NewKnown(a:command, a:sync, a:useV2, expand("%:p"), line("."), col("."), a:handler)
endfunction

View file

@ -4,6 +4,37 @@ endif
let s:loaded = 1
let s:idtypes = {
\ 'skProc': ["p", "Function"],
\ 'skTemplate': ["t", "Template"],
\ 'skType': ["T", "Type"],
\ 'skMacro': ["M", "Macro"],
\ 'skMethod': ["m", "Method"],
\ 'skField': ["field", "Field"],
\ 'skAlias': ["a", "Alias"],
\ 'skConditional': ["c", "Conditional"],
\ 'skConst': ["C", "Constant"],
\ 'skConverter': ["c", "Converter"],
\ 'skDynLib': ["d", "Dynamic library"],
\ 'skEnumField': ["e", "Enum field"],
\ 'skForVar': ["l", "Loop variable"],
\ 'skGenericParam': ["g", "Generic parameter"],
\ 'skGlobalVar': ["g", "Global variable"],
\ 'skGlobalLet': ["g", "Global constant"],
\ 'skIterator': ["i", "Iterator"],
\ 'skLabel': ["l", "Label"],
\ 'skLet': ["r", "Runtime constant"],
\ 'skModule': ["m", "Module"],
\ 'skPackage': ["p", "Package"],
\ 'skParam': ["p", "Parameter"],
\ 'skResult': ["r", "Result"],
\ 'skStub': ["s", "Stub"],
\ 'skTemp': ["t", "Temporary"],
\ 'skUnknown': ["u", "Unknown"],
\ 'skVar': ["v", "Variable"],
\ }
function! util#FirstNonEmpty(lines)
for line in a:lines
if len(line) > 0
@ -48,9 +79,15 @@ function! util#StartQuery()
endfunction
function! s:GetModule(path)
return a:path[0]
endfunction
function! util#ParseV1(line)
let res = split(a:line, " ")
let path = split(res[2], "\\.")
let result = {
\ "ctype": res[0],
\ "kind": res[1],
@ -60,9 +97,11 @@ function! util#ParseV1(line)
\ "line": res[5],
\ "col": res[6],
\ "doc": res[7],
\ "module": join(path[0:-3], "."),
\ "module": s:GetModule(path),
\ "location": join(path[0:-2], "."),
\ "lname": path[-1],
\ "kindstr": s:idtypes[res[1]][1],
\ "kindshort": s:idtypes[res[1]][0],
\ }
return result
endfunction
@ -80,10 +119,13 @@ function! util#ParseV2(line)
\ "line": res[5],
\ "col": res[6],
\ "doc": res[7],
\ "module": join(path[0:-3], "."),
\ "quality": res[8],
\ "module": s:GetModule(path),
\ "location": join(path[0:-2], "."),
\ "name": path[-1],
\ "lname": path[-1],
\ "kindstr": s:idtypes[res[1]][1],
\ "kindshort": s:idtypes[res[1]][0],
\ }
return result
endfunction

View file

@ -0,0 +1,4 @@
if exists("s:loaded")
finish
endif
let s:loaded = 1

View file

@ -7,7 +7,7 @@ au BufNewFile,BufRead *.nim set filetype=nim
au BufNewFile,BufRead *.nims set filetype=nims
let g:nvim_nim_enable_highlighter = 0
let g:nvim_nim_enable_async = 0
let g:nvim_nim_enable_async = 1
let g:nvim_nim_highlight_builtin = 1
let g:nvim_nim_highlight_use_unite = 0
let g:nvim_nim_autocomplete = "omni" " omni, deoplete, ycm

View file

@ -7,6 +7,7 @@ setlocal formatoptions-=t formatoptions+=l
setlocal comments=s1:#[,mb:#,ex:]#,:#
setlocal commentstring=#\ %s
setlocal expandtab
setlocal omnifunc=omni#nim
command! NimDefinition :call features#definition#run()
command! NimInfo :call features#info#run()

View file

@ -13,7 +13,7 @@ syntax keyword nimKeyword let const var static
syntax keyword nimKeyword addr asm atomic bind cast defer discard
syntax keyword nimKeyword do expr stmt end generic mixin iterator
syntax keyword nimKeyword typedesc openarray out ptr ref return using
syntax keyword nimKeyword varargs with without yield
syntax keyword nimKeyword varargs with without yield nil
syntax keyword nimRepeat for while
syntax keyword nimBoolean true false
@ -144,7 +144,7 @@ highlight link nimConditional Conditional
highlight link nimConstant Constant
highlight link nimDefine Define
highlight link nimException Exception
highlight link nimGlobal Constant
highlight link nimGlobals Constant
highlight link nimInclude Include
highlight link nimLabel Label
highlight link nimMacro Macro