Autocompleiton and friends
This commit is contained in:
parent
4c5dfe3ea5
commit
d07c351677
13 changed files with 167 additions and 79 deletions
20
README.md
20
README.md
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
40
autoload/omni.vim
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
if exists("s:loaded")
|
||||
finish
|
||||
endif
|
||||
let s:loaded = 1
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue