Merge branch 'master' into Windows
This commit is contained in:
commit
17ac9c235d
74 changed files with 1931 additions and 598 deletions
|
@ -328,3 +328,10 @@ Cope mappings:
|
|||
Just do following:
|
||||
* Remove `~/.vim_runtime`
|
||||
* Remove any lines that reference `.vim_runtime` in your `~/.vimrc`
|
||||
|
||||
|
||||
## Doist
|
||||
|
||||
Maintaining this Vim configuration isn't my day job. Daily I am the founder of [Doist](https://doist.com/). You could come and help us build the workplace of the future while living a balanced life (anywhere in the world 🌍🌎🌏).
|
||||
|
||||
PS: Using Vim isn't a requirement 😄
|
||||
|
|
|
@ -37,11 +37,22 @@ function! ale_linters#elixir#credo#Handle(buffer, lines) abort
|
|||
return l:output
|
||||
endfunction
|
||||
|
||||
function! ale_linters#elixir#credo#GetMode() abort
|
||||
if get(g:, 'ale_elixir_credo_strict', 0)
|
||||
return '--strict'
|
||||
else
|
||||
return 'suggest'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! ale_linters#elixir#credo#GetCommand(buffer) abort
|
||||
let l:project_root = ale#handlers#elixir#FindMixProjectRoot(a:buffer)
|
||||
let l:mode = ale_linters#elixir#credo#GetMode()
|
||||
|
||||
return ale#path#CdString(l:project_root)
|
||||
\ . ' mix help credo && mix credo suggest --format=flycheck --read-from-stdin %s'
|
||||
\ . 'mix help credo && '
|
||||
\ . 'mix credo ' . ale_linters#elixir#credo#GetMode()
|
||||
\ . ' --format=flycheck --read-from-stdin %s'
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('elixir', {
|
||||
|
|
22
sources_non_forked/ale/ale_linters/elm/elm_lsp.vim
Normal file
22
sources_non_forked/ale/ale_linters/elm/elm_lsp.vim
Normal file
|
@ -0,0 +1,22 @@
|
|||
" Author: antew - https://github.com/antew
|
||||
" Description: LSP integration for elm, currently supports diagnostics (linting)
|
||||
|
||||
call ale#Set('elm_lsp_executable', 'elm-lsp')
|
||||
call ale#Set('elm_lsp_use_global', get(g:, 'ale_use_global_executables', 0))
|
||||
|
||||
function! elm_lsp#GetRootDir(buffer) abort
|
||||
let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm.json')
|
||||
|
||||
return !empty(l:elm_json) ? fnamemodify(l:elm_json, ':p:h') : ''
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('elm', {
|
||||
\ 'name': 'elm_lsp',
|
||||
\ 'lsp': 'stdio',
|
||||
\ 'executable': {b -> ale#node#FindExecutable(b, 'elm_lsp', [
|
||||
\ 'node_modules/.bin/elm-lsp',
|
||||
\ ])},
|
||||
\ 'command': '%e --stdio',
|
||||
\ 'project_root': function('elm_lsp#GetRootDir'),
|
||||
\ 'language': 'elm'
|
||||
\})
|
|
@ -1,4 +1,21 @@
|
|||
" Author: KabbAmine <amine.kabb@gmail.com>
|
||||
" Author: KabbAmine <amine.kabb@gmail.com>, David Sierra <https://github.com/davidsierradz>
|
||||
|
||||
call ale#Set('json_jsonlint_executable', 'jsonlint')
|
||||
call ale#Set('json_jsonlint_use_global', get(g:, 'ale_use_global_executables', 0))
|
||||
|
||||
function! ale_linters#json#jsonlint#GetExecutable(buffer) abort
|
||||
return ale#node#FindExecutable(a:buffer, 'json_jsonlint', [
|
||||
\ 'node_modules/.bin/jsonlint',
|
||||
\ 'node_modules/jsonlint/lib/cli.js',
|
||||
\])
|
||||
endfunction
|
||||
|
||||
function! ale_linters#json#jsonlint#GetCommand(buffer) abort
|
||||
let l:executable = ale_linters#json#jsonlint#GetExecutable(a:buffer)
|
||||
|
||||
return ale#node#Executable(a:buffer, l:executable)
|
||||
\ . ' --compact -'
|
||||
endfunction
|
||||
|
||||
function! ale_linters#json#jsonlint#Handle(buffer, lines) abort
|
||||
" Matches patterns like the following:
|
||||
|
@ -19,8 +36,8 @@ endfunction
|
|||
|
||||
call ale#linter#Define('json', {
|
||||
\ 'name': 'jsonlint',
|
||||
\ 'executable': 'jsonlint',
|
||||
\ 'executable': function('ale_linters#json#jsonlint#GetExecutable'),
|
||||
\ 'output_stream': 'stderr',
|
||||
\ 'command': 'jsonlint --compact -',
|
||||
\ 'command': function('ale_linters#json#jsonlint#GetCommand'),
|
||||
\ 'callback': 'ale_linters#json#jsonlint#Handle',
|
||||
\})
|
||||
|
|
5
sources_non_forked/ale/ale_linters/mail/languagetool.vim
Normal file
5
sources_non_forked/ale/ale_linters/mail/languagetool.vim
Normal file
|
@ -0,0 +1,5 @@
|
|||
" Author: Vincent (wahrwolf [ät] wolfpit.net)
|
||||
" Description: languagetool for mails
|
||||
|
||||
|
||||
call ale#handlers#languagetool#DefineLinter('mail')
|
|
@ -0,0 +1,5 @@
|
|||
" Author: Vincent (wahrwolf [ät] wolfpit.net)
|
||||
" Description: languagetool for markdown files
|
||||
|
||||
|
||||
call ale#handlers#languagetool#DefineLinter('markdown')
|
|
@ -5,6 +5,12 @@ call ale#Set('php_langserver_executable', 'php-language-server.php')
|
|||
call ale#Set('php_langserver_use_global', get(g:, 'ale_use_global_executables', 0))
|
||||
|
||||
function! ale_linters#php#langserver#GetProjectRoot(buffer) abort
|
||||
let l:composer_path = ale#path#FindNearestFile(a:buffer, 'composer.json')
|
||||
|
||||
if (!empty(l:composer_path))
|
||||
return fnamemodify(l:composer_path, ':h')
|
||||
endif
|
||||
|
||||
let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
|
||||
|
||||
return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : ''
|
||||
|
|
4
sources_non_forked/ale/ale_linters/text/languagetool.vim
Normal file
4
sources_non_forked/ale/ale_linters/text/languagetool.vim
Normal file
|
@ -0,0 +1,4 @@
|
|||
" Author: Vincent (wahrwolf [ät] wolfpit.net)
|
||||
" Description: languagetool for text files
|
||||
|
||||
call ale#handlers#languagetool#DefineLinter('text')
|
|
@ -39,6 +39,9 @@ let s:LSP_COMPLETION_COLOR_KIND = 16
|
|||
let s:LSP_COMPLETION_FILE_KIND = 17
|
||||
let s:LSP_COMPLETION_REFERENCE_KIND = 18
|
||||
|
||||
let s:LSP_INSERT_TEXT_FORMAT_PLAIN = 1
|
||||
let s:LSP_INSERT_TEXT_FORMAT_SNIPPET = 2
|
||||
|
||||
let s:lisp_regex = '\v[a-zA-Z_\-][a-zA-Z_\-0-9]*$'
|
||||
|
||||
" Regular expressions for checking the characters in the line before where
|
||||
|
@ -165,14 +168,18 @@ function! s:ReplaceCompletionOptions() abort
|
|||
|
||||
let &l:omnifunc = 'ale#completion#OmniFunc'
|
||||
|
||||
if !exists('b:ale_old_completopt')
|
||||
let b:ale_old_completopt = &l:completeopt
|
||||
endif
|
||||
let l:info = get(b:, 'ale_completion_info', {})
|
||||
|
||||
if &l:completeopt =~# 'preview'
|
||||
let &l:completeopt = 'menu,menuone,preview,noselect,noinsert'
|
||||
else
|
||||
let &l:completeopt = 'menu,menuone,noselect,noinsert'
|
||||
if !get(l:info, 'manual')
|
||||
if !exists('b:ale_old_completeopt')
|
||||
let b:ale_old_completeopt = &l:completeopt
|
||||
endif
|
||||
|
||||
if &l:completeopt =~# 'preview'
|
||||
let &l:completeopt = 'menu,menuone,preview,noselect,noinsert'
|
||||
else
|
||||
let &l:completeopt = 'menu,menuone,noselect,noinsert'
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
@ -186,9 +193,9 @@ function! ale#completion#RestoreCompletionOptions() abort
|
|||
unlet b:ale_old_omnifunc
|
||||
endif
|
||||
|
||||
if exists('b:ale_old_completopt')
|
||||
let &l:completeopt = b:ale_old_completopt
|
||||
unlet b:ale_old_completopt
|
||||
if exists('b:ale_old_completeopt')
|
||||
let &l:completeopt = b:ale_old_completeopt
|
||||
unlet b:ale_old_completeopt
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
@ -346,7 +353,14 @@ function! ale#completion#ParseLSPCompletions(response) abort
|
|||
continue
|
||||
endif
|
||||
|
||||
let l:word = matchstr(l:item.label, '\v^[^(]+')
|
||||
if get(l:item, 'insertTextFormat') is s:LSP_INSERT_TEXT_FORMAT_PLAIN
|
||||
\&& type(get(l:item, 'textEdit')) is v:t_dict
|
||||
let l:text = l:item.textEdit.newText
|
||||
else
|
||||
let l:text = l:item.label
|
||||
endif
|
||||
|
||||
let l:word = matchstr(l:text, '\v^[^(]+')
|
||||
|
||||
if empty(l:word)
|
||||
continue
|
||||
|
@ -385,10 +399,10 @@ function! ale#completion#ParseLSPCompletions(response) abort
|
|||
endfor
|
||||
|
||||
if has_key(l:info, 'prefix')
|
||||
return ale#completion#Filter(l:buffer, &filetype, l:results, l:info.prefix)
|
||||
let l:results = ale#completion#Filter(l:buffer, &filetype, l:results, l:info.prefix)
|
||||
endif
|
||||
|
||||
return l:results
|
||||
return l:results[: g:ale_completion_max_suggestions - 1]
|
||||
endfunction
|
||||
|
||||
function! ale#completion#HandleTSServerResponse(conn_id, response) abort
|
||||
|
@ -503,22 +517,14 @@ function! s:OnReady(linter, lsp_details) abort
|
|||
endif
|
||||
endfunction
|
||||
|
||||
function! ale#completion#GetCompletions() abort
|
||||
if !g:ale_completion_enabled
|
||||
return
|
||||
endif
|
||||
|
||||
call ale#completion#AlwaysGetCompletions(1)
|
||||
endfunction
|
||||
|
||||
" This function can be used to manually trigger autocomplete, even when
|
||||
" g:ale_completion_enabled is set to false
|
||||
function! ale#completion#AlwaysGetCompletions(need_prefix) abort
|
||||
function! ale#completion#GetCompletions(manual) abort
|
||||
let [l:line, l:column] = getpos('.')[1:2]
|
||||
|
||||
let l:prefix = ale#completion#GetPrefix(&filetype, l:line, l:column)
|
||||
|
||||
if a:need_prefix && empty(l:prefix)
|
||||
if !a:manual && empty(l:prefix)
|
||||
return
|
||||
endif
|
||||
|
||||
|
@ -531,6 +537,7 @@ function! ale#completion#AlwaysGetCompletions(need_prefix) abort
|
|||
\ 'prefix': l:prefix,
|
||||
\ 'conn_id': 0,
|
||||
\ 'request_id': 0,
|
||||
\ 'manual': a:manual,
|
||||
\}
|
||||
|
||||
let l:buffer = bufnr('')
|
||||
|
@ -544,6 +551,10 @@ function! ale#completion#AlwaysGetCompletions(need_prefix) abort
|
|||
endfunction
|
||||
|
||||
function! s:TimerHandler(...) abort
|
||||
if !g:ale_completion_enabled
|
||||
return
|
||||
endif
|
||||
|
||||
let s:timer_id = -1
|
||||
|
||||
let [l:line, l:column] = getpos('.')[1:2]
|
||||
|
@ -551,7 +562,7 @@ function! s:TimerHandler(...) abort
|
|||
" When running the timer callback, we have to be sure that the cursor
|
||||
" hasn't moved from where it was when we requested completions by typing.
|
||||
if s:timer_pos == [l:line, l:column] && ale#util#Mode() is# 'i'
|
||||
call ale#completion#GetCompletions()
|
||||
call ale#completion#GetCompletions(0)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
|
|
@ -142,8 +142,8 @@ let s:default_registry = {
|
|||
\ },
|
||||
\ 'clang-format': {
|
||||
\ 'function': 'ale#fixers#clangformat#Fix',
|
||||
\ 'suggested_filetypes': ['c', 'cpp'],
|
||||
\ 'description': 'Fix C/C++ files with clang-format.',
|
||||
\ 'suggested_filetypes': ['c', 'cpp', 'cuda'],
|
||||
\ 'description': 'Fix C/C++ and cuda files with clang-format.',
|
||||
\ },
|
||||
\ 'cmakeformat': {
|
||||
\ 'function': 'ale#fixers#cmakeformat#Fix',
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
scriptencoding utf-8
|
||||
" Author: Johannes Wienke <languitar@semipol.de>
|
||||
" Description: Error handling for errors in alex output format
|
||||
|
||||
|
@ -44,8 +45,8 @@ function! ale#handlers#alex#DefineLinter(filetype, flags) abort
|
|||
|
||||
call ale#linter#Define(a:filetype, {
|
||||
\ 'name': 'alex',
|
||||
\ 'executable_callback': 'ale#handlers#alex#GetExecutable',
|
||||
\ 'command_callback': ale#handlers#alex#CreateCommandCallback(a:flags),
|
||||
\ 'executable': function('ale#handlers#alex#GetExecutable'),
|
||||
\ 'command': ale#handlers#alex#CreateCommandCallback(a:flags),
|
||||
\ 'output_stream': 'stderr',
|
||||
\ 'callback': 'ale#handlers#alex#Handle',
|
||||
\ 'lint_file': 1,
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
" Author: Vincent (wahrwolf [at] wolfpit.net)
|
||||
" Description: languagetool for markdown files
|
||||
"
|
||||
call ale#Set('languagetool_executable', 'languagetool')
|
||||
|
||||
function! ale#handlers#languagetool#GetExecutable(buffer) abort
|
||||
return ale#Var(a:buffer, 'languagetool_executable')
|
||||
endfunction
|
||||
|
||||
function! ale#handlers#languagetool#GetCommand(buffer) abort
|
||||
let l:executable = ale#handlers#languagetool#GetExecutable(a:buffer)
|
||||
|
||||
return ale#Escape(l:executable) . ' --autoDetect %s'
|
||||
endfunction
|
||||
|
||||
function! ale#handlers#languagetool#HandleOutput(buffer, lines) abort
|
||||
" Match lines like:
|
||||
" 1.) Line 5, column 1, Rule ID:
|
||||
let l:head_pattern = '^\v.+.\) Line (\d+), column (\d+), Rule ID. (.+)$'
|
||||
let l:head_matches = ale#util#GetMatches(a:lines, l:head_pattern)
|
||||
|
||||
" Match lines like:
|
||||
" Message: Did you forget a comma after a conjunctive/linking adverb?
|
||||
let l:message_pattern = '^\vMessage. (.+)$'
|
||||
let l:message_matches = ale#util#GetMatches(a:lines, l:message_pattern)
|
||||
|
||||
" Match lines like:
|
||||
" ^^^^^ "
|
||||
let l:markers_pattern = '^\v *(\^+) *$'
|
||||
let l:markers_matches = ale#util#GetMatches(a:lines, l:markers_pattern)
|
||||
|
||||
let l:output = []
|
||||
|
||||
|
||||
" Okay tbh I was to lazy to figure out a smarter solution here
|
||||
" We just check that the arrays are same sized and merge everything
|
||||
" together
|
||||
let l:i = 0
|
||||
|
||||
while l:i < len(l:head_matches)
|
||||
\ && (
|
||||
\ (len(l:head_matches) == len(l:markers_matches))
|
||||
\ && (len(l:head_matches) == len(l:message_matches))
|
||||
\ )
|
||||
let l:item = {
|
||||
\ 'lnum' : str2nr(l:head_matches[l:i][1]),
|
||||
\ 'col' : str2nr(l:head_matches[l:i][2]),
|
||||
\ 'end_col' : str2nr(l:head_matches[l:i][2]) + len(l:markers_matches[l:i][1])-1,
|
||||
\ 'type' : 'W',
|
||||
\ 'code' : l:head_matches[l:i][3],
|
||||
\ 'text' : l:message_matches[l:i][1]
|
||||
\}
|
||||
call add(l:output, l:item)
|
||||
let l:i+=1
|
||||
endwhile
|
||||
|
||||
return l:output
|
||||
endfunction
|
||||
|
||||
" Define the languagetool linter for a given filetype.
|
||||
" TODO:
|
||||
" - Add language detection settings based on user env (for mothertongue)
|
||||
" - Add fixer
|
||||
" - Add config options for rules
|
||||
function! ale#handlers#languagetool#DefineLinter(filetype) abort
|
||||
call ale#linter#Define(a:filetype, {
|
||||
\ 'name': 'languagetool',
|
||||
\ 'executable': function('ale#handlers#languagetool#GetExecutable'),
|
||||
\ 'command': function('ale#handlers#languagetool#GetCommand'),
|
||||
\ 'output_stream': 'stdout',
|
||||
\ 'callback': 'ale#handlers#languagetool#HandleOutput',
|
||||
\ 'lint_file': 1,
|
||||
\})
|
||||
endfunction
|
|
@ -60,7 +60,7 @@ function! ale#handlers#rust#HandleRustErrors(buffer, lines) abort
|
|||
\ 'lnum': l:span.line_start,
|
||||
\ 'end_lnum': l:span.line_end,
|
||||
\ 'col': l:span.column_start,
|
||||
\ 'end_col': l:span.column_end,
|
||||
\ 'end_col': l:span.column_end-1,
|
||||
\ 'text': empty(l:span.label) ? l:error.message : printf('%s: %s', l:error.message, l:span.label),
|
||||
\ 'type': toupper(l:error.level[0]),
|
||||
\})
|
||||
|
|
|
@ -26,7 +26,6 @@ function! ale#handlers#sml#GetCmFile(buffer) abort
|
|||
endfunction
|
||||
|
||||
" Only one of smlnj or smlnj-cm can be enabled at a time.
|
||||
" executable_callback is called before *every* lint attempt
|
||||
function! s:GetExecutable(buffer, source) abort
|
||||
if ale#handlers#sml#GetCmFile(a:buffer) is# ''
|
||||
" No CM file found; only allow single-file mode to be enabled
|
||||
|
|
|
@ -65,8 +65,8 @@ function! ale#handlers#writegood#DefineLinter(filetype) abort
|
|||
call ale#linter#Define(a:filetype, {
|
||||
\ 'name': 'writegood',
|
||||
\ 'aliases': ['write-good'],
|
||||
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
|
||||
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
|
||||
\ 'executable': function('ale#handlers#writegood#GetExecutable'),
|
||||
\ 'command': function('ale#handlers#writegood#GetCommand'),
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
endfunction
|
||||
|
|
|
@ -205,10 +205,13 @@ function! ale#path#FromURI(uri) abort
|
|||
let l:encoded_path = a:uri
|
||||
endif
|
||||
|
||||
let l:path = ale#uri#Decode(l:encoded_path)
|
||||
|
||||
" If the path is like /C:/foo/bar, it should be C:\foo\bar instead.
|
||||
if l:encoded_path =~# '^/[a-zA-Z]:'
|
||||
let l:encoded_path = substitute(l:encoded_path[1:], '/', '\\', 'g')
|
||||
if has('win32') && l:path =~# '^/[a-zA-Z][:|]'
|
||||
let l:path = substitute(l:path[1:], '/', '\\', 'g')
|
||||
let l:path = l:path[0] . ':' . l:path[2:]
|
||||
endif
|
||||
|
||||
return ale#uri#Decode(l:encoded_path)
|
||||
return l:path
|
||||
endfunction
|
||||
|
|
|
@ -14,10 +14,10 @@ function! ale#semver#GetVersion(executable, version_lines) abort
|
|||
let l:version = get(s:version_cache, a:executable, [])
|
||||
|
||||
for l:line in a:version_lines
|
||||
let l:match = matchlist(l:line, '\v(\d+)\.(\d+)\.?(\d?)')
|
||||
let l:match = matchlist(l:line, '\v(\d+)\.(\d+)(\.(\d+))?')
|
||||
|
||||
if !empty(l:match)
|
||||
let l:version = [l:match[1] + 0, l:match[2] + 0, l:match[3] + 0]
|
||||
let l:version = [l:match[1] + 0, l:match[2] + 0, l:match[4] + 0]
|
||||
let s:version_cache[a:executable] = l:version
|
||||
|
||||
break
|
||||
|
|
|
@ -64,16 +64,21 @@ if !hlexists('ALESignColumnWithoutErrors')
|
|||
call ale#sign#SetUpDefaultColumnWithoutErrorsHighlight()
|
||||
endif
|
||||
|
||||
" Spaces and backslashes need to be escaped for signs.
|
||||
function! s:EscapeSignText(sign_text) abort
|
||||
return substitute(a:sign_text, '\\\| ', '\\\0', 'g')
|
||||
endfunction
|
||||
|
||||
" Signs show up on the left for error markers.
|
||||
execute 'sign define ALEErrorSign text=' . g:ale_sign_error
|
||||
execute 'sign define ALEErrorSign text=' . s:EscapeSignText(g:ale_sign_error)
|
||||
\ . ' texthl=ALEErrorSign linehl=ALEErrorLine'
|
||||
execute 'sign define ALEStyleErrorSign text=' . g:ale_sign_style_error
|
||||
execute 'sign define ALEStyleErrorSign text=' . s:EscapeSignText(g:ale_sign_style_error)
|
||||
\ . ' texthl=ALEStyleErrorSign linehl=ALEErrorLine'
|
||||
execute 'sign define ALEWarningSign text=' . g:ale_sign_warning
|
||||
execute 'sign define ALEWarningSign text=' . s:EscapeSignText(g:ale_sign_warning)
|
||||
\ . ' texthl=ALEWarningSign linehl=ALEWarningLine'
|
||||
execute 'sign define ALEStyleWarningSign text=' . g:ale_sign_style_warning
|
||||
execute 'sign define ALEStyleWarningSign text=' . s:EscapeSignText(g:ale_sign_style_warning)
|
||||
\ . ' texthl=ALEStyleWarningSign linehl=ALEWarningLine'
|
||||
execute 'sign define ALEInfoSign text=' . g:ale_sign_info
|
||||
execute 'sign define ALEInfoSign text=' . s:EscapeSignText(g:ale_sign_info)
|
||||
\ . ' texthl=ALEInfoSign linehl=ALEInfoLine'
|
||||
sign define ALEDummySign
|
||||
|
||||
|
|
|
@ -21,5 +21,12 @@ g:ale_cuda_nvcc_options *g:ale_cuda_nvcc_options*
|
|||
|
||||
This variable can be changed to modify flags given to nvcc.
|
||||
|
||||
===============================================================================
|
||||
clang-format *ale-cuda-clangformat*
|
||||
|
||||
See |ale-c-clangformat| for information about the available options.
|
||||
Note that the C options are also used for cuda.
|
||||
|
||||
|
||||
===============================================================================
|
||||
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
|
||||
|
|
|
@ -72,6 +72,18 @@ g:ale_elixir_elixir_ls_config *g:ale_elixir_elixir_ls_config*
|
|||
\ }
|
||||
<
|
||||
Consult the ElixirLS documentation for more information about settings.
|
||||
===============================================================================
|
||||
credo *ale-elixir-credo*
|
||||
|
||||
Credo (https://github.com/rrrene/credo)
|
||||
|
||||
g:ale_elixir_credo_strict *g:ale_elixir_credo_strict*
|
||||
|
||||
Type: Integer
|
||||
Default: 0
|
||||
|
||||
Tells credo to run in strict mode or suggest mode. Set variable to 1 to
|
||||
enable --strict mode.
|
||||
|
||||
===============================================================================
|
||||
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
|
||||
|
|
|
@ -28,6 +28,24 @@ g:ale_elm_format_options *g:ale_elm_format_options*
|
|||
|
||||
This variable can be set to pass additional options to elm-format.
|
||||
|
||||
===============================================================================
|
||||
elm-lsp *ale-elm-elm-lsp*
|
||||
|
||||
g:ale_elm_lsp_executable *g:ale_elm_lsp_executable*
|
||||
*b:ale_elm_lsp_executable*
|
||||
Type: |String|
|
||||
Default: `'elm-lsp'`
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
|
||||
g:ale_elm_lsp_use_global *g:ale_elm_lsp_use_global*
|
||||
*b:ale_elm_lsp_use_global*
|
||||
Type: |Number|
|
||||
Default: `get(g:, 'ale_use_global_executables', 0)`
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
===============================================================================
|
||||
elm-make *ale-elm-elm-make*
|
||||
|
||||
|
|
|
@ -52,7 +52,21 @@ g:ale_json_fixjson_use_global *g:ale_json_fixjson_use_global*
|
|||
===============================================================================
|
||||
jsonlint *ale-json-jsonlint*
|
||||
|
||||
There are no options available.
|
||||
g:ale_json_jsonlint_executable *g:ale_json_jsonlint_executable*
|
||||
*b:ale_json_jsonlint_executable*
|
||||
|
||||
Type: |String|
|
||||
Default: `'jsonlint'`
|
||||
|
||||
The executable that will be run for jsonlint.
|
||||
|
||||
g:ale_json_jsonlint_use_global *g:ale_json_jsonlint_use_global*
|
||||
*b:ale_json_jsonlint_use_global*
|
||||
|
||||
Type: |Number|
|
||||
Default: `get(g:, 'ale_use_global_executables', 0)`
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
|
||||
===============================================================================
|
||||
|
|
|
@ -118,6 +118,7 @@ Notes:
|
|||
* `mix`!!
|
||||
* Elm
|
||||
* `elm-format`
|
||||
* `elm-lsp`
|
||||
* `elm-make`
|
||||
* Erb
|
||||
* `erb`
|
||||
|
@ -241,12 +242,14 @@ Notes:
|
|||
* `luacheck`
|
||||
* Mail
|
||||
* `alex`!!
|
||||
* `languagetool`!!
|
||||
* `proselint`
|
||||
* `vale`
|
||||
* Make
|
||||
* `checkmake`
|
||||
* Markdown
|
||||
* `alex`!!
|
||||
* `languagetool`!!
|
||||
* `markdownlint`!!
|
||||
* `mdl`
|
||||
* `prettier`
|
||||
|
@ -417,6 +420,7 @@ Notes:
|
|||
* `write-good`
|
||||
* Text^
|
||||
* `alex`!!
|
||||
* `languagetool`!!
|
||||
* `proselint`
|
||||
* `redpen`
|
||||
* `textlint`
|
||||
|
|
|
@ -22,8 +22,9 @@ CONTENTS *ale-contents*
|
|||
6.1 Highlights........................|ale-highlights|
|
||||
7. Linter/Fixer Options.................|ale-integration-options|
|
||||
7.1 Options for alex..................|ale-alex-options|
|
||||
7.2 Options for write-good............|ale-write-good-options|
|
||||
7.3 Other Linter/Fixer Options........|ale-other-integration-options|
|
||||
7.2 Options for languagetool..........|ale-languagetool-options|
|
||||
7.3 Options for write-good............|ale-write-good-options|
|
||||
7.4 Other Linter/Fixer Options........|ale-other-integration-options|
|
||||
8. Commands/Keybinds....................|ale-commands|
|
||||
9. API..................................|ale-api|
|
||||
10. Special Thanks......................|ale-special-thanks|
|
||||
|
@ -103,6 +104,7 @@ ALE supports the following key features for linting:
|
|||
stylelint...........................|ale-css-stylelint|
|
||||
cuda..................................|ale-cuda-options|
|
||||
nvcc................................|ale-cuda-nvcc|
|
||||
clang-format........................|ale-cuda-clangformat|
|
||||
d.....................................|ale-d-options|
|
||||
dls.................................|ale-d-dls|
|
||||
uncrustify..........................|ale-d-uncrustify|
|
||||
|
@ -117,8 +119,10 @@ ALE supports the following key features for linting:
|
|||
mix_format..........................|ale-elixir-mix-format|
|
||||
dialyxir............................|ale-elixir-dialyxir|
|
||||
elixir-ls...........................|ale-elixir-elixir-ls|
|
||||
credo...............................|ale-elixir-credo|
|
||||
elm...................................|ale-elm-options|
|
||||
elm-format..........................|ale-elm-elm-format|
|
||||
elm-lsp.............................|ale-elm-elm-lsp|
|
||||
elm-make............................|ale-elm-elm-make|
|
||||
erlang................................|ale-erlang-options|
|
||||
erlc................................|ale-erlang-erlc|
|
||||
|
@ -699,13 +703,13 @@ with |g:ale_completion_excluded_words| or |b:ale_completion_excluded_words|.
|
|||
The |ALEComplete| command can be used to show completion suggestions manually,
|
||||
even when |g:ale_completion_enabled| is set to `0`.
|
||||
|
||||
*ale-completion-completopt-bug*
|
||||
*ale-completion-completeopt-bug*
|
||||
|
||||
ALE implements completion as you type by temporarily adjusting |completeopt|
|
||||
before opening the omnicomplete menu with <C-x><C-o>. In some versions of Vim,
|
||||
the value set for the option will not be respected. If you experience issues
|
||||
with Vim automatically inserting text while you type, set the following option
|
||||
in vimrc, and your issues should go away. >
|
||||
Automatic completion replaces |completeopt| before opening the omnicomplete
|
||||
menu with <C-x><C-o>. In some versions of Vim, the value set for the option
|
||||
will not be respected. If you experience issues with Vim automatically
|
||||
inserting text while you type, set the following option in vimrc, and your
|
||||
issues should go away. >
|
||||
|
||||
set completeopt=menu,menuone,preview,noselect,noinsert
|
||||
<
|
||||
|
@ -2136,7 +2140,19 @@ g:ale_alex_use_global *g:ale_alex_use_global*
|
|||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
7.2. Options for write-good *ale-write-good-options*
|
||||
7.2. Options for languagetool *ale-languagetool-options*
|
||||
|
||||
g:ale_languagetool_executable *g:ale_languagetool_executable*
|
||||
*b:ale_languagetool_executable*
|
||||
|
||||
Type: |String|
|
||||
Default: `'languagetool'`
|
||||
|
||||
The executable to run for languagetool.
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
7.3. Options for write-good *ale-write-good-options*
|
||||
|
||||
The options for `write-good` are shared between all filetypes, so options can
|
||||
be configured once.
|
||||
|
@ -2166,7 +2182,7 @@ g:ale_writegood_use_global *g:ale_writegood_use_global*
|
|||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
7.3. Other Linter/Fixer Options *ale-other-integration-options*
|
||||
7.4. Other Linter/Fixer Options *ale-other-integration-options*
|
||||
|
||||
ALE supports a very wide variety of tools. Other linter or fixer options are
|
||||
documented in additional help files.
|
||||
|
@ -2227,6 +2243,7 @@ documented in additional help files.
|
|||
stylelint.............................|ale-css-stylelint|
|
||||
cuda....................................|ale-cuda-options|
|
||||
nvcc..................................|ale-cuda-nvcc|
|
||||
clang-format..........................|ale-cuda-clangformat|
|
||||
d.......................................|ale-d-options|
|
||||
dls...................................|ale-d-dls|
|
||||
uncrustify............................|ale-d-uncrustify|
|
||||
|
@ -2241,8 +2258,10 @@ documented in additional help files.
|
|||
mix_format............................|ale-elixir-mix-format|
|
||||
dialyxir..............................|ale-elixir-dialyxir|
|
||||
elixir-ls.............................|ale-elixir-elixir-ls|
|
||||
credo.................................|ale-elixir-credo|
|
||||
elm.....................................|ale-elm-options|
|
||||
elm-format............................|ale-elm-elm-format|
|
||||
elm-lsp...............................|ale-elm-elm-lsp|
|
||||
elm-make..............................|ale-elm-elm-make|
|
||||
erlang..................................|ale-erlang-options|
|
||||
erlc..................................|ale-erlang-erlc|
|
||||
|
|
|
@ -216,7 +216,7 @@ command! -bar ALEDocumentation :call ale#hover#ShowDocumentationAtCursor()
|
|||
" Search for appearances of a symbol, such as a type name or function name.
|
||||
command! -nargs=1 ALESymbolSearch :call ale#symbol#Search(<q-args>)
|
||||
|
||||
command! -bar ALEComplete :call ale#completion#AlwaysGetCompletions(0)
|
||||
command! -bar ALEComplete :call ale#completion#GetCompletions(1)
|
||||
|
||||
" <Plug> mappings for commands
|
||||
nnoremap <silent> <Plug>(ale_previous) :ALEPrevious<Return>
|
||||
|
|
|
@ -127,6 +127,7 @@ formatting.
|
|||
* [mix](https://hexdocs.pm/mix/Mix.html) :warning: :floppy_disk:
|
||||
* Elm
|
||||
* [elm-format](https://github.com/avh4/elm-format)
|
||||
* [elm-lsp](https://github.com/antew/elm-lsp)
|
||||
* [elm-make](https://github.com/elm-lang/elm-make)
|
||||
* Erb
|
||||
* [erb](https://apidock.com/ruby/ERB)
|
||||
|
@ -250,12 +251,14 @@ formatting.
|
|||
* [luacheck](https://github.com/mpeterv/luacheck)
|
||||
* Mail
|
||||
* [alex](https://github.com/wooorm/alex) :floppy_disk:
|
||||
* [languagetool](https://languagetool.org/) :floppy_disk:
|
||||
* [proselint](http://proselint.com/)
|
||||
* [vale](https://github.com/ValeLint/vale)
|
||||
* Make
|
||||
* [checkmake](https://github.com/mrtazz/checkmake)
|
||||
* Markdown
|
||||
* [alex](https://github.com/wooorm/alex) :floppy_disk:
|
||||
* [languagetool](https://languagetool.org/) :floppy_disk:
|
||||
* [markdownlint](https://github.com/DavidAnson/markdownlint) :floppy_disk:
|
||||
* [mdl](https://github.com/mivok/markdownlint)
|
||||
* [prettier](https://github.com/prettier/prettier)
|
||||
|
@ -426,6 +429,7 @@ formatting.
|
|||
* [write-good](https://github.com/btford/write-good)
|
||||
* Text
|
||||
* [alex](https://github.com/wooorm/alex) :warning: :floppy_disk:
|
||||
* [languagetool](https://languagetool.org/) :floppy_disk:
|
||||
* [proselint](http://proselint.com/) :warning:
|
||||
* [redpen](http://redpen.cc/) :warning:
|
||||
* [textlint](https://textlint.github.io/) :warning:
|
||||
|
|
|
@ -492,8 +492,7 @@ function! s:openNodeRecursively(node)
|
|||
call nerdtree#echo("Recursively opening node. Please wait...")
|
||||
call a:node.openRecursively()
|
||||
call b:NERDTree.render()
|
||||
redraw
|
||||
call nerdtree#echo("Recursively opening node. Please wait... DONE")
|
||||
redraw!
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:previewBookmark(bookmark) {{{1
|
||||
|
@ -544,9 +543,8 @@ function! s:refreshRoot()
|
|||
call nerdtree#exec(g:NERDTree.GetWinNum() . "wincmd w")
|
||||
call b:NERDTree.root.refresh()
|
||||
call b:NERDTree.render()
|
||||
redraw
|
||||
redraw!
|
||||
call nerdtree#exec(l:curWin . "wincmd w")
|
||||
call nerdtree#echo("Refreshing the root node. This could take a while... DONE")
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:refreshCurrent(node) {{{1
|
||||
|
@ -560,8 +558,7 @@ function! s:refreshCurrent(node)
|
|||
call nerdtree#echo("Refreshing node. This could take a while...")
|
||||
call node.refresh()
|
||||
call b:NERDTree.render()
|
||||
redraw
|
||||
call nerdtree#echo("Refreshing node. This could take a while... DONE")
|
||||
redraw!
|
||||
endfunction
|
||||
|
||||
" FUNCTION: nerdtree#ui_glue#setupCommands() {{{1
|
||||
|
|
|
@ -564,7 +564,11 @@ endfunction
|
|||
" Args:
|
||||
" path: the other path obj to compare this with
|
||||
function! s:Path.equals(path)
|
||||
return self.str() ==# a:path.str()
|
||||
if nerdtree#runningWindows()
|
||||
return self.str() ==? a:path.str()
|
||||
else
|
||||
return self.str() ==# a:path.str()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Path.New(pathStr) {{{1
|
||||
|
|
|
@ -432,9 +432,7 @@ function! s:TreeDirNode._initChildren(silent)
|
|||
|
||||
call self.sortChildren()
|
||||
|
||||
if !a:silent && len(files) > g:NERDTreeNotificationThreshold
|
||||
call nerdtree#echo("Please wait, caching a large dir ... DONE (". self.getChildCount() ." nodes cached).")
|
||||
endif
|
||||
redraw!
|
||||
|
||||
if invalidFilesFound
|
||||
call nerdtree#echoWarning(invalidFilesFound . " file(s) could not be loaded into the NERD tree")
|
||||
|
|
|
@ -60,8 +60,10 @@ function! s:on_stdout_nvim(_job_id, data, _event) dict abort
|
|||
endif
|
||||
endfunction
|
||||
|
||||
function! s:on_stderr_nvim(_job_id, _data, _event) dict abort
|
||||
call self.handler.err(self.buffer)
|
||||
function! s:on_stderr_nvim(_job_id, data, _event) dict abort
|
||||
if a:data != [''] " With Neovim there is always [''] reported on stderr.
|
||||
call self.handler.err(self.buffer)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:on_exit_nvim(_job_id, exit_code, _event) dict abort
|
||||
|
|
|
@ -171,17 +171,17 @@ endfunction
|
|||
|
||||
function! gitgutter#hunk#stage() abort
|
||||
call s:hunk_op(function('s:stage'))
|
||||
silent! call repeat#set("\<Plug>GitGutterStageHunk", -1)<CR>
|
||||
silent! call repeat#set("\<Plug>GitGutterStageHunk", -1)
|
||||
endfunction
|
||||
|
||||
function! gitgutter#hunk#undo() abort
|
||||
call s:hunk_op(function('s:undo'))
|
||||
silent! call repeat#set("\<Plug>GitGutterUndoHunk", -1)<CR>
|
||||
silent! call repeat#set("\<Plug>GitGutterUndoHunk", -1)
|
||||
endfunction
|
||||
|
||||
function! gitgutter#hunk#preview() abort
|
||||
call s:hunk_op(function('s:preview'))
|
||||
silent! call repeat#set("\<Plug>GitGutterPreviewHunk", -1)<CR>
|
||||
silent! call repeat#set("\<Plug>GitGutterPreviewHunk", -1)
|
||||
endfunction
|
||||
|
||||
|
||||
|
|
|
@ -212,9 +212,16 @@ augroup gitgutter
|
|||
" vim -o file1 file2
|
||||
autocmd VimEnter * if winnr() != winnr('$') | call gitgutter#all(0) | endif
|
||||
|
||||
autocmd FocusGained,ShellCmdPost * call gitgutter#all(1)
|
||||
autocmd ShellCmdPost * call gitgutter#all(1)
|
||||
autocmd BufLeave term://* call gitgutter#all(1)
|
||||
|
||||
" Handle all buffers when focus is gained, but only after it was lost.
|
||||
" FocusGained gets triggered on startup with Neovim at least already.
|
||||
" Therefore this tracks also if it was lost before.
|
||||
let s:focus_was_lost = 0
|
||||
autocmd FocusGained * if s:focus_was_lost | let focus_was_lost = 0 | call gitgutter#all(1) | endif
|
||||
autocmd FocusLost * let s:focus_was_lost = 1
|
||||
|
||||
if exists('##VimResume')
|
||||
autocmd VimResume * call gitgutter#all(1)
|
||||
endif
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
.local/
|
||||
.config/
|
||||
.cache/
|
||||
.dlv/
|
||||
.git/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
language: go
|
||||
go:
|
||||
- 1.11.x
|
||||
- 1.12.1
|
||||
notifications:
|
||||
email: false
|
||||
matrix:
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
## unplanned
|
||||
|
||||
FEATURES:
|
||||
* ***gopls support!***
|
||||
* use gopls for autocompletion by default in Vim8 and Neovim.
|
||||
* use gopls for `:GoDef` by setting `g:go_def_mode='gopls'`.
|
||||
* Add support for golangci-lint.
|
||||
* set `g:go_metalinter_command='golanci-lint'` to use golangci-lint instead
|
||||
of gometalinter.
|
||||
* New `:GoDefType` command to jump to a type definition from an instance of the
|
||||
type.
|
||||
|
||||
BACKWARDS INCOMPATABILITIES:
|
||||
* g:go_highlight_function_arguments is renamed to g:go_highlight_function_parameters
|
||||
* `g:go_highlight_function_arguments` is renamed to `g:go_highlight_function_parameters`
|
||||
[[GH-2117]](https://github.com/fatih/vim-go/pull/2117)
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
@ -19,12 +29,12 @@ IMPROVEMENTS:
|
|||
* Do not require `'autowrite'` or `'autowriteall'` to be set when using
|
||||
autocompletion in module mode.
|
||||
[[GH-2091]](https://github.com/fatih/vim-go/pull/2091)
|
||||
* Fix use of g:go_metalinter_command _and_ apply it even when autosaving.
|
||||
* Fix use of `g:go_metalinter_command` _and_ apply it even when autosaving.
|
||||
[[GH-2101]](https://github.com/fatih/vim-go/pull/2101)
|
||||
* Report errors in quickfix when Delve fails to start (e.g. compiler errors).
|
||||
[[GH-2111]](https://github.com/fatih/vim-go/pull/2111)
|
||||
* Support undo_ftplugin, make most autocmd's buffer-local, and only do the bare
|
||||
minimum based on file names alone.
|
||||
* Support `'undo_ftplugin'`, make most autocmds buffer-local, and only do the
|
||||
bare minimum based on file names alone.
|
||||
[[GH-2108]](https://github.com/fatih/vim-go/pull/2108)
|
||||
* Write a message when `:GoInfo` can't display any results when `g:go_info_mode='gocode'`.
|
||||
[[GH-2122]](https://github.com/fatih/vim-go/pull/2122)
|
||||
|
@ -35,8 +45,21 @@ IMPROVEMENTS:
|
|||
* Run `godef` from the current buffer's directory to make sure it works with modules.
|
||||
[[GH-2150]](https://github.com/fatih/vim-go/pull/2150)
|
||||
* Add a function, `go#tool#DescribeBalloon`, to show information in a balloon
|
||||
with `'balloonexpr`. (Vim8 only).
|
||||
with `'balloonexpr'`. (Vim8 only).
|
||||
[[GH-1975]](https://github.com/fatih/vim-go/pull/1975)
|
||||
* Add initial support for `gopls`.
|
||||
[[GH-2163]](https://github.com/fatih/vim-go/pull/2163).
|
||||
* Add `:GoDefType` to jump to the type definition of the identifier under the
|
||||
cursor.
|
||||
[[GH-2165]](https://github.com/fatih/vim-go/pull/2165)
|
||||
* Notify gopls about changes.
|
||||
[[GH-2171]](https://github.com/fatih/vim-go/pull/2171)
|
||||
* Respect `g:go_jump_to_error` when running `gometalinter` automatically on
|
||||
save. [[GH-2176]](https://github.com/fatih/vim-go/pull/2176)
|
||||
* Use gopls for code completion by default in Vim8 and Neovim.
|
||||
[[GH-2172]](https://github.com/fatih/vim-go/pull/2172)
|
||||
* Add support for golangci-lint.
|
||||
[[GH-2182]](https://github.com/fatih/vim-go/pull/2182)
|
||||
|
||||
BUG FIXES:
|
||||
* Fix opening of non-existent file from `:GoDeclsDir` when the current
|
||||
|
@ -55,10 +78,10 @@ BUG FIXES:
|
|||
[[GH-2097]](https://github.com/fatih/vim-go/pull/2097)
|
||||
* Do not clear buffer-local autocmds of other buffers.
|
||||
[[GH-2109]](https://github.com/fatih/vim-go/pull/2109)
|
||||
* Highlight return parameter types when g:go_highlight_function_arguments is set.
|
||||
[[GH-2116]](https://github.com/fatih/vim-go/pull/2116)
|
||||
* Fix lockup in Neovim when trying to run `:GoDebugTest` when there are no tests.
|
||||
[[GH-2125]](https://github.com/fatih/vim-go/pull/2125)
|
||||
* Highlight return parameter types when g:go_highlight_function_arguments is
|
||||
set. [[GH-2116]](https://github.com/fatih/vim-go/pull/2116)
|
||||
* Fix lockup in Neovim when trying to run `:GoDebugTest` when there are no
|
||||
tests. [[GH-2125]](https://github.com/fatih/vim-go/pull/2125)
|
||||
* Keep track of breakpoints correctly when buffer is edited after breakpoints
|
||||
are set.
|
||||
[[GH-2126]](https://github.com/fatih/vim-go/pull/2126)
|
||||
|
@ -66,6 +89,10 @@ BUG FIXES:
|
|||
[[GH-2127]](https://github.com/fatih/vim-go/pull/2127)
|
||||
* Fix jumping to module or package using godef.
|
||||
[[GH-2141]](https://github.com/fatih/vim-go/pull/2141)
|
||||
* Fix errors caused by redefining functions within functions.
|
||||
[[GH-2189]](https://github.com/fatih/vim-go/pull/2189)
|
||||
* Highlight pre-release and metadata in versions in go.mod.
|
||||
[[GH-2192]](https://github.com/fatih/vim-go/pull/2192)
|
||||
|
||||
## 1.19 - (November 4, 2018)
|
||||
|
||||
|
@ -80,7 +107,7 @@ FEATURES:
|
|||
* Auto format on save feature for `:GoModFmt`, enabled automatically. Can be
|
||||
toggled of with the setting `g:go_mod_fmt_autosave` or with the command:
|
||||
`GoModFmtAutoSaveToggle`
|
||||
[[GH-1931]](https://github.com/fatih/vim-go/pull/1931)
|
||||
[[GH-1931]](https://github.com/fatih/vim-go/pull/1931)
|
||||
|
||||
IMPROVEMENTS:
|
||||
* Unify async job handling for Vim8 and Neovim.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.11
|
||||
FROM golang:1.12.1
|
||||
|
||||
RUN apt-get update -y && \
|
||||
apt-get install -y build-essential curl git libncurses5-dev python3-pip && \
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
VIMS ?= vim-7.4 vim-8.0 nvim
|
||||
|
||||
all: install test lint
|
||||
all: install lint test
|
||||
|
||||
install:
|
||||
@echo "==> Installing Vims: $(VIMS)"
|
||||
|
|
|
@ -13,7 +13,7 @@ This plugin adds Go language support for Vim, with the following main features:
|
|||
* Quickly execute your current file(s) with `:GoRun`.
|
||||
* Improved syntax highlighting and folding.
|
||||
* Debug programs with integrated `delve` support with `:GoDebugStart`.
|
||||
* Completion support via `gocode`.
|
||||
* Completion support via `gocode` and `gopls`.
|
||||
* `gofmt` or `goimports` on save keeps the cursor position and undo history.
|
||||
* Go to symbol/declaration with `:GoDef`.
|
||||
* Look up documentation with `:GoDoc` or `:GoDocBrowser`.
|
||||
|
|
|
@ -65,7 +65,7 @@ function! go#auto#metalinter_autosave()
|
|||
endif
|
||||
|
||||
" run gometalinter on save
|
||||
call go#lint#Gometa(0, 1)
|
||||
call go#lint#Gometa(!g:go_jump_to_error, 1)
|
||||
endfunction
|
||||
|
||||
function! go#auto#modfmt_autosave()
|
||||
|
|
|
@ -219,12 +219,22 @@ function! s:trim_bracket(val) abort
|
|||
return a:val
|
||||
endfunction
|
||||
|
||||
let s:completions = ""
|
||||
function! go#complete#Complete(findstart, base) abort
|
||||
let s:completions = []
|
||||
|
||||
function! go#complete#GocodeComplete(findstart, base) abort
|
||||
"findstart = 1 when we need to get the text length
|
||||
if a:findstart == 1
|
||||
execute "silent let s:completions = " . s:gocodeAutocomplete()
|
||||
return col('.') - s:completions[0] - 1
|
||||
let l:completions = []
|
||||
execute "silent let l:completions = " . s:gocodeAutocomplete()
|
||||
|
||||
if len(l:completions) == 0 || len(l:completions) >= 2 && len(l:completions[1]) == 0
|
||||
" no matches. cancel and leave completion mode.
|
||||
call go#util#EchoInfo("no matches")
|
||||
return -3
|
||||
endif
|
||||
|
||||
let s:completions = l:completions[1]
|
||||
return col('.') - l:completions[0] - 1
|
||||
"findstart = 0 when we need to return the list of completions
|
||||
else
|
||||
let s = getline(".")[col('.') - 1]
|
||||
|
@ -236,6 +246,36 @@ function! go#complete#Complete(findstart, base) abort
|
|||
endif
|
||||
endfunction
|
||||
|
||||
function! go#complete#Complete(findstart, base) abort
|
||||
let l:state = {'done': 0, 'matches': []}
|
||||
|
||||
function! s:handler(state, matches) abort dict
|
||||
let a:state.matches = a:matches
|
||||
let a:state.done = 1
|
||||
endfunction
|
||||
|
||||
"findstart = 1 when we need to get the start of the match
|
||||
if a:findstart == 1
|
||||
call go#lsp#Completion(expand('%:p'), line('.'), col('.'), funcref('s:handler', [l:state]))
|
||||
|
||||
while !l:state.done
|
||||
sleep 10m
|
||||
endwhile
|
||||
|
||||
let s:completions = l:state.matches
|
||||
|
||||
if len(l:state.matches) == 0
|
||||
" no matches. cancel and leave completion mode.
|
||||
call go#util#EchoInfo("no matches")
|
||||
return -3
|
||||
endif
|
||||
|
||||
return col('.')
|
||||
else "findstart = 0 when we need to return the list of completions
|
||||
return s:completions
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! go#complete#ToggleAutoTypeInfo() abort
|
||||
if go#config#AutoTypeInfo()
|
||||
call go#config#SetAutoTypeInfo(0)
|
||||
|
|
|
@ -210,6 +210,12 @@ function! go#config#DebugCommands() abort
|
|||
return g:go_debug_commands
|
||||
endfunction
|
||||
|
||||
function! go#config#LspLog() abort
|
||||
" make sure g:go_lsp_log is set so that it can be added to easily.
|
||||
let g:go_lsp_log = get(g:, 'go_lsp_log', [])
|
||||
return g:go_lsp_log
|
||||
endfunction
|
||||
|
||||
function! go#config#SetDebugDiag(value) abort
|
||||
let g:go_debug_diag = a:value
|
||||
endfunction
|
||||
|
@ -235,15 +241,27 @@ function! go#config#SetTemplateAutocreate(value) abort
|
|||
endfunction
|
||||
|
||||
function! go#config#MetalinterCommand() abort
|
||||
return get(g:, "go_metalinter_command", "")
|
||||
return get(g:, "go_metalinter_command", "gometalinter")
|
||||
endfunction
|
||||
|
||||
function! go#config#MetalinterAutosaveEnabled() abort
|
||||
return get(g:, 'go_metalinter_autosave_enabled', ['vet', 'golint'])
|
||||
let l:default_enabled = ["vet", "golint"]
|
||||
|
||||
if go#config#MetalinterCommand() == "golangci-lint"
|
||||
let l:default_enabled = ["govet", "golint"]
|
||||
endif
|
||||
|
||||
return get(g:, "go_metalinter_autosave_enabled", default_enabled)
|
||||
endfunction
|
||||
|
||||
function! go#config#MetalinterEnabled() abort
|
||||
return get(g:, "go_metalinter_enabled", ['vet', 'golint', 'errcheck'])
|
||||
let l:default_enabled = ["vet", "golint", "errcheck"]
|
||||
|
||||
if go#config#MetalinterCommand() == "golangci-lint"
|
||||
let l:default_enabled = ["govet", "golint"]
|
||||
endif
|
||||
|
||||
return get(g:, "go_metalinter_enabled", default_enabled)
|
||||
endfunction
|
||||
|
||||
function! go#config#MetalinterDisabled() abort
|
||||
|
@ -444,7 +462,6 @@ function! go#config#EchoGoInfo() abort
|
|||
return get(g:, "go_echo_go_info", 1)
|
||||
endfunction
|
||||
|
||||
|
||||
" Set the default value. A value of "1" is a shortcut for this, for
|
||||
" compatibility reasons.
|
||||
if exists("g:go_gorename_prefill") && g:go_gorename_prefill == 1
|
||||
|
|
|
@ -507,23 +507,7 @@ function! s:out_cb(ch, msg) abort
|
|||
if has('nvim')
|
||||
let s:state['data'] = []
|
||||
let l:state = {'databuf': ''}
|
||||
function! s:on_data(ch, data, event) dict abort closure
|
||||
let l:data = self.databuf
|
||||
for msg in a:data
|
||||
let l:data .= l:msg
|
||||
endfor
|
||||
|
||||
try
|
||||
let l:res = json_decode(l:data)
|
||||
let s:state['data'] = add(s:state['data'], l:res)
|
||||
let self.databuf = ''
|
||||
catch
|
||||
" there isn't a complete message in databuf: buffer l:data and try
|
||||
" again when more data comes in.
|
||||
let self.databuf = l:data
|
||||
finally
|
||||
endtry
|
||||
endfunction
|
||||
" explicitly bind callback to state so that within it, self will
|
||||
" always refer to state. See :help Partial for more information.
|
||||
let l:state.on_data = function('s:on_data', [], l:state)
|
||||
|
@ -560,6 +544,24 @@ function! s:out_cb(ch, msg) abort
|
|||
endif
|
||||
endfunction
|
||||
|
||||
function! s:on_data(ch, data, event) dict abort
|
||||
let l:data = self.databuf
|
||||
for l:msg in a:data
|
||||
let l:data .= l:msg
|
||||
endfor
|
||||
|
||||
try
|
||||
let l:res = json_decode(l:data)
|
||||
let s:state['data'] = add(s:state['data'], l:res)
|
||||
let self.databuf = ''
|
||||
catch
|
||||
" there isn't a complete message in databuf: buffer l:data and try
|
||||
" again when more data comes in.
|
||||
let self.databuf = l:data
|
||||
finally
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
" Start the debug mode. The first argument is the package name to compile and
|
||||
" debug, anything else will be passed to the running program.
|
||||
function! go#debug#Start(is_test, ...) abort
|
||||
|
|
|
@ -5,7 +5,7 @@ set cpo&vim
|
|||
let s:go_stack = []
|
||||
let s:go_stack_level = 0
|
||||
|
||||
function! go#def#Jump(mode) abort
|
||||
function! go#def#Jump(mode, type) abort
|
||||
let fname = fnamemodify(expand("%"), ':p:gs?\\?/?')
|
||||
|
||||
" so guru right now is slow for some people. previously we were using
|
||||
|
@ -65,8 +65,18 @@ function! go#def#Jump(mode) abort
|
|||
else
|
||||
let [l:out, l:err] = go#util#ExecInDir(l:cmd)
|
||||
endif
|
||||
elseif bin_name == 'gopls'
|
||||
let [l:line, l:col] = getpos('.')[1:2]
|
||||
" delegate to gopls, with an empty job object and an exit status of 0
|
||||
" (they're irrelevant for gopls).
|
||||
if a:type
|
||||
call go#lsp#TypeDef(l:fname, l:line, l:col, function('s:jump_to_declaration_cb', [a:mode, 'gopls', {}, 0]))
|
||||
else
|
||||
call go#lsp#Definition(l:fname, l:line, l:col, function('s:jump_to_declaration_cb', [a:mode, 'gopls', {}, 0]))
|
||||
endif
|
||||
return
|
||||
else
|
||||
call go#util#EchoError('go_def_mode value: '. bin_name .' is not valid. Valid values are: [godef, guru]')
|
||||
call go#util#EchoError('go_def_mode value: '. bin_name .' is not valid. Valid values are: [godef, guru, gopls]')
|
||||
return
|
||||
endif
|
||||
|
||||
|
@ -85,15 +95,19 @@ function! s:jump_to_declaration_cb(mode, bin_name, job, exit_status, data) abort
|
|||
|
||||
call go#def#jump_to_declaration(a:data[0], a:mode, a:bin_name)
|
||||
|
||||
" capture the active window so that after the exit_cb and close_cb callbacks
|
||||
" can return to it when a:mode caused a split.
|
||||
" capture the active window so that callbacks for jobs, exit_cb and
|
||||
" close_cb, and callbacks for gopls can return to it when a:mode caused a
|
||||
" split.
|
||||
let self.winid = win_getid(winnr())
|
||||
endfunction
|
||||
|
||||
" go#def#jump_to_declaration parses out (expected to be
|
||||
" 'filename:line:col: message').
|
||||
function! go#def#jump_to_declaration(out, mode, bin_name) abort
|
||||
let final_out = a:out
|
||||
if a:bin_name == "godef"
|
||||
" append the type information to the same line so our we can parse it.
|
||||
" append the type information to the same line so it will be parsed
|
||||
" correctly using guru's output format.
|
||||
" This makes it compatible with guru output.
|
||||
let final_out = join(split(a:out, '\n'), ':')
|
||||
endif
|
||||
|
|
|
@ -50,7 +50,7 @@ func! Test_Jump_leaves_lists() abort
|
|||
|
||||
let l:bufnr = bufnr('%')
|
||||
call cursor(6, 7)
|
||||
call go#def#Jump('')
|
||||
call go#def#Jump('', 0)
|
||||
|
||||
let start = reltime()
|
||||
while bufnr('%') == l:bufnr && reltimefloat(reltime(start)) < 10
|
||||
|
|
|
@ -128,10 +128,6 @@ function! s:async_guru(args) abort
|
|||
\ 'parse' : get(a:args, 'custom_parse', funcref("s:parse_guru_output"))
|
||||
\ }
|
||||
|
||||
function! s:complete(job, exit_status, messages) dict abort
|
||||
let output = join(a:messages, "\n")
|
||||
call self.parse(a:exit_status, output, self.mode)
|
||||
endfunction
|
||||
" explicitly bind complete to state so that within it, self will
|
||||
" always refer to state. See :help Partial for more information.
|
||||
let state.complete = function('s:complete', [], state)
|
||||
|
@ -164,6 +160,11 @@ function! s:async_guru(args) abort
|
|||
endif
|
||||
endfunc
|
||||
|
||||
function! s:complete(job, exit_status, messages) dict abort
|
||||
let output = join(a:messages, "\n")
|
||||
call self.parse(a:exit_status, output, self.mode)
|
||||
endfunction
|
||||
|
||||
" run_guru runs the given guru argument
|
||||
function! s:run_guru(args) abort
|
||||
if go#util#has_job()
|
||||
|
@ -239,91 +240,6 @@ function! go#guru#DescribeInfo(showstatus) abort
|
|||
return
|
||||
endif
|
||||
|
||||
function! s:info(exit_val, output, mode)
|
||||
if a:exit_val != 0
|
||||
return
|
||||
endif
|
||||
|
||||
if a:output[0] !=# '{'
|
||||
return
|
||||
endif
|
||||
|
||||
if empty(a:output) || type(a:output) != type("")
|
||||
return
|
||||
endif
|
||||
|
||||
let result = json_decode(a:output)
|
||||
if type(result) != type({})
|
||||
call go#util#EchoError(printf("malformed output from guru: %s", a:output))
|
||||
return
|
||||
endif
|
||||
|
||||
if !has_key(result, 'detail')
|
||||
" if there is no detail check if there is a description and print it
|
||||
if has_key(result, "desc")
|
||||
call go#util#EchoInfo(result["desc"])
|
||||
return
|
||||
endif
|
||||
|
||||
call go#util#EchoError("detail key is missing. Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let detail = result['detail']
|
||||
let info = ""
|
||||
|
||||
" guru gives different information based on the detail mode. Let try to
|
||||
" extract the most useful information
|
||||
|
||||
if detail == "value"
|
||||
if !has_key(result, 'value')
|
||||
call go#util#EchoError("value key is missing. Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let val = result["value"]
|
||||
if !has_key(val, 'type')
|
||||
call go#util#EchoError("type key is missing (value.type). Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let info = val["type"]
|
||||
elseif detail == "type"
|
||||
if !has_key(result, 'type')
|
||||
call go#util#EchoError("type key is missing. Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let type = result["type"]
|
||||
if !has_key(type, 'type')
|
||||
call go#util#EchoError("type key is missing (type.type). Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let info = type["type"]
|
||||
elseif detail == "package"
|
||||
if !has_key(result, 'package')
|
||||
call go#util#EchoError("package key is missing. Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let package = result["package"]
|
||||
if !has_key(package, 'path')
|
||||
call go#util#EchoError("path key is missing (package.path). Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let info = printf("package %s", package["path"])
|
||||
elseif detail == "unknown"
|
||||
let info = result["desc"]
|
||||
else
|
||||
call go#util#EchoError(printf("unknown detail mode found '%s'. Please open a bug report on vim-go repo", detail))
|
||||
return
|
||||
endif
|
||||
|
||||
call go#util#ShowInfo(info)
|
||||
endfunction
|
||||
|
||||
let args = {
|
||||
\ 'mode': 'describe',
|
||||
\ 'format': 'json',
|
||||
|
@ -336,6 +252,91 @@ function! go#guru#DescribeInfo(showstatus) abort
|
|||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
||||
function! s:info(exit_val, output, mode)
|
||||
if a:exit_val != 0
|
||||
return
|
||||
endif
|
||||
|
||||
if a:output[0] !=# '{'
|
||||
return
|
||||
endif
|
||||
|
||||
if empty(a:output) || type(a:output) != type("")
|
||||
return
|
||||
endif
|
||||
|
||||
let result = json_decode(a:output)
|
||||
if type(result) != type({})
|
||||
call go#util#EchoError(printf("malformed output from guru: %s", a:output))
|
||||
return
|
||||
endif
|
||||
|
||||
if !has_key(result, 'detail')
|
||||
" if there is no detail check if there is a description and print it
|
||||
if has_key(result, "desc")
|
||||
call go#util#EchoInfo(result["desc"])
|
||||
return
|
||||
endif
|
||||
|
||||
call go#util#EchoError("detail key is missing. Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let detail = result['detail']
|
||||
let info = ""
|
||||
|
||||
" guru gives different information based on the detail mode. Let try to
|
||||
" extract the most useful information
|
||||
|
||||
if detail == "value"
|
||||
if !has_key(result, 'value')
|
||||
call go#util#EchoError("value key is missing. Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let val = result["value"]
|
||||
if !has_key(val, 'type')
|
||||
call go#util#EchoError("type key is missing (value.type). Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let info = val["type"]
|
||||
elseif detail == "type"
|
||||
if !has_key(result, 'type')
|
||||
call go#util#EchoError("type key is missing. Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let type = result["type"]
|
||||
if !has_key(type, 'type')
|
||||
call go#util#EchoError("type key is missing (type.type). Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let info = type["type"]
|
||||
elseif detail == "package"
|
||||
if !has_key(result, 'package')
|
||||
call go#util#EchoError("package key is missing. Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let package = result["package"]
|
||||
if !has_key(package, 'path')
|
||||
call go#util#EchoError("path key is missing (package.path). Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let info = printf("package %s", package["path"])
|
||||
elseif detail == "unknown"
|
||||
let info = result["desc"]
|
||||
else
|
||||
call go#util#EchoError(printf("unknown detail mode found '%s'. Please open a bug report on vim-go repo", detail))
|
||||
return
|
||||
endif
|
||||
|
||||
call go#util#ShowInfo(info)
|
||||
endfunction
|
||||
|
||||
" Show possible targets of selected function call
|
||||
function! go#guru#Callees(selected) abort
|
||||
let args = {
|
||||
|
@ -609,105 +610,6 @@ function! go#guru#DescribeBalloon() abort
|
|||
return
|
||||
endif
|
||||
|
||||
function! s:describe_balloon(exit_val, output, mode)
|
||||
if a:exit_val != 0
|
||||
return
|
||||
endif
|
||||
|
||||
if a:output[0] !=# '{'
|
||||
return
|
||||
endif
|
||||
|
||||
if empty(a:output) || type(a:output) != type("")
|
||||
return
|
||||
endif
|
||||
|
||||
let l:result = json_decode(a:output)
|
||||
if type(l:result) != type({})
|
||||
call go#util#EchoError(printf('malformed output from guru: %s', a:output))
|
||||
return
|
||||
endif
|
||||
|
||||
let l:info = []
|
||||
if has_key(l:result, 'desc')
|
||||
if l:result['desc'] != 'identifier'
|
||||
let l:info = add(l:info, l:result['desc'])
|
||||
endif
|
||||
endif
|
||||
|
||||
if has_key(l:result, 'detail')
|
||||
let l:detail = l:result['detail']
|
||||
|
||||
" guru gives different information based on the detail mode. Let try to
|
||||
" extract the most useful information
|
||||
|
||||
if l:detail == 'value'
|
||||
if !has_key(l:result, 'value')
|
||||
call go#util#EchoError('value key is missing. Please open a bug report on vim-go repo.')
|
||||
return
|
||||
endif
|
||||
|
||||
let l:val = l:result['value']
|
||||
if !has_key(l:val, 'type')
|
||||
call go#util#EchoError('type key is missing (value.type). Please open a bug report on vim-go repo.')
|
||||
return
|
||||
endif
|
||||
|
||||
let l:info = add(l:info, printf('type: %s', l:val['type']))
|
||||
if has_key(l:val, 'value')
|
||||
let l:info = add(l:info, printf('value: %s', l:val['value']))
|
||||
endif
|
||||
elseif l:detail == 'type'
|
||||
if !has_key(l:result, 'type')
|
||||
call go#util#EchoError('type key is missing. Please open a bug report on vim-go repo.')
|
||||
return
|
||||
endif
|
||||
|
||||
let l:type = l:result['type']
|
||||
if !has_key(l:type, 'type')
|
||||
call go#util#EchoError('type key is missing (type.type). Please open a bug report on vim-go repo.')
|
||||
return
|
||||
endif
|
||||
|
||||
let l:info = add(l:info, printf('type: %s', l:type['type']))
|
||||
|
||||
if has_key(l:type, 'methods')
|
||||
let l:info = add(l:info, 'methods:')
|
||||
for l:m in l:type.methods
|
||||
let l:info = add(l:info, printf("\t%s", l:m['name']))
|
||||
endfor
|
||||
endif
|
||||
elseif l:detail == 'package'
|
||||
if !has_key(l:result, 'package')
|
||||
call go#util#EchoError('package key is missing. Please open a bug report on vim-go repo.')
|
||||
return
|
||||
endif
|
||||
|
||||
let l:package = result['package']
|
||||
if !has_key(l:package, 'path')
|
||||
call go#util#EchoError('path key is missing (package.path). Please open a bug report on vim-go repo.')
|
||||
return
|
||||
endif
|
||||
|
||||
let l:info = add(l:info, printf('package: %s', l:package["path"]))
|
||||
elseif l:detail == 'unknown'
|
||||
" the description is already included in l:info, and there's no other
|
||||
" information on unknowns.
|
||||
else
|
||||
call go#util#EchoError(printf('unknown detail mode (%s) found. Please open a bug report on vim-go repo', l:detail))
|
||||
return
|
||||
endif
|
||||
endif
|
||||
|
||||
if has('balloon_eval')
|
||||
call balloon_show(join(l:info, "\n"))
|
||||
return
|
||||
endif
|
||||
|
||||
call balloon_show(l:info)
|
||||
endfunction
|
||||
|
||||
|
||||
" change the active window to the window where the cursor is.
|
||||
let l:winid = win_getid(winnr())
|
||||
call win_gotoid(v:beval_winid)
|
||||
|
@ -730,6 +632,104 @@ function! go#guru#DescribeBalloon() abort
|
|||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:describe_balloon(exit_val, output, mode)
|
||||
if a:exit_val != 0
|
||||
return
|
||||
endif
|
||||
|
||||
if a:output[0] !=# '{'
|
||||
return
|
||||
endif
|
||||
|
||||
if empty(a:output) || type(a:output) != type("")
|
||||
return
|
||||
endif
|
||||
|
||||
let l:result = json_decode(a:output)
|
||||
if type(l:result) != type({})
|
||||
call go#util#EchoError(printf('malformed output from guru: %s', a:output))
|
||||
return
|
||||
endif
|
||||
|
||||
let l:info = []
|
||||
if has_key(l:result, 'desc')
|
||||
if l:result['desc'] != 'identifier'
|
||||
let l:info = add(l:info, l:result['desc'])
|
||||
endif
|
||||
endif
|
||||
|
||||
if has_key(l:result, 'detail')
|
||||
let l:detail = l:result['detail']
|
||||
|
||||
" guru gives different information based on the detail mode. Let try to
|
||||
" extract the most useful information
|
||||
|
||||
if l:detail == 'value'
|
||||
if !has_key(l:result, 'value')
|
||||
call go#util#EchoError('value key is missing. Please open a bug report on vim-go repo.')
|
||||
return
|
||||
endif
|
||||
|
||||
let l:val = l:result['value']
|
||||
if !has_key(l:val, 'type')
|
||||
call go#util#EchoError('type key is missing (value.type). Please open a bug report on vim-go repo.')
|
||||
return
|
||||
endif
|
||||
|
||||
let l:info = add(l:info, printf('type: %s', l:val['type']))
|
||||
if has_key(l:val, 'value')
|
||||
let l:info = add(l:info, printf('value: %s', l:val['value']))
|
||||
endif
|
||||
elseif l:detail == 'type'
|
||||
if !has_key(l:result, 'type')
|
||||
call go#util#EchoError('type key is missing. Please open a bug report on vim-go repo.')
|
||||
return
|
||||
endif
|
||||
|
||||
let l:type = l:result['type']
|
||||
if !has_key(l:type, 'type')
|
||||
call go#util#EchoError('type key is missing (type.type). Please open a bug report on vim-go repo.')
|
||||
return
|
||||
endif
|
||||
|
||||
let l:info = add(l:info, printf('type: %s', l:type['type']))
|
||||
|
||||
if has_key(l:type, 'methods')
|
||||
let l:info = add(l:info, 'methods:')
|
||||
for l:m in l:type.methods
|
||||
let l:info = add(l:info, printf("\t%s", l:m['name']))
|
||||
endfor
|
||||
endif
|
||||
elseif l:detail == 'package'
|
||||
if !has_key(l:result, 'package')
|
||||
call go#util#EchoError('package key is missing. Please open a bug report on vim-go repo.')
|
||||
return
|
||||
endif
|
||||
|
||||
let l:package = result['package']
|
||||
if !has_key(l:package, 'path')
|
||||
call go#util#EchoError('path key is missing (package.path). Please open a bug report on vim-go repo.')
|
||||
return
|
||||
endif
|
||||
|
||||
let l:info = add(l:info, printf('package: %s', l:package["path"]))
|
||||
elseif l:detail == 'unknown'
|
||||
" the description is already included in l:info, and there's no other
|
||||
" information on unknowns.
|
||||
else
|
||||
call go#util#EchoError(printf('unknown detail mode (%s) found. Please open a bug report on vim-go repo', l:detail))
|
||||
return
|
||||
endif
|
||||
endif
|
||||
|
||||
if has('balloon_eval')
|
||||
call balloon_show(join(l:info, "\n"))
|
||||
return
|
||||
endif
|
||||
|
||||
call balloon_show(l:info)
|
||||
endfunction
|
||||
|
||||
" restore Vi compatibility settings
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
|
|
@ -6,11 +6,14 @@ function! Test_gomodVersion_highlight() abort
|
|||
try
|
||||
syntax on
|
||||
|
||||
let l:dir= gotest#write_file('gomodtest/go.mod', [
|
||||
let l:dir = gotest#write_file('gomodtest/go.mod', [
|
||||
\ 'module github.com/fatih/vim-go',
|
||||
\ '',
|
||||
\ '\x1frequire (',
|
||||
\ '\tversion/simple v1.0.0',
|
||||
\ '\tversion/simple-pre-release v1.0.0-rc',
|
||||
\ '\tversion/simple-pre-release v1.0.0+meta',
|
||||
\ '\tversion/simple-pre-release v1.0.0-rc+meta',
|
||||
\ '\tversion/pseudo/premajor v1.0.0-20060102150405-0123456789abcdef',
|
||||
\ '\tversion/pseudo/prerelease v1.0.0-prerelease.0.20060102150405-0123456789abcdef',
|
||||
\ '\tversion/pseudo/prepatch v1.0.1-0.20060102150405-0123456789abcdef',
|
||||
|
@ -55,11 +58,10 @@ function! Test_gomodVersion_incompatible_highlight() abort
|
|||
try
|
||||
syntax on
|
||||
|
||||
let l:dir= gotest#write_file('gomodtest/go.mod', [
|
||||
let l:dir = gotest#write_file('gomodtest/go.mod', [
|
||||
\ 'module github.com/fatih/vim-go',
|
||||
\ '',
|
||||
\ '\x1frequire (',
|
||||
\ '\tversion/invalid/incompatible v1.0.0+incompatible',
|
||||
\ '\tversion/invalid/premajor/incompatible v1.0.0-20060102150405-0123456789abcdef+incompatible',
|
||||
\ '\tversion/invalid/prerelease/incompatible v1.0.0-prerelease.0.20060102150405-0123456789abcdef+incompatible',
|
||||
\ '\tversion/invalid/prepatch/incompatible v1.0.1-0.20060102150405-0123456789abcdef+incompatible',
|
||||
|
|
|
@ -5,7 +5,7 @@ set cpo&vim
|
|||
let s:templatepath = go#util#Join(expand('<sfile>:p:h:h:h'), '.github', 'ISSUE_TEMPLATE.md')
|
||||
|
||||
function! go#issue#New() abort
|
||||
let body = substitute(s:issuebody(), '[^A-Za-z0-9_.~-]', '\="%".printf("%02X",char2nr(submatch(0)))', 'g')
|
||||
let body = go#uriEncode(s:issuebody())
|
||||
let url = "https://github.com/fatih/vim-go/issues/new?body=" . l:body
|
||||
call go#util#OpenBrowser(l:url)
|
||||
endfunction
|
||||
|
|
|
@ -145,23 +145,6 @@ function! go#job#Options(args)
|
|||
let state.custom_complete = a:args.complete
|
||||
endif
|
||||
|
||||
function! s:start(args) dict
|
||||
if go#config#EchoCommandInfo() && self.statustype != ""
|
||||
let prefix = '[' . self.statustype . '] '
|
||||
call go#util#EchoSuccess(prefix . "dispatched")
|
||||
endif
|
||||
|
||||
if self.statustype != ''
|
||||
let status = {
|
||||
\ 'desc': 'current status',
|
||||
\ 'type': self.statustype,
|
||||
\ 'state': "started",
|
||||
\ }
|
||||
|
||||
call go#statusline#Update(self.jobdir, status)
|
||||
endif
|
||||
let self.started_at = reltime()
|
||||
endfunction
|
||||
" explicitly bind _start to state so that within it, self will
|
||||
" always refer to state. See :help Partial for more information.
|
||||
"
|
||||
|
@ -169,35 +152,14 @@ function! go#job#Options(args)
|
|||
" outside of this file.
|
||||
let cbs._start = function('s:start', [''], state)
|
||||
|
||||
function! s:callback(chan, msg) dict
|
||||
call add(self.messages, a:msg)
|
||||
endfunction
|
||||
" explicitly bind callback to state so that within it, self will
|
||||
" always refer to state. See :help Partial for more information.
|
||||
let cbs.callback = function('s:callback', [], state)
|
||||
|
||||
function! s:exit_cb(job, exitval) dict
|
||||
let self.exit_status = a:exitval
|
||||
let self.exited = 1
|
||||
|
||||
call self.show_status(a:job, a:exitval)
|
||||
|
||||
if self.closed || has('nvim')
|
||||
call self.complete(a:job, self.exit_status, self.messages)
|
||||
endif
|
||||
endfunction
|
||||
" explicitly bind exit_cb to state so that within it, self will always refer
|
||||
" to state. See :help Partial for more information.
|
||||
let cbs.exit_cb = function('s:exit_cb', [], state)
|
||||
|
||||
function! s:close_cb(ch) dict
|
||||
let self.closed = 1
|
||||
|
||||
if self.exited
|
||||
let job = ch_getjob(a:ch)
|
||||
call self.complete(job, self.exit_status, self.messages)
|
||||
endif
|
||||
endfunction
|
||||
" explicitly bind close_cb to state so that within it, self will
|
||||
" always refer to state. See :help Partial for more information.
|
||||
let cbs.close_cb = function('s:close_cb', [], state)
|
||||
|
@ -261,6 +223,48 @@ function! go#job#Options(args)
|
|||
return cbs
|
||||
endfunction
|
||||
|
||||
function! s:start(args) dict
|
||||
if go#config#EchoCommandInfo() && self.statustype != ""
|
||||
let prefix = '[' . self.statustype . '] '
|
||||
call go#util#EchoSuccess(prefix . "dispatched")
|
||||
endif
|
||||
|
||||
if self.statustype != ''
|
||||
let status = {
|
||||
\ 'desc': 'current status',
|
||||
\ 'type': self.statustype,
|
||||
\ 'state': "started",
|
||||
\ }
|
||||
|
||||
call go#statusline#Update(self.jobdir, status)
|
||||
endif
|
||||
let self.started_at = reltime()
|
||||
endfunction
|
||||
|
||||
function! s:callback(chan, msg) dict
|
||||
call add(self.messages, a:msg)
|
||||
endfunction
|
||||
|
||||
function! s:exit_cb(job, exitval) dict
|
||||
let self.exit_status = a:exitval
|
||||
let self.exited = 1
|
||||
|
||||
call self.show_status(a:job, a:exitval)
|
||||
|
||||
if self.closed || has('nvim')
|
||||
call self.complete(a:job, self.exit_status, self.messages)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:close_cb(ch) dict
|
||||
let self.closed = 1
|
||||
|
||||
if self.exited
|
||||
let job = ch_getjob(a:ch)
|
||||
call self.complete(job, self.exit_status, self.messages)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" go#job#Start runs a job. The options are expected to be the options
|
||||
" suitable for Vim8 jobs. When called from Neovim, Vim8 options will be
|
||||
" transformed to their Neovim equivalents.
|
||||
|
@ -276,17 +280,24 @@ function! go#job#Start(cmd, options)
|
|||
" early if the directory does not exist. This helps avoid errors when
|
||||
" working with plugins that use virtual files that don't actually exist on
|
||||
" the file system.
|
||||
let filedir = expand("%:p:h")
|
||||
let l:filedir = expand("%:p:h")
|
||||
if has_key(l:options, 'cwd') && !isdirectory(l:options.cwd)
|
||||
return
|
||||
elseif !isdirectory(filedir)
|
||||
elseif !isdirectory(l:filedir)
|
||||
return
|
||||
endif
|
||||
|
||||
let l:manualcd = 0
|
||||
if !has_key(l:options, 'cwd')
|
||||
" pre start
|
||||
let l:manualcd = 1
|
||||
let dir = getcwd()
|
||||
execute l:cd fnameescape(filedir)
|
||||
elseif !(has("patch-8.0.0902") || has('nvim'))
|
||||
let l:manualcd = 1
|
||||
let l:dir = l:options.cwd
|
||||
execute l:cd fnameescape(l:dir)
|
||||
call remove(l:options, 'cwd')
|
||||
endif
|
||||
|
||||
if has_key(l:options, '_start')
|
||||
|
@ -296,6 +307,11 @@ function! go#job#Start(cmd, options)
|
|||
unlet l:options._start
|
||||
endif
|
||||
|
||||
" noblock was added in 8.1.350; remove it if it's not supported.
|
||||
if has_key(l:options, 'noblock') && (has('nvim') || !has("patch-8.1.350"))
|
||||
call remove(l:options, 'noblock')
|
||||
endif
|
||||
|
||||
if go#util#HasDebug('shell-commands')
|
||||
call go#util#EchoInfo('job command: ' . string(a:cmd))
|
||||
endif
|
||||
|
@ -322,9 +338,9 @@ function! go#job#Start(cmd, options)
|
|||
let job = job_start(l:cmd, l:options)
|
||||
endif
|
||||
|
||||
if !has_key(l:options, 'cwd')
|
||||
if l:manualcd
|
||||
" post start
|
||||
execute l:cd fnameescape(dir)
|
||||
execute l:cd fnameescape(l:dir)
|
||||
endif
|
||||
|
||||
return job
|
||||
|
@ -337,6 +353,9 @@ function! s:neooptions(options)
|
|||
let l:options['stdout_buf'] = ''
|
||||
let l:options['stderr_buf'] = ''
|
||||
|
||||
let l:err_mode = get(a:options, 'err_mode', get(a:options, 'mode', ''))
|
||||
let l:out_mode = get(a:options, 'out_mode', get(a:options, 'mode', ''))
|
||||
|
||||
for key in keys(a:options)
|
||||
if key == 'cwd'
|
||||
let l:options['cwd'] = a:options['cwd']
|
||||
|
@ -347,17 +366,11 @@ function! s:neooptions(options)
|
|||
let l:options['callback'] = a:options['callback']
|
||||
|
||||
if !has_key(a:options, 'out_cb')
|
||||
function! s:callback2on_stdout(ch, data, event) dict
|
||||
let self.stdout_buf = s:neocb(a:ch, self.stdout_buf, a:data, self.callback)
|
||||
endfunction
|
||||
let l:options['on_stdout'] = function('s:callback2on_stdout', [], l:options)
|
||||
let l:options['on_stdout'] = function('s:callback2on_stdout', [l:out_mode], l:options)
|
||||
endif
|
||||
|
||||
if !has_key(a:options, 'err_cb')
|
||||
function! s:callback2on_stderr(ch, data, event) dict
|
||||
let self.stderr_buf = s:neocb(a:ch, self.stderr_buf, a:data, self.callback)
|
||||
endfunction
|
||||
let l:options['on_stderr'] = function('s:callback2on_stderr', [], l:options)
|
||||
let l:options['on_stderr'] = function('s:callback2on_stderr', [l:err_mode], l:options)
|
||||
endif
|
||||
|
||||
continue
|
||||
|
@ -365,29 +378,20 @@ function! s:neooptions(options)
|
|||
|
||||
if key == 'out_cb'
|
||||
let l:options['out_cb'] = a:options['out_cb']
|
||||
function! s:on_stdout(ch, data, event) dict
|
||||
let self.stdout_buf = s:neocb(a:ch, self.stdout_buf, a:data, self.out_cb)
|
||||
endfunction
|
||||
let l:options['on_stdout'] = function('s:on_stdout', [], l:options)
|
||||
let l:options['on_stdout'] = function('s:on_stdout', [l:out_mode], l:options)
|
||||
|
||||
continue
|
||||
endif
|
||||
|
||||
if key == 'err_cb'
|
||||
let l:options['err_cb'] = a:options['err_cb']
|
||||
function! s:on_stderr(ch, data, event) dict
|
||||
let self.stderr_buf = s:neocb(a:ch, self.stderr_buf, a:data, self.err_cb )
|
||||
endfunction
|
||||
let l:options['on_stderr'] = function('s:on_stderr', [], l:options)
|
||||
let l:options['on_stderr'] = function('s:on_stderr', [l:err_mode], l:options)
|
||||
|
||||
continue
|
||||
endif
|
||||
|
||||
if key == 'exit_cb'
|
||||
let l:options['exit_cb'] = a:options['exit_cb']
|
||||
function! s:on_exit(jobid, exitval, event) dict
|
||||
call self.exit_cb(a:jobid, a:exitval)
|
||||
endfunction
|
||||
let l:options['on_exit'] = function('s:on_exit', [], l:options)
|
||||
|
||||
continue
|
||||
|
@ -407,6 +411,26 @@ function! s:neooptions(options)
|
|||
return l:options
|
||||
endfunction
|
||||
|
||||
function! s:callback2on_stdout(mode, ch, data, event) dict
|
||||
let self.stdout_buf = s:neocb(a:mode, a:ch, self.stdout_buf, a:data, self.callback)
|
||||
endfunction
|
||||
|
||||
function! s:callback2on_stderr(mode, ch, data, event) dict
|
||||
let self.stderr_buf = s:neocb(a:mode, a:ch, self.stderr_buf, a:data, self.callback)
|
||||
endfunction
|
||||
|
||||
function! s:on_stdout(mode, ch, data, event) dict
|
||||
let self.stdout_buf = s:neocb(a:mode, a:ch, self.stdout_buf, a:data, self.out_cb)
|
||||
endfunction
|
||||
|
||||
function! s:on_stderr(mode, ch, data, event) dict
|
||||
let self.stderr_buf = s:neocb(a:mode, a:ch, self.stderr_buf, a:data, self.err_cb )
|
||||
endfunction
|
||||
|
||||
function! s:on_exit(jobid, exitval, event) dict
|
||||
call self.exit_cb(a:jobid, a:exitval)
|
||||
endfunction
|
||||
|
||||
function! go#job#Stop(job) abort
|
||||
if has('nvim')
|
||||
call jobstop(a:job)
|
||||
|
@ -436,15 +460,34 @@ function! s:winjobarg(idx, val) abort
|
|||
return a:val
|
||||
endfunction
|
||||
|
||||
function! s:neocb(ch, buf, data, callback)
|
||||
function! s:neocb(mode, ch, buf, data, callback)
|
||||
" dealing with the channel lines of Neovim is awful. The docs (:help
|
||||
" channel-lines) say:
|
||||
" stream event handlers may receive partial (incomplete) lines. For a
|
||||
" given invocation of on_stdout etc, `a:data` is not guaranteed to end
|
||||
" with a newline.
|
||||
" - `abcdefg` may arrive as `['abc']`, `['defg']`.
|
||||
" - `abc\nefg` may arrive as `['abc', '']`, `['efg']` or `['abc']`,
|
||||
" `['','efg']`, or even `['ab']`, `['c','efg']`.
|
||||
" stream event handlers may receive partial (incomplete) lines. For a
|
||||
" given invocation of on_stdout etc, `a:data` is not guaranteed to end
|
||||
" with a newline.
|
||||
" - `abcdefg` may arrive as `['abc']`, `['defg']`.
|
||||
" - `abc\nefg` may arrive as `['abc', '']`, `['efg']` or `['abc']`,
|
||||
" `['','efg']`, or even `['ab']`, `['c','efg']`.
|
||||
"
|
||||
" Thankfully, though, this is explained a bit better in an issue:
|
||||
" https://github.com/neovim/neovim/issues/3555. Specifically in these two
|
||||
" comments:
|
||||
" * https://github.com/neovim/neovim/issues/3555#issuecomment-152290804
|
||||
" * https://github.com/neovim/neovim/issues/3555#issuecomment-152588749
|
||||
"
|
||||
" The key is
|
||||
" Every item in the list passed to job control callbacks represents a
|
||||
" string after a newline(Except the first, of course). If the program
|
||||
" outputs: "hello\nworld" the corresponding list is ["hello", "world"].
|
||||
" If the program outputs "hello\nworld\n", the corresponding list is
|
||||
" ["hello", "world", ""]. In other words, you can always determine if
|
||||
" the last line received is complete or not.
|
||||
" and
|
||||
" for every list you receive in a callback, all items except the first
|
||||
" represent newlines.
|
||||
|
||||
let l:buf = ''
|
||||
|
||||
" a single empty string means EOF was reached.
|
||||
if len(a:data) == 1 && a:data[0] == ''
|
||||
|
@ -455,20 +498,28 @@ function! s:neocb(ch, buf, data, callback)
|
|||
endif
|
||||
|
||||
let l:data = [a:buf]
|
||||
let l:buf = ''
|
||||
else
|
||||
let l:data = copy(a:data)
|
||||
let l:data[0] = a:buf . l:data[0]
|
||||
|
||||
" The last element may be a partial line; save it for next time.
|
||||
let l:buf = l:data[-1]
|
||||
|
||||
let l:data = l:data[:-2]
|
||||
if a:mode != 'raw'
|
||||
let l:buf = l:data[-1]
|
||||
let l:data = l:data[:-2]
|
||||
endif
|
||||
endif
|
||||
|
||||
for l:msg in l:data
|
||||
let l:i = 0
|
||||
let l:last = len(l:data) - 1
|
||||
while l:i <= l:last
|
||||
let l:msg = l:data[l:i]
|
||||
if a:mode == 'raw' && l:i < l:last
|
||||
let l:msg = l:msg . "\n"
|
||||
endif
|
||||
call a:callback(a:ch, l:msg)
|
||||
endfor
|
||||
|
||||
let l:i += 1
|
||||
endwhile
|
||||
|
||||
return l:buf
|
||||
endfunction
|
||||
|
|
|
@ -9,22 +9,14 @@ function! go#lint#Gometa(bang, autosave, ...) abort
|
|||
let goargs = a:000
|
||||
endif
|
||||
|
||||
if empty(go#config#MetalinterCommand())
|
||||
let bin_path = go#path#CheckBinPath("gometalinter")
|
||||
if empty(bin_path)
|
||||
let l:metalinter = go#config#MetalinterCommand()
|
||||
|
||||
if l:metalinter == 'gometalinter' || l:metalinter == 'golangci-lint'
|
||||
let cmd = s:metalintercmd(l:metalinter)
|
||||
if empty(cmd)
|
||||
return
|
||||
endif
|
||||
|
||||
let cmd = [bin_path]
|
||||
let cmd += ["--disable-all"]
|
||||
|
||||
" gometalinter has a --tests flag to tell its linters whether to run
|
||||
" against tests. While not all of its linters respect this flag, for those
|
||||
" that do, it means if we don't pass --tests, the linter won't run against
|
||||
" test files. One example of a linter that will not run against tests if
|
||||
" we do not specify this flag is errcheck.
|
||||
let cmd += ["--tests"]
|
||||
|
||||
" linters
|
||||
let linters = a:autosave ? go#config#MetalinterAutosaveEnabled() : go#config#MetalinterEnabled()
|
||||
for linter in linters
|
||||
|
@ -44,15 +36,19 @@ function! go#lint#Gometa(bang, autosave, ...) abort
|
|||
" will be cleared
|
||||
redraw
|
||||
|
||||
" Include only messages for the active buffer for autosave.
|
||||
let include = [printf('--include=^%s:.*$', fnamemodify(expand('%:p'), ":."))]
|
||||
if go#util#has_job()
|
||||
let include = [printf('--include=^%s:.*$', expand('%:p:t'))]
|
||||
if l:metalinter == "gometalinter"
|
||||
" Include only messages for the active buffer for autosave.
|
||||
let include = [printf('--include=^%s:.*$', fnamemodify(expand('%:p'), ":."))]
|
||||
if go#util#has_job()
|
||||
let include = [printf('--include=^%s:.*$', expand('%:p:t'))]
|
||||
endif
|
||||
let cmd += include
|
||||
elseif l:metalinter == "golangci-lint"
|
||||
let goargs[0] = expand('%:p')
|
||||
endif
|
||||
let cmd += include
|
||||
endif
|
||||
|
||||
" Call gometalinter asynchronously.
|
||||
" Call metalinter asynchronously.
|
||||
let deadline = go#config#MetalinterDeadline()
|
||||
if deadline != ''
|
||||
let cmd += ["--deadline=" . deadline]
|
||||
|
@ -60,8 +56,21 @@ function! go#lint#Gometa(bang, autosave, ...) abort
|
|||
|
||||
let cmd += goargs
|
||||
|
||||
if l:metalinter == "gometalinter"
|
||||
" Gometalinter can output one of the two, so we look for both:
|
||||
" <file>:<line>:<column>:<severity>: <message> (<linter>)
|
||||
" <file>:<line>::<severity>: <message> (<linter>)
|
||||
" This can be defined by the following errorformat:
|
||||
let errformat = "%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m"
|
||||
else
|
||||
" Golangci-lint can output the following:
|
||||
" <file>:<line>:<column>: <message> (<linter>)
|
||||
" This can be defined by the following errorformat:
|
||||
let errformat = "%f:%l:%c:\ %m"
|
||||
endif
|
||||
|
||||
if go#util#has_job()
|
||||
call s:lint_job({'cmd': cmd}, a:bang, a:autosave)
|
||||
call s:lint_job({'cmd': cmd, 'statustype': l:metalinter, 'errformat': errformat}, a:bang, a:autosave)
|
||||
return
|
||||
endif
|
||||
|
||||
|
@ -77,12 +86,6 @@ function! go#lint#Gometa(bang, autosave, ...) abort
|
|||
call go#list#Clean(l:listtype)
|
||||
echon "vim-go: " | echohl Function | echon "[metalinter] PASS" | echohl None
|
||||
else
|
||||
" GoMetaLinter can output one of the two, so we look for both:
|
||||
" <file>:<line>:<column>:<severity>: <message> (<linter>)
|
||||
" <file>:<line>::<severity>: <message> (<linter>)
|
||||
" This can be defined by the following errorformat:
|
||||
let errformat = "%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m"
|
||||
|
||||
" Parse and populate our location list
|
||||
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'GoMetaLinter')
|
||||
|
||||
|
@ -205,8 +208,8 @@ endfunction
|
|||
|
||||
function! s:lint_job(args, bang, autosave)
|
||||
let l:opts = {
|
||||
\ 'statustype': "gometalinter",
|
||||
\ 'errorformat': '%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m',
|
||||
\ 'statustype': a:args.statustype,
|
||||
\ 'errorformat': a:args.errformat,
|
||||
\ 'for': "GoMetaLinter",
|
||||
\ 'bang': a:bang,
|
||||
\ }
|
||||
|
@ -221,6 +224,45 @@ function! s:lint_job(args, bang, autosave)
|
|||
call go#job#Spawn(a:args.cmd, l:opts)
|
||||
endfunction
|
||||
|
||||
function! s:metalintercmd(metalinter)
|
||||
let l:cmd = []
|
||||
let bin_path = go#path#CheckBinPath(a:metalinter)
|
||||
if !empty(bin_path)
|
||||
if a:metalinter == "gometalinter"
|
||||
let l:cmd = s:gometalintercmd(bin_path)
|
||||
elseif a:metalinter == "golangci-lint"
|
||||
let l:cmd = s:golangcilintcmd(bin_path)
|
||||
endif
|
||||
endif
|
||||
|
||||
return cmd
|
||||
endfunction
|
||||
|
||||
function! s:gometalintercmd(bin_path)
|
||||
let cmd = [a:bin_path]
|
||||
let cmd += ["--disable-all"]
|
||||
|
||||
" gometalinter has a --tests flag to tell its linters whether to run
|
||||
" against tests. While not all of its linters respect this flag, for those
|
||||
" that do, it means if we don't pass --tests, the linter won't run against
|
||||
" test files. One example of a linter that will not run against tests if
|
||||
" we do not specify this flag is errcheck.
|
||||
let cmd += ["--tests"]
|
||||
return cmd
|
||||
endfunction
|
||||
|
||||
function! s:golangcilintcmd(bin_path)
|
||||
let cmd = [a:bin_path]
|
||||
let cmd += ["run"]
|
||||
let cmd += ["--print-issued-lines=false"]
|
||||
let cmd += ["--disable-all"]
|
||||
" do not use the default exclude patterns, because doing so causes golint
|
||||
" problems about missing doc strings to be ignored and other things that
|
||||
" golint identifies.
|
||||
let cmd += ["--exclude-use-default=false"]
|
||||
return cmd
|
||||
endfunction
|
||||
|
||||
" restore Vi compatibility settings
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
|
|
@ -3,92 +3,128 @@ let s:cpo_save = &cpo
|
|||
set cpo&vim
|
||||
|
||||
func! Test_Gometa() abort
|
||||
call s:gometa('gometaliner')
|
||||
endfunc
|
||||
|
||||
func! Test_GometaGolangciLint() abort
|
||||
call s:gometa('golangci-lint')
|
||||
endfunc
|
||||
|
||||
func! s:gometa(metalinter) abort
|
||||
let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint'
|
||||
silent exe 'e ' . $GOPATH . '/src/lint/lint.go'
|
||||
|
||||
let expected = [
|
||||
\ {'lnum': 5, 'bufnr': bufnr('%')+1, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingFooDoc should have comment or be unexported (golint)'}
|
||||
\ ]
|
||||
try
|
||||
let g:go_metalinter_comand = a:metalinter
|
||||
let expected = [
|
||||
\ {'lnum': 5, 'bufnr': bufnr('%')+1, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingFooDoc should have comment or be unexported (golint)'}
|
||||
\ ]
|
||||
|
||||
" clear the quickfix lists
|
||||
call setqflist([], 'r')
|
||||
" clear the quickfix lists
|
||||
call setqflist([], 'r')
|
||||
|
||||
let g:go_metalinter_enabled = ['golint']
|
||||
let g:go_metalinter_enabled = ['golint']
|
||||
|
||||
call go#lint#Gometa(0, 0, $GOPATH . '/src/foo')
|
||||
call go#lint#Gometa(0, 0, $GOPATH . '/src/foo')
|
||||
|
||||
let actual = getqflist()
|
||||
let start = reltime()
|
||||
while len(actual) == 0 && reltimefloat(reltime(start)) < 10
|
||||
sleep 100m
|
||||
let actual = getqflist()
|
||||
endwhile
|
||||
let start = reltime()
|
||||
while len(actual) == 0 && reltimefloat(reltime(start)) < 10
|
||||
sleep 100m
|
||||
let actual = getqflist()
|
||||
endwhile
|
||||
|
||||
call gotest#assert_quickfix(actual, expected)
|
||||
unlet g:go_metalinter_enabled
|
||||
call gotest#assert_quickfix(actual, expected)
|
||||
finally
|
||||
unlet g:go_metalinter_enabled
|
||||
endtry
|
||||
endfunc
|
||||
|
||||
func! Test_GometaWithDisabled() abort
|
||||
call s:gometawithdisabled('gometalinter')
|
||||
endfunc
|
||||
|
||||
func! Test_GometaWithDisabledGolangciLint() abort
|
||||
call s:gometawithdisabled('golangci-lint')
|
||||
endfunc
|
||||
|
||||
func! s:gometawithdisabled(metalinter) abort
|
||||
let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint'
|
||||
silent exe 'e ' . $GOPATH . '/src/lint/lint.go'
|
||||
|
||||
let expected = [
|
||||
\ {'lnum': 5, 'bufnr': bufnr('%')+1, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingFooDoc should have comment or be unexported (golint)'}
|
||||
\ ]
|
||||
try
|
||||
let g:go_metalinter_comand = a:metalinter
|
||||
let expected = [
|
||||
\ {'lnum': 5, 'bufnr': bufnr('%')+1, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingFooDoc should have comment or be unexported (golint)'}
|
||||
\ ]
|
||||
|
||||
" clear the quickfix lists
|
||||
call setqflist([], 'r')
|
||||
" clear the quickfix lists
|
||||
call setqflist([], 'r')
|
||||
|
||||
let g:go_metalinter_disabled = ['vet']
|
||||
let g:go_metalinter_disabled = ['vet']
|
||||
|
||||
call go#lint#Gometa(0, 0, $GOPATH . '/src/foo')
|
||||
call go#lint#Gometa(0, 0, $GOPATH . '/src/foo')
|
||||
|
||||
let actual = getqflist()
|
||||
let start = reltime()
|
||||
while len(actual) == 0 && reltimefloat(reltime(start)) < 10
|
||||
sleep 100m
|
||||
let actual = getqflist()
|
||||
endwhile
|
||||
let start = reltime()
|
||||
while len(actual) == 0 && reltimefloat(reltime(start)) < 10
|
||||
sleep 100m
|
||||
let actual = getqflist()
|
||||
endwhile
|
||||
|
||||
call gotest#assert_quickfix(actual, expected)
|
||||
unlet g:go_metalinter_disabled
|
||||
call gotest#assert_quickfix(actual, expected)
|
||||
finally
|
||||
unlet g:go_metalinter_disabled
|
||||
endtry
|
||||
endfunc
|
||||
|
||||
func! Test_GometaAutoSave() abort
|
||||
call s:gometaautosave('gometalinter')
|
||||
endfunc
|
||||
|
||||
func! Test_GometaAutoSaveGolangciLint() abort
|
||||
call s:gometaautosave('golangci-lint')
|
||||
endfunc
|
||||
|
||||
func! s:gometaautosave(metalinter) abort
|
||||
let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint'
|
||||
silent exe 'e ' . $GOPATH . '/src/lint/lint.go'
|
||||
|
||||
let expected = [
|
||||
\ {'lnum': 5, 'bufnr': bufnr('%'), 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingDoc should have comment or be unexported (golint)'}
|
||||
\ ]
|
||||
try
|
||||
let g:go_metalinter_comand = a:metalinter
|
||||
let expected = [
|
||||
\ {'lnum': 5, 'bufnr': bufnr('%'), 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingDoc should have comment or be unexported (golint)'}
|
||||
\ ]
|
||||
|
||||
let winnr = winnr()
|
||||
let winnr = winnr()
|
||||
|
||||
" clear the location lists
|
||||
call setloclist(l:winnr, [], 'r')
|
||||
" clear the location lists
|
||||
call setloclist(l:winnr, [], 'r')
|
||||
|
||||
let g:go_metalinter_autosave_enabled = ['golint']
|
||||
let g:go_metalinter_autosave_enabled = ['golint']
|
||||
|
||||
call go#lint#Gometa(0, 1)
|
||||
call go#lint#Gometa(0, 1)
|
||||
|
||||
let actual = getloclist(l:winnr)
|
||||
let start = reltime()
|
||||
while len(actual) == 0 && reltimefloat(reltime(start)) < 10
|
||||
sleep 100m
|
||||
let actual = getloclist(l:winnr)
|
||||
endwhile
|
||||
let start = reltime()
|
||||
while len(actual) == 0 && reltimefloat(reltime(start)) < 10
|
||||
sleep 100m
|
||||
let actual = getloclist(l:winnr)
|
||||
endwhile
|
||||
|
||||
call gotest#assert_quickfix(actual, expected)
|
||||
unlet g:go_metalinter_autosave_enabled
|
||||
call gotest#assert_quickfix(actual, expected)
|
||||
finally
|
||||
unlet g:go_metalinter_autosave_enabled
|
||||
endtry
|
||||
endfunc
|
||||
|
||||
func! Test_Vet()
|
||||
func! Test_Vet() abort
|
||||
let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint'
|
||||
silent exe 'e ' . $GOPATH . '/src/vet/vet.go'
|
||||
compiler go
|
||||
|
||||
let expected = [
|
||||
\ {'lnum': 7, 'bufnr': bufnr('%'), 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '',
|
||||
\ {'lnum': 7, 'bufnr': bufnr('%'), 'col': 2, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '',
|
||||
\ 'text': 'Printf format %d has arg str of wrong type string'}
|
||||
\ ]
|
||||
|
||||
|
|
444
sources_non_forked/vim-go/autoload/go/lsp.vim
Normal file
444
sources_non_forked/vim-go/autoload/go/lsp.vim
Normal file
|
@ -0,0 +1,444 @@
|
|||
" don't spam the user when Vim is started in Vi compatibility mode
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
|
||||
scriptencoding utf-8
|
||||
|
||||
let s:lspfactory = {}
|
||||
|
||||
function! s:lspfactory.get() dict abort
|
||||
if !has_key(self, 'current')
|
||||
" TODO(bc): check that the lsp is still running.
|
||||
let self.current = s:newlsp()
|
||||
endif
|
||||
|
||||
return self.current
|
||||
endfunction
|
||||
|
||||
function! s:lspfactory.reset() dict abort
|
||||
if has_key(self, 'current')
|
||||
call remove(self, 'current')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:newlsp()
|
||||
if !go#util#has_job()
|
||||
" TODO(bc): start the server in the background using a shell that waits for the right output before returning.
|
||||
call go#util#EchoError('This feature requires either Vim 8.0.0087 or newer with +job or Neovim.')
|
||||
return
|
||||
endif
|
||||
|
||||
" job is the job used to talk to the backing instance of gopls.
|
||||
" ready is 0 until the initialize response has been received. 1 afterwards.
|
||||
" queue is messages to send after initialization
|
||||
" last_request_id is id of the most recently sent request.
|
||||
" buf is unprocessed/incomplete responses
|
||||
" handlers is a mapping of request ids to dictionaries of functions.
|
||||
" request id -> {start, requestComplete, handleResult, error}
|
||||
" * start is a function that takes no arguments
|
||||
" * requestComplete is a function that takes 1 argument. The parameter will be 1
|
||||
" if the call was succesful.
|
||||
" * handleResult takes a single argument, the result message received from gopls
|
||||
" * error takes a single argument, the error message received from gopls.
|
||||
" The error method is optional.
|
||||
let l:lsp = {
|
||||
\ 'job': '',
|
||||
\ 'ready': 0,
|
||||
\ 'queue': [],
|
||||
\ 'last_request_id': 0,
|
||||
\ 'buf': '',
|
||||
\ 'handlers': {},
|
||||
\ }
|
||||
|
||||
function! l:lsp.readMessage(data) dict abort
|
||||
let l:responses = []
|
||||
let l:rest = a:data
|
||||
|
||||
while 1
|
||||
" Look for the end of the HTTP headers
|
||||
let l:body_start_idx = matchend(l:rest, "\r\n\r\n")
|
||||
|
||||
if l:body_start_idx < 0
|
||||
" incomplete header
|
||||
break
|
||||
endif
|
||||
|
||||
" Parse the Content-Length header.
|
||||
let l:header = l:rest[:l:body_start_idx - 4]
|
||||
let l:length_match = matchlist(
|
||||
\ l:header,
|
||||
\ '\vContent-Length: *(\d+)'
|
||||
\)
|
||||
|
||||
if empty(l:length_match)
|
||||
" TODO(bc): shutdown gopls?
|
||||
throw "invalid JSON-RPC header:\n" . l:header
|
||||
endif
|
||||
|
||||
" get the start of the rest
|
||||
let l:rest_start_idx = l:body_start_idx + str2nr(l:length_match[1])
|
||||
|
||||
if len(l:rest) < l:rest_start_idx
|
||||
" incomplete response body
|
||||
break
|
||||
endif
|
||||
|
||||
if go#util#HasDebug('lsp')
|
||||
let g:go_lsp_log = add(go#config#LspLog(), "<-\n" . l:rest[:l:rest_start_idx - 1])
|
||||
endif
|
||||
|
||||
let l:body = l:rest[l:body_start_idx : l:rest_start_idx - 1]
|
||||
let l:rest = l:rest[l:rest_start_idx :]
|
||||
|
||||
try
|
||||
" add the json body to the list.
|
||||
call add(l:responses, json_decode(l:body))
|
||||
catch
|
||||
" TODO(bc): log the message and/or show an error message.
|
||||
finally
|
||||
" intentionally left blank.
|
||||
endtry
|
||||
endwhile
|
||||
|
||||
return [l:rest, l:responses]
|
||||
endfunction
|
||||
|
||||
function! l:lsp.handleMessage(ch, data) dict abort
|
||||
let self.buf .= a:data
|
||||
|
||||
let [self.buf, l:responses] = self.readMessage(self.buf)
|
||||
|
||||
" TODO(bc): handle notifications (e.g. window/showMessage).
|
||||
|
||||
for l:response in l:responses
|
||||
if has_key(l:response, 'id') && has_key(self.handlers, l:response.id)
|
||||
try
|
||||
let l:handler = self.handlers[l:response.id]
|
||||
|
||||
if has_key(l:response, 'error')
|
||||
call l:handler.requestComplete(0)
|
||||
call go#util#EchoError(l:response.error.message)
|
||||
if has_key(l:handler, 'error')
|
||||
call call(l:handler.error, [l:response.error.message])
|
||||
endif
|
||||
return
|
||||
endif
|
||||
call l:handler.requestComplete(1)
|
||||
call call(l:handler.handleResult, [l:response.result])
|
||||
finally
|
||||
call remove(self.handlers, l:response.id)
|
||||
endtry
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! l:lsp.handleInitializeResult(result) dict abort
|
||||
let self.ready = 1
|
||||
" TODO(bc): send initialized message to the server?
|
||||
|
||||
" send messages queued while waiting for ready.
|
||||
for l:item in self.queue
|
||||
call self.sendMessage(l:item.data, l:item.handler)
|
||||
endfor
|
||||
|
||||
" reset the queue
|
||||
let self.queue = []
|
||||
endfunction
|
||||
|
||||
function! l:lsp.sendMessage(data, handler) dict abort
|
||||
if !self.last_request_id
|
||||
" TODO(bc): run a server per module and one per GOPATH? (may need to
|
||||
" keep track of servers by rootUri).
|
||||
let l:msg = self.newMessage(go#lsp#message#Initialize(getcwd()))
|
||||
|
||||
let l:state = s:newHandlerState('gopls')
|
||||
let l:state.handleResult = funcref('self.handleInitializeResult', [], l:self)
|
||||
let self.handlers[l:msg.id] = l:state
|
||||
|
||||
call l:state.start()
|
||||
call self.write(l:msg)
|
||||
endif
|
||||
|
||||
if !self.ready
|
||||
call add(self.queue, {'data': a:data, 'handler': a:handler})
|
||||
return
|
||||
endif
|
||||
|
||||
let l:msg = self.newMessage(a:data)
|
||||
if has_key(l:msg, 'id')
|
||||
let self.handlers[l:msg.id] = a:handler
|
||||
endif
|
||||
|
||||
call a:handler.start()
|
||||
call self.write(l:msg)
|
||||
endfunction
|
||||
|
||||
" newMessage returns a message constructed from data. data should be a dict
|
||||
" with 2 or 3 keys: notification, method, and optionally params.
|
||||
function! l:lsp.newMessage(data) dict abort
|
||||
let l:msg = {
|
||||
\ 'method': a:data.method,
|
||||
\ 'jsonrpc': '2.0',
|
||||
\ }
|
||||
|
||||
if !a:data.notification
|
||||
let self.last_request_id += 1
|
||||
let l:msg.id = self.last_request_id
|
||||
endif
|
||||
|
||||
if has_key(a:data, 'params')
|
||||
let l:msg.params = a:data.params
|
||||
endif
|
||||
|
||||
return l:msg
|
||||
endfunction
|
||||
|
||||
function! l:lsp.write(msg) dict abort
|
||||
let l:body = json_encode(a:msg)
|
||||
let l:data = 'Content-Length: ' . strlen(l:body) . "\r\n\r\n" . l:body
|
||||
|
||||
if go#util#HasDebug('lsp')
|
||||
let g:go_lsp_log = add(go#config#LspLog(), "->\n" . l:data)
|
||||
endif
|
||||
|
||||
if has('nvim')
|
||||
call chansend(self.job, l:data)
|
||||
return
|
||||
endif
|
||||
|
||||
call ch_sendraw(self.job, l:data)
|
||||
endfunction
|
||||
|
||||
function! l:lsp.exit_cb(job, exit_status) dict abort
|
||||
call s:lspfactory.reset()
|
||||
endfunction
|
||||
" explicitly bind close_cb to state so that within it, self will always refer
|
||||
|
||||
function! l:lsp.close_cb(ch) dict abort
|
||||
" TODO(bc): does anything need to be done here?
|
||||
endfunction
|
||||
|
||||
function! l:lsp.err_cb(ch, msg) dict abort
|
||||
if go#util#HasDebug('lsp')
|
||||
let g:go_lsp_log = add(go#config#LspLog(), "<-stderr\n" . a:msg)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" explicitly bind callbacks to l:lsp so that within it, self will always refer
|
||||
" to l:lsp instead of l:opts. See :help Partial for more information.
|
||||
let l:opts = {
|
||||
\ 'in_mode': 'raw',
|
||||
\ 'out_mode': 'raw',
|
||||
\ 'err_mode': 'nl',
|
||||
\ 'noblock': 1,
|
||||
\ 'err_cb': funcref('l:lsp.err_cb', [], l:lsp),
|
||||
\ 'out_cb': funcref('l:lsp.handleMessage', [], l:lsp),
|
||||
\ 'close_cb': funcref('l:lsp.close_cb', [], l:lsp),
|
||||
\ 'exit_cb': funcref('l:lsp.exit_cb', [], l:lsp),
|
||||
\ 'cwd': getcwd(),
|
||||
\}
|
||||
|
||||
let l:bin_path = go#path#CheckBinPath("gopls")
|
||||
if empty(l:bin_path)
|
||||
return
|
||||
endif
|
||||
|
||||
" TODO(bc): output a message indicating which directory lsp is going to
|
||||
" start in.
|
||||
let l:lsp.job = go#job#Start([l:bin_path], l:opts)
|
||||
|
||||
" TODO(bc): send the initialize message now?
|
||||
return l:lsp
|
||||
endfunction
|
||||
|
||||
function! s:noop()
|
||||
endfunction
|
||||
|
||||
function! s:newHandlerState(statustype)
|
||||
let l:state = {
|
||||
\ 'winid': win_getid(winnr()),
|
||||
\ 'statustype': a:statustype,
|
||||
\ 'jobdir': getcwd(),
|
||||
\ }
|
||||
|
||||
" explicitly bind requestComplete to state so that within it, self will
|
||||
" always refer to state. See :help Partial for more information.
|
||||
let l:state.requestComplete = funcref('s:requestComplete', [], l:state)
|
||||
|
||||
" explicitly bind start to state so that within it, self will
|
||||
" always refer to state. See :help Partial for more information.
|
||||
let l:state.start = funcref('s:start', [], l:state)
|
||||
|
||||
return l:state
|
||||
endfunction
|
||||
|
||||
function! s:requestComplete(ok) abort dict
|
||||
if self.statustype == ''
|
||||
return
|
||||
endif
|
||||
|
||||
if go#config#EchoCommandInfo()
|
||||
let prefix = '[' . self.statustype . '] '
|
||||
if a:ok
|
||||
call go#util#EchoSuccess(prefix . "SUCCESS")
|
||||
else
|
||||
call go#util#EchoError(prefix . "FAIL")
|
||||
endif
|
||||
endif
|
||||
|
||||
let status = {
|
||||
\ 'desc': 'last status',
|
||||
\ 'type': self.statustype,
|
||||
\ 'state': "success",
|
||||
\ }
|
||||
|
||||
if !a:ok
|
||||
let status.state = "failed"
|
||||
endif
|
||||
|
||||
if has_key(self, 'started_at')
|
||||
let elapsed_time = reltimestr(reltime(self.started_at))
|
||||
" strip whitespace
|
||||
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||
let status.state .= printf(" (%ss)", elapsed_time)
|
||||
endif
|
||||
|
||||
call go#statusline#Update(self.jobdir, status)
|
||||
endfunction
|
||||
|
||||
function! s:start() abort dict
|
||||
if self.statustype != ''
|
||||
let status = {
|
||||
\ 'desc': 'current status',
|
||||
\ 'type': self.statustype,
|
||||
\ 'state': "started",
|
||||
\ }
|
||||
|
||||
call go#statusline#Update(self.jobdir, status)
|
||||
endif
|
||||
let self.started_at = reltime()
|
||||
endfunction
|
||||
|
||||
" go#lsp#Definition calls gopls to get the definition of the identifier at
|
||||
" line and col in fname. handler should be a dictionary function that takes a
|
||||
" list of strings in the form 'file:line:col: message'. handler will be
|
||||
" attached to a dictionary that manages state (statuslines, sets the winid,
|
||||
" etc.)
|
||||
function! go#lsp#Definition(fname, line, col, handler)
|
||||
call go#lsp#DidChange(a:fname)
|
||||
|
||||
let l:lsp = s:lspfactory.get()
|
||||
let l:state = s:newHandlerState('definition')
|
||||
let l:state.handleResult = funcref('s:definitionHandler', [function(a:handler, [], l:state)], l:state)
|
||||
let l:msg = go#lsp#message#Definition(fnamemodify(a:fname, ':p'), a:line, a:col)
|
||||
call l:lsp.sendMessage(l:msg, l:state)
|
||||
endfunction
|
||||
|
||||
function! s:definitionHandler(next, msg) abort dict
|
||||
" gopls returns a []Location; just take the first one.
|
||||
let l:msg = a:msg[0]
|
||||
let l:args = [[printf('%s:%d:%d: %s', go#path#FromURI(l:msg.uri), l:msg.range.start.line+1, l:msg.range.start.character+1, 'lsp does not supply a description')]]
|
||||
call call(a:next, l:args)
|
||||
endfunction
|
||||
|
||||
" go#lsp#Type calls gopls to get the type definition of the identifier at
|
||||
" line and col in fname. handler should be a dictionary function that takes a
|
||||
" list of strings in the form 'file:line:col: message'. handler will be
|
||||
" attached to a dictionary that manages state (statuslines, sets the winid,
|
||||
" etc.)
|
||||
function! go#lsp#TypeDef(fname, line, col, handler)
|
||||
call go#lsp#DidChange(a:fname)
|
||||
|
||||
let l:lsp = s:lspfactory.get()
|
||||
let l:state = s:newHandlerState('type definition')
|
||||
let l:msg = go#lsp#message#TypeDefinition(fnamemodify(a:fname, ':p'), a:line, a:col)
|
||||
let l:state.handleResult = funcref('s:typeDefinitionHandler', [function(a:handler, [], l:state)], l:state)
|
||||
call l:lsp.sendMessage(l:msg, l:state)
|
||||
endfunction
|
||||
|
||||
function! s:typeDefinitionHandler(next, msg) abort dict
|
||||
" gopls returns a []Location; just take the first one.
|
||||
let l:msg = a:msg[0]
|
||||
let l:args = [[printf('%s:%d:%d: %s', go#path#FromURI(l:msg.uri), l:msg.range.start.line+1, l:msg.range.start.character+1, 'lsp does not supply a description')]]
|
||||
call call(a:next, l:args)
|
||||
endfunction
|
||||
|
||||
function! go#lsp#DidOpen(fname)
|
||||
if get(b:, 'go_lsp_did_open', 0)
|
||||
return
|
||||
endif
|
||||
|
||||
let l:lsp = s:lspfactory.get()
|
||||
let l:msg = go#lsp#message#DidOpen(fnamemodify(a:fname, ':p'), join(go#util#GetLines(), "\n") . "\n")
|
||||
let l:state = s:newHandlerState('')
|
||||
let l:state.handleResult = funcref('s:noop')
|
||||
call l:lsp.sendMessage(l:msg, l:state)
|
||||
|
||||
let b:go_lsp_did_open = 1
|
||||
endfunction
|
||||
|
||||
function! go#lsp#DidChange(fname)
|
||||
if get(b:, 'go_lsp_did_open', 0)
|
||||
return go#lsp#DidOpen(a:fname)
|
||||
endif
|
||||
|
||||
let l:lsp = s:lspfactory.get()
|
||||
let l:msg = go#lsp#message#DidChange(fnamemodify(a:fname, ':p'), join(go#util#GetLines(), "\n") . "\n")
|
||||
let l:state = s:newHandlerState('')
|
||||
let l:state.handleResult = funcref('s:noop')
|
||||
call l:lsp.sendMessage(l:msg, l:state)
|
||||
endfunction
|
||||
|
||||
function! go#lsp#DidClose(fname)
|
||||
if !get(b:, 'go_lsp_did_open', 0)
|
||||
return
|
||||
endif
|
||||
|
||||
let l:lsp = s:lspfactory.get()
|
||||
let l:msg = go#lsp#message#DidClose(fnamemodify(a:fname, ':p'))
|
||||
let l:state = s:newHandlerState('')
|
||||
let l:state.handleResult = funcref('s:noop')
|
||||
call l:lsp.sendMessage(l:msg, l:state)
|
||||
|
||||
let b:go_lsp_did_open = 0
|
||||
endfunction
|
||||
|
||||
function! go#lsp#Completion(fname, line, col, handler)
|
||||
call go#lsp#DidChange(a:fname)
|
||||
|
||||
let l:lsp = s:lspfactory.get()
|
||||
let l:msg = go#lsp#message#Completion(a:fname, a:line, a:col)
|
||||
let l:state = s:newHandlerState('completion')
|
||||
let l:state.handleResult = funcref('s:completionHandler', [function(a:handler, [], l:state)], l:state)
|
||||
let l:state.error = funcref('s:completionErrorHandler', [function(a:handler, [], l:state)], l:state)
|
||||
call l:lsp.sendMessage(l:msg, l:state)
|
||||
endfunction
|
||||
|
||||
function! s:completionHandler(next, msg) abort dict
|
||||
" gopls returns a CompletionList.
|
||||
let l:matches = []
|
||||
for l:item in a:msg.items
|
||||
let l:match = {'abbr': l:item.label, 'word': l:item.textEdit.newText, 'info': '', 'kind': go#lsp#completionitemkind#Vim(l:item.kind)}
|
||||
if has_key(l:item, 'detail')
|
||||
let l:item.info = l:item.detail
|
||||
endif
|
||||
|
||||
if has_key(l:item, 'documentation')
|
||||
let l:match.info .= "\n\n" . l:item.documentation
|
||||
endif
|
||||
|
||||
let l:matches = add(l:matches, l:match)
|
||||
endfor
|
||||
let l:args = [l:matches]
|
||||
call call(a:next, l:args)
|
||||
endfunction
|
||||
|
||||
function! s:completionErrorHandler(next, error) abort dict
|
||||
call call(a:next, [[]])
|
||||
endfunction
|
||||
|
||||
" restore Vi compatibility settings
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
" vim: sw=2 ts=2 et
|
|
@ -0,0 +1,47 @@
|
|||
" don't spam the user when Vim is started in Vi compatibility mode
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:Text = 1
|
||||
let s:Method = 2
|
||||
let s:Function = 3
|
||||
let s:Constructor = 4
|
||||
let s:Field = 5
|
||||
let s:Variable = 6
|
||||
let s:Class = 7
|
||||
let s:Interface = 8
|
||||
let s:Module = 9
|
||||
let s:Property = 10
|
||||
let s:Unit = 11
|
||||
let s:Value = 12
|
||||
let s:Enum = 13
|
||||
let s:Keyword = 14
|
||||
let s:Snippet = 15
|
||||
let s:Color = 16
|
||||
let s:File = 17
|
||||
let s:Reference = 18
|
||||
let s:Folder = 19
|
||||
let s:EnumMember = 20
|
||||
let s:Constant = 21
|
||||
let s:Struct = 22
|
||||
let s:Event = 23
|
||||
let s:Operator = 24
|
||||
let s:TypeParameter = 25
|
||||
|
||||
function! go#lsp#completionitemkind#Vim(kind)
|
||||
if a:kind == s:Method || a:kind == s:Function || a:kind == s:Constructor
|
||||
return 'f'
|
||||
elseif a:kind == s:Variable || a:kind == s:Constant
|
||||
return 'v'
|
||||
elseif a:kind == s:Field || a:kind == s:Property
|
||||
return 'm'
|
||||
elseif a:kind == s:Class || a:kind == s:Interface || a:kind == s:Struct
|
||||
return 't'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" restore Vi compatibility settings
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
" vim: sw=2 ts=2 et
|
111
sources_non_forked/vim-go/autoload/go/lsp/message.vim
Normal file
111
sources_non_forked/vim-go/autoload/go/lsp/message.vim
Normal file
|
@ -0,0 +1,111 @@
|
|||
" don't spam the user when Vim is started in Vi compatibility mode
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! go#lsp#message#Initialize(wd)
|
||||
return {
|
||||
\ 'notification': 0,
|
||||
\ 'method': 'initialize',
|
||||
\ 'params': {
|
||||
\ 'processId': getpid(),
|
||||
\ 'rootUri': go#path#ToURI(a:wd),
|
||||
\ 'capabilities': {
|
||||
\ 'workspace': {},
|
||||
\ 'textDocument': {}
|
||||
\ }
|
||||
\ }
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
function! go#lsp#message#Definition(file, line, col)
|
||||
return {
|
||||
\ 'notification': 0,
|
||||
\ 'method': 'textDocument/definition',
|
||||
\ 'params': {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': go#path#ToURI(a:file)
|
||||
\ },
|
||||
\ 'position': s:position(a:line, a:col)
|
||||
\ }
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
|
||||
function! go#lsp#message#TypeDefinition(file, line, col)
|
||||
return {
|
||||
\ 'notification': 0,
|
||||
\ 'method': 'textDocument/typeDefinition',
|
||||
\ 'params': {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': go#path#ToURI(a:file)
|
||||
\ },
|
||||
\ 'position': s:position(a:line, a:col)
|
||||
\ }
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
function! go#lsp#message#DidOpen(file, content)
|
||||
return {
|
||||
\ 'notification': 1,
|
||||
\ 'method': 'textDocument/didOpen',
|
||||
\ 'params': {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': go#path#ToURI(a:file),
|
||||
\ 'languageId': 'go',
|
||||
\ 'text': a:content,
|
||||
\ }
|
||||
\ }
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
function! go#lsp#message#DidChange(file, content)
|
||||
return {
|
||||
\ 'notification': 1,
|
||||
\ 'method': 'textDocument/didChange',
|
||||
\ 'params': {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': go#path#ToURI(a:file),
|
||||
\ },
|
||||
\ 'contentChanges': [
|
||||
\ {
|
||||
\ 'text': a:content,
|
||||
\ }
|
||||
\ ]
|
||||
\ }
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
function! go#lsp#message#DidClose(file)
|
||||
return {
|
||||
\ 'notification': 1,
|
||||
\ 'method': 'textDocument/didClose',
|
||||
\ 'params': {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': go#path#ToURI(a:file),
|
||||
\ }
|
||||
\ }
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
function! go#lsp#message#Completion(file, line, col)
|
||||
return {
|
||||
\ 'notification': 0,
|
||||
\ 'method': 'textDocument/completion',
|
||||
\ 'params': {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': go#path#ToURI(a:file)
|
||||
\ },
|
||||
\ 'position': s:position(a:line, a:col),
|
||||
\ }
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
function! s:position(line, col)
|
||||
return {'line': a:line - 1, 'character': a:col-1}
|
||||
endfunction
|
||||
|
||||
" restore Vi compatibility settings
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
" vim: sw=2 ts=2 et
|
|
@ -205,6 +205,37 @@ function! s:CygwinPath(path)
|
|||
return substitute(a:path, '\\', '/', "g")
|
||||
endfunction
|
||||
|
||||
" go#path#ToURI converts path to a file URI. path should be an absolute path.
|
||||
" Relative paths cannot be properly converted to a URI; when path is a
|
||||
" relative path, the file scheme will not be prepended.
|
||||
function! go#path#ToURI(path)
|
||||
let l:path = a:path
|
||||
if l:path[1:2] is# ':\'
|
||||
let l:path = '/' . l:path[0:1] . l:path[3:]
|
||||
endif
|
||||
|
||||
return substitute(
|
||||
\ (l:path[0] is# '/' ? 'file://' : '') . go#uri#EncodePath(l:path),
|
||||
\ '\\',
|
||||
\ '/',
|
||||
\ 'g',
|
||||
\)
|
||||
endfunction
|
||||
|
||||
function! go#path#FromURI(uri) abort
|
||||
let l:i = len('file://')
|
||||
let l:encoded_path = a:uri[: l:i - 1] is# 'file://' ? a:uri[l:i :] : a:uri
|
||||
|
||||
let l:path = go#uri#Decode(l:encoded_path)
|
||||
|
||||
" If the path is like /C:/foo/bar, it should be C:\foo\bar instead.
|
||||
if l:path =~# '^/[a-zA-Z]:'
|
||||
let l:path = substitute(l:path[1:], '/', '\\', 'g')
|
||||
endif
|
||||
|
||||
return l:path
|
||||
endfunction
|
||||
|
||||
" restore Vi compatibility settings
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
|
|
@ -241,7 +241,7 @@ function! s:errorformat() abort
|
|||
" e.g.:
|
||||
" '\t/usr/local/go/src/time.go:1313 +0x5d'
|
||||
|
||||
" panicaddress, and readyaddress are identical except for
|
||||
" panicaddress and readyaddress are identical except for
|
||||
" panicaddress sets the filename and line number.
|
||||
let panicaddress = "%\\t%f:%l +0x%[0-9A-Fa-f]%\\+"
|
||||
let readyaddress = "%\\t%\\f%\\+:%\\d%\\+ +0x%[0-9A-Fa-f]%\\+"
|
||||
|
@ -264,6 +264,11 @@ function! s:errorformat() abort
|
|||
" the running goroutine's stack.
|
||||
let format .= ",%Z" . panicaddress
|
||||
|
||||
" Match and ignore errors from runtime.goparkunlock(). These started
|
||||
" appearing in stack traces from Go 1.12 test timeouts.
|
||||
let format .= ",%-Gruntime.goparkunlock(%.%#"
|
||||
let format .= ",%-G%\\t" . goroot . "%\\f%\\+:%\\d%\\+"
|
||||
|
||||
" Match and ignore panic address without being part of a multi-line message.
|
||||
" This is to catch those lines that come after the top most non-standard
|
||||
" library line in stack traces.
|
||||
|
@ -290,8 +295,8 @@ function! s:errorformat() abort
|
|||
" It would be nice if this weren't necessary, but panic lines from tests are
|
||||
" prefixed with a single leading tab, making them very similar to 2nd and
|
||||
" later lines of a multi-line compiler error. Swallow it so that it doesn't
|
||||
" cause a quickfix entry since the next entry can add a quickfix entry for
|
||||
" 2nd and later lines of a multi-line compiler error.
|
||||
" cause a quickfix entry since the next %G entry can add a quickfix entry
|
||||
" for 2nd and later lines of a multi-line compiler error.
|
||||
let format .= ",%-C%\\tpanic: %.%#"
|
||||
let format .= ",%G%\\t%m"
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ endfunc
|
|||
|
||||
func! Test_GoTestVet() abort
|
||||
let expected = [
|
||||
\ {'lnum': 6, 'bufnr': 16, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'Errorf format %v reads arg #1, but call has 0 args'},
|
||||
\ {'lnum': 6, 'bufnr': 16, 'col': 2, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'Errorf format %v reads arg #1, but call has 0 args'},
|
||||
\ ]
|
||||
call s:test('veterror/veterror.go', expected)
|
||||
endfunc
|
||||
|
|
34
sources_non_forked/vim-go/autoload/go/uri.vim
Normal file
34
sources_non_forked/vim-go/autoload/go/uri.vim
Normal file
|
@ -0,0 +1,34 @@
|
|||
" don't spam the user when Vim is started in Vi compatibility mode
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! go#uri#Encode(value) abort
|
||||
return s:encode(a:value, '[^A-Za-z0-9_.~-]')
|
||||
endfunction
|
||||
|
||||
function! go#uri#EncodePath(value) abort
|
||||
return s:encode(a:value, '[^/A-Za-z0-9_.~-]')
|
||||
endfunction
|
||||
|
||||
function! s:encode(value, unreserved)
|
||||
return substitute(
|
||||
\ a:value,
|
||||
\ a:unreserved,
|
||||
\ '\="%".printf(''%02X'', char2nr(submatch(0)))',
|
||||
\ 'g'
|
||||
\)
|
||||
endfunction
|
||||
|
||||
function! go#uri#Decode(value) abort
|
||||
return substitute(
|
||||
\ a:value,
|
||||
\ '%\(\x\x\)',
|
||||
\ '\=nr2char(''0X'' . submatch(1))',
|
||||
\ 'g'
|
||||
\)
|
||||
endfunction
|
||||
" restore Vi compatibility settings
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
" vim: sw=2 ts=2 et
|
|
@ -42,7 +42,7 @@ tools developed by the Go community to provide a seamless Vim experience.
|
|||
* Quickly execute your current file(s) with |:GoRun|.
|
||||
* Improved syntax highlighting and folding.
|
||||
* Debug programs with integrated `delve` support with |:GoDebugStart|.
|
||||
* Completion support via `gocode`.
|
||||
* Completion support via `gocode` and `gopls`.
|
||||
* `gofmt` or `goimports` on save keeps the cursor position and undo history.
|
||||
* Go to symbol/declaration with |:GoDef|.
|
||||
* Look up documentation with |:GoDoc| or |:GoDocBrowser|.
|
||||
|
@ -260,7 +260,7 @@ CTRL-]
|
|||
g<C-LeftMouse>
|
||||
<C-LeftMouse>
|
||||
|
||||
Goto declaration/definition for the declaration under the cursor. By
|
||||
Go to declaration/definition for the identifier under the cursor. By
|
||||
default the CTRL-] shortcut, the mapping `gd` and <C-LeftMouse>,
|
||||
g<LeftMouse> are enabled to invoke :GoDef for the identifier under the
|
||||
cursor. See |'g:go_def_mapping_enabled'| to disable them. No explicit
|
||||
|
@ -272,6 +272,14 @@ g<C-LeftMouse>
|
|||
list of file locations you have visited with :GoDef that is retained to
|
||||
help you navigate software.
|
||||
|
||||
The per-window location stack is shared with |:GoDefType|.
|
||||
|
||||
*:GoDefType*
|
||||
:GoDefType
|
||||
|
||||
Go to type definition for the identifier under the cursor.
|
||||
|
||||
The per-window location stack is shared with |:GoDef|.
|
||||
*:GoDefStack*
|
||||
:GoDefStack [number]
|
||||
|
||||
|
@ -1176,6 +1184,15 @@ cleaned for each package after `60` seconds. This can be changed with the
|
|||
Returns the description of the identifer under the cursor. Can be used to plug
|
||||
into the statusline.
|
||||
|
||||
*go#complete#Complete()*
|
||||
|
||||
Uses `gopls` for autocompletion. By default, it is hooked up to |'omnifunc'|
|
||||
for Vim8 and Neovim.
|
||||
|
||||
*go#complete#GocodeComplete()*
|
||||
|
||||
Uses `gocode` for autocompletion. By default, it is hooked up to |'omnifunc'|
|
||||
for Vim 7.4.
|
||||
|
||||
*go#tool#DescribeBalloon()*
|
||||
|
||||
|
@ -1350,7 +1367,7 @@ a private internal service. Default is 'https://godoc.org'.
|
|||
|
||||
Use this option to define the command to be used for |:GoDef|. By default
|
||||
`guru` is being used as it covers all edge cases. But one might also use
|
||||
`godef` as it's faster. Current valid options are: `[guru, godef]` >
|
||||
`godef` as it's faster. Current valid options are: `[guru, godef, gopls]` >
|
||||
|
||||
let g:go_def_mode = 'guru'
|
||||
<
|
||||
|
@ -1498,11 +1515,12 @@ it's empty
|
|||
<
|
||||
*'g:go_metalinter_command'*
|
||||
|
||||
Overrides the command to be executed when |:GoMetaLinter| is called. This is
|
||||
an advanced settings and is for users who want to have a complete control
|
||||
over how `gometalinter` should be executed. By default it's empty.
|
||||
Overrides the command to be executed when |:GoMetaLinter| is called. By
|
||||
default it's `gometalinter`. `golangci-lint` is also supported. It can also be
|
||||
used as an advanced setting for users who want to have more control over
|
||||
the metalinter.
|
||||
>
|
||||
let g:go_metalinter_command = ""
|
||||
let g:go_metalinter_command = "gometalinter"
|
||||
<
|
||||
*'g:go_metalinter_deadline'*
|
||||
|
||||
|
@ -1761,6 +1779,7 @@ Currently accepted values:
|
|||
debugger-state Expose debugger state in 'g:go_debug_diag'.
|
||||
debugger-commands Echo communication between vim-go and `dlv`; requests and
|
||||
responses are recorded in `g:go_debug_commands`.
|
||||
lsp Record lsp requests and responses in g:go_lsp_log.
|
||||
>
|
||||
let g:go_debug = []
|
||||
<
|
||||
|
|
|
@ -25,8 +25,11 @@ setlocal noexpandtab
|
|||
|
||||
compiler go
|
||||
|
||||
" Set gocode completion
|
||||
" Set autocompletion
|
||||
setlocal omnifunc=go#complete#Complete
|
||||
if !go#util#has_job()
|
||||
setlocal omnifunc=go#complete#GocodeComplete
|
||||
endif
|
||||
|
||||
if get(g:, "go_doc_keywordprg_enabled", 1)
|
||||
" keywordprg doesn't allow to use vim commands, override it
|
||||
|
@ -40,8 +43,8 @@ if get(g:, "go_def_mapping_enabled", 1)
|
|||
nnoremap <buffer> <silent> <C-]> :GoDef<cr>
|
||||
nnoremap <buffer> <silent> <C-LeftMouse> <LeftMouse>:GoDef<cr>
|
||||
nnoremap <buffer> <silent> g<LeftMouse> <LeftMouse>:GoDef<cr>
|
||||
nnoremap <buffer> <silent> <C-w><C-]> :<C-u>call go#def#Jump("split")<CR>
|
||||
nnoremap <buffer> <silent> <C-w>] :<C-u>call go#def#Jump("split")<CR>
|
||||
nnoremap <buffer> <silent> <C-w><C-]> :<C-u>call go#def#Jump("split", 0)<CR>
|
||||
nnoremap <buffer> <silent> <C-w>] :<C-u>call go#def#Jump("split", 0)<CR>
|
||||
nnoremap <buffer> <silent> <C-t> :<C-U>call go#def#StackPop(v:count1)<cr>
|
||||
endif
|
||||
|
||||
|
@ -79,6 +82,10 @@ endif
|
|||
augroup vim-go-buffer
|
||||
autocmd! * <buffer>
|
||||
|
||||
" TODO(bc): notify gopls about changes on CursorHold when the buffer is
|
||||
" modified.
|
||||
" TODO(bc): notify gopls that the file on disk is correct on BufWritePost
|
||||
|
||||
autocmd CursorHold <buffer> call go#auto#auto_type_info()
|
||||
autocmd CursorHold <buffer> call go#auto#auto_sameids()
|
||||
|
||||
|
|
|
@ -54,7 +54,8 @@ command! -nargs=* -bang GoCoverageBrowser call go#coverage#Browser(<bang>0, <f-a
|
|||
command! -nargs=0 -range=% GoPlay call go#play#Share(<count>, <line1>, <line2>)
|
||||
|
||||
" -- def
|
||||
command! -nargs=* -range GoDef :call go#def#Jump('')
|
||||
command! -nargs=* -range GoDef :call go#def#Jump('', 0)
|
||||
command! -nargs=* -range GoDefType :call go#def#Jump('', 1)
|
||||
command! -nargs=? GoDefPop :call go#def#StackPop(<f-args>)
|
||||
command! -nargs=? GoDefStack :call go#def#Stack(<f-args>)
|
||||
command! -nargs=? GoDefStackClear :call go#def#StackClear(<f-args>)
|
||||
|
|
|
@ -53,10 +53,15 @@ nnoremap <silent> <Plug>(go-rename) :<C-u>call go#rename#Rename(!g:go_jump_to_er
|
|||
nnoremap <silent> <Plug>(go-decls) :<C-u>call go#decls#Decls(0, '')<CR>
|
||||
nnoremap <silent> <Plug>(go-decls-dir) :<C-u>call go#decls#Decls(1, '')<CR>
|
||||
|
||||
nnoremap <silent> <Plug>(go-def) :<C-u>call go#def#Jump('')<CR>
|
||||
nnoremap <silent> <Plug>(go-def-vertical) :<C-u>call go#def#Jump("vsplit")<CR>
|
||||
nnoremap <silent> <Plug>(go-def-split) :<C-u>call go#def#Jump("split")<CR>
|
||||
nnoremap <silent> <Plug>(go-def-tab) :<C-u>call go#def#Jump("tab")<CR>
|
||||
nnoremap <silent> <Plug>(go-def) :<C-u>call go#def#Jump('', 0)<CR>
|
||||
nnoremap <silent> <Plug>(go-def-vertical) :<C-u>call go#def#Jump("vsplit", 0)<CR>
|
||||
nnoremap <silent> <Plug>(go-def-split) :<C-u>call go#def#Jump("split", 0)<CR>
|
||||
nnoremap <silent> <Plug>(go-def-tab) :<C-u>call go#def#Jump("tab", 0)<CR>
|
||||
|
||||
nnoremap <silent> <Plug>(go-def-type) :<C-u>call go#def#Jump('', 1)<CR>
|
||||
nnoremap <silent> <Plug>(go-def-type-vertical) :<C-u>call go#def#Jump("vsplit", 1)<CR>
|
||||
nnoremap <silent> <Plug>(go-def-type-split) :<C-u>call go#def#Jump("split", 1)<CR>
|
||||
nnoremap <silent> <Plug>(go-def-type-tab) :<C-u>call go#def#Jump("tab", 1)<CR>
|
||||
|
||||
nnoremap <silent> <Plug>(go-def-pop) :<C-u>call go#def#StackPop()<CR>
|
||||
nnoremap <silent> <Plug>(go-def-stack) :<C-u>call go#def#Stack()<CR>
|
||||
|
|
|
@ -56,7 +56,9 @@ let s:packages = {
|
|||
\ 'gogetdoc': ['github.com/zmb3/gogetdoc'],
|
||||
\ 'goimports': ['golang.org/x/tools/cmd/goimports'],
|
||||
\ 'golint': ['golang.org/x/lint/golint'],
|
||||
\ 'gopls': ['golang.org/x/tools/cmd/gopls'],
|
||||
\ 'gometalinter': ['github.com/alecthomas/gometalinter'],
|
||||
\ 'golangci-lint': ['github.com/golangci/golangci-lint/cmd/golangci-lint'],
|
||||
\ 'gomodifytags': ['github.com/fatih/gomodifytags'],
|
||||
\ 'gorename': ['golang.org/x/tools/cmd/gorename'],
|
||||
\ 'gotags': ['github.com/jstemmer/gotags'],
|
||||
|
|
|
@ -38,25 +38,48 @@ highlight default link gomodReplaceOperator Operator
|
|||
|
||||
|
||||
" highlight versions:
|
||||
" * vX.Y.Z-pre
|
||||
" * vX.Y.Z
|
||||
" * vX.0.0-yyyyymmddhhmmss-abcdefabcdef
|
||||
" * vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef
|
||||
" * vX.Y.(Z+1)-0.yyyymmddhhss-abcdefabcdef
|
||||
" * +incompatible suffix when X > 1
|
||||
" see https://godoc.org/golang.org/x/tools/internal/semver for more
|
||||
" information about how semantic versions are parsed and
|
||||
" https://golang.org/cmd/go/ for how pseudo-versions and +incompatible
|
||||
" are applied.
|
||||
|
||||
|
||||
" match vX.Y.Z and their prereleases
|
||||
syntax match gomodVersion "v\d\+\.\d\+\.\d\+\%(-\%(\w\+\.\)\+0\.\d\{14}-\x\+\)\?"
|
||||
" match target when most recent version before the target is X.Y.Z
|
||||
syntax match gomodVersion "v\d\+\.\d\+\.[1-9]\{1}\d*\%(-0\.\%(\d\{14}-\x\+\)\)\?"
|
||||
" match target without a major version before the commit (e.g. vX.0.0-yyyymmddhhmmss-abcdefabcdef)
|
||||
syntax match gomodVersion "v\d\+\.0\.0-\d\{14\}-\x\+"
|
||||
syntax match gomodVersion "v\d\+\.\d\+\.\d\+\%(-\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\)\?\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?"
|
||||
" ^--- version ---^^------------ pre-release ---------------------^^--------------- metadata ---------------------^
|
||||
" ^--------------------------------------- semantic version -------------------------------------------------------^
|
||||
|
||||
" match vX.Y.Z and their prereleases for X>1
|
||||
syntax match gomodVersion "v[2-9]\{1}\d\?\.\d\+\.\d\+\%(-\%(\w\+\.\)\+0\.\d\{14\}-\x\+\)\?\%(+incompatible\>\)\?"
|
||||
" match target when most recent version before the target is X.Y.Z for X>1
|
||||
syntax match gomodVersion "v[2-9]\{1}\d\?\.\d\+\.[1-9]\{1}\d*\%(-0\.\%(\d\{14\}-\x\+\)\)\?\%(+incompatible\>\)\?"
|
||||
" match target without a major version before the commit (e.g. vX.0.0-yyyymmddhhmmss-abcdefabcdef) for X>1
|
||||
syntax match gomodVersion "v[2-9]\{1}\d\?\.0\.0-\d\{14\}-\x\+\%(+incompatible\>\)\?"
|
||||
" match pseudo versions
|
||||
" without a major version before the commit (e.g. vX.0.0-yyyymmddhhmmss-abcdefabcdef)
|
||||
syntax match gomodVersion "v\d\+\.0\.0-\d\{14\}-\x\+"
|
||||
" when most recent version before target is a pre-release
|
||||
syntax match gomodVersion "v\d\+\.\d\+\.\d\+-\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?\.0\.\d\{14}-\x\+"
|
||||
" ^--- version ---^^--- ------ pre-release -----------------^^--------------- metadata ---------------------^
|
||||
" ^------------------------------------- semantic version --------------------------------------------------^
|
||||
" most recent version before the target is X.Y.Z
|
||||
syntax match gomodVersion "v\d\+\.\d\+\.\d\+\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?-0\.\d\{14}-\x\+"
|
||||
" ^--- version ---^^--------------- metadata ---------------------^
|
||||
|
||||
" match incompatible vX.Y.Z and their prereleases
|
||||
syntax match gomodVersion "v[2-9]\{1}\d*\.\d\+\.\d\+\%(-\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\)\?\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?+incompatible"
|
||||
" ^------- version -------^^------------- pre-release ---------------------^^--------------- metadata ---------------------^
|
||||
" ^------------------------------------------- semantic version -----------------------------------------------------------^
|
||||
|
||||
" match incompatible pseudo versions
|
||||
" incompatible without a major version before the commit (e.g. vX.0.0-yyyymmddhhmmss-abcdefabcdef)
|
||||
syntax match gomodVersion "v[2-9]\{1}\d*\.0\.0-\d\{14\}-\x\++incompatible"
|
||||
" when most recent version before target is a pre-release
|
||||
syntax match gomodVersion "v[2-9]\{1}\d*\.\d\+\.\d\+-\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\%(+\%([0-9A-Za-z-]\+\)\(\.[0-9A-Za-z-]\+\)*\)\?\.0\.\d\{14}-\x\++incompatible"
|
||||
" ^------- version -------^^---------- pre-release -----------------^^--------------- metadata ---------------------^
|
||||
" ^---------------------------------------- semantic version ------------------------------------------------------^
|
||||
" most recent version before the target is X.Y.Z
|
||||
syntax match gomodVersion "v[2-9]\{1}\d*\.\d\+\.\d\+\%(+\%([0-9A-Za-z-]\+\)\%(\.[0-9A-Za-z-]\+\)*\)\?-0\.\d\{14}-\x\++incompatible"
|
||||
" ^------- version -------^^---------------- metadata ---------------------^
|
||||
highlight default link gomodVersion Identifier
|
||||
|
||||
let b:current_syntax = "gomod"
|
||||
|
|
|
@ -14,7 +14,7 @@ Syntax highlighting, matching rules and mappings for [the original Markdown](htt
|
|||
|
||||
## Installation
|
||||
|
||||
If you use [Vundle](https://github.com/gmarik/vundle), add the following line to your `~/.vimrc`:
|
||||
If you use [Vundle](https://github.com/gmarik/vundle), add the following lines to your `~/.vimrc`:
|
||||
|
||||
```vim
|
||||
Plugin 'godlygeek/tabular'
|
||||
|
|
|
@ -151,10 +151,20 @@ let b:fenced_block = 0
|
|||
let b:front_matter = 0
|
||||
let s:vim_markdown_folding_level = get(g:, "vim_markdown_folding_level", 1)
|
||||
|
||||
if !get(g:, "vim_markdown_folding_disabled", 0)
|
||||
setlocal foldexpr=Foldexpr_markdown(v:lnum)
|
||||
setlocal foldmethod=expr
|
||||
if get(g:, "vim_markdown_folding_style_pythonic", 0) && get(g:, "vim_markdown_override_foldtext", 1)
|
||||
setlocal foldtext=Foldtext_markdown()
|
||||
endif
|
||||
endif
|
||||
function! s:MarkdownSetupFolding()
|
||||
if !get(g:, "vim_markdown_folding_disabled", 0)
|
||||
setlocal foldexpr=Foldexpr_markdown(v:lnum)
|
||||
setlocal foldmethod=expr
|
||||
if get(g:, "vim_markdown_folding_style_pythonic", 0) && get(g:, "vim_markdown_override_foldtext", 1)
|
||||
setlocal foldtext=Foldtext_markdown()
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
call s:MarkdownSetupFolding()
|
||||
augroup Mkd
|
||||
" These autocmds need to be kept in sync with the autocmds calling
|
||||
" s:MarkdownRefreshSyntax in ftplugin/markdown.vim.
|
||||
autocmd BufWinEnter,BufWritePost <buffer> call s:MarkdownSetupFolding()
|
||||
autocmd InsertEnter,InsertLeave <buffer> call s:MarkdownSetupFolding()
|
||||
autocmd CursorHold,CursorHoldI <buffer> call s:MarkdownSetupFolding()
|
||||
augroup END
|
||||
|
|
|
@ -780,6 +780,8 @@ function! s:MarkdownClearSyntaxVariables()
|
|||
endfunction
|
||||
|
||||
augroup Mkd
|
||||
" These autocmd calling s:MarkdownRefreshSyntax need to be kept in sync with
|
||||
" the autocmds calling s:MarkdownSetupFolding in after/ftplugin/markdown.vim.
|
||||
autocmd! * <buffer>
|
||||
autocmd BufWinEnter <buffer> call s:MarkdownRefreshSyntax(1)
|
||||
autocmd BufUnload <buffer> call s:MarkdownClearSyntaxVariables()
|
||||
|
|
|
@ -4,6 +4,8 @@ set rtp+=../build/tabular/
|
|||
set rtp+=../build/vim-toml/
|
||||
set rtp+=../build/vim-json/
|
||||
set rtp+=../build/vader.vim/
|
||||
set rtp-=~/.vim
|
||||
set rtp-=~/.vim/after
|
||||
let $LANG='en_US'
|
||||
filetype on
|
||||
filetype plugin on
|
||||
|
|
|
@ -1230,7 +1230,7 @@ function! s:wait_for_user_input(mode)
|
|||
let s:saved_keys = ""
|
||||
endif
|
||||
|
||||
" ambiguous mappings are note supported; e.g.:
|
||||
" ambiguous mappings are not supported; e.g.:
|
||||
" imap jj JJ
|
||||
" imap jjj JJJ
|
||||
" will always trigger the 'jj' mapping
|
||||
|
@ -1239,8 +1239,8 @@ function! s:wait_for_user_input(mode)
|
|||
let s_time = s:get_time_in_ms()
|
||||
while 1
|
||||
let map_dict = maparg(s:char, "i", 0, 1)
|
||||
" break if chars exactly match mapping or if chars don't match beging of mapping anymore
|
||||
if map_dict != {} || mapcheck(s:char, "i") == ""
|
||||
" break if chars exactly match mapping
|
||||
if map_dict != {}
|
||||
if get(map_dict, 'expr', 0)
|
||||
" handle case where {rhs} is a function
|
||||
exec 'let char_mapping = ' . map_dict['rhs']
|
||||
|
@ -1251,6 +1251,10 @@ function! s:wait_for_user_input(mode)
|
|||
exec 'let s:char = "'.substitute(char_mapping, '<', '\\<', 'g').'"'
|
||||
break
|
||||
endif
|
||||
" break if chars don't match beginning of mapping anymore
|
||||
if mapcheck(s:char, "i") == ""
|
||||
break
|
||||
endif
|
||||
if s:get_time_in_ms() > (s_time + &timeoutlen)
|
||||
break
|
||||
endif
|
||||
|
|
|
@ -170,9 +170,12 @@ describe "Multiple Cursors op pending & exit from insert|visual mode" do
|
|||
|
||||
end
|
||||
|
||||
describe "Multiple Cursors when using insert mapings" do
|
||||
describe "Multiple Cursors when using insert mappings" do
|
||||
let(:filename) { 'test.txt' }
|
||||
let(:options) { ['set timeoutlen=10000', 'imap jj <esc>', 'imap jojo dude'] }
|
||||
let(:options) { ['set timeoutlen=10000',
|
||||
'imap jj <esc>',
|
||||
'imap jojo dude',
|
||||
'imap jk <esc>:%s/bla/hey/g<cr>'] }
|
||||
specify "#mapping doing <Esc>" do
|
||||
before <<-EOF
|
||||
hello world!
|
||||
|
@ -191,6 +194,24 @@ describe "Multiple Cursors when using insert mapings" do
|
|||
EOF
|
||||
end
|
||||
|
||||
specify "#mapping doing <Esc> and running a command" do
|
||||
before <<-EOF
|
||||
hello world!
|
||||
hello world!
|
||||
bla bla bla
|
||||
bla bla bla
|
||||
EOF
|
||||
|
||||
type 'w<C-n><C-n>ctherejk'
|
||||
|
||||
after <<-EOF
|
||||
hello there!
|
||||
hello there!
|
||||
hey hey hey
|
||||
hey hey hey
|
||||
EOF
|
||||
end
|
||||
|
||||
specify "#mapping using more than 2 characters" do
|
||||
before <<-EOF
|
||||
hello
|
||||
|
@ -209,6 +230,24 @@ describe "Multiple Cursors when using insert mapings" do
|
|||
EOF
|
||||
end
|
||||
|
||||
specify "#unused mapping" do
|
||||
before <<-EOF
|
||||
hello world!
|
||||
hello world!
|
||||
bla bla bla
|
||||
bla bla bla
|
||||
EOF
|
||||
|
||||
type 'w<C-n><C-n>chey joseph blah blah blah<Esc>'
|
||||
|
||||
after <<-EOF
|
||||
hello hey joseph blah blah blah!
|
||||
hello hey joseph blah blah blah!
|
||||
bla bla bla
|
||||
bla bla bla
|
||||
EOF
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "Multiple Cursors when normal_maps is empty" do
|
||||
|
|
|
@ -96,4 +96,54 @@ snippet fund "function declaration" b
|
|||
${1:void} ${2:function_name}($3);
|
||||
endsnippet
|
||||
|
||||
global !p
|
||||
def split_line(text):
|
||||
import textwrap
|
||||
lines = textwrap.wrap(text, 78 - 19)
|
||||
output = list()
|
||||
for line in lines:
|
||||
output.append('*' + ' '*19 + line)
|
||||
snip_line = snip.tabstops[4].end[0]
|
||||
snip.buffer.append(output, snip_line + 1)
|
||||
del snip.buffer[snip_line]
|
||||
|
||||
def get_args(arglist):
|
||||
args = [arg.strip() for arg in arglist.split(',') if arg]
|
||||
return args
|
||||
endglobal
|
||||
|
||||
post_jump "if snip.tabstop == 0 : split_line(snip.tabstops[4].current_text)"
|
||||
snippet head "File Header" b
|
||||
/******************************************************************************
|
||||
* File: `!p snip.rv = fn`
|
||||
*
|
||||
* Author: ${2}
|
||||
* Created: `date +%m/%d/%y`
|
||||
* Description: ${4:${VISUAL}}
|
||||
*****************************************************************************/
|
||||
${0}
|
||||
endsnippet
|
||||
|
||||
post_jump "if snip.tabstop == 0 : split_line(snip.tabstops[4].current_text)"
|
||||
snippet func "Function Header"
|
||||
/******************************************************************************
|
||||
* Function: $1
|
||||
* Description: ${4:${VISUAL}}
|
||||
* Where:`!p
|
||||
snip.rv = ""
|
||||
snip >> 2
|
||||
|
||||
args = get_args(t[2])
|
||||
if args:
|
||||
for arg in args:
|
||||
snip.rv += '\n' + '*' + ' '*19 + arg + ' - TODO'
|
||||
snip << 2
|
||||
`
|
||||
* Return: $5
|
||||
* Error: $6
|
||||
*****************************************************************************/
|
||||
${1}($2){
|
||||
${0}
|
||||
}
|
||||
endsnippet
|
||||
# vim:ft=snippets:
|
||||
|
|
|
@ -656,6 +656,10 @@ snippet desc
|
|||
describe ${1:`substitute(substitute(vim_snippets#Filename(), '_spec$', '', ''), '\(_\|^\)\(.\)', '\u\2', 'g')`} do
|
||||
${0}
|
||||
end
|
||||
snippet rdesc
|
||||
RSpec.describe ${1:`substitute(substitute(vim_snippets#Filename(), '_spec$', '', ''), '\(_\|^\)\(.\)', '\u\2', 'g')`} do
|
||||
${0}
|
||||
end
|
||||
snippet descm
|
||||
describe '${1:#method}' do
|
||||
${0:pending 'Not implemented'}
|
||||
|
|
|
@ -212,7 +212,7 @@ snippet under underline text
|
|||
snippet over overline text
|
||||
\\overline{${1:${VISUAL:text}}} ${0}
|
||||
snippet emp emphasize text
|
||||
\\emph{${1:${VISUAL:text}}} ${0}
|
||||
\\emph{${1:${VISUAL:text}}}${0}
|
||||
snippet sc small caps text
|
||||
\\textsc{${1:${VISUAL:text}}} ${0}
|
||||
#Choosing font
|
||||
|
|
|
@ -28,26 +28,27 @@ snippet vbase
|
|||
|
||||
<script>
|
||||
export default{
|
||||
|
||||
${0}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
snippet vimport:c
|
||||
import New from './components/New.vue';
|
||||
|
||||
export default{
|
||||
snippet vimport:c
|
||||
import ${1:Name} from './components/$1.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
appNew: New
|
||||
$1
|
||||
}
|
||||
}
|
||||
|
||||
snippet vactionsis now
|
||||
|
||||
snippet vactions
|
||||
actions: {
|
||||
updateValue({commit}, payload) {
|
||||
commit(updateValue, payload);
|
||||
${1:updateValue}({commit}, ${2:payload}) {
|
||||
commit($1, $2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,6 +59,7 @@ snippet vanim:js:el
|
|||
@enter="enter"
|
||||
@after-enter="afterEnter"
|
||||
@enter-cancelled="enterCancelled"
|
||||
|
||||
@before-Leave="beforeLeave"
|
||||
@leave="leave"
|
||||
@after-leave="afterLeave"
|
||||
|
@ -68,116 +70,109 @@ snippet vanim:js:el
|
|||
|
||||
snippet vanim:js:method
|
||||
methods: {
|
||||
beforeEnter(el) {
|
||||
console.log('beforeEnter');
|
||||
},
|
||||
enter(el, done) {
|
||||
console.log('enter');
|
||||
done();
|
||||
},
|
||||
afterEnter(el) {
|
||||
console.log('afterEnter');
|
||||
},
|
||||
enterCancelled(el, done) {
|
||||
console.log('enterCancelled');
|
||||
},
|
||||
beforeLeave(el) {
|
||||
console.log('beforeLeave');
|
||||
},
|
||||
leave(el, done) {
|
||||
console.log('leave');
|
||||
done();
|
||||
},
|
||||
afterLeave(el) {
|
||||
console.log('afterLeave');
|
||||
},
|
||||
leaveCancelled(el, done) {
|
||||
console.log('leaveCancelled');
|
||||
}
|
||||
beforeEnter(el) {
|
||||
console.log('beforeEnter');
|
||||
},
|
||||
enter(el, done) {
|
||||
console.log('enter');
|
||||
done();
|
||||
},
|
||||
afterEnter(el) {
|
||||
console.log('afterEnter');
|
||||
},
|
||||
enterCancelled(el, done) {
|
||||
console.log('enterCancelled');
|
||||
},
|
||||
beforeLeave(el) {
|
||||
console.log('beforeLeave');
|
||||
},
|
||||
leave(el, done) {
|
||||
console.log('leave');
|
||||
done();
|
||||
},
|
||||
afterLeave(el) {
|
||||
console.log('afterLeave');
|
||||
},
|
||||
leaveCancelled(el, done) {
|
||||
console.log('leaveCancelled');
|
||||
}
|
||||
}
|
||||
|
||||
snippet vcl
|
||||
@click=""
|
||||
@click="${1}"
|
||||
|
||||
snippet vdata
|
||||
data: function () {
|
||||
return {
|
||||
key: value
|
||||
};
|
||||
data() {
|
||||
return {
|
||||
${1:key}: ${2:value}
|
||||
};
|
||||
}
|
||||
|
||||
snippet vfilter
|
||||
filters: {
|
||||
fnName: function (v) {
|
||||
return;
|
||||
}
|
||||
${1:fnName}: function(${2:value}) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
snippet vfor
|
||||
<div v-for="item in items" :key="item.id">
|
||||
{{ item }}
|
||||
<div v-for="${1:item} in ${2:items}" :key="$1.id">
|
||||
{{ $1 }}
|
||||
</div
|
||||
|
||||
snippet vgetters
|
||||
getters: {
|
||||
value: state => {
|
||||
return state.value;
|
||||
${1:value}: state => {
|
||||
return state.$1;
|
||||
}
|
||||
}
|
||||
|
||||
snippet vimport
|
||||
import New from './components/New.vue';
|
||||
import ${1:New} from './components/$1.vue';
|
||||
|
||||
snippet vkeep
|
||||
<keep-alive>
|
||||
<component :is="">
|
||||
<p>default</p>
|
||||
</component>
|
||||
<component :is="">
|
||||
<p>default</p>
|
||||
</component>
|
||||
</keep-alive>
|
||||
|
||||
snippet vmixin
|
||||
// define a mixin object
|
||||
var myMixin = {
|
||||
created: function () {
|
||||
this.hello()
|
||||
},
|
||||
methods: {
|
||||
hello: function () {
|
||||
console.log('hello from mixin!')
|
||||
}
|
||||
}
|
||||
const ${1:mixinName} = {
|
||||
mounted() {
|
||||
console.log('hello from mixin!')
|
||||
},
|
||||
}
|
||||
// define a component that uses this mixin
|
||||
var Component = Vue.extend({
|
||||
mixins: [myMixin]
|
||||
const ${2:Component} = Vue.extend({
|
||||
mixins: [$1]
|
||||
})
|
||||
var component = new Component() // -> "hello from mixin!"
|
||||
|
||||
snippet vmutations
|
||||
// define a mixin object
|
||||
var myMixin = {
|
||||
created: function () {
|
||||
this.hello()
|
||||
},
|
||||
methods: {
|
||||
hello: function () {
|
||||
console.log('hello from mixin!')
|
||||
mutations: {
|
||||
${1:updateValue}(state, ${3:payload}) => {
|
||||
state.${2:value} = $3;
|
||||
}
|
||||
}
|
||||
}
|
||||
// define a component that uses this mixin
|
||||
var Component = Vue.extend({
|
||||
mixins: [myMixin]
|
||||
})
|
||||
var component = new Component() // -> "hello from mixin!"
|
||||
|
||||
snippet vprops:d
|
||||
propName: {
|
||||
type: Number,
|
||||
default: 100
|
||||
${1:propName}: {
|
||||
type: ${2:Number},
|
||||
default: ${0}
|
||||
},
|
||||
|
||||
snippet vprops
|
||||
propName: {
|
||||
type: Number
|
||||
${1:propName}: {
|
||||
type: ${2:Number}
|
||||
},
|
||||
|
||||
snippet vstore
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
export const store = new Vuex.Store({
|
||||
state: {
|
||||
${1:key}: ${2:value}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -135,6 +135,16 @@ tag, its attributes are kept in the new tag. End your input with > to discard
|
|||
the those attributes. If <C-T> is used, the tags will appear on lines by
|
||||
themselves.
|
||||
|
||||
If f, F, or <C-F> is used, Vim prompts for a function name to insert. The target
|
||||
text will be wrapped in a function call. If f is used, the text is wrapped with
|
||||
() parentheses; F adds additional spaces inside the parentheses. <C-F> inserts the
|
||||
function name inside the parentheses.
|
||||
|
||||
Old text Command New text ~
|
||||
"hello" ysWfprint<cr> print("hello")
|
||||
"hello" ysWFprint<cr> print( "hello" )
|
||||
"hello" ysW<C-f>print<cr> (print "hello")
|
||||
|
||||
If s is used, a leading but not trailing space is added. This is useful for
|
||||
removing parentheses from a function call with csbs.
|
||||
|
||||
|
|
Loading…
Reference in a new issue