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] Keywords
- [x] Operator precedence different colors - [x] Operator precedence different colors
- [x] Numbers - [x] Numbers
- [ ] String - [x] String
- [ ] Multiline comments - [ ] Multiline comments
- [ ] Highlight variable names semantically - [ ] Highlight variable names semantically
- [ ] Indendation - [ ] Indendation
- [ ] Compiler support - [ ] Compiler support
- [x] Omnicomplete
- [ ] Make for errors - [ ] Make for errors
- [ ] Omnicomplete
- [x] Nimsuggest - [x] Nimsuggest
- [x] Usages - [x] Usages
- [x] Jump to definition - [x] Jump to definition
@ -34,14 +34,16 @@ Nim support for Neovim
- [x] NimRenameSymbol - [x] NimRenameSymbol
- [ ] NimRenameSymbolProject - [ ] NimRenameSymbolProject
- [ ] IDE features - [ ] IDE features
- [ ] Parse proc parameter types for parameter completion - [x] Neomake
- [ ] Auto complete modules - [x] Autocompletion with ycm
- [ ] Search and view online documentation
- [ ] Usages with unite
- [ ] Outline with unite - [ ] Outline with unite
- [ ] Outline with a proper tagbar - [ ] Outline with a proper tagbar
- [ ] Usages with unite - [ ] Auto complete modules
- [ ] Autocompletion with ycm - [ ] Parse proc parameter types for parameter completion
- [ ] Autocompletion with deoplete
- [ ] REPL interaction - [ ] REPL interaction
- [ ] Airline integration
- [ ] Add tests - [ ] Add tests
- [x] CI integration - [x] CI integration
- [x] Test nimsuggest for surprises - [x] Test nimsuggest for surprises
@ -61,9 +63,9 @@ Nim support for Neovim
# TASKS # TASKS
- [x] Sync version communicating with nimsuggest - [x] Sync version communicating with nimsuggest
- [ ] Test the user's versions - [ ] Test dependency versions
- [ ] Add roadmap - [ ] Add roadmap
# BUGS # 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() function! features#definition#run()
call suggest#New("def", 0, s:DefinitionImpl) call suggest#New("def", 1, 0, s:DefinitionImpl)
endfunction endfunction

View file

@ -6,66 +6,38 @@ let s:loaded = 1
let s:InfoImpl = {} 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) function! s:InfoImpl.run(data)
if len(a:data.lines) == 0 if len(a:data.lines) == 0
echo "No information found" echo "No information found"
else else
let res = util#ParseV1(a:data.lines[0])
echohl None echohl None
let [_, ctype, name, type, filename, l, c, doc] = split(a:data.lines[0], "\\t") echohl Function | echon res.lname
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 Comment | echon "\n » " 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" echon "\n"
echohl Comment | echon " » " echohl Comment | echon " » "
echohl Typedef | echon type echohl Typedef | echon res.name
end end
echohl Comment | echon "\n » " echohl Comment | echon "\n » "
echohl Include | echon path echohl Include | echon res.location
echohl Comment | echon " (" echohl Comment | echon " ("
echohl String | echon filename echohl String | echon res.file
echohl Comment | echon ")" echohl Comment | echon ")"
if res.doc != "\"\""
echohl Comment | echon "\n » "
echohl Normal | echon res.doc
endif
endif endif
endfunction endfunction
function! features#info#run() function! features#info#run()
call suggest#New("def", 0, s:InfoImpl) call suggest#New("def", 1, 0, s:InfoImpl)
endfunction endfunction

View file

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

View file

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

View file

