From d937b937c925eeb4f050de73b1ee2eae682e6e3c Mon Sep 17 00:00:00 2001 From: baabelfish Date: Wed, 27 Jan 2016 10:59:11 +0200 Subject: [PATCH] Initial commit --- LICENSE | 21 +++++ README.md | 29 +++++++ ftdetect/nim.vim | 2 + ftplugin/nim.vim | 3 + plugin/nim.vim | 214 +++++++++++++++++++++++++++++++++++++++++++++++ syntax/nim.vim | 37 ++++++++ 6 files changed, 306 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 ftdetect/nim.vim create mode 100644 ftplugin/nim.vim create mode 100644 plugin/nim.vim create mode 100644 syntax/nim.vim diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..821cb95 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 baabelfish + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f4bcf21 --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +# nvim-structure +Attempt at writing an async outline/structure listing/navigator for files/modules. + +# TODO +- [ ] Syntax +- [ ] Indendation +- [ ] Compiler support +- [ ] Autocompletion +- [x] Nimsuggest + - [x] Usages + - [x] Jump to definition + - [x] Show typeinfo + - [x] Outline +- [x] Commands + - [x] NimDefinition + - [x] NimOutline + - [x] NimInfo + - [x] NimUsages + - [x] NimUsagesProject + - [ ] NimRenameSymbol + - [ ] NimRenameSymbolProject + +# TODO For advanced +- [ ] Syntax with nim compiler highlight +- [ ] Outline with unite +- [ ] Outline with proper tagbar +- [ ] Usages with unite +- [ ] Autocompletion with ycm +- [ ] Autocompletion with deoplete diff --git a/ftdetect/nim.vim b/ftdetect/nim.vim new file mode 100644 index 0000000..053f8c2 --- /dev/null +++ b/ftdetect/nim.vim @@ -0,0 +1,2 @@ +au BufNewFile,BufRead *.nim set filetype=nim +au BufNewFile,BufRead *.nims set filetype=nims diff --git a/ftplugin/nim.vim b/ftplugin/nim.vim new file mode 100644 index 0000000..cbee180 --- /dev/null +++ b/ftplugin/nim.vim @@ -0,0 +1,3 @@ +nnoremap :NimDefinition +nnoremap gd :NimDefinition +nnoremap gt :NimInfo diff --git a/plugin/nim.vim b/plugin/nim.vim new file mode 100644 index 0000000..0c3fa45 --- /dev/null +++ b/plugin/nim.vim @@ -0,0 +1,214 @@ +if exists("b:loaded") + " finish +else + function! s:NimsuggestProxy(id, data, event) + call s:HandleNimsuggestProxy(a:id, a:data, a:event) + endfunction +endif + +function! s:HandleNimsuggestProxy(id, data, event) + if a:event == 'stdout' + if len(a:data[0]) == 0 + elseif !(a:data[0] =~ "^usage") + call s:HandleNimsuggest(a:data, s:type) + endif + endif +endfunction + +" Check dependedncies +function! s:CheckDependency(command) + if !executable(a:command) + echoerr "Not found: " . a:command + finish + endif + return exepath(a:command) +endfunction + +let s:nim = s:CheckDependency("nim") +let s:nimble = s:CheckDependency("nimble") +let s:nimsuggest = s:CheckDependency("nimsuggest") +let s:bash = s:CheckDependency("bash") +let s:nimserver = 0 +let s:type = '' +let s:findInProject = 1 + +function! s:IsRunning() + return s:nimserver> 0 +endfunction + +function! s:JumpToLocation(file, line, col) + execute ":e " . a:file + execute ":" . a:line + execute ":norm " . a:col . "|" +endfunction + +function! s:JumpFromQuickfix() + let [file, location, _] = split(getline(line(".")), "|") + let [l, c] = split(location, " col ") + wincmd p + call s:JumpToLocation(file, l, c) +endfunction + +function! s:HandleNimsuggest(data, type) + if a:type == 'outline' + for entry in a:data + if len(entry) == 0 + continue + endif + + let [_, node, fullname, type, filename, line, column, doc, random] = split(entry, " ") + let name = join(split(fullname, "\\.")[1:], ".") + call setqflist([{ + \ 'filename': filename, + \ 'lnum': line, + \ 'col': column + 1, + \ 'text': node . " : " . name }], + \ 'a') + endfor + copen + nnoremap :call JumpFromQuickfix() + + elseif a:type == 'info' + let [_, ctype, name, type, filename, l, c, doc] = split(a:data[0], " ") + if type != "" + echo "Type: " . type + else + echo "No information found" + endif + + elseif a:type == 'def' + let [_, _, _, _, filename, l, c, _] = split(a:data[0], " ") + call s:JumpToLocation(filename, l, c + 1) + + elseif a:type == 'use' + for entry in a:data + if len(entry) == 0 + continue + endif + + let [ctype, context, fullname, type, filename, line, column, doc, random] = split(entry, " ") + if !s:findInProject && filename != expand("%") + continue + endif + + let module = split(fullname, '\.')[0] + let name = split(fullname, '\.')[-1] + call setqflist([{ + \ 'filename': filename, + \ 'lnum': line, + \ 'col': column + 1, + \ 'text': ctype . ": " . name . " (" . fullname . ")"}], + \ 'a') + endfor + copen + nnoremap :call JumpFromQuickfix() + + else + echoerr "No support for " . a:type + endif +endfunction + +function! s:Cleanup() +endfunction + +" Internal implementation +function! s:AskNimsuggest(command, useV2) + let s:result = [] + let file = expand("%") + let line = line(".") + let col = col(".") + + let completion = a:command + if completion == "info" + let completion = "def" + endif + + let nimcom = completion . " " . file . ":" . line . ":" . col + let s:type = a:command + + call s:NimStartServer(a:useV2) + call jobsend(s:nimserver, nimcom . "\n") +endfunction + +" Public API +function! s:NotImplementedYet() + echo "Not implemented yet" +endfunction + +function! s:NimJumpToDefinition() + call s:AskNimsuggest("def", 0) +endfunction + +function! s:NimOutline() + cclose + call setqflist([]) + call s:AskNimsuggest("outline", 1) +endfunction + +function! s:NimUsages(findInProject) + cclose + call setqflist([]) + let s:findInProject = a:findInProject + call s:AskNimsuggest("use", 1) +endfunction + +function! s:NimRenameSymbol() + call s:NotImplementedYet() +endfunction + +function! s:NimRenameSymbolProject() + call s:NotImplementedYet() +endfunction + +function! s:NimStartServer(useV2) + if s:nimserver > 0 + call s:NimStopServer() + endif + let s:nimserver = jobstart([s:nimsuggest, (a:useV2 ? '--v2' : ''), '--stdin', '/home/bbl/temp/asdf.nim'], { + \ 'on_stdout': 's:NimsuggestProxy', + \ 'on_stderr': 's:NimsuggestProxy', + \ 'on_exit': 's:NimsuggestProxy' + \ }) +endfunction + +function! s:NimStatusServer() + if s:nimserver <= 0 + echo "No nimsuggest server running" + else + echo "Nimsuggest running with id: " . s:nimserver + endif +endfunction + +function! s:NimStopServer() + if s:nimserver > 0 + call jobstop(s:nimserver) + let s:nimserver = 0 + endif +endfunction + +function! s:NimInfo() + call s:AskNimsuggest("info", 0) +endfunction + +function! s:NimDebug() + echo "Nim tools debugging info" + echo "------------------------" + echo "\n" + echo "-------- Tools ---------" + echo "Nim: " . s:nim + echo "Nimble: " . s:nimble + echo "Nimsuggest: " . s:nimsuggest +endfunction + +command! NimDefinition :call s:NimJumpToDefinition() +command! NimInfo :call s:NimInfo() +command! NimUsages :call s:NimUsages(0) +command! NimUsagesProject :call s:NimUsages(1) +command! NimOutline :call s:NimOutline() +command! NimServerStart :call s:NimStartServer() +command! NimServerStop :call s:NimStopServer() +command! NimRenameSymbol :call s:NimRenameSymbol() +command! NimRenameSymbolProject :call s:NimRenameSymbolProject() +command! NimDebug :call s:NimDebug() + +let b:loaded = 1 diff --git a/syntax/nim.vim b/syntax/nim.vim new file mode 100644 index 0000000..d921148 --- /dev/null +++ b/syntax/nim.vim @@ -0,0 +1,37 @@ +if exists("b:current_syntax") + finish +endif + +syntax keyword nimKeyword let const var +syntax keyword nimKeyword addr and as asm atomic +syntax keyword nimKeyword bind block break +syntax keyword nimKeyword case cast concept const continue converter +syntax keyword nimKeyword defer discard distinct div do +syntax keyword nimKeyword elif else end enum except export +syntax keyword nimKeyword finally for from func +syntax keyword nimKeyword generic +syntax keyword nimKeyword if import in include interface is isnot iterator +syntax keyword nimKeyword let +syntax keyword nimKeyword macro method mixin mod +syntax keyword nimKeyword nil not notin +syntax keyword nimKeyword object of or out +syntax keyword nimKeyword proc ptr +syntax keyword nimKeyword raise ref return +syntax keyword nimKeyword shl shr static +syntax keyword nimKeyword template try tuple type +syntax keyword nimKeyword using +syntax keyword nimKeyword var +syntax keyword nimKeyword when while with without +syntax keyword nimKeyword xor +syntax keyword nimKeyword yield + +syntax keyword nimBuiltinFunction echo + +syntax keyword nimOperator and or not xor shl shr div mod in notin is isnot of. +" syntax keyword nimOperator =+-*/<>@$~&%|!?^.:\ + +highlight link nimOperator Operator +highlight link nimKeyword Keyword +highlight link nimBuiltinFunction Function + +let b:current_syntax = "nim"