diff --git a/autoload/nim.vim b/autoload/nim.vim index 0bfb1f7..27b8fb7 100644 --- a/autoload/nim.vim +++ b/autoload/nim.vim @@ -15,13 +15,37 @@ elseif has("python") exe 'pyfile ' . fnameescape(s:plugin_path) . '/nim_vim.py' endif +if !exists('g:nim_use_nimsuggest') + if executable('nimsuggest') + let g:nim_use_nimsuggest = 1 + else + let g:nim_use_nimsuggest = 0 + endif +endif + +if g:nim_use_nimsuggest + let g:nim_server_cmd = ['nimsuggest', '--stdin', '--v2'] + let s:nim_cmd_template = 'echo %s | nimsuggest --stdin --v2 %s' + let s:nim_suggestions_option = 'sug' + let s:nim_definitions_option = 'def' + let s:nim_dirty_cmd_generator = 'printf(''%s "%s";"%s":%d:%d'', a:op, s:CurrentNimFile(), tmp, line("."), col(".")-1)' + let s:nim_cmd_generator = 'printf(''%s "%s":%d:%d'', a:op, s:CurrentNimFile(), line("."), col(".")-1)' +else + let g:nim_server_cmd = ['nim', 'serve', '--server.type:stdin'] + let s:nim_cmd_template = 'nim %s "%s"' + let s:nim_suggestions_option = '--suggest' + let s:nim_definitions_option = '--def' + let s:nim_dirty_cmd_generator = 'printf(''idetools %s --trackDirty:"%s,%s,%d,%d"'', a:op, tmp, substitute(expand(''%:p''), ''\\'', "/", "g"), line("."), col(".") - 1)' + let s:nim_cmd_generator = 'printf(''idetools %s --track:"%s,%d,%d"'', a:op, substitute(expand(''%:p''), ''\\'', "/", "g"), line("."), col(".") - 1)' +endif + fun! nim#init() let cmd = printf("nim --dump.format:json --verbosity:0 dump %s", s:CurrentNimFile()) let raw_dumpdata = system(cmd) if !v:shell_error && expand("%:e") == "nim" let dumpdata = eval(substitute(raw_dumpdata, "\n", "", "g")) - - let b:nim_project_root = dumpdata['project_path'] + + let b:nim_project_root = substitute(dumpdata['project_path'], '\\', '/', 'g') let b:nim_defined_symbols = dumpdata['defined_symbols'] let b:nim_caas_enabled = g:nim_caas_enabled || index(dumpdata['defined_symbols'], 'forcecaas') != -1 @@ -79,7 +103,7 @@ fun! s:CurrentNimFile() endif call setpos('.', save_cur) - return l:to_check + return substitute(fnamemodify(l:to_check, ':p'), '\\', '/', 'g') endf let g:nim_symbol_types = { @@ -103,26 +127,35 @@ let g:nim_symbol_types = { \ } fun! NimExec(op) + + " This is the "projectfile.nim that nimsuggest wants. It defaluts to + " the file we're operating on and only set to a real project file if the + " appropriate global configuration is set. + let project_file = s:CurrentNimFile() + if g:nim_use_nimsuggest && exists("g:nim_project_file") + let project_file = g:nim_project_file + endif + let isDirty = getbufvar(bufnr('%'), "&modified") if isDirty let tmp = tempname() . bufname("%") . "_dirty.nim" silent! exe ":w " . tmp + let tmp = substitute(tmp, '\\', '/', 'g') - let cmd = printf("idetools %s --trackDirty:\"%s,%s,%d,%d\" \"%s\"", - \ a:op, tmp, expand('%:p'), line('.'), col('.')-1, s:CurrentNimFile()) + let cmd = eval(s:nim_dirty_cmd_generator) else - let cmd = printf("idetools %s --track:\"%s,%d,%d\" \"%s\"", - \ a:op, expand('%:p'), line('.'), col('.')-1, s:CurrentNimFile()) + let cmd = eval(s:nim_cmd_generator) endif if b:nim_caas_enabled exe printf("py nimExecCmd('%s', '%s', False)", b:nim_project_root, cmd) let output = l:py_res else - let output = system("nim " . cmd) + let output = system(printf(s:nim_cmd_template, cmd, project_file)) endif + let output = substitute(output, '.\{-}>\s\+', '', '') - call add(g:nim_log, "nim " . cmd . "\n" . output) + call add(g:nim_log, cmd . "\n" . output) return output endf @@ -143,7 +176,7 @@ fun! NimComplete(findstart, base) return col('.') else let result = [] - let sugOut = NimExec("--suggest") + let sugOut = NimExec(s:nim_suggestions_option) for line in split(sugOut, '\n') let lineData = split(line, '\t') if len(lineData) > 0 && lineData[0] == "sug" @@ -202,7 +235,7 @@ fun! GotoDefinition_nim_ready(def_output) endf fun! GotoDefinition_nim() - call NimExecAsync("--def", function("GotoDefinition_nim_ready")) + call NimExecAsync(s:nim_definitions_option, function("GotoDefinition_nim_ready")) endf fun! FindReferences_nim() diff --git a/autoload/nim_vim.py b/autoload/nim_vim.py index dde6e9f..754d643 100644 --- a/autoload/nim_vim.py +++ b/autoload/nim_vim.py @@ -1,5 +1,6 @@ from sys import version_info -import threading, subprocess, signal, os, platform, getpass +from os import name +import threading, subprocess, signal, os, platform, getpass, re, copy if version_info[0] == 3: import queue as Queue @@ -16,17 +17,25 @@ def command(self, x): vim = Vim() class NimThread(threading.Thread): - def __init__(self, project_path): + def __init__(self, cmd, project_path): super(NimThread, self).__init__() self.tasks = Queue.Queue() self.responses = Queue.Queue() + if name == 'nt': + si = subprocess.STARTUPINFO() + si.dwFlags |= subprocess.STARTF_USESHOWWINDOW + si.wShowWindow = subprocess.SW_HIDE + else: + si = None + cmd.append(project_path) self.nim = subprocess.Popen( - ["nim", "serve", "--server.type:stdin", project_path], + cmd, cwd = os.path.dirname(project_path), stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, universal_newlines = True, + startupinfo = si, bufsize = 1) def postNimCmd(self, msg, async = True): @@ -43,12 +52,13 @@ def run(self): break self.nim.stdin.write(msg + "\n") + self.nim.stdin.flush() result = "" while True: line = self.nim.stdout.readline() result += line - if line == "\n": + if re.match('^(?:\n|>\s*)$', line) is not None: if not async: self.responses.put(result) else: @@ -66,8 +76,8 @@ def asyncOpComplete(self, msg, result): NimProjects = {} -def nimStartService(project): - target = NimVimThread(project) +def nimStartService(cmd, project): + target = NimVimThread(cmd, project) NimProjects[project] = target target.start() return target @@ -79,14 +89,22 @@ def nimTerminateService(project): def nimRestartService(project): nimTerminateService(project) - nimStartService(project) + server = copy.copy(vim.vars['nim_server_cmd'][0:]) + if version_info[0] == 3: + for i in range(len(server)): + server[i] = server[i].decode() + nimStartService(server, project) def nimExecCmd(project, cmd, async = True): target = None if NimProjects.has_key(project): target = NimProjects[project] else: - target = nimStartService(project) + server = copy.copy(vim.vars['nim_server_cmd'][0:]) + if version_info[0] == 3: + for i in range(len(server)): + server[i] = server[i].decode() + target = nimStartService(server, project) result = target.postNimCmd(cmd, async)