@ -46,13 +46,15 @@ endfunction
let s:UsagesDefinitionImpl = {} let s:UsagesDefinitionImpl = {}
function! s:UsagesDefinitionImpl.run(data) function! s:UsagesDefinitionImpl.run(data)
let res = util#ParseV1(a:data.lines[0]) " let res = util#ParseV1(a:data.lines[0])
call suggest#NewKnown("use", 1, res.file, res.line, res.col + 1, s:UsagesImpl) " call suggest#NewKnown("use", 1, res.file, res.line, res.col + 1, s:UsagesImpl)
call suggest#New("use", 1, 1, s:UsagesImpl)
endfunction endfunction
function! features#usages#run(findInProject) function! features#usages#run(findInProject)
cclose cclose
call setqflist([]) call setqflist([])
let s:findInProject = a:findInProject let s:findInProject = a:findInProject
call suggest#New("def", 0, s:UsagesDefinitionImpl) call suggest#New("def", 1, 0, s:UsagesDefinitionImpl)
endfunction 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: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 " NimSuggest
let s:NimSuggest = {} let s:NimSuggest = {}
function! s:NimSuggest.on_stdout(job, chunk) function! s:NimSuggest.on_stdout(job, chunk)
if len(a:chunk[0]) != 0 && !(a:chunk[0] =~ "^usage") call extend(self.lines, a:chunk)
call extend(self.lines, a:chunk)
endif
endfunction endfunction
function! s:NimSuggest.on_stderr() function! s:NimSuggest.on_stderr(job, chunk)
endfunction endfunction
function! s:NimSuggest.on_exit() 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 if len(self.lines) > 0
call self.handler.run(self) call self.handler.run(self)
else else
" Clear cli echo ""
echo ""
endif endif
endfunction 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 = copy(s:NimSuggest)
let result.lines = [] let result.lines = []
let result.file = a:file 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.line = a:line
let result.col = a:col let result.col = a:col
let result.handler = a:handler let result.handler = a:handler
let result.isAsync = has("nvim") && !a:sync && g:nvim_nim_enable_async
" if a:useTempFile " if a:useTempFile
" call writefile(getline(1, '$'), result.tempfile) " call writefile(getline(1, '$'), result.tempfile)
" endif " endif
" let nimcom = completion . " " . file . (a:useTempFile ? (";" . result.tempfile) : "") . ":" . line . ":" . col " let nimcom = completion . " " . file . (a:useTempFile ? (";" . result.tempfile) : "") . ":" . line . ":" . col
let jobcmd = [g:nvim_nim_exec_nimsuggest, (a:useV2 ? '--v2' : ''), '--stdin', result.file] let query = a:command . " " . result.file . ":" . result.line . ":" . result.col
let jobcmdstr = g:nvim_nim_exec_nimsuggest . " " . (a:useV2 ? '--v2' : '') . " " . '--stdin' . " " . result.file
let jobstdin = a:command . " " . result.file . ":" . result.line . ":" . result.col
if !g:nvim_nim_enable_async || !has("nvim") if !result.isAsync
let fullcmd = 'echo -e ' . shellescape(jobstdin, 1) . '|' . jobcmdstr 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] let result.lines = split(system(fullcmd), "\n")[4:-2]
call a:handler.run(result) call a:handler.run(result)
else else
call util#StartQuery() call util#StartQuery()
let result.job = jobstart([g:nvim_nim_exec_nimsuggest, (a:useV2 ? '--v2' : ''), '--stdin', result.file], result) let result.job_server = jobstart([g:nvim_nim_exec_nimsuggest, '--port:5999', '--address:localhost', (a:useV2 ? '--v2' : ''), result.file], s:NimSuggestServer)
call jobsend(result.job, jobcmd) 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 endif
return result return result
endfunction endfunction
function! suggest#New(command, useV2, handler) function! suggest#New(command, sync, useV2, handler)
return suggest#NewKnown(a:command, a:useV2, expand("%:p"), line("."), col("."), a:handler) return suggest#NewKnown(a:command, a:sync, a:useV2, expand("%:p"), line("."), col("."), a:handler)
endfunction endfunction

View file

@ -4,6 +4,37 @@ endif
let s:loaded = 1 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) function! util#FirstNonEmpty(lines)
for line in a:lines for line in a:lines
if len(line) > 0 if len(line) > 0
@ -48,9 +79,15 @@ function! util#StartQuery()
endfunction endfunction
function! s:GetModule(path)
return a:path[0]
endfunction
function! util#ParseV1(line) function! util#ParseV1(line)
let res = split(a:line, " ") let res = split(a:line, " ")
let path = split(res[2], "\\.") let path = split(res[2], "\\.")
let result = { let result = {
\ "ctype": res[0], \ "ctype": res[0],
\ "kind": res[1], \ "kind": res[1],
@ -60,9 +97,11 @@ function! util#ParseV1(line)
\ "line": res[5], \ "line": res[5],
\ "col": res[6], \ "col": res[6],
\ "doc": res[7], \ "doc": res[7],
\ "module": join(path[0:-3], "."), \ "module": s:GetModule(path),
\ "location": join(path[0:-2], "."), \ "location": join(path[0:-2], "."),
\ "lname": path[-1], \ "lname": path[-1],
\ "kindstr": s:idtypes[res[1]][1],
\ "kindshort": s:idtypes[res[1]][0],
\ } \ }
return result return result
endfunction endfunction
@ -80,10 +119,13 @@ function! util#ParseV2(line)
\ "line": res[5], \ "line": res[5],
\ "col": res[6], \ "col": res[6],
\ "doc": res[7], \ "doc": res[7],
\ "module": join(path[0:-3], "."), \ "quality": res[8],
\ "module": s:GetModule(path),
\ "location": join(path[0:-2], "."), \ "location": join(path[0:-2], "."),
\ "name": path[-1], \ "name": path[-1],
\ "lname": path[-1], \ "lname": path[-1],
\ "kindstr": s:idtypes[res[1]][1],
\ "kindshort": s:idtypes[res[1]][0],
\ } \ }
return result return result
endfunction 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 au BufNewFile,BufRead *.nims set filetype=nims
let g:nvim_nim_enable_highlighter = 0 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_builtin = 1
let g:nvim_nim_highlight_use_unite = 0 let g:nvim_nim_highlight_use_unite = 0
let g:nvim_nim_autocomplete = "omni" " omni, deoplete, ycm 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 comments=s1:#[,mb:#,ex:]#,:#
setlocal commentstring=#\ %s setlocal commentstring=#\ %s
setlocal expandtab setlocal expandtab
setlocal omnifunc=omni#nim
command! NimDefinition :call features#definition#run() command! NimDefinition :call features#definition#run()
command! NimInfo :call features#info#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 addr asm atomic bind cast defer discard
syntax keyword nimKeyword do expr stmt end generic mixin iterator syntax keyword nimKeyword do expr stmt end generic mixin iterator
syntax keyword nimKeyword typedesc openarray out ptr ref return using 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 nimRepeat for while
syntax keyword nimBoolean true false syntax keyword nimBoolean true false
@ -144,7 +144,7 @@ highlight link nimConditional Conditional
highlight link nimConstant Constant highlight link nimConstant Constant
highlight link nimDefine Define highlight link nimDefine Define
highlight link nimException Exception highlight link nimException Exception
highlight link nimGlobal Constant highlight link nimGlobals Constant
highlight link nimInclude Include highlight link nimInclude Include
highlight link nimLabel Label highlight link nimLabel Label
highlight link nimMacro Macro highlight link nimMacro Macro