Updated plugins
This commit is contained in:
parent
46f1a1bd52
commit
587a185a98
89 changed files with 2619 additions and 1634 deletions
|
@ -31,6 +31,6 @@ call ale#linter#Define('apiblueprint', {
|
|||
\ 'name': 'drafter',
|
||||
\ 'output_stream': 'stderr',
|
||||
\ 'executable': 'drafter',
|
||||
\ 'command': 'drafter --use-line-num --validate %t',
|
||||
\ 'command': 'drafter --use-line-num --validate',
|
||||
\ 'callback': 'ale_linters#apiblueprint#drafter#HandleErrors',
|
||||
\})
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
" Author: Sumner Evans <sumner.evans98@gmail.com>
|
||||
" Description: write-good for AsciiDoc files
|
||||
|
||||
call ale#linter#Define('asciidoc', {
|
||||
\ 'name': 'write-good',
|
||||
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
|
||||
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
call ale#handlers#writegood#DefineLinter('asciidoc')
|
||||
|
|
|
@ -14,10 +14,10 @@ function! ale_linters#c#clang#GetCommand(buffer, output) abort
|
|||
" -iquote with the directory the file is in makes #include work for
|
||||
" headers in the same directory.
|
||||
return ale#Escape(ale_linters#c#clang#GetExecutable(a:buffer))
|
||||
\ . ' -S -x c -fsyntax-only '
|
||||
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' '
|
||||
\ . l:cflags
|
||||
\ . ale#Var(a:buffer, 'c_clang_options') . ' -'
|
||||
\ . ' -S -x c -fsyntax-only'
|
||||
\ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
|
||||
\ . ale#Pad(l:cflags)
|
||||
\ . ale#Pad(ale#Var(a:buffer, 'c_clang_options')) . ' -'
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('c', {
|
||||
|
@ -28,5 +28,5 @@ call ale#linter#Define('c', {
|
|||
\ {'callback': 'ale#c#GetMakeCommand', 'output_stream': 'stdout'},
|
||||
\ {'callback': 'ale_linters#c#clang#GetCommand'}
|
||||
\ ],
|
||||
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
|
||||
\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes',
|
||||
\})
|
||||
|
|
29
sources_non_forked/ale/ale_linters/c/clangd.vim
Normal file
29
sources_non_forked/ale/ale_linters/c/clangd.vim
Normal file
|
@ -0,0 +1,29 @@
|
|||
" Author: Andrey Melentyev <andrey.melentyev@protonmail.com>
|
||||
" Description: Clangd language server
|
||||
|
||||
call ale#Set('c_clangd_executable', 'clangd')
|
||||
call ale#Set('c_clangd_options', '')
|
||||
|
||||
function! ale_linters#c#clangd#GetProjectRoot(buffer) abort
|
||||
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
|
||||
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
|
||||
endfunction
|
||||
|
||||
function! ale_linters#c#clangd#GetExecutable(buffer) abort
|
||||
return ale#Var(a:buffer, 'c_clangd_executable')
|
||||
endfunction
|
||||
|
||||
function! ale_linters#c#clangd#GetCommand(buffer) abort
|
||||
let l:executable = ale_linters#c#clangd#GetExecutable(a:buffer)
|
||||
let l:options = ale#Var(a:buffer, 'c_clangd_options')
|
||||
|
||||
return ale#Escape(l:executable) . (!empty(l:options) ? ' ' . l:options : '')
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('c', {
|
||||
\ 'name': 'clangd',
|
||||
\ 'lsp': 'stdio',
|
||||
\ 'executable_callback': 'ale_linters#c#clangd#GetExecutable',
|
||||
\ 'command_callback': 'ale_linters#c#clangd#GetCommand',
|
||||
\ 'project_root_callback': 'ale_linters#c#clangd#GetProjectRoot',
|
||||
\})
|
|
@ -35,7 +35,7 @@ function! s:GetBuildDirectory(buffer) abort
|
|||
return l:build_dir
|
||||
endif
|
||||
|
||||
return ale#c#FindCompileCommands(a:buffer)
|
||||
return ale#path#Dirname(ale#c#FindCompileCommands(a:buffer))
|
||||
endfunction
|
||||
|
||||
function! ale_linters#c#clangtidy#GetCommand(buffer) abort
|
||||
|
|
32
sources_non_forked/ale/ale_linters/c/cquery.vim
Normal file
32
sources_non_forked/ale/ale_linters/c/cquery.vim
Normal file
|
@ -0,0 +1,32 @@
|
|||
" Author: Ben Falconer <ben@falconers.me.uk>, jtalowell <jtalowell@protonmail.com>
|
||||
" Description: A language server for C
|
||||
|
||||
call ale#Set('c_cquery_executable', 'cquery')
|
||||
call ale#Set('c_cquery_cache_directory', expand('~/.cache/cquery'))
|
||||
|
||||
function! ale_linters#c#cquery#GetProjectRoot(buffer) abort
|
||||
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
|
||||
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
|
||||
endfunction
|
||||
|
||||
function! ale_linters#c#cquery#GetExecutable(buffer) abort
|
||||
return ale#Var(a:buffer, 'c_cquery_executable')
|
||||
endfunction
|
||||
|
||||
function! ale_linters#c#cquery#GetCommand(buffer) abort
|
||||
let l:executable = ale_linters#c#cquery#GetExecutable(a:buffer)
|
||||
return ale#Escape(l:executable)
|
||||
endfunction
|
||||
|
||||
function! ale_linters#c#cquery#GetInitializationOptions(buffer) abort
|
||||
return {'cacheDirectory': ale#Var(a:buffer, 'c_cquery_cache_directory')}
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('c', {
|
||||
\ 'name': 'cquery',
|
||||
\ 'lsp': 'stdio',
|
||||
\ 'executable_callback': 'ale_linters#c#cquery#GetExecutable',
|
||||
\ 'command_callback': 'ale_linters#c#cquery#GetCommand',
|
||||
\ 'project_root_callback': 'ale_linters#c#cquery#GetProjectRoot',
|
||||
\ 'initialization_options_callback': 'ale_linters#c#cquery#GetInitializationOptions',
|
||||
\})
|
|
@ -14,10 +14,10 @@ function! ale_linters#c#gcc#GetCommand(buffer, output) abort
|
|||
" -iquote with the directory the file is in makes #include work for
|
||||
" headers in the same directory.
|
||||
return ale#Escape(ale_linters#c#gcc#GetExecutable(a:buffer))
|
||||
\ . ' -S -x c -fsyntax-only '
|
||||
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' '
|
||||
\ . l:cflags
|
||||
\ . ale#Var(a:buffer, 'c_gcc_options') . ' -'
|
||||
\ . ' -S -x c -fsyntax-only'
|
||||
\ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
|
||||
\ . ale#Pad(l:cflags)
|
||||
\ . ale#Pad(ale#Var(a:buffer, 'c_gcc_options')) . ' -'
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('c', {
|
||||
|
@ -28,5 +28,5 @@ call ale#linter#Define('c', {
|
|||
\ {'callback': 'ale#c#GetMakeCommand', 'output_stream': 'stdout'},
|
||||
\ {'callback': 'ale_linters#c#gcc#GetCommand'}
|
||||
\ ],
|
||||
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
|
||||
\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes',
|
||||
\})
|
||||
|
|
|
@ -27,6 +27,6 @@ call ale#linter#Define('clojure', {
|
|||
\ 'name': 'joker',
|
||||
\ 'output_stream': 'stderr',
|
||||
\ 'executable': 'joker',
|
||||
\ 'command': 'joker --lint %t',
|
||||
\ 'command': 'joker --working-dir %s --lint %t',
|
||||
\ 'callback': 'ale_linters#clojure#joker#HandleJokerFormat',
|
||||
\})
|
||||
|
|
|
@ -14,10 +14,10 @@ function! ale_linters#cpp#clang#GetCommand(buffer, output) abort
|
|||
" -iquote with the directory the file is in makes #include work for
|
||||
" headers in the same directory.
|
||||
return ale#Escape(ale_linters#cpp#clang#GetExecutable(a:buffer))
|
||||
\ . ' -S -x c++ -fsyntax-only '
|
||||
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' '
|
||||
\ . l:cflags
|
||||
\ . ale#Var(a:buffer, 'cpp_clang_options') . ' -'
|
||||
\ . ' -S -x c++ -fsyntax-only'
|
||||
\ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
|
||||
\ . ale#Pad(l:cflags)
|
||||
\ . ale#Pad(ale#Var(a:buffer, 'cpp_clang_options')) . ' -'
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('cpp', {
|
||||
|
@ -28,5 +28,5 @@ call ale#linter#Define('cpp', {
|
|||
\ {'callback': 'ale#c#GetMakeCommand', 'output_stream': 'stdout'},
|
||||
\ {'callback': 'ale_linters#cpp#clang#GetCommand'},
|
||||
\ ],
|
||||
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
|
||||
\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes',
|
||||
\})
|
||||
|
|
|
@ -16,7 +16,7 @@ function! ale_linters#cpp#clangcheck#GetCommand(buffer) abort
|
|||
let l:build_dir = ale#Var(a:buffer, 'c_build_dir')
|
||||
|
||||
if empty(l:build_dir)
|
||||
let l:build_dir = ale#c#FindCompileCommands(a:buffer)
|
||||
let l:build_dir = ale#path#Dirname(ale#c#FindCompileCommands(a:buffer))
|
||||
endif
|
||||
|
||||
" The extra arguments in the command are used to prevent .plist files from
|
||||
|
|
|
@ -29,7 +29,7 @@ function! s:GetBuildDirectory(buffer) abort
|
|||
return l:build_dir
|
||||
endif
|
||||
|
||||
return ale#c#FindCompileCommands(a:buffer)
|
||||
return ale#path#Dirname(ale#c#FindCompileCommands(a:buffer))
|
||||
endfunction
|
||||
|
||||
function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort
|
||||
|
|
|
@ -14,10 +14,10 @@ function! ale_linters#cpp#gcc#GetCommand(buffer, output) abort
|
|||
" -iquote with the directory the file is in makes #include work for
|
||||
" headers in the same directory.
|
||||
return ale#Escape(ale_linters#cpp#gcc#GetExecutable(a:buffer))
|
||||
\ . ' -S -x c++ -fsyntax-only '
|
||||
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' '
|
||||
\ . l:cflags
|
||||
\ . ale#Var(a:buffer, 'cpp_gcc_options') . ' -'
|
||||
\ . ' -S -x c++ -fsyntax-only'
|
||||
\ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
|
||||
\ . ale#Pad(l:cflags)
|
||||
\ . ale#Pad(ale#Var(a:buffer, 'cpp_gcc_options')) . ' -'
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('cpp', {
|
||||
|
@ -29,5 +29,5 @@ call ale#linter#Define('cpp', {
|
|||
\ {'callback': 'ale#c#GetMakeCommand', 'output_stream': 'stdout'},
|
||||
\ {'callback': 'ale_linters#cpp#gcc#GetCommand'},
|
||||
\ ],
|
||||
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
|
||||
\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes',
|
||||
\})
|
||||
|
|
|
@ -28,7 +28,7 @@ endfunction
|
|||
call ale#linter#Define('elixir', {
|
||||
\ 'name': 'dialyxir',
|
||||
\ 'executable': 'mix',
|
||||
\ 'command': 'mix dialyzer',
|
||||
\ 'command': 'mix help dialyzer && mix dialyzer',
|
||||
\ 'callback': 'ale_linters#elixir#dialyxir#Handle',
|
||||
\})
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ function! ale_linters#elm#make#ParseMessage(message) abort
|
|||
endfunction
|
||||
|
||||
function! ale_linters#elm#make#ParseMessageItem(item) abort
|
||||
if type(a:item) == type('')
|
||||
if type(a:item) is v:t_string
|
||||
return a:item
|
||||
else
|
||||
return a:item.string
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
" Author: unpairedbracket ben.spiers22@gmail.com
|
||||
" Description: A language server for fortran
|
||||
|
||||
call ale#Set('fortran_language_server_executable', 'fortls')
|
||||
call ale#Set('fortran_language_server_use_global', get(g:, 'ale_use_global_executables', 0))
|
||||
|
||||
function! ale_linters#fortran#language_server#GetExecutable(buffer) abort
|
||||
return ale#Var(a:buffer, 'fortran_language_server_executable')
|
||||
endfunction
|
||||
|
||||
function! ale_linters#fortran#language_server#GetCommand(buffer) abort
|
||||
return ale#Escape(ale_linters#fortran#language_server#GetExecutable(a:buffer))
|
||||
endfunction
|
||||
|
||||
function! ale_linters#fortran#language_server#GetProjectRoot(buffer) abort
|
||||
let l:fortls_file = ale#path#FindNearestFile(a:buffer, '.fortls')
|
||||
|
||||
return !empty(l:fortls_file) ? fnamemodify(l:fortls_file, ':h') : ''
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('fortran', {
|
||||
\ 'name': 'language_server',
|
||||
\ 'lsp': 'stdio',
|
||||
\ 'executable_callback': 'ale_linters#fortran#language_server#GetExecutable',
|
||||
\ 'command_callback': 'ale_linters#fortran#language_server#GetCommand',
|
||||
\ 'project_root_callback': 'ale_linters#fortran#language_server#GetProjectRoot',
|
||||
\})
|
|
@ -70,7 +70,8 @@ function! ale_linters#go#gobuild#Handler(buffer, lines) abort
|
|||
endfunction
|
||||
|
||||
call ale#linter#Define('go', {
|
||||
\ 'name': 'go build',
|
||||
\ 'name': 'gobuild',
|
||||
\ 'aliases': ['go build'],
|
||||
\ 'executable': 'go',
|
||||
\ 'command_chain': [
|
||||
\ {'callback': 'ale_linters#go#gobuild#GoEnv', 'output_stream': 'stdout'},
|
||||
|
|
|
@ -9,7 +9,8 @@ function! ale_linters#go#govet#GetCommand(buffer) abort
|
|||
endfunction
|
||||
|
||||
call ale#linter#Define('go', {
|
||||
\ 'name': 'go vet',
|
||||
\ 'name': 'govet',
|
||||
\ 'aliases': ['go vet'],
|
||||
\ 'output_stream': 'stderr',
|
||||
\ 'executable': 'go',
|
||||
\ 'command_callback': 'ale_linters#go#govet#GetCommand',
|
||||
|
|
19
sources_non_forked/ale/ale_linters/haskell/cabal_ghc.vim
Normal file
19
sources_non_forked/ale/ale_linters/haskell/cabal_ghc.vim
Normal file
|
@ -0,0 +1,19 @@
|
|||
" Author: Eric Wolf <ericwolf42@gmail.com>
|
||||
" Description: ghc for Haskell files called with cabal exec
|
||||
|
||||
call ale#Set('haskell_cabal_ghc_options', '-fno-code -v0')
|
||||
|
||||
function! ale_linters#haskell#cabal_ghc#GetCommand(buffer) abort
|
||||
return 'cabal exec -- ghc '
|
||||
\ . ale#Var(a:buffer, 'haskell_cabal_ghc_options')
|
||||
\ . ' %t'
|
||||
endfunction
|
||||
|
||||
call ale#linter#Define('haskell', {
|
||||
\ 'name': 'cabal_ghc',
|
||||
\ 'aliases': ['cabal-ghc'],
|
||||
\ 'output_stream': 'stderr',
|
||||
\ 'executable': 'cabal',
|
||||
\ 'command_callback': 'ale_linters#haskell#cabal_ghc#GetCommand',
|
||||
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
|
||||
\})
|
|
@ -2,14 +2,16 @@
|
|||
" Description: ghc-mod for Haskell files
|
||||
|
||||
call ale#linter#Define('haskell', {
|
||||
\ 'name': 'ghc-mod',
|
||||
\ 'name': 'ghc_mod',
|
||||
\ 'aliases': ['ghc-mod'],
|
||||
\ 'executable': 'ghc-mod',
|
||||
\ 'command': 'ghc-mod --map-file %s=%t check %s',
|
||||
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
|
||||
\})
|
||||
|
||||
call ale#linter#Define('haskell', {
|
||||
\ 'name': 'stack-ghc-mod',
|
||||
\ 'name': 'stack_ghc_mod',
|
||||
\ 'aliases': ['stack-ghc-mod'],
|
||||
\ 'executable': 'stack',
|
||||
\ 'command': 'stack exec ghc-mod -- --map-file %s=%t check %s',
|
||||
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
|
||||
|
|
|
@ -13,7 +13,8 @@ function! ale_linters#haskell#stack_build#GetCommand(buffer) abort
|
|||
endfunction
|
||||
|
||||
call ale#linter#Define('haskell', {
|
||||
\ 'name': 'stack-build',
|
||||
\ 'name': 'stack_build',
|
||||
\ 'aliases': ['stack-build'],
|
||||
\ 'output_stream': 'stderr',
|
||||
\ 'executable': 'stack',
|
||||
\ 'command_callback': 'ale_linters#haskell#stack_build#GetCommand',
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
" Description: ghc for Haskell files, using Stack
|
||||
|
||||
call ale#linter#Define('haskell', {
|
||||
\ 'name': 'stack-ghc',
|
||||
\ 'name': 'stack_ghc',
|
||||
\ 'aliases': ['stack-ghc'],
|
||||
\ 'output_stream': 'stderr',
|
||||
\ 'executable': 'stack',
|
||||
\ 'command': 'stack ghc -- -fno-code -v0 %t',
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
" Author: Sumner Evans <sumner.evans98@gmail.com>
|
||||
" Description: write-good for vim Help files
|
||||
|
||||
call ale#linter#Define('help', {
|
||||
\ 'name': 'write-good',
|
||||
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
|
||||
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
call ale#handlers#writegood#DefineLinter('help')
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
" Author: Sumner Evans <sumner.evans98@gmail.com>
|
||||
" Description: write-good for nroff files
|
||||
" Description: write-good for html files
|
||||
|
||||
call ale#linter#Define('html', {
|
||||
\ 'name': 'write-good',
|
||||
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
|
||||
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
call ale#handlers#writegood#DefineLinter('html')
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
scriptencoding utf-8
|
||||
" Author rhysd https://rhysd.github.io/, Dirk Roorda (dirkroorda), Adrián González Rus (@adrigzr)
|
||||
" Description: remark-lint for Markdown files
|
||||
call ale#Set('markdown_remark_lint_executable', 'remark')
|
||||
|
@ -43,7 +44,8 @@ function! ale_linters#markdown#remark_lint#Handle(buffer, lines) abort
|
|||
endfunction
|
||||
|
||||
call ale#linter#Define('markdown', {
|
||||
\ 'name': 'remark-lint',
|
||||
\ 'name': 'remark_lint',
|
||||
\ 'aliases': ['remark-lint'],
|
||||
\ 'executable_callback': 'ale_linters#markdown#remark_lint#GetExecutable',
|
||||
\ 'command_callback': 'ale_linters#markdown#remark_lint#GetCommand',
|
||||
\ 'callback': 'ale_linters#markdown#remark_lint#Handle',
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
" Author: Sumner Evans <sumner.evans98@gmail.com>
|
||||
" Description: write-good for Markdown files
|
||||
|
||||
call ale#linter#Define('markdown', {
|
||||
\ 'name': 'write-good',
|
||||
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
|
||||
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
call ale#handlers#writegood#DefineLinter('markdown')
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
" Author: Sumner Evans <sumner.evans98@gmail.com>
|
||||
" Description: write-good for nroff files
|
||||
|
||||
call ale#linter#Define('nroff', {
|
||||
\ 'name': 'write-good',
|
||||
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
|
||||
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
call ale#handlers#writegood#DefineLinter('nroff')
|
||||
|
|
|
@ -19,5 +19,5 @@ call ale#linter#Define('objc', {
|
|||
\ 'output_stream': 'stderr',
|
||||
\ 'executable': 'clang',
|
||||
\ 'command_callback': 'ale_linters#objc#clang#GetCommand',
|
||||
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
|
||||
\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes',
|
||||
\})
|
||||
|
|
|
@ -19,5 +19,5 @@ call ale#linter#Define('objcpp', {
|
|||
\ 'output_stream': 'stderr',
|
||||
\ 'executable': 'clang++',
|
||||
\ 'command_callback': 'ale_linters#objcpp#clang#GetCommand',
|
||||
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
|
||||
\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes',
|
||||
\})
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
" Author: Cian Butler https://github.com/butlerx
|
||||
" Description: write-good for PO files
|
||||
|
||||
call ale#linter#Define('po', {
|
||||
\ 'name': 'write-good',
|
||||
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
|
||||
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
call ale#handlers#writegood#DefineLinter('po')
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
" Author: Sumner Evans <sumner.evans98@gmail.com>
|
||||
" Description: write-good for Pod files
|
||||
|
||||
call ale#linter#Define('pod', {
|
||||
\ 'name': 'write-good',
|
||||
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
|
||||
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
call ale#handlers#writegood#DefineLinter('pod')
|
||||
|
|
85
sources_non_forked/ale/ale_linters/python/vulture.vim
Normal file
85
sources_non_forked/ale/ale_linters/python/vulture.vim
Normal file
|
@ -0,0 +1,85 @@
|
|||
" Author: Yauheni Kirylau <actionless.loveless@gmail.com>
|
||||
" Description: vulture linting for python files
|
||||
|
||||
call ale#Set('python_vulture_executable', 'vulture')
|
||||
call ale#Set('python_vulture_options', '')
|
||||
call ale#Set('python_vulture_use_global', get(g:, 'ale_use_global_executables', 0))
|
||||
call ale#Set('python_vulture_change_directory', 1)
|
||||
|
||||
|
||||
" The directory to change to before running vulture
|
||||
function! s:GetDir(buffer) abort
|
||||
let l:project_root = ale#python#FindProjectRoot(a:buffer)
|
||||
|
||||
return !empty(l:project_root)
|
||||
\ ? l:project_root
|
||||
\ : expand('#' . a:buffer . ':p:h')
|
||||
endfunction
|
||||
|
||||
|
||||
function! ale_linters#python#vulture#GetExecutable(buffer) abort
|
||||
return ale#python#FindExecutable(a:buffer, 'python_vulture', ['vulture'])
|
||||
endfunction
|
||||
|
||||
|
||||
function! ale_linters#python#vulture#GetCommand(buffer) abort
|
||||
let l:change_dir = ale#Var(a:buffer, 'python_vulture_change_directory')
|
||||
\ ? ale#path#CdString(s:GetDir(a:buffer))
|
||||
\ : ''
|
||||
|
||||
let l:executable = ale_linters#python#vulture#GetExecutable(a:buffer)
|
||||
|
||||
let l:exec_args = l:executable =~? 'pipenv$'
|
||||
\ ? ' run vulture'
|
||||
\ : ''
|
||||
|
||||
let l:lint_dest = ale#Var(a:buffer, 'python_vulture_change_directory')
|
||||
\ ? ' .'
|
||||
\ : ' %s'
|
||||
|
||||
return l:change_dir
|
||||
\ . ale#Escape(l:executable) . l:exec_args
|
||||
\ . ' '
|
||||
\ . ale#Var(a:buffer, 'python_vulture_options')
|
||||
\ . l:lint_dest
|
||||
endfunction
|
||||
|
||||
|
||||
function! ale_linters#python#vulture#Handle(buffer, lines) abort
|
||||
for l:line in a:lines[:10]
|
||||
if match(l:line, '^Traceback') >= 0
|
||||
return [{
|
||||
\ 'lnum': 1,
|
||||
\ 'text': 'An exception was thrown. See :ALEDetail',
|
||||
\ 'detail': join(a:lines, "\n"),
|
||||
\}]
|
||||
endif
|
||||
endfor
|
||||
|
||||
" Matches patterns line the following:
|
||||
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+): (.*)$'
|
||||
let l:output = []
|
||||
let l:dir = s:GetDir(a:buffer)
|
||||
|
||||
for l:match in ale#util#GetMatches(a:lines, l:pattern)
|
||||
let l:abspath = ale#path#GetAbsPath(l:dir, l:match[1])
|
||||
let l:item = {
|
||||
\ 'filename': l:abspath,
|
||||
\ 'lnum': l:match[2] + 0,
|
||||
\ 'text': l:match[3],
|
||||
\ 'type': 'W',
|
||||
\}
|
||||
call add(l:output, l:item)
|
||||
endfor
|
||||
|
||||
return l:output
|
||||
endfunction
|
||||
|
||||
|
||||
call ale#linter#Define('python', {
|
||||
\ 'name': 'vulture',
|
||||
\ 'executable_callback': 'ale_linters#python#vulture#GetExecutable',
|
||||
\ 'command_callback': 'ale_linters#python#vulture#GetCommand',
|
||||
\ 'callback': 'ale_linters#python#vulture#Handle',
|
||||
\ 'lint_file': 1,
|
||||
\})
|
|
@ -1,9 +1,4 @@
|
|||
" Author: Sumner Evans <sumner.evans98@gmail.com>
|
||||
" Description: write-good for reStructuredText files
|
||||
|
||||
call ale#linter#Define('rst', {
|
||||
\ 'name': 'write-good',
|
||||
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
|
||||
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
call ale#handlers#writegood#DefineLinter('rst')
|
||||
|
|
|
@ -9,7 +9,8 @@ endfunction
|
|||
" Using CM requires that we set "lint_file: 1", since it reads the files
|
||||
" from the disk itself.
|
||||
call ale#linter#Define('sml', {
|
||||
\ 'name': 'smlnj-cm',
|
||||
\ 'name': 'smlnj_cm',
|
||||
\ 'aliases': ['smlnj-cm'],
|
||||
\ 'executable_callback': 'ale#handlers#sml#GetExecutableSmlnjCm',
|
||||
\ 'lint_file': 1,
|
||||
\ 'command_callback': 'ale_linters#sml#smlnj_cm#GetCommand',
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
" Author: Sumner Evans <sumner.evans98@gmail.com>
|
||||
" Description: write-good for TeX files
|
||||
|
||||
call ale#linter#Define('tex', {
|
||||
\ 'name': 'write-good',
|
||||
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
|
||||
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
call ale#handlers#writegood#DefineLinter('tex')
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
" Author: Sumner Evans <sumner.evans98@gmail.com>
|
||||
" Description: write-good for Texinfo files
|
||||
|
||||
call ale#linter#Define('texinfo', {
|
||||
\ 'name': 'write-good',
|
||||
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
|
||||
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
call ale#handlers#writegood#DefineLinter('texinfo')
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
" Author: Sumner Evans <sumner.evans98@gmail.com>
|
||||
" Description: write-good for text files
|
||||
|
||||
call ale#linter#Define('text', {
|
||||
\ 'name': 'write-good',
|
||||
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
|
||||
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
call ale#handlers#writegood#DefineLinter('text')
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
" Author: Sumner Evans <sumner.evans98@gmail.com>
|
||||
" Description: write-good for XHTML files
|
||||
|
||||
call ale#linter#Define('xhtml', {
|
||||
\ 'name': 'write-good',
|
||||
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
|
||||
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
call ale#handlers#writegood#DefineLinter('xhtml')
|
||||
|
|
|
@ -95,7 +95,7 @@ function! ale#Queue(delay, ...) abort
|
|||
throw "linting_flag must be either '' or 'lint_file'"
|
||||
endif
|
||||
|
||||
if type(l:buffer) != type(0)
|
||||
if type(l:buffer) isnot v:t_number
|
||||
throw 'buffer_number must be a Number'
|
||||
endif
|
||||
|
||||
|
@ -192,12 +192,7 @@ endfunction
|
|||
" Every variable name will be prefixed with 'ale_'.
|
||||
function! ale#Var(buffer, variable_name) abort
|
||||
let l:full_name = 'ale_' . a:variable_name
|
||||
let l:vars = getbufvar(str2nr(a:buffer), '', 0)
|
||||
|
||||
if l:vars is 0
|
||||
" Look for variables from deleted buffers, saved from :ALEFix
|
||||
let l:vars = get(get(g:ale_fix_buffer_data, a:buffer, {}), 'vars', {})
|
||||
endif
|
||||
let l:vars = getbufvar(str2nr(a:buffer), '', {})
|
||||
|
||||
return get(l:vars, l:full_name, g:[l:full_name])
|
||||
endfunction
|
||||
|
|
|
@ -30,7 +30,7 @@ function! ale#assert#Linter(expected_executable, expected_command) abort
|
|||
let l:callbacks = map(copy(l:linter.command_chain), 'v:val.callback')
|
||||
|
||||
" If the expected command is a string, just check the last one.
|
||||
if type(a:expected_command) is type('')
|
||||
if type(a:expected_command) is v:t_string
|
||||
if len(l:callbacks) is 1
|
||||
let l:command = call(l:callbacks[0], [l:buffer])
|
||||
else
|
||||
|
|
|
@ -34,26 +34,25 @@ function! ale#balloon#Expr() abort
|
|||
endfunction
|
||||
|
||||
function! ale#balloon#Disable() abort
|
||||
if has('balloon_eval_term')
|
||||
set noballoonevalterm
|
||||
if has('balloon_eval')
|
||||
set noballooneval
|
||||
set balloonexpr=
|
||||
endif
|
||||
|
||||
set noballooneval
|
||||
set balloonexpr=
|
||||
if has('balloon_eval_term')
|
||||
set noballoonevalterm
|
||||
set balloonexpr=
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! ale#balloon#Enable() abort
|
||||
if !has('balloon_eval') && !has('balloon_eval_term')
|
||||
return
|
||||
endif
|
||||
|
||||
if has('balloon_eval')
|
||||
set ballooneval
|
||||
set balloonexpr=ale#balloon#Expr()
|
||||
endif
|
||||
|
||||
if has('balloon_eval_term')
|
||||
set balloonevalterm
|
||||
set balloonexpr=ale#balloon#Expr()
|
||||
endif
|
||||
|
||||
set balloonexpr=ale#balloon#Expr()
|
||||
endfunction
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
" Description: Functions for integrating with C-family linters.
|
||||
|
||||
call ale#Set('c_parse_makefile', 0)
|
||||
call ale#Set('c_parse_compile_commands', 0)
|
||||
let s:sep = has('win32') ? '\' : '/'
|
||||
|
||||
" Set just so tests can override it.
|
||||
let g:__ale_c_project_filenames = ['.git/HEAD', 'configure', 'Makefile', 'CMakeLists.txt']
|
||||
|
||||
function! ale#c#FindProjectRoot(buffer) abort
|
||||
for l:project_filename in ['.git/HEAD', 'configure', 'Makefile', 'CMakeLists.txt']
|
||||
for l:project_filename in g:__ale_c_project_filenames
|
||||
let l:full_path = ale#path#FindNearestFile(a:buffer, l:project_filename)
|
||||
|
||||
if !empty(l:full_path)
|
||||
|
@ -23,11 +27,11 @@ function! ale#c#FindProjectRoot(buffer) abort
|
|||
return ''
|
||||
endfunction
|
||||
|
||||
function! ale#c#ParseCFlagsToList(path_prefix, cflags) abort
|
||||
function! ale#c#ParseCFlags(path_prefix, cflag_line) abort
|
||||
let l:cflags_list = []
|
||||
let l:previous_options = []
|
||||
|
||||
for l:option in a:cflags
|
||||
for l:option in split(a:cflag_line, '-')
|
||||
call add(l:previous_options, l:option)
|
||||
" Check if cflag contained a '-' and should not have been splitted
|
||||
let l:option_list = split(l:option, '\zs')
|
||||
|
@ -59,32 +63,122 @@ function! ale#c#ParseCFlagsToList(path_prefix, cflags) abort
|
|||
endif
|
||||
endfor
|
||||
|
||||
return l:cflags_list
|
||||
return join(l:cflags_list, ' ')
|
||||
endfunction
|
||||
|
||||
function! ale#c#ParseCFlags(buffer, stdout_make) abort
|
||||
function! ale#c#ParseCFlagsFromMakeOutput(buffer, make_output) abort
|
||||
if !g:ale_c_parse_makefile
|
||||
return []
|
||||
return ''
|
||||
endif
|
||||
|
||||
let l:buffer_filename = expand('#' . a:buffer . ':t')
|
||||
let l:cflags = []
|
||||
for l:lines in split(a:stdout_make, '\\n')
|
||||
if stridx(l:lines, l:buffer_filename) >= 0
|
||||
let l:cflags = split(l:lines, '-')
|
||||
let l:cflag_line = ''
|
||||
|
||||
" Find a line matching this buffer's filename in the make output.
|
||||
for l:line in a:make_output
|
||||
if stridx(l:line, l:buffer_filename) >= 0
|
||||
let l:cflag_line = l:line
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
|
||||
let l:makefile_path = ale#path#FindNearestFile(a:buffer, 'Makefile')
|
||||
return ale#c#ParseCFlagsToList(fnamemodify(l:makefile_path, ':p:h'), l:cflags)
|
||||
let l:makefile_dir = fnamemodify(l:makefile_path, ':p:h')
|
||||
|
||||
return ale#c#ParseCFlags(l:makefile_dir, l:cflag_line)
|
||||
endfunction
|
||||
|
||||
" Given a buffer number, find the build subdirectory with compile commands
|
||||
" The subdirectory is returned without the trailing /
|
||||
function! ale#c#FindCompileCommands(buffer) abort
|
||||
" Look above the current source file to find compile_commands.json
|
||||
let l:json_file = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
|
||||
|
||||
if !empty(l:json_file)
|
||||
return l:json_file
|
||||
endif
|
||||
|
||||
" Search in build directories if we can't find it in the project.
|
||||
for l:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h'))
|
||||
for l:dirname in ale#Var(a:buffer, 'c_build_dir_names')
|
||||
let l:c_build_dir = l:path . s:sep . l:dirname
|
||||
let l:json_file = l:c_build_dir . s:sep . 'compile_commands.json'
|
||||
|
||||
if filereadable(l:json_file)
|
||||
return l:json_file
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
" Cache compile_commands.json data in a Dictionary, so we don't need to read
|
||||
" the same files over and over again. The key in the dictionary will include
|
||||
" the last modified time of the file.
|
||||
if !exists('s:compile_commands_cache')
|
||||
let s:compile_commands_cache = {}
|
||||
endif
|
||||
|
||||
function! s:GetListFromCompileCommandsFile(compile_commands_file) abort
|
||||
if empty(a:compile_commands_file)
|
||||
return []
|
||||
endif
|
||||
|
||||
let l:time = getftime(a:compile_commands_file)
|
||||
|
||||
if l:time < 0
|
||||
return []
|
||||
endif
|
||||
|
||||
let l:key = a:compile_commands_file . ':' . l:time
|
||||
|
||||
if has_key(s:compile_commands_cache, l:key)
|
||||
return s:compile_commands_cache[l:key]
|
||||
endif
|
||||
|
||||
let l:data = []
|
||||
silent! let l:data = json_decode(join(readfile(a:compile_commands_file), ''))
|
||||
|
||||
if !empty(l:data)
|
||||
let s:compile_commands_cache[l:key] = l:data
|
||||
|
||||
return l:data
|
||||
endif
|
||||
|
||||
return []
|
||||
endfunction
|
||||
|
||||
function! ale#c#ParseCompileCommandsFlags(buffer, dir, json_list) abort
|
||||
for l:item in a:json_list
|
||||
if bufnr(l:item.file) is a:buffer
|
||||
return ale#c#ParseCFlags(a:dir, l:item.command)
|
||||
endif
|
||||
endfor
|
||||
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! ale#c#FlagsFromCompileCommands(buffer, compile_commands_file) abort
|
||||
let l:dir = ale#path#Dirname(a:compile_commands_file)
|
||||
let l:json_list = s:GetListFromCompileCommandsFile(a:compile_commands_file)
|
||||
|
||||
return ale#c#ParseCompileCommandsFlags(a:buffer, l:dir, l:json_list)
|
||||
endfunction
|
||||
|
||||
function! ale#c#GetCFlags(buffer, output) abort
|
||||
let l:cflags = ' '
|
||||
|
||||
if g:ale_c_parse_makefile && !empty(a:output)
|
||||
let l:cflags = join(ale#c#ParseCFlags(a:buffer, join(a:output, '\n')), ' ') . ' '
|
||||
if ale#Var(a:buffer, 'c_parse_makefile') && !empty(a:output)
|
||||
let l:cflags = ale#c#ParseCFlagsFromMakeOutput(a:buffer, a:output)
|
||||
endif
|
||||
|
||||
if ale#Var(a:buffer, 'c_parse_compile_commands')
|
||||
let l:json_file = ale#c#FindCompileCommands(a:buffer)
|
||||
|
||||
if !empty(l:json_file)
|
||||
let l:cflags = ale#c#FlagsFromCompileCommands(a:buffer, l:json_file)
|
||||
endif
|
||||
endif
|
||||
|
||||
if l:cflags is# ' '
|
||||
|
@ -95,8 +189,9 @@ function! ale#c#GetCFlags(buffer, output) abort
|
|||
endfunction
|
||||
|
||||
function! ale#c#GetMakeCommand(buffer) abort
|
||||
if g:ale_c_parse_makefile
|
||||
if ale#Var(a:buffer, 'c_parse_makefile')
|
||||
let l:makefile_path = ale#path#FindNearestFile(a:buffer, 'Makefile')
|
||||
|
||||
if !empty(l:makefile_path)
|
||||
return 'cd '. fnamemodify(l:makefile_path, ':p:h') . ' && make -n'
|
||||
endif
|
||||
|
@ -158,19 +253,3 @@ let g:ale_c_build_dir_names = get(g:, 'ale_c_build_dir_names', [
|
|||
\ 'build',
|
||||
\ 'bin',
|
||||
\])
|
||||
|
||||
" Given a buffer number, find the build subdirectory with compile commands
|
||||
" The subdirectory is returned without the trailing /
|
||||
function! ale#c#FindCompileCommands(buffer) abort
|
||||
for l:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h'))
|
||||
for l:dirname in ale#Var(a:buffer, 'c_build_dir_names')
|
||||
let l:c_build_dir = l:path . s:sep . l:dirname
|
||||
|
||||
if filereadable(l:c_build_dir . '/compile_commands.json')
|
||||
return l:c_build_dir
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
|
||||
return ''
|
||||
endfunction
|
||||
|
|
|
@ -113,7 +113,7 @@ function! ale#completion#Filter(buffer, suggestions, prefix) abort
|
|||
for l:item in a:suggestions
|
||||
" A List of String values or a List of completion item Dictionaries
|
||||
" is accepted here.
|
||||
let l:word = type(l:item) == type('') ? l:item : l:item.word
|
||||
let l:word = type(l:item) is v:t_string ? l:item : l:item.word
|
||||
|
||||
" Add suggestions if the suggestion starts with a case-insensitive
|
||||
" match for the prefix.
|
||||
|
@ -133,7 +133,7 @@ function! ale#completion#Filter(buffer, suggestions, prefix) abort
|
|||
" Remove suggestions with words in the exclusion List.
|
||||
call filter(
|
||||
\ l:filtered_suggestions,
|
||||
\ 'index(l:excluded_words, type(v:val) is type('''') ? v:val : v:val.word) < 0',
|
||||
\ 'index(l:excluded_words, type(v:val) is v:t_string ? v:val : v:val.word) < 0',
|
||||
\)
|
||||
endif
|
||||
|
||||
|
@ -214,8 +214,10 @@ function! ale#completion#Show(response, completion_parser) abort
|
|||
" function, and then start omni-completion.
|
||||
let b:ale_completion_response = a:response
|
||||
let b:ale_completion_parser = a:completion_parser
|
||||
" Replace completion options shortly before opening the menu.
|
||||
call s:ReplaceCompletionOptions()
|
||||
call ale#util#FeedKeys("\<Plug>(ale_show_completion_menu)")
|
||||
|
||||
call timer_start(0, {-> ale#util#FeedKeys("\<Plug>(ale_show_completion_menu)")})
|
||||
endfunction
|
||||
|
||||
function! s:CompletionStillValid(request_id) abort
|
||||
|
@ -315,10 +317,10 @@ function! ale#completion#ParseLSPCompletions(response) abort
|
|||
|
||||
let l:item_list = []
|
||||
|
||||
if type(get(a:response, 'result')) is type([])
|
||||
if type(get(a:response, 'result')) is v:t_list
|
||||
let l:item_list = a:response.result
|
||||
elseif type(get(a:response, 'result')) is type({})
|
||||
\&& type(get(a:response.result, 'items')) is type([])
|
||||
elseif type(get(a:response, 'result')) is v:t_dict
|
||||
\&& type(get(a:response.result, 'items')) is v:t_list
|
||||
let l:item_list = a:response.result.items
|
||||
endif
|
||||
|
||||
|
@ -336,7 +338,9 @@ function! ale#completion#ParseLSPCompletions(response) abort
|
|||
endif
|
||||
|
||||
" See :help complete-items for Vim completion kinds
|
||||
if l:item.kind is s:LSP_COMPLETION_METHOD_KIND
|
||||
if !has_key(l:item, 'kind')
|
||||
let l:kind = 'v'
|
||||
elseif l:item.kind is s:LSP_COMPLETION_METHOD_KIND
|
||||
let l:kind = 'm'
|
||||
elseif l:item.kind is s:LSP_COMPLETION_CONSTRUCTOR_KIND
|
||||
let l:kind = 'm'
|
||||
|
@ -422,54 +426,65 @@ endfunction
|
|||
|
||||
function! s:GetLSPCompletions(linter) abort
|
||||
let l:buffer = bufnr('')
|
||||
let l:Callback = a:linter.lsp is# 'tsserver'
|
||||
\ ? function('ale#completion#HandleTSServerResponse')
|
||||
\ : function('ale#completion#HandleLSPResponse')
|
||||
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(l:buffer, a:linter, l:Callback)
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(l:buffer, a:linter)
|
||||
|
||||
if empty(l:lsp_details)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:id = l:lsp_details.connection_id
|
||||
let l:root = l:lsp_details.project_root
|
||||
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:message = ale#lsp#tsserver_message#Completions(
|
||||
\ l:buffer,
|
||||
\ b:ale_completion_info.line,
|
||||
\ b:ale_completion_info.column,
|
||||
\ b:ale_completion_info.prefix,
|
||||
\)
|
||||
else
|
||||
" Send a message saying the buffer has changed first, otherwise
|
||||
" completions won't know what text is nearby.
|
||||
call ale#lsp#NotifyForChanges(l:lsp_details)
|
||||
|
||||
" For LSP completions, we need to clamp the column to the length of
|
||||
" the line. python-language-server and perhaps others do not implement
|
||||
" this correctly.
|
||||
let l:message = ale#lsp#message#Completion(
|
||||
\ l:buffer,
|
||||
\ b:ale_completion_info.line,
|
||||
\ min([
|
||||
\ b:ale_completion_info.line_length,
|
||||
\ b:ale_completion_info.column,
|
||||
\ ]),
|
||||
\ ale#completion#GetTriggerCharacter(&filetype, b:ale_completion_info.prefix),
|
||||
\)
|
||||
endif
|
||||
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:lsp_details.project_root)
|
||||
|
||||
if l:request_id
|
||||
let b:ale_completion_info.conn_id = l:id
|
||||
let b:ale_completion_info.request_id = l:request_id
|
||||
|
||||
if has_key(a:linter, 'completion_filter')
|
||||
let b:ale_completion_info.completion_filter = a:linter.completion_filter
|
||||
function! OnReady(...) abort closure
|
||||
" If we have sent a completion request already, don't send another.
|
||||
if b:ale_completion_info.request_id
|
||||
return
|
||||
endif
|
||||
endif
|
||||
|
||||
let l:Callback = a:linter.lsp is# 'tsserver'
|
||||
\ ? function('ale#completion#HandleTSServerResponse')
|
||||
\ : function('ale#completion#HandleLSPResponse')
|
||||
call ale#lsp#RegisterCallback(l:id, l:Callback)
|
||||
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:message = ale#lsp#tsserver_message#Completions(
|
||||
\ l:buffer,
|
||||
\ b:ale_completion_info.line,
|
||||
\ b:ale_completion_info.column,
|
||||
\ b:ale_completion_info.prefix,
|
||||
\)
|
||||
else
|
||||
" Send a message saying the buffer has changed first, otherwise
|
||||
" completions won't know what text is nearby.
|
||||
call ale#lsp#NotifyForChanges(l:id, l:root, l:buffer)
|
||||
|
||||
" For LSP completions, we need to clamp the column to the length of
|
||||
" the line. python-language-server and perhaps others do not implement
|
||||
" this correctly.
|
||||
let l:message = ale#lsp#message#Completion(
|
||||
\ l:buffer,
|
||||
\ b:ale_completion_info.line,
|
||||
\ min([
|
||||
\ b:ale_completion_info.line_length,
|
||||
\ b:ale_completion_info.column,
|
||||
\ ]),
|
||||
\ ale#completion#GetTriggerCharacter(&filetype, b:ale_completion_info.prefix),
|
||||
\)
|
||||
endif
|
||||
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:lsp_details.project_root)
|
||||
|
||||
if l:request_id
|
||||
let b:ale_completion_info.conn_id = l:id
|
||||
let b:ale_completion_info.request_id = l:request_id
|
||||
|
||||
if has_key(a:linter, 'completion_filter')
|
||||
let b:ale_completion_info.completion_filter = a:linter.completion_filter
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
call ale#lsp#WaitForCapability(l:id, l:root, 'completion', function('OnReady'))
|
||||
endfunction
|
||||
|
||||
function! ale#completion#GetCompletions() abort
|
||||
|
|
|
@ -40,9 +40,9 @@ function! ale#definition#HandleLSPResponse(conn_id, response) abort
|
|||
" The result can be a Dictionary item, a List of the same, or null.
|
||||
let l:result = get(a:response, 'result', v:null)
|
||||
|
||||
if type(l:result) is type({})
|
||||
if type(l:result) is v:t_dict
|
||||
let l:result = [l:result]
|
||||
elseif type(l:result) isnot type([])
|
||||
elseif type(l:result) isnot v:t_list
|
||||
let l:result = []
|
||||
endif
|
||||
|
||||
|
@ -60,43 +60,50 @@ endfunction
|
|||
function! s:GoToLSPDefinition(linter, options) abort
|
||||
let l:buffer = bufnr('')
|
||||
let [l:line, l:column] = getcurpos()[1:2]
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(l:buffer, a:linter)
|
||||
|
||||
let l:Callback = a:linter.lsp is# 'tsserver'
|
||||
\ ? function('ale#definition#HandleTSServerResponse')
|
||||
\ : function('ale#definition#HandleLSPResponse')
|
||||
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(l:buffer, a:linter, l:Callback)
|
||||
if a:linter.lsp isnot# 'tsserver'
|
||||
let l:column = min([l:column, len(getline(l:line))])
|
||||
endif
|
||||
|
||||
if empty(l:lsp_details)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:id = l:lsp_details.connection_id
|
||||
let l:root = l:lsp_details.project_root
|
||||
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:message = ale#lsp#tsserver_message#Definition(
|
||||
\ l:buffer,
|
||||
\ l:line,
|
||||
\ l:column
|
||||
\)
|
||||
else
|
||||
" Send a message saying the buffer has changed first, or the
|
||||
" definition position probably won't make sense.
|
||||
call ale#lsp#NotifyForChanges(l:lsp_details)
|
||||
function! OnReady(...) abort closure
|
||||
let l:Callback = a:linter.lsp is# 'tsserver'
|
||||
\ ? function('ale#definition#HandleTSServerResponse')
|
||||
\ : function('ale#definition#HandleLSPResponse')
|
||||
call ale#lsp#RegisterCallback(l:id, l:Callback)
|
||||
|
||||
let l:column = min([l:column, len(getline(l:line))])
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:message = ale#lsp#tsserver_message#Definition(
|
||||
\ l:buffer,
|
||||
\ l:line,
|
||||
\ l:column
|
||||
\)
|
||||
else
|
||||
" Send a message saying the buffer has changed first, or the
|
||||
" definition position probably won't make sense.
|
||||
call ale#lsp#NotifyForChanges(l:id, l:root, l:buffer)
|
||||
|
||||
" For LSP completions, we need to clamp the column to the length of
|
||||
" the line. python-language-server and perhaps others do not implement
|
||||
" this correctly.
|
||||
let l:message = ale#lsp#message#Definition(l:buffer, l:line, l:column)
|
||||
endif
|
||||
" For LSP completions, we need to clamp the column to the length of
|
||||
" the line. python-language-server and perhaps others do not implement
|
||||
" this correctly.
|
||||
let l:message = ale#lsp#message#Definition(l:buffer, l:line, l:column)
|
||||
endif
|
||||
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:lsp_details.project_root)
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:lsp_details.project_root)
|
||||
|
||||
let s:go_to_definition_map[l:request_id] = {
|
||||
\ 'open_in_tab': get(a:options, 'open_in_tab', 0),
|
||||
\}
|
||||
let s:go_to_definition_map[l:request_id] = {
|
||||
\ 'open_in_tab': get(a:options, 'open_in_tab', 0),
|
||||
\}
|
||||
endfunction
|
||||
|
||||
call ale#lsp#WaitForCapability(l:id, l:root, 'definition', function('OnReady'))
|
||||
endfunction
|
||||
|
||||
function! ale#definition#GoTo(options) abort
|
||||
|
|
|
@ -557,7 +557,7 @@ function! s:RunJob(options) abort
|
|||
if get(g:, 'ale_run_synchronously') == 1
|
||||
" Run a command synchronously if this test option is set.
|
||||
let s:job_info_map[l:job_id].output = systemlist(
|
||||
\ type(l:command) == type([])
|
||||
\ type(l:command) is v:t_list
|
||||
\ ? join(l:command[0:1]) . ' ' . ale#Escape(l:command[2])
|
||||
\ : l:command
|
||||
\)
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
" Given a filetype and a configuration for ignoring linters, return a List of
|
||||
" Strings for linter names to ignore.
|
||||
function! ale#engine#ignore#GetList(filetype, config) abort
|
||||
if type(a:config) is type([])
|
||||
if type(a:config) is v:t_list
|
||||
return a:config
|
||||
endif
|
||||
|
||||
if type(a:config) is type({})
|
||||
if type(a:config) is v:t_dict
|
||||
let l:names_to_remove = []
|
||||
|
||||
for l:part in split(a:filetype , '\.')
|
||||
|
|
|
@ -275,7 +275,7 @@ function! s:RunJob(options) abort
|
|||
if get(g:, 'ale_run_synchronously') == 1
|
||||
" Run a command synchronously if this test option is set.
|
||||
let l:output = systemlist(
|
||||
\ type(l:command) == type([])
|
||||
\ type(l:command) is v:t_list
|
||||
\ ? join(l:command[0:1]) . ' ' . ale#Escape(l:command[2])
|
||||
\ : l:command
|
||||
\)
|
||||
|
@ -313,10 +313,10 @@ function! s:RunFixer(options) abort
|
|||
\ : call(l:Function, [l:buffer, copy(l:input)])
|
||||
endif
|
||||
|
||||
if type(l:result) == type(0) && l:result == 0
|
||||
if type(l:result) is v:t_number && l:result == 0
|
||||
" When `0` is returned, skip this item.
|
||||
let l:index += 1
|
||||
elseif type(l:result) == type([])
|
||||
elseif type(l:result) is v:t_list
|
||||
let l:input = l:result
|
||||
let l:index += 1
|
||||
else
|
||||
|
@ -351,9 +351,9 @@ function! s:RunFixer(options) abort
|
|||
endfunction
|
||||
|
||||
function! s:AddSubCallbacks(full_list, callbacks) abort
|
||||
if type(a:callbacks) == type('')
|
||||
if type(a:callbacks) is v:t_string
|
||||
call add(a:full_list, a:callbacks)
|
||||
elseif type(a:callbacks) == type([])
|
||||
elseif type(a:callbacks) is v:t_list
|
||||
call extend(a:full_list, a:callbacks)
|
||||
else
|
||||
return 0
|
||||
|
@ -365,7 +365,7 @@ endfunction
|
|||
function! s:GetCallbacks(buffer, fixers) abort
|
||||
if len(a:fixers)
|
||||
let l:callback_list = a:fixers
|
||||
elseif type(get(b:, 'ale_fixers')) is type([])
|
||||
elseif type(get(b:, 'ale_fixers')) is v:t_list
|
||||
" Lists can be used for buffer-local variables only
|
||||
let l:callback_list = b:ale_fixers
|
||||
else
|
||||
|
@ -396,7 +396,7 @@ function! s:GetCallbacks(buffer, fixers) abort
|
|||
" Variables with capital characters are needed, or Vim will complain about
|
||||
" funcref variables.
|
||||
for l:Item in l:callback_list
|
||||
if type(l:Item) == type('')
|
||||
if type(l:Item) is v:t_string
|
||||
let l:Func = ale#fix#registry#GetFunc(l:Item)
|
||||
|
||||
if !empty(l:Func)
|
||||
|
@ -420,9 +420,7 @@ function! ale#fix#InitBufferData(buffer, fixing_flag) abort
|
|||
" The 'done' flag tells the function for applying changes when fixing
|
||||
" is complete.
|
||||
let g:ale_fix_buffer_data[a:buffer] = {
|
||||
\ 'vars': getbufvar(a:buffer, ''),
|
||||
\ 'lines_before': getbufline(a:buffer, 1, '$'),
|
||||
\ 'filename': expand('#' . a:buffer . ':p'),
|
||||
\ 'done': 0,
|
||||
\ 'should_save': a:fixing_flag is# 'save_file',
|
||||
\ 'temporary_directory_list': [],
|
||||
|
|
|
@ -245,32 +245,32 @@ function! ale#fix#registry#Add(name, func, filetypes, desc, ...) abort
|
|||
" This command will throw from the sandbox.
|
||||
let &equalprg=&equalprg
|
||||
|
||||
if type(a:name) != type('')
|
||||
if type(a:name) isnot v:t_string
|
||||
throw '''name'' must be a String'
|
||||
endif
|
||||
|
||||
if type(a:func) != type('')
|
||||
if type(a:func) isnot v:t_string
|
||||
throw '''func'' must be a String'
|
||||
endif
|
||||
|
||||
if type(a:filetypes) != type([])
|
||||
if type(a:filetypes) isnot v:t_list
|
||||
throw '''filetypes'' must be a List'
|
||||
endif
|
||||
|
||||
for l:type in a:filetypes
|
||||
if type(l:type) != type('')
|
||||
if type(l:type) isnot v:t_string
|
||||
throw 'Each entry of ''filetypes'' must be a String'
|
||||
endif
|
||||
endfor
|
||||
|
||||
if type(a:desc) != type('')
|
||||
if type(a:desc) isnot v:t_string
|
||||
throw '''desc'' must be a String'
|
||||
endif
|
||||
|
||||
let l:aliases = get(a:000, 0, [])
|
||||
|
||||
if type(l:aliases) != type([])
|
||||
\|| !empty(filter(copy(l:aliases), 'type(v:val) != type('''')'))
|
||||
if type(l:aliases) isnot v:t_list
|
||||
\|| !empty(filter(copy(l:aliases), 'type(v:val) isnot v:t_string'))
|
||||
throw '''aliases'' must be a List of String values'
|
||||
endif
|
||||
|
||||
|
|
|
@ -5,6 +5,13 @@ scriptencoding utf-8
|
|||
|
||||
let s:pragma_error = '#pragma once in main file'
|
||||
|
||||
" Look for lines like the following.
|
||||
"
|
||||
" <stdin>:8:5: warning: conversion lacks type at end of format [-Wformat=]
|
||||
" <stdin>:10:27: error: invalid operands to binary - (have ‘int’ and ‘char *’)
|
||||
" -:189:7: note: $/${} is unnecessary on arithmetic variables. [SC2004]
|
||||
let s:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): (.+)$'
|
||||
|
||||
function! s:IsHeaderFile(filename) abort
|
||||
return a:filename =~? '\v\.(h|hpp)$'
|
||||
endfunction
|
||||
|
@ -18,16 +25,63 @@ function! s:RemoveUnicodeQuotes(text) abort
|
|||
return l:text
|
||||
endfunction
|
||||
|
||||
" Report problems inside of header files just for gcc and clang
|
||||
function! s:ParseProblemsInHeaders(buffer, lines) abort
|
||||
let l:output = []
|
||||
let l:include_item = {}
|
||||
|
||||
for l:line in a:lines[: -2]
|
||||
let l:include_match = matchlist(l:line, '\v^In file included from')
|
||||
|
||||
if !empty(l:include_item)
|
||||
let l:pattern_match = matchlist(l:line, s:pattern)
|
||||
|
||||
if !empty(l:pattern_match) && l:pattern_match[1] is# '<stdin>'
|
||||
if has_key(l:include_item, 'lnum')
|
||||
call add(l:output, l:include_item)
|
||||
endif
|
||||
|
||||
let l:include_item = {}
|
||||
|
||||
continue
|
||||
endif
|
||||
|
||||
let l:include_item.detail .= "\n" . l:line
|
||||
endif
|
||||
|
||||
if !empty(l:include_match)
|
||||
if empty(l:include_item)
|
||||
let l:include_item = {
|
||||
\ 'text': 'Error found in header. See :ALEDetail',
|
||||
\ 'detail': l:line,
|
||||
\}
|
||||
endif
|
||||
endif
|
||||
|
||||
if !empty(l:include_item)
|
||||
let l:stdin_match = matchlist(l:line, '\vfrom \<stdin\>:(\d+):(\d*):?$')
|
||||
|
||||
if !empty(l:stdin_match)
|
||||
let l:include_item.lnum = str2nr(l:stdin_match[1])
|
||||
|
||||
if str2nr(l:stdin_match[2])
|
||||
let l:include_item.col = str2nr(l:stdin_match[2])
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
|
||||
if !empty(l:include_item) && has_key(l:include_item, 'lnum')
|
||||
call add(l:output, l:include_item)
|
||||
endif
|
||||
|
||||
return l:output
|
||||
endfunction
|
||||
|
||||
function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort
|
||||
" Look for lines like the following.
|
||||
"
|
||||
" <stdin>:8:5: warning: conversion lacks type at end of format [-Wformat=]
|
||||
" <stdin>:10:27: error: invalid operands to binary - (have ‘int’ and ‘char *’)
|
||||
" -:189:7: note: $/${} is unnecessary on arithmetic variables. [SC2004]
|
||||
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): (.+)$'
|
||||
let l:output = []
|
||||
|
||||
for l:match in ale#util#GetMatches(a:lines, l:pattern)
|
||||
for l:match in ale#util#GetMatches(a:lines, s:pattern)
|
||||
" Filter out the pragma errors
|
||||
if s:IsHeaderFile(bufname(bufnr('')))
|
||||
\&& l:match[5][:len(s:pragma_error) - 1] is# s:pragma_error
|
||||
|
@ -67,3 +121,12 @@ function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort
|
|||
|
||||
return l:output
|
||||
endfunction
|
||||
|
||||
" Handle problems with the GCC format, but report problems inside of headers.
|
||||
function! ale#handlers#gcc#HandleGCCFormatWithIncludes(buffer, lines) abort
|
||||
let l:output = ale#handlers#gcc#HandleGCCFormat(a:buffer, a:lines)
|
||||
|
||||
call extend(l:output, s:ParseProblemsInHeaders(a:buffer, a:lines))
|
||||
|
||||
return l:output
|
||||
endfunction
|
||||
|
|
|
@ -32,7 +32,7 @@ function! ale#handlers#rust#HandleRustErrors(buffer, lines) abort
|
|||
|
||||
let l:error = json_decode(l:errorline)
|
||||
|
||||
if has_key(l:error, 'message') && type(l:error.message) == type({})
|
||||
if has_key(l:error, 'message') && type(l:error.message) is v:t_dict
|
||||
let l:error = l:error.message
|
||||
endif
|
||||
|
||||
|
|
|
@ -59,3 +59,14 @@ function! ale#handlers#writegood#Handle(buffer, lines) abort
|
|||
|
||||
return l:output
|
||||
endfunction
|
||||
|
||||
" Define the writegood linter for a given filetype.
|
||||
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',
|
||||
\ 'callback': 'ale#handlers#writegood#Handle',
|
||||
\})
|
||||
endfunction
|
||||
|
|
|
@ -63,19 +63,19 @@ function! ale#hover#HandleLSPResponse(conn_id, response) abort
|
|||
|
||||
let l:result = l:result.contents
|
||||
|
||||
if type(l:result) is type('')
|
||||
if type(l:result) is v:t_string
|
||||
" The result can be just a string.
|
||||
let l:result = [l:result]
|
||||
endif
|
||||
|
||||
if type(l:result) is type({})
|
||||
if type(l:result) is v:t_dict
|
||||
" If the result is an object, then it's markup content.
|
||||
let l:result = [l:result.value]
|
||||
endif
|
||||
|
||||
if type(l:result) is type([])
|
||||
if type(l:result) is v:t_list
|
||||
" Replace objects with text values.
|
||||
call map(l:result, 'type(v:val) is type('''') ? v:val : v:val.value')
|
||||
call map(l:result, 'type(v:val) is v:t_string ? v:val : v:val.value')
|
||||
let l:str = join(l:result, "\n")
|
||||
let l:str = substitute(l:str, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||
|
||||
|
@ -93,45 +93,51 @@ function! ale#hover#HandleLSPResponse(conn_id, response) abort
|
|||
endfunction
|
||||
|
||||
function! s:ShowDetails(linter, buffer, line, column, opt) abort
|
||||
let l:Callback = a:linter.lsp is# 'tsserver'
|
||||
\ ? function('ale#hover#HandleTSServerResponse')
|
||||
\ : function('ale#hover#HandleLSPResponse')
|
||||
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(a:buffer, a:linter, l:Callback)
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(a:buffer, a:linter)
|
||||
|
||||
if empty(l:lsp_details)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:id = l:lsp_details.connection_id
|
||||
let l:root = l:lsp_details.project_root
|
||||
let l:language_id = l:lsp_details.language_id
|
||||
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:column = a:column
|
||||
function! OnReady(...) abort closure
|
||||
let l:Callback = a:linter.lsp is# 'tsserver'
|
||||
\ ? function('ale#hover#HandleTSServerResponse')
|
||||
\ : function('ale#hover#HandleLSPResponse')
|
||||
call ale#lsp#RegisterCallback(l:id, l:Callback)
|
||||
|
||||
let l:message = ale#lsp#tsserver_message#Quickinfo(
|
||||
\ a:buffer,
|
||||
\ a:line,
|
||||
\ l:column
|
||||
\)
|
||||
else
|
||||
" Send a message saying the buffer has changed first, or the
|
||||
" hover position probably won't make sense.
|
||||
call ale#lsp#NotifyForChanges(l:lsp_details)
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:column = a:column
|
||||
|
||||
let l:column = min([a:column, len(getbufline(a:buffer, a:line)[0])])
|
||||
let l:message = ale#lsp#tsserver_message#Quickinfo(
|
||||
\ a:buffer,
|
||||
\ a:line,
|
||||
\ l:column
|
||||
\)
|
||||
else
|
||||
" Send a message saying the buffer has changed first, or the
|
||||
" hover position probably won't make sense.
|
||||
call ale#lsp#NotifyForChanges(l:id, l:root, a:buffer)
|
||||
|
||||
let l:message = ale#lsp#message#Hover(a:buffer, a:line, l:column)
|
||||
endif
|
||||
let l:column = min([a:column, len(getbufline(a:buffer, a:line)[0])])
|
||||
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:lsp_details.project_root)
|
||||
let l:message = ale#lsp#message#Hover(a:buffer, a:line, l:column)
|
||||
endif
|
||||
|
||||
let s:hover_map[l:request_id] = {
|
||||
\ 'buffer': a:buffer,
|
||||
\ 'line': a:line,
|
||||
\ 'column': l:column,
|
||||
\ 'hover_from_balloonexpr': get(a:opt, 'called_from_balloonexpr', 0),
|
||||
\}
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:lsp_details.project_root)
|
||||
|
||||
let s:hover_map[l:request_id] = {
|
||||
\ 'buffer': a:buffer,
|
||||
\ 'line': a:line,
|
||||
\ 'column': l:column,
|
||||
\ 'hover_from_balloonexpr': get(a:opt, 'called_from_balloonexpr', 0),
|
||||
\}
|
||||
endfunction
|
||||
|
||||
call ale#lsp#WaitForCapability(l:id, l:root, 'hover', function('OnReady'))
|
||||
endfunction
|
||||
|
||||
" Obtain Hover information for the specified position
|
||||
|
|
|
@ -57,11 +57,11 @@ function! ale#linter#GetLintersLoaded() abort
|
|||
endfunction
|
||||
|
||||
function! s:IsCallback(value) abort
|
||||
return type(a:value) == type('') || type(a:value) == type(function('type'))
|
||||
return type(a:value) is v:t_string || type(a:value) is v:t_func
|
||||
endfunction
|
||||
|
||||
function! s:IsBoolean(value) abort
|
||||
return type(a:value) == type(0) && (a:value == 0 || a:value == 1)
|
||||
return type(a:value) is v:t_number && (a:value == 0 || a:value == 1)
|
||||
endfunction
|
||||
|
||||
function! s:LanguageGetter(buffer) dict abort
|
||||
|
@ -69,7 +69,7 @@ function! s:LanguageGetter(buffer) dict abort
|
|||
endfunction
|
||||
|
||||
function! ale#linter#PreProcess(filetype, linter) abort
|
||||
if type(a:linter) != type({})
|
||||
if type(a:linter) isnot v:t_dict
|
||||
throw 'The linter object must be a Dictionary'
|
||||
endif
|
||||
|
||||
|
@ -79,7 +79,7 @@ function! ale#linter#PreProcess(filetype, linter) abort
|
|||
\ 'lsp': get(a:linter, 'lsp', ''),
|
||||
\}
|
||||
|
||||
if type(l:obj.name) != type('')
|
||||
if type(l:obj.name) isnot v:t_string
|
||||
throw '`name` must be defined to name the linter'
|
||||
endif
|
||||
|
||||
|
@ -114,7 +114,7 @@ function! ale#linter#PreProcess(filetype, linter) abort
|
|||
elseif has_key(a:linter, 'executable')
|
||||
let l:obj.executable = a:linter.executable
|
||||
|
||||
if type(l:obj.executable) != type('')
|
||||
if type(l:obj.executable) isnot v:t_string
|
||||
throw '`executable` must be a string if defined'
|
||||
endif
|
||||
else
|
||||
|
@ -130,7 +130,7 @@ function! ale#linter#PreProcess(filetype, linter) abort
|
|||
elseif has_key(a:linter, 'command_chain')
|
||||
let l:obj.command_chain = a:linter.command_chain
|
||||
|
||||
if type(l:obj.command_chain) != type([])
|
||||
if type(l:obj.command_chain) isnot v:t_list
|
||||
throw '`command_chain` must be a List'
|
||||
endif
|
||||
|
||||
|
@ -148,7 +148,7 @@ function! ale#linter#PreProcess(filetype, linter) abort
|
|||
endif
|
||||
|
||||
if has_key(l:link, 'output_stream')
|
||||
if type(l:link.output_stream) != type('')
|
||||
if type(l:link.output_stream) isnot v:t_string
|
||||
\|| index(['stdout', 'stderr', 'both'], l:link.output_stream) < 0
|
||||
throw l:err_prefix . '`output_stream` flag must be '
|
||||
\ . "'stdout', 'stderr', or 'both'"
|
||||
|
@ -170,7 +170,7 @@ function! ale#linter#PreProcess(filetype, linter) abort
|
|||
elseif has_key(a:linter, 'command')
|
||||
let l:obj.command = a:linter.command
|
||||
|
||||
if type(l:obj.command) != type('')
|
||||
if type(l:obj.command) isnot v:t_string
|
||||
throw '`command` must be a string if defined'
|
||||
endif
|
||||
else
|
||||
|
@ -217,7 +217,7 @@ function! ale#linter#PreProcess(filetype, linter) abort
|
|||
" Default to using the filetype as the language.
|
||||
let l:obj.language = get(a:linter, 'language', a:filetype)
|
||||
|
||||
if type(l:obj.language) != type('')
|
||||
if type(l:obj.language) isnot v:t_string
|
||||
throw '`language` must be a string'
|
||||
endif
|
||||
|
||||
|
@ -257,7 +257,7 @@ function! ale#linter#PreProcess(filetype, linter) abort
|
|||
|
||||
let l:obj.output_stream = get(a:linter, 'output_stream', 'stdout')
|
||||
|
||||
if type(l:obj.output_stream) != type('')
|
||||
if type(l:obj.output_stream) isnot v:t_string
|
||||
\|| index(['stdout', 'stderr', 'both'], l:obj.output_stream) < 0
|
||||
throw "`output_stream` must be 'stdout', 'stderr', or 'both'"
|
||||
endif
|
||||
|
@ -283,8 +283,8 @@ function! ale#linter#PreProcess(filetype, linter) abort
|
|||
|
||||
let l:obj.aliases = get(a:linter, 'aliases', [])
|
||||
|
||||
if type(l:obj.aliases) != type([])
|
||||
\|| len(filter(copy(l:obj.aliases), 'type(v:val) != type('''')')) > 0
|
||||
if type(l:obj.aliases) isnot v:t_list
|
||||
\|| len(filter(copy(l:obj.aliases), 'type(v:val) isnot v:t_string')) > 0
|
||||
throw '`aliases` must be a List of String values'
|
||||
endif
|
||||
|
||||
|
@ -336,7 +336,7 @@ function! s:GetAliasedFiletype(original_filetype) abort
|
|||
let l:buffer_aliases = get(b:, 'ale_linter_aliases', {})
|
||||
|
||||
" b:ale_linter_aliases can be set to a List.
|
||||
if type(l:buffer_aliases) is type([])
|
||||
if type(l:buffer_aliases) is v:t_list
|
||||
return l:buffer_aliases
|
||||
endif
|
||||
|
||||
|
@ -360,7 +360,7 @@ endfunction
|
|||
function! ale#linter#ResolveFiletype(original_filetype) abort
|
||||
let l:filetype = s:GetAliasedFiletype(a:original_filetype)
|
||||
|
||||
if type(l:filetype) != type([])
|
||||
if type(l:filetype) isnot v:t_list
|
||||
return [l:filetype]
|
||||
endif
|
||||
|
||||
|
@ -376,7 +376,7 @@ function! s:GetLinterNames(original_filetype) abort
|
|||
endif
|
||||
|
||||
" b:ale_linters can be set to a List.
|
||||
if type(l:buffer_ale_linters) is type([])
|
||||
if type(l:buffer_ale_linters) is v:t_list
|
||||
return l:buffer_ale_linters
|
||||
endif
|
||||
|
||||
|
@ -414,9 +414,9 @@ function! ale#linter#Get(original_filetypes) abort
|
|||
let l:all_linters = ale#linter#GetAll(l:filetype)
|
||||
let l:filetype_linters = []
|
||||
|
||||
if type(l:linter_names) == type('') && l:linter_names is# 'all'
|
||||
if type(l:linter_names) is v:t_string && l:linter_names is# 'all'
|
||||
let l:filetype_linters = l:all_linters
|
||||
elseif type(l:linter_names) == type([])
|
||||
elseif type(l:linter_names) is v:t_list
|
||||
" Select only the linters we or the user has specified.
|
||||
for l:linter in l:all_linters
|
||||
let l:name_list = [l:linter.name] + l:linter.aliases
|
||||
|
|
|
@ -66,6 +66,7 @@ function! ale#loclist_jumping#Jump(direction, wrap) abort
|
|||
let l:nearest = ale#loclist_jumping#FindNearest(a:direction, a:wrap)
|
||||
|
||||
if !empty(l:nearest)
|
||||
normal! m`
|
||||
call cursor(l:nearest)
|
||||
endif
|
||||
endfunction
|
||||
|
@ -82,6 +83,7 @@ function! ale#loclist_jumping#JumpToIndex(index) abort
|
|||
let l:item = l:loclist[a:index]
|
||||
|
||||
if !empty(l:item)
|
||||
normal! m`
|
||||
call cursor([l:item.lnum, l:item.col])
|
||||
endif
|
||||
endfunction
|
||||
|
|
|
@ -15,13 +15,23 @@ function! ale#lsp#NewConnection(initialization_options) abort
|
|||
" open_documents: A Dictionary mapping buffers to b:changedtick, keeping
|
||||
" track of when documents were opened, and when we last changed them.
|
||||
" callback_list: A list of callbacks for handling LSP responses.
|
||||
" initialization_options: Options to send to the server.
|
||||
" capabilities: Features the server supports.
|
||||
let l:conn = {
|
||||
\ 'is_tsserver': 0,
|
||||
\ 'id': '',
|
||||
\ 'data': '',
|
||||
\ 'projects': {},
|
||||
\ 'open_documents': {},
|
||||
\ 'callback_list': [],
|
||||
\ 'initialization_options': a:initialization_options,
|
||||
\ 'capabilities': {
|
||||
\ 'hover': 0,
|
||||
\ 'references': 0,
|
||||
\ 'completion': 0,
|
||||
\ 'completion_trigger_characters': [],
|
||||
\ 'definition': 0,
|
||||
\ },
|
||||
\}
|
||||
|
||||
call add(s:connections, l:conn)
|
||||
|
@ -44,6 +54,11 @@ function! s:FindConnection(key, value) abort
|
|||
return {}
|
||||
endfunction
|
||||
|
||||
" Get the capabilities for a connection, or an empty Dictionary.
|
||||
function! ale#lsp#GetConnectionCapabilities(id) abort
|
||||
return get(s:FindConnection('id', a:id), 'capabilities', {})
|
||||
endfunction
|
||||
|
||||
function! ale#lsp#GetNextMessageID() abort
|
||||
" Use the current ID
|
||||
let l:id = g:ale_lsp_next_message_id
|
||||
|
@ -174,6 +189,16 @@ function! s:MarkProjectAsInitialized(conn, project) abort
|
|||
|
||||
" Remove the messages now.
|
||||
let a:conn.message_queue = []
|
||||
|
||||
" Call capabilities callbacks queued for the project.
|
||||
for [l:capability, l:Callback] in a:project.capabilities_queue
|
||||
if a:conn.is_tsserver || a:conn.capabilities[l:capability]
|
||||
call call(l:Callback, [a:conn.id, a:project.root])
|
||||
endif
|
||||
endfor
|
||||
|
||||
" Clear the queued callbacks now.
|
||||
let a:project.capabilities_queue = []
|
||||
endfunction
|
||||
|
||||
function! s:HandleInitializeResponse(conn, response) abort
|
||||
|
@ -185,6 +210,38 @@ function! s:HandleInitializeResponse(conn, response) abort
|
|||
endif
|
||||
endfunction
|
||||
|
||||
" Update capabilities from the server, so we know which features the server
|
||||
" supports.
|
||||
function! s:UpdateCapabilities(conn, capabilities) abort
|
||||
if type(a:capabilities) isnot v:t_dict
|
||||
return
|
||||
endif
|
||||
|
||||
if get(a:capabilities, 'hoverProvider') is v:true
|
||||
let a:conn.capabilities.hover = 1
|
||||
endif
|
||||
|
||||
if get(a:capabilities, 'referencesProvider') is v:true
|
||||
let a:conn.capabilities.references = 1
|
||||
endif
|
||||
|
||||
if !empty(get(a:capabilities, 'completionProvider'))
|
||||
let a:conn.capabilities.completion = 1
|
||||
endif
|
||||
|
||||
if type(get(a:capabilities, 'completionProvider')) is v:t_dict
|
||||
let l:chars = get(a:capabilities.completionProvider, 'triggerCharacters')
|
||||
|
||||
if type(l:chars) is v:t_list
|
||||
let a:conn.capabilities.completion_trigger_characters = l:chars
|
||||
endif
|
||||
endif
|
||||
|
||||
if get(a:capabilities, 'definitionProvider') is v:true
|
||||
let a:conn.capabilities.definition = 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! ale#lsp#HandleOtherInitializeResponses(conn, response) abort
|
||||
let l:uninitialized_projects = []
|
||||
|
||||
|
@ -200,6 +257,8 @@ function! ale#lsp#HandleOtherInitializeResponses(conn, response) abort
|
|||
|
||||
if get(a:response, 'method', '') is# ''
|
||||
if has_key(get(a:response, 'result', {}), 'capabilities')
|
||||
call s:UpdateCapabilities(a:conn, a:response.result.capabilities)
|
||||
|
||||
for [l:dir, l:project] in l:uninitialized_projects
|
||||
call s:MarkProjectAsInitialized(a:conn, l:project)
|
||||
endfor
|
||||
|
@ -216,7 +275,7 @@ function! ale#lsp#HandleOtherInitializeResponses(conn, response) abort
|
|||
endfunction
|
||||
|
||||
function! ale#lsp#HandleMessage(conn, message) abort
|
||||
if type(a:message) != type('')
|
||||
if type(a:message) isnot v:t_string
|
||||
" Ignore messages that aren't strings.
|
||||
return
|
||||
endif
|
||||
|
@ -254,22 +313,43 @@ function! s:HandleCommandMessage(job_id, message) abort
|
|||
call ale#lsp#HandleMessage(l:conn, a:message)
|
||||
endfunction
|
||||
|
||||
function! ale#lsp#RegisterProject(conn, project_root) abort
|
||||
" Given a connection ID, mark it as a tsserver connection, so it will be
|
||||
" handled that way.
|
||||
function! ale#lsp#MarkConnectionAsTsserver(conn_id) abort
|
||||
let l:conn = s:FindConnection('id', a:conn_id)
|
||||
|
||||
if !empty(l:conn)
|
||||
let l:conn.is_tsserver = 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Register a project for an LSP connection.
|
||||
"
|
||||
" This function will throw if the connection doesn't exist.
|
||||
function! ale#lsp#RegisterProject(conn_id, project_root) abort
|
||||
let l:conn = s:FindConnection('id', a:conn_id)
|
||||
|
||||
" Empty strings can't be used for Dictionary keys in NeoVim, due to E713.
|
||||
" This appears to be a nonsensical bug in NeoVim.
|
||||
let l:key = empty(a:project_root) ? '<<EMPTY>>' : a:project_root
|
||||
|
||||
if !has_key(a:conn.projects, l:key)
|
||||
if !has_key(l:conn.projects, l:key)
|
||||
" Tools without project roots are ready right away, like tsserver.
|
||||
let a:conn.projects[l:key] = {
|
||||
let l:conn.projects[l:key] = {
|
||||
\ 'root': a:project_root,
|
||||
\ 'initialized': empty(a:project_root),
|
||||
\ 'init_request_id': 0,
|
||||
\ 'message_queue': [],
|
||||
\ 'capabilities_queue': [],
|
||||
\}
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! ale#lsp#GetProject(conn, project_root) abort
|
||||
if empty(a:conn)
|
||||
return {}
|
||||
endif
|
||||
|
||||
let l:key = empty(a:project_root) ? '<<EMPTY>>' : a:project_root
|
||||
|
||||
return get(a:conn.projects, l:key, {})
|
||||
|
@ -279,7 +359,7 @@ endfunction
|
|||
"
|
||||
" The job ID will be returned for for the program if it ran, otherwise
|
||||
" 0 will be returned.
|
||||
function! ale#lsp#StartProgram(executable, command, project_root, callback, initialization_options) abort
|
||||
function! ale#lsp#StartProgram(executable, command, init_options) abort
|
||||
if !executable(a:executable)
|
||||
return 0
|
||||
endif
|
||||
|
@ -287,7 +367,7 @@ function! ale#lsp#StartProgram(executable, command, project_root, callback, init
|
|||
let l:conn = s:FindConnection('executable', a:executable)
|
||||
|
||||
" Get the current connection or a new one.
|
||||
let l:conn = !empty(l:conn) ? l:conn : ale#lsp#NewConnection(a:initialization_options)
|
||||
let l:conn = !empty(l:conn) ? l:conn : ale#lsp#NewConnection(a:init_options)
|
||||
let l:conn.executable = a:executable
|
||||
|
||||
if !has_key(l:conn, 'id') || !ale#job#IsRunning(l:conn.id)
|
||||
|
@ -305,18 +385,15 @@ function! ale#lsp#StartProgram(executable, command, project_root, callback, init
|
|||
endif
|
||||
|
||||
let l:conn.id = l:job_id
|
||||
" Add the callback to the List if it's not there already.
|
||||
call uniq(sort(add(l:conn.callback_list, a:callback)))
|
||||
call ale#lsp#RegisterProject(l:conn, a:project_root)
|
||||
|
||||
return l:job_id
|
||||
endfunction
|
||||
|
||||
" Connect to an address and set up a callback for handling responses.
|
||||
function! ale#lsp#ConnectToAddress(address, project_root, callback, initialization_options) abort
|
||||
function! ale#lsp#ConnectToAddress(address, init_options) abort
|
||||
let l:conn = s:FindConnection('id', a:address)
|
||||
" Get the current connection or a new one.
|
||||
let l:conn = !empty(l:conn) ? l:conn : ale#lsp#NewConnection(a:initialization_options)
|
||||
let l:conn = !empty(l:conn) ? l:conn : ale#lsp#NewConnection(a:init_options)
|
||||
|
||||
if !has_key(l:conn, 'channel_id') || !ale#socket#IsOpen(l:conn.channel_id)
|
||||
let l:conn.channel_id = ale#socket#Open(a:address, {
|
||||
|
@ -329,13 +406,21 @@ function! ale#lsp#ConnectToAddress(address, project_root, callback, initializati
|
|||
endif
|
||||
|
||||
let l:conn.id = a:address
|
||||
" Add the callback to the List if it's not there already.
|
||||
call uniq(sort(add(l:conn.callback_list, a:callback)))
|
||||
call ale#lsp#RegisterProject(l:conn, a:project_root)
|
||||
|
||||
return a:address
|
||||
endfunction
|
||||
|
||||
" Given a connection ID and a callback, register that callback for handling
|
||||
" messages if the connection exists.
|
||||
function! ale#lsp#RegisterCallback(conn_id, callback) abort
|
||||
let l:conn = s:FindConnection('id', a:conn_id)
|
||||
|
||||
if !empty(l:conn)
|
||||
" Add the callback to the List if it's not there already.
|
||||
call uniq(sort(add(l:conn.callback_list, a:callback)))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Stop all LSP connections, closing all jobs and channels, and removing any
|
||||
" queued messages.
|
||||
function! ale#lsp#StopAll() abort
|
||||
|
@ -373,11 +458,6 @@ function! ale#lsp#Send(conn_id, message, ...) abort
|
|||
let l:project_root = get(a:000, 0, '')
|
||||
|
||||
let l:conn = s:FindConnection('id', a:conn_id)
|
||||
|
||||
if empty(l:conn)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:project = ale#lsp#GetProject(l:conn, l:project_root)
|
||||
|
||||
if empty(l:project)
|
||||
|
@ -411,45 +491,22 @@ function! ale#lsp#Send(conn_id, message, ...) abort
|
|||
return l:id == 0 ? -1 : l:id
|
||||
endfunction
|
||||
|
||||
" The Document details Dictionary should contain the following keys.
|
||||
"
|
||||
" buffer - The buffer number for the document.
|
||||
" connection_id - The connection ID for the LSP server.
|
||||
" command - The command to run to start the LSP connection.
|
||||
" project_root - The project root for the LSP project.
|
||||
" language_id - The language ID for the project, like 'python', 'rust', etc.
|
||||
|
||||
" Create a new Dictionary containing more connection details, with the
|
||||
" following information added:
|
||||
"
|
||||
" conn - An existing LSP connection for the document.
|
||||
" document_open - 1 if the document is currently open, 0 otherwise.
|
||||
function! s:ExtendDocumentDetails(details) abort
|
||||
let l:extended = copy(a:details)
|
||||
let l:conn = s:FindConnection('id', a:details.connection_id)
|
||||
|
||||
let l:extended.conn = l:conn
|
||||
let l:extended.document_open = !empty(l:conn)
|
||||
\ && has_key(l:conn.open_documents, a:details.buffer)
|
||||
|
||||
return l:extended
|
||||
endfunction
|
||||
|
||||
" Notify LSP servers or tsserver if a document is opened, if needed.
|
||||
" If a document is opened, 1 will be returned, otherwise 0 will be returned.
|
||||
function! ale#lsp#OpenDocument(basic_details) abort
|
||||
let l:d = s:ExtendDocumentDetails(a:basic_details)
|
||||
function! ale#lsp#OpenDocument(conn_id, project_root, buffer, language_id) abort
|
||||
let l:conn = s:FindConnection('id', a:conn_id)
|
||||
let l:opened = 0
|
||||
|
||||
if !empty(l:d.conn) && !l:d.document_open
|
||||
if empty(l:d.language_id)
|
||||
let l:message = ale#lsp#tsserver_message#Open(l:d.buffer)
|
||||
" FIXME: Return 1 if the document is already open?
|
||||
if !empty(l:conn) && !has_key(l:conn.open_documents, a:buffer)
|
||||
if l:conn.is_tsserver
|
||||
let l:message = ale#lsp#tsserver_message#Open(a:buffer)
|
||||
else
|
||||
let l:message = ale#lsp#message#DidOpen(l:d.buffer, l:d.language_id)
|
||||
let l:message = ale#lsp#message#DidOpen(a:buffer, a:language_id)
|
||||
endif
|
||||
|
||||
call ale#lsp#Send(l:d.connection_id, l:message, l:d.project_root)
|
||||
let l:d.conn.open_documents[l:d.buffer] = getbufvar(l:d.buffer, 'changedtick')
|
||||
call ale#lsp#Send(a:conn_id, l:message, a:project_root)
|
||||
let l:conn.open_documents[a:buffer] = getbufvar(a:buffer, 'changedtick')
|
||||
let l:opened = 1
|
||||
endif
|
||||
|
||||
|
@ -458,25 +515,50 @@ endfunction
|
|||
|
||||
" Notify LSP servers or tsserver that a document has changed, if needed.
|
||||
" If a notification is sent, 1 will be returned, otherwise 0 will be returned.
|
||||
function! ale#lsp#NotifyForChanges(basic_details) abort
|
||||
let l:d = s:ExtendDocumentDetails(a:basic_details)
|
||||
function! ale#lsp#NotifyForChanges(conn_id, project_root, buffer) abort
|
||||
let l:conn = s:FindConnection('id', a:conn_id)
|
||||
let l:notified = 0
|
||||
|
||||
if l:d.document_open
|
||||
let l:new_tick = getbufvar(l:d.buffer, 'changedtick')
|
||||
if !empty(l:conn) && has_key(l:conn.open_documents, a:buffer)
|
||||
let l:new_tick = getbufvar(a:buffer, 'changedtick')
|
||||
|
||||
if l:d.conn.open_documents[l:d.buffer] < l:new_tick
|
||||
if empty(l:d.language_id)
|
||||
let l:message = ale#lsp#tsserver_message#Change(l:d.buffer)
|
||||
if l:conn.open_documents[a:buffer] < l:new_tick
|
||||
if l:conn.is_tsserver
|
||||
let l:message = ale#lsp#tsserver_message#Change(a:buffer)
|
||||
else
|
||||
let l:message = ale#lsp#message#DidChange(l:d.buffer)
|
||||
let l:message = ale#lsp#message#DidChange(a:buffer)
|
||||
endif
|
||||
|
||||
call ale#lsp#Send(l:d.connection_id, l:message, l:d.project_root)
|
||||
let l:d.conn.open_documents[l:d.buffer] = l:new_tick
|
||||
call ale#lsp#Send(a:conn_id, l:message, a:project_root)
|
||||
let l:conn.open_documents[a:buffer] = l:new_tick
|
||||
let l:notified = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
return l:notified
|
||||
endfunction
|
||||
|
||||
" Given some LSP details that must contain at least `connection_id` and
|
||||
" `project_root` keys,
|
||||
function! ale#lsp#WaitForCapability(conn_id, project_root, capability, callback) abort
|
||||
let l:conn = s:FindConnection('id', a:conn_id)
|
||||
let l:project = ale#lsp#GetProject(l:conn, a:project_root)
|
||||
|
||||
if empty(l:project)
|
||||
return 0
|
||||
endif
|
||||
|
||||
if type(get(l:conn.capabilities, a:capability, v:null)) isnot v:t_number
|
||||
throw 'Invalid capability ' . a:capability
|
||||
endif
|
||||
|
||||
if l:project.initialized
|
||||
if l:conn.is_tsserver || l:conn.capabilities[a:capability]
|
||||
" The project has been initialized, so call the callback now.
|
||||
call call(a:callback, [a:conn_id, a:project_root])
|
||||
endif
|
||||
else
|
||||
" Call the callback later, once we have the information we need.
|
||||
call add(l:project.capabilities_queue, [a:capability, a:callback])
|
||||
endif
|
||||
endfunction
|
||||
|
|
|
@ -88,7 +88,7 @@ function! ale#lsp#response#ReadTSServerDiagnostics(response) abort
|
|||
endfunction
|
||||
|
||||
function! ale#lsp#response#GetErrorMessage(response) abort
|
||||
if type(get(a:response, 'error', 0)) isnot type({})
|
||||
if type(get(a:response, 'error', 0)) isnot v:t_dict
|
||||
return ''
|
||||
endif
|
||||
|
||||
|
@ -108,12 +108,12 @@ function! ale#lsp#response#GetErrorMessage(response) abort
|
|||
" Include the traceback or error data as details, if present.
|
||||
let l:error_data = get(a:response.error, 'data', {})
|
||||
|
||||
if type(l:error_data) is type('')
|
||||
if type(l:error_data) is v:t_string
|
||||
let l:message .= "\n" . l:error_data
|
||||
else
|
||||
let l:traceback = get(l:error_data, 'traceback', [])
|
||||
|
||||
if type(l:traceback) is type([]) && !empty(l:traceback)
|
||||
if type(l:traceback) is v:t_list && !empty(l:traceback)
|
||||
let l:message .= "\n" . join(l:traceback, "\n")
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -126,10 +126,9 @@ function! ale#lsp_linter#GetOptions(buffer, linter) abort
|
|||
return l:initialization_options
|
||||
endfunction
|
||||
|
||||
" Given a buffer, an LSP linter, and a callback to register for handling
|
||||
" messages, start up an LSP linter and get ready to receive errors or
|
||||
" completions.
|
||||
function! ale#lsp_linter#StartLSP(buffer, linter, callback) abort
|
||||
" Given a buffer, an LSP linter, start up an LSP linter and get ready to
|
||||
" receive messages for the document.
|
||||
function! ale#lsp_linter#StartLSP(buffer, linter) abort
|
||||
let l:command = ''
|
||||
let l:address = ''
|
||||
let l:root = ale#util#GetFunction(a:linter.project_root_callback)(a:buffer)
|
||||
|
@ -140,16 +139,11 @@ function! ale#lsp_linter#StartLSP(buffer, linter, callback) abort
|
|||
return {}
|
||||
endif
|
||||
|
||||
let l:initialization_options = ale#lsp_linter#GetOptions(a:buffer, a:linter)
|
||||
let l:init_options = ale#lsp_linter#GetOptions(a:buffer, a:linter)
|
||||
|
||||
if a:linter.lsp is# 'socket'
|
||||
let l:address = ale#linter#GetAddress(a:buffer, a:linter)
|
||||
let l:conn_id = ale#lsp#ConnectToAddress(
|
||||
\ l:address,
|
||||
\ l:root,
|
||||
\ a:callback,
|
||||
\ l:initialization_options,
|
||||
\)
|
||||
let l:conn_id = ale#lsp#ConnectToAddress(l:address, l:init_options)
|
||||
else
|
||||
let l:executable = ale#linter#GetExecutable(a:buffer, a:linter)
|
||||
|
||||
|
@ -164,14 +158,10 @@ function! ale#lsp_linter#StartLSP(buffer, linter, callback) abort
|
|||
let l:conn_id = ale#lsp#StartProgram(
|
||||
\ l:executable,
|
||||
\ l:command,
|
||||
\ l:root,
|
||||
\ a:callback,
|
||||
\ l:initialization_options,
|
||||
\ l:init_options,
|
||||
\)
|
||||
endif
|
||||
|
||||
let l:language_id = ale#util#GetFunction(a:linter.language_callback)(a:buffer)
|
||||
|
||||
if empty(l:conn_id)
|
||||
if g:ale_history_enabled && !empty(l:command)
|
||||
call ale#history#Add(a:buffer, 'failed', l:conn_id, l:command)
|
||||
|
@ -180,6 +170,16 @@ function! ale#lsp_linter#StartLSP(buffer, linter, callback) abort
|
|||
return {}
|
||||
endif
|
||||
|
||||
" tsserver behaves differently, so tell the LSP API that it is tsserver.
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
call ale#lsp#MarkConnectionAsTsserver(l:conn_id)
|
||||
endif
|
||||
|
||||
" Register the project now the connection is ready.
|
||||
call ale#lsp#RegisterProject(l:conn_id, l:root)
|
||||
|
||||
let l:language_id = ale#util#GetFunction(a:linter.language_callback)(a:buffer)
|
||||
|
||||
let l:details = {
|
||||
\ 'buffer': a:buffer,
|
||||
\ 'connection_id': l:conn_id,
|
||||
|
@ -188,7 +188,7 @@ function! ale#lsp_linter#StartLSP(buffer, linter, callback) abort
|
|||
\ 'language_id': l:language_id,
|
||||
\}
|
||||
|
||||
if ale#lsp#OpenDocument(l:details)
|
||||
if ale#lsp#OpenDocument(l:conn_id, l:root, a:buffer, l:language_id)
|
||||
if g:ale_history_enabled && !empty(l:command)
|
||||
call ale#history#Add(a:buffer, 'started', l:conn_id, l:command)
|
||||
endif
|
||||
|
@ -196,7 +196,7 @@ function! ale#lsp_linter#StartLSP(buffer, linter, callback) abort
|
|||
|
||||
" The change message needs to be sent for tsserver before doing anything.
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
call ale#lsp#NotifyForChanges(l:details)
|
||||
call ale#lsp#NotifyForChanges(l:conn_id, l:root, a:buffer)
|
||||
endif
|
||||
|
||||
return l:details
|
||||
|
@ -204,11 +204,7 @@ endfunction
|
|||
|
||||
function! ale#lsp_linter#CheckWithLSP(buffer, linter) abort
|
||||
let l:info = g:ale_buffer_info[a:buffer]
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(
|
||||
\ a:buffer,
|
||||
\ a:linter,
|
||||
\ function('ale#lsp_linter#HandleLSPResponse'),
|
||||
\)
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(a:buffer, a:linter)
|
||||
|
||||
if empty(l:lsp_details)
|
||||
return 0
|
||||
|
@ -217,25 +213,25 @@ function! ale#lsp_linter#CheckWithLSP(buffer, linter) abort
|
|||
let l:id = l:lsp_details.connection_id
|
||||
let l:root = l:lsp_details.project_root
|
||||
|
||||
" Register a callback now for handling errors now.
|
||||
let l:Callback = function('ale#lsp_linter#HandleLSPResponse')
|
||||
call ale#lsp#RegisterCallback(l:id, l:Callback)
|
||||
|
||||
" Remember the linter this connection is for.
|
||||
let s:lsp_linter_map[l:id] = a:linter.name
|
||||
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:message = ale#lsp#tsserver_message#Geterr(a:buffer)
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:root)
|
||||
|
||||
let l:notified = l:request_id != 0
|
||||
let l:notified = ale#lsp#Send(l:id, l:message, l:root) != 0
|
||||
else
|
||||
let l:notified = ale#lsp#NotifyForChanges(l:lsp_details)
|
||||
let l:notified = ale#lsp#NotifyForChanges(l:id, l:root, a:buffer)
|
||||
endif
|
||||
|
||||
" If this was a file save event, also notify the server of that.
|
||||
if a:linter.lsp isnot# 'tsserver'
|
||||
\&& getbufvar(a:buffer, 'ale_save_event_fired', 0)
|
||||
let l:save_message = ale#lsp#message#DidSave(a:buffer)
|
||||
let l:request_id = ale#lsp#Send(l:id, l:save_message, l:root)
|
||||
|
||||
let l:notified = l:request_id != 0
|
||||
let l:notified = ale#lsp#Send(l:id, l:save_message, l:root) != 0
|
||||
endif
|
||||
|
||||
if l:notified
|
||||
|
|
|
@ -105,6 +105,21 @@ function! ale#path#GetAbsPath(base_directory, filename) abort
|
|||
return ale#path#Simplify(a:base_directory . l:sep . a:filename)
|
||||
endfunction
|
||||
|
||||
" Given a path, return the directory name for that path, with no trailing
|
||||
" slashes. If the argument is empty(), return an empty string.
|
||||
function! ale#path#Dirname(path) abort
|
||||
if empty(a:path)
|
||||
return ''
|
||||
endif
|
||||
|
||||
" For /foo/bar/ we need :h:h to get /foo
|
||||
if a:path[-1:] is# '/'
|
||||
return fnamemodify(a:path, ':h:h')
|
||||
endif
|
||||
|
||||
return fnamemodify(a:path, ':h')
|
||||
endfunction
|
||||
|
||||
" Given a buffer number and a relative or absolute path, return 1 if the
|
||||
" two paths represent the same file on disk.
|
||||
function! ale#path#IsBufferPath(buffer, complex_filename) abort
|
||||
|
|
|
@ -68,37 +68,46 @@ function! s:FindReferences(linter) abort
|
|||
let l:buffer = bufnr('')
|
||||
let [l:line, l:column] = getcurpos()[1:2]
|
||||
|
||||
let l:Callback = a:linter.lsp is# 'tsserver'
|
||||
\ ? function('ale#references#HandleTSServerResponse')
|
||||
\ : function('ale#references#HandleLSPResponse')
|
||||
if a:linter.lsp isnot# 'tsserver'
|
||||
let l:column = min([l:column, len(getline(l:line))])
|
||||
endif
|
||||
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(l:buffer, a:linter, l:Callback)
|
||||
let l:lsp_details = ale#lsp_linter#StartLSP(l:buffer, a:linter)
|
||||
|
||||
if empty(l:lsp_details)
|
||||
return 0
|
||||
endif
|
||||
|
||||
let l:id = l:lsp_details.connection_id
|
||||
let l:root = l:lsp_details.project_root
|
||||
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:message = ale#lsp#tsserver_message#References(
|
||||
\ l:buffer,
|
||||
\ l:line,
|
||||
\ l:column
|
||||
\)
|
||||
else
|
||||
" Send a message saying the buffer has changed first, or the
|
||||
" references position probably won't make sense.
|
||||
call ale#lsp#NotifyForChanges(l:lsp_details)
|
||||
function! OnReady(...) abort closure
|
||||
let l:Callback = a:linter.lsp is# 'tsserver'
|
||||
\ ? function('ale#references#HandleTSServerResponse')
|
||||
\ : function('ale#references#HandleLSPResponse')
|
||||
|
||||
let l:column = min([l:column, len(getline(l:line))])
|
||||
call ale#lsp#RegisterCallback(l:id, l:Callback)
|
||||
|
||||
let l:message = ale#lsp#message#References(l:buffer, l:line, l:column)
|
||||
endif
|
||||
if a:linter.lsp is# 'tsserver'
|
||||
let l:message = ale#lsp#tsserver_message#References(
|
||||
\ l:buffer,
|
||||
\ l:line,
|
||||
\ l:column
|
||||
\)
|
||||
else
|
||||
" Send a message saying the buffer has changed first, or the
|
||||
" references position probably won't make sense.
|
||||
call ale#lsp#NotifyForChanges(l:id, l:root, l:buffer)
|
||||
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:lsp_details.project_root)
|
||||
let l:message = ale#lsp#message#References(l:buffer, l:line, l:column)
|
||||
endif
|
||||
|
||||
let s:references_map[l:request_id] = {}
|
||||
let l:request_id = ale#lsp#Send(l:id, l:message, l:lsp_details.project_root)
|
||||
|
||||
let s:references_map[l:request_id] = {}
|
||||
endfunction
|
||||
|
||||
call ale#lsp#WaitForCapability(l:id, l:root, 'references', function('OnReady'))
|
||||
endfunction
|
||||
|
||||
function! ale#references#Find() abort
|
||||
|
|
|
@ -211,7 +211,7 @@ function! s:BuildSignMap(buffer, current_sign_list, grouped_items) abort
|
|||
|
||||
if l:max_signs is 0
|
||||
let l:selected_grouped_items = []
|
||||
elseif type(l:max_signs) is type(0) && l:max_signs > 0
|
||||
elseif type(l:max_signs) is v:t_number && l:max_signs > 0
|
||||
let l:selected_grouped_items = a:grouped_items[:l:max_signs - 1]
|
||||
else
|
||||
let l:selected_grouped_items = a:grouped_items
|
||||
|
|
|
@ -52,3 +52,26 @@ function! ale#test#SetFilename(path) abort
|
|||
|
||||
silent! noautocmd execute 'file ' . fnameescape(ale#path#Simplify(l:full_path))
|
||||
endfunction
|
||||
|
||||
function! s:RemoveModule(results) abort
|
||||
for l:item in a:results
|
||||
if has_key(l:item, 'module')
|
||||
call remove(l:item, 'module')
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" Return loclist data without the module string, only in newer Vim versions.
|
||||
function! ale#test#GetLoclistWithoutModule() abort
|
||||
let l:results = getloclist(0)
|
||||
call s:RemoveModule(l:results)
|
||||
|
||||
return l:results
|
||||
endfunction
|
||||
|
||||
function! ale#test#GetQflistWithoutModule() abort
|
||||
let l:results = getqflist()
|
||||
call s:RemoveModule(l:results)
|
||||
|
||||
return l:results
|
||||
endfunction
|
||||
|
|
|
@ -43,7 +43,7 @@ function! ale#toggle#Toggle() abort
|
|||
call s:CleanupEveryBuffer()
|
||||
call s:DisablePostamble()
|
||||
|
||||
if has('balloon_eval')
|
||||
if exists('*ale#balloon#Disable')
|
||||
call ale#balloon#Disable()
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -79,7 +79,7 @@ function! ale#util#GetLineCount(buffer) abort
|
|||
endfunction
|
||||
|
||||
function! ale#util#GetFunction(string_or_ref) abort
|
||||
if type(a:string_or_ref) == type('')
|
||||
if type(a:string_or_ref) is v:t_string
|
||||
return function(a:string_or_ref)
|
||||
endif
|
||||
|
||||
|
@ -89,11 +89,11 @@ endfunction
|
|||
function! ale#util#Open(filename, line, column, options) abort
|
||||
if get(a:options, 'open_in_tab', 0)
|
||||
call ale#util#Execute('tabedit ' . fnameescape(a:filename))
|
||||
else
|
||||
elseif bufnr(a:filename) isnot bufnr('')
|
||||
" Open another file only if we need to.
|
||||
if bufnr(a:filename) isnot bufnr('')
|
||||
call ale#util#Execute('edit ' . fnameescape(a:filename))
|
||||
endif
|
||||
call ale#util#Execute('edit ' . fnameescape(a:filename))
|
||||
else
|
||||
normal! m`
|
||||
endif
|
||||
|
||||
call cursor(a:line, a:column)
|
||||
|
@ -303,8 +303,8 @@ endfunction
|
|||
" Only the first pattern which matches a line will be returned.
|
||||
function! ale#util#GetMatches(lines, patterns) abort
|
||||
let l:matches = []
|
||||
let l:lines = type(a:lines) == type([]) ? a:lines : [a:lines]
|
||||
let l:patterns = type(a:patterns) == type([]) ? a:patterns : [a:patterns]
|
||||
let l:lines = type(a:lines) is v:t_list ? a:lines : [a:lines]
|
||||
let l:patterns = type(a:patterns) is v:t_list ? a:patterns : [a:patterns]
|
||||
|
||||
for l:line in l:lines
|
||||
for l:pattern in l:patterns
|
||||
|
@ -382,7 +382,7 @@ function! ale#util#FuzzyJSONDecode(data, default) abort
|
|||
return a:default
|
||||
endif
|
||||
|
||||
let l:str = type(a:data) == type('') ? a:data : join(a:data, '')
|
||||
let l:str = type(a:data) is v:t_string ? a:data : join(a:data, '')
|
||||
|
||||
try
|
||||
let l:result = json_decode(l:str)
|
||||
|
|
|
@ -25,13 +25,28 @@ g:ale_c_build_dir *g:ale_c_build_dir*
|
|||
Type: |String|
|
||||
Default: `''`
|
||||
|
||||
A path to the directory containing the `compile_commands.json` file to use
|
||||
with c-family linters. Usually setting this option to a non-empty string
|
||||
will override the |g:ale_c_build_dir_names| option to impose a compilation
|
||||
database (it can be useful if multiple builds are in multiple build
|
||||
subdirectories in the project tree).
|
||||
This feature is also most useful for the clang tools linters, wrapped
|
||||
around LibTooling (namely clang-tidy here)
|
||||
For programs that can read `compile_commands.json` files, this option can be
|
||||
set to the directory containing the file for the project. ALE will try to
|
||||
determine the location of `compile_commands.json` automatically, but if your
|
||||
file exists in some other directory, you can set this option so ALE will
|
||||
know where it is.
|
||||
|
||||
This directory will be searched instead of |g:ale_c_build_dir_names|.
|
||||
|
||||
|
||||
g:ale_c_parse_compile_commands *g:ale_c_parse_compile_commands*
|
||||
*b:ale_c_parse_compile_commands*
|
||||
Type: |Number|
|
||||
Default: `0`
|
||||
|
||||
If set to `1`, ALE will parse `compile_commands.json` files to automatically
|
||||
determine flags for C or C++ compilers. ALE will first search for the
|
||||
nearest `compile_commands.json` file, and then look for
|
||||
`compile_commands.json` files in the directories for
|
||||
|g:ale_c_build_dir_names|.
|
||||
|
||||
If |g:ale_c_parse_makefile| or |b:ale_c_parse_makefile| is set to `1`, the
|
||||
output of `make -n` will be preferred over `compile_commands.json` files.
|
||||
|
||||
|
||||
g:ale_c_parse_makefile *g:ale_c_parse_makefile*
|
||||
|
@ -63,6 +78,25 @@ g:ale_c_clang_options *g:ale_c_clang_options*
|
|||
This variable can be changed to modify flags given to clang.
|
||||
|
||||
|
||||
===============================================================================
|
||||
clangd *ale-c-clangd*
|
||||
|
||||
g:ale_c_clangd_executable *g:ale_c_clangd_executable*
|
||||
*b:ale_c_clangd_executable*
|
||||
Type: |String|
|
||||
Default: `'clangd'`
|
||||
|
||||
This variable can be changed to use a different executable for clangd.
|
||||
|
||||
|
||||
g:ale_c_clangd_options *g:ale_c_clangd_options*
|
||||
*b:ale_c_clangd_options*
|
||||
Type: |String|
|
||||
Default: `''`
|
||||
|
||||
This variable can be changed to modify flags given to clangd.
|
||||
|
||||
|
||||
===============================================================================
|
||||
clang-format *ale-c-clangformat*
|
||||
|
||||
|
@ -154,6 +188,26 @@ g:ale_c_cppcheck_options *g:ale_c_cppcheck_options*
|
|||
This variable can be changed to modify flags given to cppcheck.
|
||||
|
||||
|
||||
===============================================================================
|
||||
cquery *ale-c-cquery*
|
||||
|
||||
g:ale_c_cquery_executable *g:ale_c_cquery_executable*
|
||||
*b:ale_c_cquery_executable*
|
||||
Type: |String|
|
||||
Default: `'cquery'`
|
||||
|
||||
This variable can be changed to use a different executable for cquery.
|
||||
|
||||
|
||||
g:ale_cpp_cquery_cache_directory *g:ale_c_cquery_cache_directory*
|
||||
*b:ale_c_cquery_cache_directory*
|
||||
Type: |String|
|
||||
Default: `'~/.cache/cquery'`
|
||||
|
||||
This variable can be changed to decide which directory cquery uses for its
|
||||
cache.
|
||||
|
||||
|
||||
===============================================================================
|
||||
flawfinder *ale-c-flawfinder*
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ The following C options also apply to some C++ linters too.
|
|||
* |g:ale_c_build_dir_names|
|
||||
* |g:ale_c_build_dir|
|
||||
* |g:ale_c_parse_makefile|
|
||||
* |g:ale_c_parse_compile_commands|
|
||||
|
||||
|
||||
===============================================================================
|
||||
|
|
|
@ -115,6 +115,10 @@ these are reported with ALE's `custom-linting-rules` script. See
|
|||
* Don't use the `tempname()` function. It doesn't work when `$TMPDIR` isn't
|
||||
set. Use `ale#util#Tempname()` instead, which temporarily sets `$TMPDIR`
|
||||
appropriately where needed.
|
||||
* Use `snake_case` names for linter names, so they can be used as part of
|
||||
variable names. You can define `aliases` for linters, for other names people
|
||||
might try to configure linters with.
|
||||
* Use |v:t_TYPE| variables instead of `type()`, which are more readable.
|
||||
|
||||
Apply the following guidelines when writing Vader test files.
|
||||
|
||||
|
@ -145,9 +149,10 @@ ALE is tested with a suite of tests executed in Travis CI and AppVeyor. ALE
|
|||
runs tests with the following versions of Vim in the following environments.
|
||||
|
||||
1. Vim 8.0.0027 on Linux via Travis CI.
|
||||
2. NeoVim 0.2.0 on Linux via Travis CI.
|
||||
3. NeoVim 0.3.0 on Linux via Travis CI.
|
||||
4. Vim 8 (stable builds) on Windows via AppVeyor.
|
||||
2. Vim 8.1.0204 on Linux via Travis CI.
|
||||
3. NeoVim 0.2.0 on Linux via Travis CI.
|
||||
4. NeoVim 0.3.0 on Linux via Travis CI.
|
||||
5. Vim 8 (stable builds) on Windows via AppVeyor.
|
||||
|
||||
If you are developing ALE code on Linux, Mac OSX, or BSD, you can run ALEs
|
||||
tests by installing Docker and running the `run-tests` script. Follow the
|
||||
|
|
|
@ -32,5 +32,24 @@ g:ale_fortran_gcc_use_free_form *g:ale_fortran_gcc_use_free_form*
|
|||
instead, for checking files with fixed form layouts.
|
||||
|
||||
|
||||
===============================================================================
|
||||
language_server *ale-fortran-language-server*
|
||||
|
||||
g:ale_fortran_language_server_executable *g:ale_fortran_language_server_executable*
|
||||
*b:ale_fortran_language_server_executable*
|
||||
Type: |String|
|
||||
Default: `'fortls'`
|
||||
|
||||
This variable can be changed to modify the executable used for the Fortran
|
||||
Language Server.
|
||||
|
||||
g:ale_fortran_language_server_use_global *g:ale_fortran_language_server_use_global*
|
||||
*b:ale_fortran_language_server_use_global*
|
||||
Type: |Number|
|
||||
Default: `get(g:, 'ale_use_global_executables', 0)`
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
|
||||
===============================================================================
|
||||
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
|
||||
|
|
|
@ -22,6 +22,17 @@ g:ale_haskell_ghc_options *g:ale_haskell_ghc_options*
|
|||
|
||||
This variable can be changed to modify flags given to ghc.
|
||||
|
||||
===============================================================================
|
||||
cabal-ghc *ale-haskell-cabal-ghc*
|
||||
|
||||
g:ale_haskell_cabal_ghc_options *g:ale_haskell_cabal_ghc_options*
|
||||
*b:ale_haskell_cabal_ghc_options*
|
||||
Type: |String|
|
||||
Default: `'-fno-code -v0'`
|
||||
|
||||
This variable can be changed to modify flags given to ghc through cabal
|
||||
exec.
|
||||
|
||||
===============================================================================
|
||||
hdevtools *ale-haskell-hdevtools*
|
||||
|
||||
|
|
|
@ -397,6 +397,36 @@ g:ale_python_pyre_use_global *g:ale_python_pyre_use_global*
|
|||
See |ale-integrations-local-executables|
|
||||
|
||||
|
||||
===============================================================================
|
||||
vulture *ale-python-vulture*
|
||||
|
||||
g:ale_python_vulture_change_directory *g:ale_python_vulture_change_directory*
|
||||
*b:ale_python_vulture_change_directory*
|
||||
Type: |Number|
|
||||
Default: `1`
|
||||
|
||||
If set to `1`, ALE will switch to the directory the Python file being
|
||||
checked with `vulture` is in before checking it and check the whole project
|
||||
directory instead of checking only the file opened in the current buffer.
|
||||
This helps `vulture` to know the context and avoid false-negative results.
|
||||
|
||||
|
||||
g:ale_python_vulture_executable *g:ale_python_vulture_executable*
|
||||
*b:ale_python_vulture_executable*
|
||||
Type: |String|
|
||||
Default: `'vulture'`
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
|
||||
g:ale_python_vulture_use_global *g:ale_python_vulture_use_global*
|
||||
*b:ale_python_vulture_use_global*
|
||||
Type: |Number|
|
||||
Default: `get(g:, 'ale_use_global_executables', 0)`
|
||||
|
||||
See |ale-integrations-local-executables|
|
||||
|
||||
|
||||
===============================================================================
|
||||
yapf *ale-python-yapf*
|
||||
|
||||
|
|
|
@ -26,9 +26,11 @@ CONTENTS *ale-contents*
|
|||
gawk................................|ale-awk-gawk|
|
||||
c.....................................|ale-c-options|
|
||||
clang...............................|ale-c-clang|
|
||||
clangd..............................|ale-c-clangd|
|
||||
clang-format........................|ale-c-clangformat|
|
||||
clangtidy...........................|ale-c-clangtidy|
|
||||
cppcheck............................|ale-c-cppcheck|
|
||||
cquery..............................|ale-c-cquery|
|
||||
flawfinder..........................|ale-c-flawfinder|
|
||||
gcc.................................|ale-c-gcc|
|
||||
chef..................................|ale-chef-options|
|
||||
|
@ -76,6 +78,7 @@ CONTENTS *ale-contents*
|
|||
fish..................................|ale-fish-options|
|
||||
fortran...............................|ale-fortran-options|
|
||||
gcc.................................|ale-fortran-gcc|
|
||||
language_server.....................|ale-fortran-language-server|
|
||||
fountain..............................|ale-fountain-options|
|
||||
fusionscript..........................|ale-fuse-options|
|
||||
fusion-lint.........................|ale-fuse-fusionlint|
|
||||
|
@ -98,6 +101,7 @@ CONTENTS *ale-contents*
|
|||
haskell...............................|ale-haskell-options|
|
||||
brittany............................|ale-haskell-brittany|
|
||||
ghc.................................|ale-haskell-ghc|
|
||||
cabal-ghc...........................|ale-haskell-cabal-ghc|
|
||||
hdevtools...........................|ale-haskell-hdevtools|
|
||||
hfmt................................|ale-haskell-hfmt|
|
||||
stack-build.........................|ale-haskell-stack-build|
|
||||
|
@ -203,6 +207,7 @@ CONTENTS *ale-contents*
|
|||
pylint..............................|ale-python-pylint|
|
||||
pyls................................|ale-python-pyls|
|
||||
pyre................................|ale-python-pyre|
|
||||
vulture.............................|ale-python-vulture|
|
||||
yapf................................|ale-python-yapf|
|
||||
qml...................................|ale-qml-options|
|
||||
qmlfmt..............................|ale-qml-qmlfmt|
|
||||
|
@ -333,7 +338,7 @@ Notes:
|
|||
* Awk: `gawk`
|
||||
* Bash: `language-server`, `shell` (-n flag), `shellcheck`, `shfmt`
|
||||
* Bourne Shell: `shell` (-n flag), `shellcheck`, `shfmt`
|
||||
* C: `cppcheck`, `cpplint`!!, `clang`, `clangtidy`!!, `clang-format`, `flawfinder`, `gcc`
|
||||
* C: `cppcheck`, `cpplint`!!, `clang`, `clangd`, `clangtidy`!!, `clang-format`, `cquery`, `flawfinder`, `gcc`
|
||||
* C++ (filetype cpp): `clang`, `clangcheck`!!, `clangtidy`!!, `clang-format`, `cppcheck`, `cpplint`!!, `cquery`, `flawfinder`, `gcc`
|
||||
* CUDA: `nvcc`!!
|
||||
* C#: `mcs`, `mcsc`!!
|
||||
|
@ -355,7 +360,7 @@ Notes:
|
|||
* Erb: `erb`, `erubi`, `erubis`
|
||||
* Erlang: `erlc`, `SyntaxErl`
|
||||
* Fish: `fish` (-n flag)
|
||||
* Fortran: `gcc`
|
||||
* Fortran: `gcc`, `language_server`
|
||||
* Fountain: `proselint`
|
||||
* FusionScript: `fusion-lint`
|
||||
* Git Commit Messages: `gitlint`
|
||||
|
@ -364,7 +369,7 @@ Notes:
|
|||
* GraphQL: `eslint`, `gqlint`, `prettier`
|
||||
* Haml: `haml-lint`
|
||||
* Handlebars: `ember-template-lint`
|
||||
* Haskell: `brittany`, `ghc`, `stack-ghc`, `stack-build`!!, `ghc-mod`, `stack-ghc-mod`, `hlint`, `hdevtools`, `hfmt`
|
||||
* Haskell: `brittany`, `ghc`, `cabal-ghc`, `stack-ghc`, `stack-build`!!, `ghc-mod`, `stack-ghc-mod`, `hlint`, `hdevtools`, `hfmt`
|
||||
* HTML: `alex`!!, `HTMLHint`, `proselint`, `tidy`, `write-good`
|
||||
* Idris: `idris`
|
||||
* Java: `checkstyle`, `javac`, `google-java-format`, `PMD`
|
||||
|
@ -395,7 +400,7 @@ Notes:
|
|||
* proto: `protoc-gen-lint`
|
||||
* Pug: `pug-lint`
|
||||
* Puppet: `languageserver`, `puppet`, `puppet-lint`
|
||||
* Python: `autopep8`, `black`, `flake8`, `isort`, `mypy`, `prospector`, `pycodestyle`, `pyls`, `pyre`, `pylint`!!, `yapf`
|
||||
* Python: `autopep8`, `black`, `flake8`, `isort`, `mypy`, `prospector`, `pycodestyle`, `pyls`, `pyre`, `pylint`!!, `vulture`!!, `yapf`
|
||||
* QML: `qmlfmt`, `qmllint`
|
||||
* R: `lintr`
|
||||
* ReasonML: `merlin`, `ols`, `refmt`
|
||||
|
@ -1413,8 +1418,7 @@ g:ale_set_balloons *g:ale_set_balloons*
|
|||
*b:ale_set_balloons*
|
||||
|
||||
Type: |Number|
|
||||
Default: `(has('balloon_eval') && has('gui_running'))`
|
||||
`|| (has('balloon_eval_term') && !has('gui_running'))`
|
||||
Default: `has('balloon_eval') && has('gui_running')`
|
||||
|
||||
When this option is set to `1`, balloon messages will be displayed for
|
||||
problems or hover information if available.
|
||||
|
@ -1424,6 +1428,12 @@ g:ale_set_balloons *g:ale_set_balloons*
|
|||
supporting "Hover" information, per |ale-hover|, then brief information
|
||||
about the symbol under the cursor will be displayed in a balloon.
|
||||
|
||||
Balloons can be enabled for terminal versions of Vim that support balloons,
|
||||
but some versions of Vim will produce strange mouse behavior when balloons
|
||||
are enabled. To configure balloons for your terminal, you should first
|
||||
configure your |ttymouse| setting, and then consider setting
|
||||
`g:ale_set_balloons` to `1` before ALE is loaded.
|
||||
|
||||
`b:ale_set_balloons` can be set to `0` to disable balloons for a buffer.
|
||||
Balloons cannot be enabled for a specific buffer when not initially enabled
|
||||
globally.
|
||||
|
|
|
@ -110,10 +110,7 @@ let g:ale_set_highlights = get(g:, 'ale_set_highlights', has('syntax'))
|
|||
let g:ale_echo_cursor = get(g:, 'ale_echo_cursor', 1)
|
||||
|
||||
" This flag can be set to 0 to disable balloon support.
|
||||
let g:ale_set_balloons = get(g:, 'ale_set_balloons',
|
||||
\ (has('balloon_eval') && has('gui_running'))
|
||||
\ || (has('balloon_eval_term') && !has('gui_running'))
|
||||
\)
|
||||
let g:ale_set_balloons = get(g:, 'ale_set_balloons', has('balloon_eval') && has('gui_running'))
|
||||
|
||||
" This flag can be set to 0 to disable warnings for trailing whitespace
|
||||
let g:ale_warn_about_trailing_whitespace = get(g:, 'ale_warn_about_trailing_whitespace', 1)
|
||||
|
|
|
@ -9,8 +9,8 @@ endif
|
|||
let g:loaded_commentary = 1
|
||||
|
||||
function! s:surroundings() abort
|
||||
return split(get(b:, 'commentary_format', substitute(substitute(
|
||||
\ &commentstring, '\S\zs%s',' %s','') ,'%s\ze\S', '%s ', '')), '%s', 1)
|
||||
return split(get(b:, 'commentary_format', substitute(substitute(substitute(
|
||||
\ &commentstring, '^$', '%s', ''), '\S\zs%s',' %s', '') ,'%s\ze\S', '%s ', '')), '%s', 1)
|
||||
endfunction
|
||||
|
||||
function! s:strip_white_space(l,r,line) abort
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -199,11 +199,7 @@ that are part of Git repositories).
|
|||
|
||||
*fugitive-:Gmove*
|
||||
:Gmove {destination} Wrapper around git-mv that renames the buffer
|
||||
afterward. The destination is relative to the current
|
||||
directory except when started with a /, in which case
|
||||
it is relative to the work tree. (This is a holdover
|
||||
from before |:Grename| and will be removed.) Add a !
|
||||
to pass -f.
|
||||
afterward. Add a ! to pass -f.
|
||||
|
||||
*fugitive-:Grename*
|
||||
:Grename {destination} Like |:Gmove| but operates relative to the parent
|
||||
|
@ -234,12 +230,11 @@ that are part of Git repositories).
|
|||
<CR> q, then open commit
|
||||
o open commit in horizontal split
|
||||
O open commit in new tab
|
||||
p open commit in preview window
|
||||
- reblame at commit
|
||||
~ reblame at [count]th first grandparent
|
||||
P reblame at [count]th parent (like HEAD^[count])
|
||||
|
||||
:[range]Gblame [flags] Run git-blame on the given range.
|
||||
|
||||
*fugitive-:Gbrowse*
|
||||
:Gbrowse Open the current file, blob, tree, commit, or tag
|
||||
in your browser at the upstream hosting provider.
|
||||
|
@ -251,12 +246,6 @@ that are part of Git repositories).
|
|||
supported by installing rhubarb.vim, available at
|
||||
<https://github.com/tpope/vim-rhubarb>.
|
||||
|
||||
The hosting provider is determined by looking at the
|
||||
remote for the current or specified branch and falls
|
||||
back to "origin". In the special case of a "."
|
||||
remote, a local instance of git-instaweb will be
|
||||
started and used.
|
||||
|
||||
:Gbrowse {revision} Like :Gbrowse, but for a given |fugitive-revision|. A
|
||||
useful value here is -, which ties the URL to the
|
||||
latest commit rather than a volatile branch.
|
||||
|
@ -334,19 +323,19 @@ refs/heads/x .git/refs/heads/x
|
|||
@ The commit referenced by @ aka HEAD
|
||||
master^ The parent of the commit referenced by master
|
||||
master: The tree referenced by master
|
||||
/master The file named master in the work tree
|
||||
./master The file named master in the work tree
|
||||
Makefile The file named Makefile in the work tree
|
||||
@^:Makefile The file named Makefile in the parent of HEAD
|
||||
:Makefile The file named Makefile in the index (writable)
|
||||
@:% The current file in HEAD
|
||||
- The current file in HEAD
|
||||
^ The current file in the previous commit
|
||||
~3 The current file 3 commits ago
|
||||
: .git/index (Same as |:Gstatus|)
|
||||
:0 The current file in the index
|
||||
:1 The current file's common ancestor during a conflict
|
||||
:2 The current file in the target branch during a conflict
|
||||
:3 The current file in the merged branch during a conflict
|
||||
:/foo The most recent commit with "foo" in the message
|
||||
:% The current file in the index
|
||||
:1:% The current file's common ancestor during a conflict
|
||||
:2:% The current file in the target branch during a conflict
|
||||
:3:% The current file in the merged branch during a conflict
|
||||
|
||||
STATUSLINE *fugitive-statusline*
|
||||
|
||||
|
|
|
@ -16,6 +16,18 @@ function! s:shellslash(path) abort
|
|||
endif
|
||||
endfunction
|
||||
|
||||
function! FugitiveGitDir(...) abort
|
||||
if !a:0 || a:1 ==# -1
|
||||
return get(b:, 'git_dir', '')
|
||||
elseif type(a:1) == type(0)
|
||||
return getbufvar(a:1, 'git_dir')
|
||||
elseif type(a:1) == type('')
|
||||
return substitute(s:shellslash(a:1), '/$', '', '')
|
||||
else
|
||||
return ''
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! FugitiveIsGitDir(path) abort
|
||||
let path = substitute(a:path, '[\/]$', '', '') . '/'
|
||||
return getfsize(path.'HEAD') > 10 && (
|
||||
|
@ -25,8 +37,8 @@ endfunction
|
|||
|
||||
let s:worktree_for_dir = {}
|
||||
let s:dir_for_worktree = {}
|
||||
function! FugitiveTreeForGitDir(git_dir) abort
|
||||
let dir = substitute(s:shellslash(a:git_dir), '/$', '', '')
|
||||
function! FugitiveWorkTree(...) abort
|
||||
let dir = substitute(s:shellslash(a:0 ? a:1 : get(b:, 'git_dir', '')), '/$', '', '')
|
||||
if dir =~# '/\.git$'
|
||||
return len(dir) ==# 5 ? '/' : dir[0:-6]
|
||||
endif
|
||||
|
@ -57,6 +69,73 @@ function! FugitiveTreeForGitDir(git_dir) abort
|
|||
endif
|
||||
endfunction
|
||||
|
||||
function! FugitiveReal(...) abort
|
||||
let file = a:0 ? a:1 : @%
|
||||
if file =~? '^fugitive:' || a:0 > 1
|
||||
return call('fugitive#Real', [file] + a:000[1:-1])
|
||||
elseif file =~# '^/\|^\a\+:\|^$'
|
||||
return file
|
||||
else
|
||||
return fnamemodify(file, ':p' . (file =~# '[\/]$' ? '' : ':s?[\/]$??'))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! FugitivePath(...) abort
|
||||
if a:0 > 1
|
||||
return fugitive#Path(a:1, a:2, FugitiveGitDir(a:0 > 2 ? a:3 : -1))
|
||||
else
|
||||
return FugitiveReal(a:0 ? a:1 : @%)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! FugitiveGenerate(...) abort
|
||||
if a:0 && s:shellslash(a:0) =~# '^\%(\a\a\+:\)\=\%(a:\)\=/\|^[~$]'
|
||||
return a:1
|
||||
endif
|
||||
return fugitive#repo(FugitiveGitDir(a:0 > 1 ? a:2 : -1)).translate(a:0 ? a:1 : '', 1)
|
||||
endfunction
|
||||
|
||||
function! FugitiveRoute(...) abort
|
||||
return call('FugitiveGenerate', a:000)
|
||||
endfunction
|
||||
|
||||
function! FugitiveParse(...) abort
|
||||
let path = s:shellslash(a:0 ? a:1 : @%)
|
||||
let vals = matchlist(path, '\c^fugitive:\%(//\)\=\(.\{-\}\)\%(//\|::\)\(\x\{40\}\|[0-3]\)\(/.*\)\=$')
|
||||
if len(vals)
|
||||
return [(vals[2] =~# '^.$' ? ':' : '') . vals[2] . substitute(vals[3], '^/', ':', ''), vals[1]]
|
||||
endif
|
||||
let v:errmsg = 'fugitive: invalid Fugitive URL ' . path
|
||||
throw v:errmsg
|
||||
endfunction
|
||||
|
||||
function! FugitiveConfig(key, ...) abort
|
||||
return fugitive#Config(a:key, FugitiveGitDir(a:0 ? a:1 : -1))
|
||||
endfunction
|
||||
|
||||
function! FugitiveRemoteUrl(...) abort
|
||||
return fugitive#RemoteUrl(a:0 ? a:1 : '', FugitiveGitDir(a:0 > 1 ? a:2 : -1))
|
||||
endfunction
|
||||
|
||||
function! FugitiveHead(...) abort
|
||||
let dir = FugitiveGitDir(a:0 > 1 ? a:2 : -1)
|
||||
if empty(dir)
|
||||
return ''
|
||||
endif
|
||||
return fugitive#repo(dir).head(a:0 ? a:1 : 0)
|
||||
endfunction
|
||||
|
||||
function! FugitiveStatusline(...) abort
|
||||
if !exists('b:git_dir')
|
||||
return ''
|
||||
endif
|
||||
return fugitive#Statusline()
|
||||
endfunction
|
||||
|
||||
function! FugitiveTreeForGitDir(path) abort
|
||||
return FugitiveWorkTree(a:path)
|
||||
endfunction
|
||||
|
||||
function! FugitiveExtractGitDir(path) abort
|
||||
let path = s:shellslash(a:path)
|
||||
if path =~# '^fugitive:'
|
||||
|
@ -66,6 +145,10 @@ function! FugitiveExtractGitDir(path) abort
|
|||
else
|
||||
let path = fnamemodify(path, ':p:h:s?/$??')
|
||||
endif
|
||||
let pre = substitute(matchstr(path, '^\a\a\+\ze:'), '^.', '\u&', '')
|
||||
if len(pre) && exists('*' . pre . 'Real')
|
||||
let path = s:shellslash({pre}Real(path))
|
||||
endif
|
||||
let root = resolve(path)
|
||||
if root !=# path
|
||||
silent! exe haslocaldir() ? 'lcd .' : 'cd .'
|
||||
|
@ -82,7 +165,7 @@ function! FugitiveExtractGitDir(path) abort
|
|||
return simplify(fnamemodify($GIT_DIR, ':p:s?[\/]$??'))
|
||||
endif
|
||||
if FugitiveIsGitDir($GIT_DIR)
|
||||
call FugitiveTreeForGitDir(simplify(fnamemodify($GIT_DIR, ':p:s?[\/]$??')))
|
||||
call FugitiveWorkTree(simplify(fnamemodify($GIT_DIR, ':p:s?[\/]$??')))
|
||||
if has_key(s:dir_for_worktree, root)
|
||||
return s:dir_for_worktree[root]
|
||||
endif
|
||||
|
@ -124,66 +207,50 @@ function! FugitiveDetect(path) abort
|
|||
endif
|
||||
endfunction
|
||||
|
||||
function! FugitiveStatusline(...) abort
|
||||
if !exists('b:git_dir')
|
||||
return ''
|
||||
endif
|
||||
return fugitive#Statusline()
|
||||
endfunction
|
||||
|
||||
function! FugitiveHead(...) abort
|
||||
if !exists('b:git_dir')
|
||||
return ''
|
||||
endif
|
||||
return fugitive#repo().head(a:0 ? a:1 : 0)
|
||||
endfunction
|
||||
|
||||
function! FugitivePath(...) abort
|
||||
let file = fnamemodify(a:0 ? a:1 : @%, ':p')
|
||||
if file =~? '^fugitive:'
|
||||
return fugitive#Path(file)
|
||||
else
|
||||
return file
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! FugitiveReal(...) abort
|
||||
return call('FugitivePath', a:000)
|
||||
endfunction
|
||||
|
||||
augroup fugitive
|
||||
autocmd!
|
||||
|
||||
autocmd BufNewFile,BufReadPost * call FugitiveDetect(expand('%:p'))
|
||||
autocmd FileType netrw call FugitiveDetect(fnamemodify(get(b:, 'netrw_curdir', @%), ':p'))
|
||||
autocmd BufNewFile,BufReadPost * call FugitiveDetect(expand('<amatch>:p'))
|
||||
autocmd FileType netrw call FugitiveDetect(fnamemodify(get(b:, 'netrw_curdir', expand('<amatch>')), ':p'))
|
||||
autocmd User NERDTreeInit,NERDTreeNewRoot
|
||||
\ if exists('b:NERDTree.root.path.str') |
|
||||
\ call FugitiveDetect(b:NERDTree.root.path.str()) |
|
||||
\ endif
|
||||
autocmd VimEnter * if expand('<amatch>')==''|call FugitiveDetect(getcwd())|endif
|
||||
autocmd VimEnter * if empty(expand('<amatch>'))|call FugitiveDetect(getcwd())|endif
|
||||
autocmd CmdWinEnter * call FugitiveDetect(expand('#:p'))
|
||||
|
||||
autocmd FileType git
|
||||
\ if exists('b:git_dir') |
|
||||
\ call fugitive#MapJumps() |
|
||||
\ endif
|
||||
autocmd FileType git,gitcommit,gitrebase
|
||||
\ if exists('b:git_dir') |
|
||||
\ call fugitive#MapJumps() |
|
||||
\ call fugitive#MapCfile() |
|
||||
\ endif
|
||||
autocmd FileType gitcommit
|
||||
\ if exists('b:git_dir') |
|
||||
\ call fugitive#MapCfile('fugitive#StatusCfile()') |
|
||||
\ endif
|
||||
autocmd FileType gitrebase
|
||||
\ let &l:include = '^\%(pick\|squash\|edit\|reword\|fixup\|drop\|[pserfd]\)\>' |
|
||||
\ if exists('b:git_dir') |
|
||||
\ let &l:includeexpr = 'v:fname =~# ''^\x\{4,40\}$'' ? FugitiveGenerate(v:fname) : ' .
|
||||
\ (len(&l:includeexpr) ? &l:includeexpr : 'v:fname') |
|
||||
\ endif |
|
||||
\ let b:undo_ftplugin = get(b:, 'undo_ftplugin', 'exe') . '|setl inex= inc='
|
||||
|
||||
autocmd BufReadCmd index{,.lock}
|
||||
autocmd BufReadCmd index{,.lock}
|
||||
\ if FugitiveIsGitDir(expand('<amatch>:p:h')) |
|
||||
\ let b:git_dir = s:shellslash(expand('<amatch>:p:h')) |
|
||||
\ exe fugitive#BufReadStatus() |
|
||||
\ elseif filereadable(expand('<amatch>')) |
|
||||
\ read <amatch> |
|
||||
\ 1delete |
|
||||
\ 1delete_ |
|
||||
\ endif
|
||||
autocmd FileReadCmd fugitive://**//[0-3]/** exe fugitive#FileRead()
|
||||
autocmd BufReadCmd fugitive://**//[0-3]/** exe fugitive#BufReadIndex()
|
||||
autocmd BufWriteCmd fugitive://**//[0-3]/** exe fugitive#BufWriteIndex()
|
||||
autocmd BufReadCmd fugitive://**//[0-9a-f][0-9a-f]* exe fugitive#BufReadObject()
|
||||
autocmd FileReadCmd fugitive://**//[0-9a-f][0-9a-f]* exe fugitive#FileRead()
|
||||
autocmd BufReadCmd fugitive://*//* exe fugitive#BufReadCmd()
|
||||
autocmd BufWriteCmd fugitive://*//[0-3]/* exe fugitive#BufWriteCmd()
|
||||
autocmd FileReadCmd fugitive://*//* exe fugitive#FileReadCmd()
|
||||
autocmd FileWriteCmd fugitive://*//[0-3]/* exe fugitive#FileWriteCmd()
|
||||
if exists('##SourceCmd')
|
||||
autocmd SourceCmd fugitive://*//* nested exe fugitive#SourceCmd()
|
||||
endif
|
||||
|
||||
autocmd User Flags call Hoist('buffer', function('FugitiveStatusline'))
|
||||
augroup END
|
||||
|
|
|
@ -100,7 +100,7 @@ function! gitgutter#diff#run_diff(bufnr, preserve_full_diff) abort
|
|||
call s:write_buffer(a:bufnr, buff_file)
|
||||
|
||||
" Call git-diff with the temporary files.
|
||||
let cmd .= g:gitgutter_git_executable.' --no-pager'
|
||||
let cmd .= g:gitgutter_git_executable.' --git-dir="" --no-pager'
|
||||
if s:c_flag
|
||||
let cmd .= ' -c "diff.autorefreshindex=0"'
|
||||
let cmd .= ' -c "diff.noprefix=false"'
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[run]
|
||||
plugins = covimerage
|
||||
data_file = .coverage.covimerage
|
||||
data_file = .coverage_covimerage
|
||||
|
|
|
@ -3,6 +3,12 @@
|
|||
IMPROVEMENTS:
|
||||
* Unify async job handling for Vim8 and Neovim.
|
||||
[[GH-1864]](https://github.com/fatih/vim-go/pull/1864)
|
||||
* Document Vim and Neovim requirements in README.md and help file.
|
||||
[[GH-1889]](https://github.com/fatih/vim-go/pull/1889)
|
||||
|
||||
BUG FIXES:
|
||||
* Fix `:GoRun %` on Windows.
|
||||
[[GH-1900]](github.com/fatih/vim-go/pull/1900)
|
||||
|
||||
## 1.18 - (July 18, 2018)
|
||||
|
||||
|
|
|
@ -33,10 +33,13 @@ This plugin adds Go language support for Vim, with the following main features:
|
|||
|
||||
## Install
|
||||
|
||||
vim-go requires at least Vim 7.4.1689 or Neovim 0.2.2.
|
||||
|
||||
The [**latest stable release**](https://github.com/fatih/vim-go/releases/latest) is the
|
||||
recommended version to use. If you choose to use the master branch instead,
|
||||
please do so with caution; it is a _development_ branch.
|
||||
|
||||
|
||||
vim-go follows the standard runtime path structure. Below are some helper lines
|
||||
for popular package managers:
|
||||
|
||||
|
@ -46,6 +49,8 @@ for popular package managers:
|
|||
* `git clone https://github.com/fatih/vim-go.git ~/.vim/bundle/vim-go`
|
||||
* [vim-plug](https://github.com/junegunn/vim-plug)
|
||||
* `Plug 'fatih/vim-go', { 'do': ':GoUpdateBinaries' }`
|
||||
* [Vundle](https://github.com/VundleVim/Vundle.vim)
|
||||
* `Plugin 'fatih/vim-go'`
|
||||
|
||||
You will also need to install all the necessary binaries. vim-go makes it easy
|
||||
to install all of them by providing a command, `:GoInstallBinaries`, which will
|
||||
|
|
|
@ -143,7 +143,12 @@ function! go#cmd#Run(bang, ...) abort
|
|||
endif
|
||||
|
||||
if go#util#IsWin()
|
||||
exec '!' . cmd . go#util#Shelljoin(go#tool#Files())
|
||||
if a:0 == 0
|
||||
exec '!' . cmd . go#util#Shelljoin(go#tool#Files(), 1)
|
||||
else
|
||||
exec '!' . cmd . go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
|
||||
endif
|
||||
|
||||
if v:shell_error
|
||||
redraws! | echon "vim-go: [run] " | echohl ErrorMsg | echon "FAILED"| echohl None
|
||||
else
|
||||
|
|
|
@ -7,15 +7,6 @@ function! go#job#Spawn(cmd, args)
|
|||
return go#job#Start(a:cmd, l:options)
|
||||
endfunction
|
||||
|
||||
" Spawn starts an asynchronous job. See the description of go#job#Options to
|
||||
" understand the args parameter.
|
||||
"
|
||||
" Spawn returns a job.
|
||||
function! go#job#Spawn(cmd, args)
|
||||
let l:options = go#job#Options(a:args)
|
||||
return go#job#Start(a:cmd, l:options)
|
||||
endfunction
|
||||
|
||||
" Options returns callbacks to be used with job_start. It is abstracted to be
|
||||
" used with various go commands, such as build, test, install, etc.. This
|
||||
" allows us to avoid writing the same callback over and over for some
|
||||
|
|
|
@ -76,6 +76,12 @@ tools developed by the Go community to provide a seamless Vim experience.
|
|||
==============================================================================
|
||||
INSTALL *go-install*
|
||||
|
||||
vim-go requires at least Vim 7.4.1689 or Neovim 0.2.2. On macOS, if you are
|
||||
still using your system version of vim, you can use homebrew to keep your
|
||||
version of Vim up-to-date with the following terminal command:
|
||||
>
|
||||
brew install vim
|
||||
|
||||
The latest stable release, https://github.com/fatih/vim-go/releases/latest, is
|
||||
the recommended version to use. If you choose to use the master branch
|
||||
instead, please do so with caution; it is a _development_ branch.
|
||||
|
|
|
@ -26,7 +26,6 @@ before_script: |
|
|||
fi
|
||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
curl https://bootstrap.pypa.io/get-pip.py | sudo python
|
||||
sudo -H easy_install pip
|
||||
fi
|
||||
sudo -H pip install virtualenv
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
Syntax highlighting, matching rules and mappings for [the original Markdown](http://daringfireball.net/projects/markdown/) and extensions.
|
||||
|
||||
1. [Installation](#installation)
|
||||
1. [Basic usage](#basic-usage)
|
||||
1. [Options](#options)
|
||||
1. [Mappings](#mappings)
|
||||
1. [Commands](#commands)
|
||||
|
@ -52,6 +53,37 @@ cd ~/.vim
|
|||
tar --strip=1 -zxf vim-markdown-master.tar.gz
|
||||
```
|
||||
|
||||
## Basic usage
|
||||
|
||||
### Folding
|
||||
|
||||
Folding is enabled for headers by default.
|
||||
|
||||
The following commands are useful to open and close folds:
|
||||
|
||||
- `zr`: reduces fold level throughout the buffer
|
||||
- `zR`: opens all folds
|
||||
- `zm`: increases fold level throughout the buffer
|
||||
- `zM`: folds everything all the way
|
||||
- `za`: open a fold your cursor is on
|
||||
- `zA`: open a fold your cursor is on recursively
|
||||
- `zc`: close a fold your cursor is on
|
||||
- `zC`: close a fold your cursor is on recursively
|
||||
|
||||
[Options](#options) are available to disable folding or change folding style.
|
||||
|
||||
Try `:help fold-expr` and `:help fold-commands` for details.
|
||||
|
||||
### Concealing
|
||||
|
||||
Concealing is set for some syntax such as bold, italic, code block and link.
|
||||
|
||||
Concealing lets you conceal text with other text. The actual source text is not modified. If you put your cursor on the concealed line, the conceal goes away.
|
||||
|
||||
[Options](#options) are available to disable or change concealing.
|
||||
|
||||
Try `:help concealcursor` and `:help conceallevel` for details.
|
||||
|
||||
## Options
|
||||
|
||||
### Disable Folding
|
||||
|
@ -293,6 +325,30 @@ If you would like to use a file extension other than `.md` you may do so using t
|
|||
let g:vim_markdown_auto_extension_ext = 'txt'
|
||||
```
|
||||
|
||||
### Do not automatically insert bulletpoints
|
||||
|
||||
Automatically inserting bulletpoints can lead to problems when wrapping text
|
||||
(see issue #232 for details), so it can be disabled:
|
||||
|
||||
```vim
|
||||
let g:vim_markdown_auto_insert_bullets = 0
|
||||
```
|
||||
|
||||
In that case, you probably also want to set the new list item indent to 0 as
|
||||
well, or you will have to remove an indent each time you add a new list item:
|
||||
|
||||
```vim
|
||||
let g:vim_markdown_new_list_item_indent = 0
|
||||
```
|
||||
|
||||
### Change how to open new files
|
||||
|
||||
By default when following a link the target file will be opened in your current buffer. This behavior can change if you prefer using splits or tabs by using the `vim_markdown_edit_url_in` variable. Possible values are `tab`, `vsplit`, `hsplit`, `current` opening in a new tab, vertical split, horizontal split, and current buffer respectively. Defaults to current buffer if not set:
|
||||
|
||||
```vim
|
||||
let g:vim_markdown_edit_url_in = 'tab'
|
||||
```
|
||||
|
||||
## Mappings
|
||||
|
||||
The following work on normal and visual modes:
|
||||
|
|
|
@ -5,7 +5,10 @@ Contents ~
|
|||
|
||||
1. Introduction |vim-markdown-introduction|
|
||||
2. Installation |vim-markdown-installation|
|
||||
3. Options |vim-markdown-options|
|
||||
3. Basic usage |vim-markdown-basic-usage|
|
||||
1. Folding |vim-markdown-folding|
|
||||
2. Concealing |vim-markdown-concealing|
|
||||
4. Options |vim-markdown-options|
|
||||
1. Disable Folding |vim-markdown-disable-folding|
|
||||
2. Change fold style |vim-markdown-change-fold-style|
|
||||
3. Set header folding level |vim-markdown-set-header-folding-level|
|
||||
|
@ -26,12 +29,16 @@ Contents ~
|
|||
|vim-markdown-do-not-require-.md-extensions-for-markdown-links|
|
||||
13. Auto-write when following link
|
||||
|vim-markdown-auto-write-when-following-link|
|
||||
14. Change default file extension |vim-markdown-auto-extension-ext|
|
||||
4. Mappings |vim-markdown-mappings|
|
||||
5. Commands |vim-markdown-commands|
|
||||
6. Credits |vim-markdown-credits|
|
||||
7. License |vim-markdown-license|
|
||||
8. References |vim-markdown-references|
|
||||
14. Change default file extension
|
||||
|vim-markdown-change-default-file-extension|
|
||||
15. Do not automatically insert bulletpoints
|
||||
|vim-markdown-do-not-automatically-insert-bulletpoints|
|
||||
16. Change how to open new files |vim-markdown-change-how-to-open-new-files|
|
||||
5. Mappings |vim-markdown-mappings|
|
||||
6. Commands |vim-markdown-commands|
|
||||
7. Credits |vim-markdown-credits|
|
||||
8. License |vim-markdown-license|
|
||||
9. References |vim-markdown-references|
|
||||
|
||||
===============================================================================
|
||||
*vim-markdown-introduction*
|
||||
|
@ -73,6 +80,52 @@ If you are not using any package manager, download the tarball [5] and do this:
|
|||
cd ~/.vim
|
||||
tar --strip=1 -zxf vim-markdown-master.tar.gz
|
||||
<
|
||||
===============================================================================
|
||||
*vim-markdown-basic-usage*
|
||||
Basic usage ~
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*vim-markdown-folding*
|
||||
Folding ~
|
||||
|
||||
Folding is enabled for headers by default.
|
||||
|
||||
The following commands are useful to open and close folds:
|
||||
|
||||
*vim-markdown-zr*
|
||||
- 'zr': reduces fold level throughout the buffer
|
||||
*vim-markdown-zR*
|
||||
- 'zR': opens all folds
|
||||
*vim-markdown-zm*
|
||||
- 'zm': increases fold level throughout the buffer
|
||||
*vim-markdown-zM*
|
||||
- 'zM': folds everything all the way
|
||||
*vim-markdown-za*
|
||||
- 'za': open a fold your cursor is on
|
||||
*vim-markdown-zA*
|
||||
- 'zA': open a fold your cursor is on recursively
|
||||
*vim-markdown-zc*
|
||||
- 'zc': close a fold your cursor is on
|
||||
*vim-markdown-zC*
|
||||
- 'zC': close a fold your cursor is on recursively
|
||||
|
||||
Options are available to disable folding or change folding style.
|
||||
|
||||
Try ':help fold-expr' and ':help fold-commands' for details.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*vim-markdown-concealing*
|
||||
Concealing ~
|
||||
|
||||
Concealing is set for some syntax such as bold, italic, code block and link.
|
||||
|
||||
Concealing lets you conceal text with other text. The actual source text is not
|
||||
modified. If you put your cursor on the concealed line, the conceal goes away.
|
||||
|
||||
Options are available to disable or change concealing.
|
||||
|
||||
Try ':help concealcursor' and ':help conceallevel' for details.
|
||||
|
||||
===============================================================================
|
||||
*vim-markdown-options*
|
||||
Options ~
|
||||
|
@ -144,7 +197,7 @@ never increases its default size (half screen), it only shrinks.
|
|||
Text emphasis restriction to single-lines ~
|
||||
|
||||
By default text emphasis works across multiple lines until a closing token is
|
||||
found. However, it's possible to restrict text emphasis to a single line (ie,
|
||||
found. However, it's possible to restrict text emphasis to a single line (i.e.,
|
||||
for it to be applied a closing token must be found on the same line). To do so:
|
||||
>
|
||||
let g:vim_markdown_emphasis_multiline = 0
|
||||
|
@ -197,9 +250,9 @@ Default is "['c++=cpp', 'viml=vim', 'bash=sh', 'ini=dosini']".
|
|||
*vim-markdown-follow-named-anchors*
|
||||
Follow named anchors ~
|
||||
|
||||
This feature allows ge to follow named anchors in links of the form
|
||||
'file#anchor' or just '#anchor', where file may omit the '.md' extension as
|
||||
usual. Two variables control its operation:
|
||||
This feature allows the 'ge' command to follow named anchors in links of the
|
||||
form 'file#anchor' or just '#anchor', where file may omit the '.md' extension
|
||||
as usual. Two variables control its operation:
|
||||
>
|
||||
let g:vim_markdown_follow_anchor = 1
|
||||
<
|
||||
|
@ -311,7 +364,7 @@ this option will automatically save any edits you made before moving you:
|
|||
let g:vim_markdown_autowrite = 1
|
||||
<
|
||||
-------------------------------------------------------------------------------
|
||||
*vim-markdown-auto-extension-ext*
|
||||
*vim-markdown-change-default-file-extension*
|
||||
Change default file extension ~
|
||||
|
||||
If you would like to use a file extension other than '.md' you may do so using
|
||||
|
@ -319,6 +372,32 @@ the 'vim_markdown_auto_extension_ext' variable:
|
|||
>
|
||||
let g:vim_markdown_auto_extension_ext = 'txt'
|
||||
<
|
||||
-------------------------------------------------------------------------------
|
||||
*vim-markdown-do-not-automatically-insert-bulletpoints*
|
||||
Do not automatically insert bulletpoints ~
|
||||
|
||||
Automatically inserting bulletpoints can lead to problems when wrapping text
|
||||
(see issue #232 for details), so it can be disabled:
|
||||
>
|
||||
let g:vim_markdown_auto_insert_bullets = 0
|
||||
<
|
||||
In that case, you probably also want to set the new list item indent to 0 as
|
||||
well, or you will have to remove an indent each time you add a new list item:
|
||||
>
|
||||
let g:vim_markdown_new_list_item_indent = 0
|
||||
<
|
||||
-------------------------------------------------------------------------------
|
||||
*vim-markdown-change-how-to-open-new-files*
|
||||
Change how to open new files ~
|
||||
|
||||
By default when following a link the target file will be opened in your current
|
||||
buffer. This behavior can change if you prefer using splits or tabs by using
|
||||
the 'vim_markdown_edit_url_in' variable. Possible values are 'tab', 'vsplit',
|
||||
'hsplit', 'current' opening in a new tab, vertical split, horizontal split, and
|
||||
current buffer respectively. Defaults to current buffer if not set:
|
||||
>
|
||||
let g:vim_markdown_edit_url_in = 'tab'
|
||||
<
|
||||
===============================================================================
|
||||
*vim-markdown-mappings*
|
||||
Mappings ~
|
||||
|
|
|
@ -609,7 +609,23 @@ if !exists('*s:EditUrlUnderCursor')
|
|||
endif
|
||||
endif
|
||||
let l:url = fnameescape(fnamemodify(expand('%:h').'/'.l:url.l:ext, ':.'))
|
||||
execute 'edit' l:url
|
||||
let l:editmethod = ''
|
||||
" determine how to open the linked file (split, tab, etc)
|
||||
if exists('g:vim_markdown_edit_url_in')
|
||||
if g:vim_markdown_edit_url_in == 'tab'
|
||||
let l:editmethod = 'tabnew'
|
||||
elseif g:vim_markdown_edit_url_in == 'vsplit'
|
||||
let l:editmethod = 'vsp'
|
||||
elseif g:vim_markdown_edit_url_in == 'hsplit'
|
||||
let l:editmethod = 'sp'
|
||||
else
|
||||
let l:editmethod = 'edit'
|
||||
endif
|
||||
else
|
||||
" default to current buffer
|
||||
let l:editmethod = 'edit'
|
||||
endif
|
||||
execute l:editmethod l:url
|
||||
endif
|
||||
if l:anchor != ''
|
||||
silent! execute '/'.l:anchor
|
||||
|
|
|
@ -5,15 +5,15 @@ setlocal indentexpr=GetMarkdownIndent()
|
|||
setlocal nolisp
|
||||
setlocal autoindent
|
||||
|
||||
" Automatically insert bullets
|
||||
setlocal formatoptions+=r
|
||||
" Do not automatically insert bullets when auto-wrapping with text-width
|
||||
setlocal formatoptions-=c
|
||||
" Accept various markers as bullets
|
||||
setlocal comments=b:*,b:+,b:-
|
||||
|
||||
" Automatically continue blockquote on line break
|
||||
setlocal comments+=b:>
|
||||
setlocal formatoptions+=r
|
||||
setlocal comments=b:>
|
||||
if get(g:, "vim_markdown_auto_insert_bullets", 1)
|
||||
" Do not automatically insert bullets when auto-wrapping with text-width
|
||||
setlocal formatoptions-=c
|
||||
" Accept various markers as bullets
|
||||
setlocal comments+=b:*,b:+,b:-
|
||||
endif
|
||||
|
||||
" Only define the function once
|
||||
if exists("*GetMarkdownIndent") | finish | endif
|
||||
|
|
|
@ -82,25 +82,25 @@ syn region mkdLinkTitle matchgroup=mkdDelimiter start=+'+ end=+'+ contained
|
|||
syn region mkdLinkTitle matchgroup=mkdDelimiter start=+(+ end=+)+ contained
|
||||
|
||||
"HTML headings
|
||||
syn region htmlH1 start="^\s*#" end="$" contains=mkdLink,mkdInlineURL,@Spell
|
||||
syn region htmlH2 start="^\s*##" end="$" contains=mkdLink,mkdInlineURL,@Spell
|
||||
syn region htmlH3 start="^\s*###" end="$" contains=mkdLink,mkdInlineURL,@Spell
|
||||
syn region htmlH4 start="^\s*####" end="$" contains=mkdLink,mkdInlineURL,@Spell
|
||||
syn region htmlH5 start="^\s*#####" end="$" contains=mkdLink,mkdInlineURL,@Spell
|
||||
syn region htmlH6 start="^\s*######" end="$" contains=mkdLink,mkdInlineURL,@Spell
|
||||
syn region htmlH1 matchgroup=mkdHeading start="^\s*#" end="$" contains=mkdLink,mkdInlineURL,@Spell
|
||||
syn region htmlH2 matchgroup=mkdHeading start="^\s*##" end="$" contains=mkdLink,mkdInlineURL,@Spell
|
||||
syn region htmlH3 matchgroup=mkdHeading start="^\s*###" end="$" contains=mkdLink,mkdInlineURL,@Spell
|
||||
syn region htmlH4 matchgroup=mkdHeading start="^\s*####" end="$" contains=mkdLink,mkdInlineURL,@Spell
|
||||
syn region htmlH5 matchgroup=mkdHeading start="^\s*#####" end="$" contains=mkdLink,mkdInlineURL,@Spell
|
||||
syn region htmlH6 matchgroup=mkdHeading start="^\s*######" end="$" contains=mkdLink,mkdInlineURL,@Spell
|
||||
syn match htmlH1 /^.\+\n=\+$/ contains=mkdLink,mkdInlineURL,@Spell
|
||||
syn match htmlH2 /^.\+\n-\+$/ contains=mkdLink,mkdInlineURL,@Spell
|
||||
|
||||
"define Markdown groups
|
||||
syn match mkdLineBreak / \+$/
|
||||
syn region mkdBlockquote start=/^\s*>/ end=/$/ contains=mkdLink,mkdInlineURL,mkdLineBreak,@Spell
|
||||
syn region mkdCode start=/\(\([^\\]\|^\)\\\)\@<!`/ end=/\(\([^\\]\|^\)\\\)\@<!`/
|
||||
syn region mkdCode start=/\s*``[^`]*/ end=/[^`]*``\s*/
|
||||
syn region mkdCode start=/^\s*\z(`\{3,}\)[^`]*$/ end=/^\s*\z1`*\s*$/
|
||||
syn region mkdCode start=/\s*\~\~[^\~]*/ end=/[^\~]*\~\~\s*/
|
||||
syn region mkdCode start=/^\s*\z(\~\{3,}\)\s*[0-9A-Za-z_+-]*\s*$/ end=/^\s*\z1\~*\s*$/
|
||||
syn region mkdCode start="<pre[^>]*\\\@<!>" end="</pre>"
|
||||
syn region mkdCode start="<code[^>]*\\\@<!>" end="</code>"
|
||||
execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/\(\([^\\]\|^\)\\\)\@<!`/ end=/\(\([^\\]\|^\)\\\)\@<!`/' . s:concealends
|
||||
execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/\(\([^\\]\|^\)\\\)\@<!``/ skip=/[^`]`[^`]/ end=/\(\([^\\]\|^\)\\\)\@<!``/' . s:concealends
|
||||
execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/^\s*\z(`\{3,}\)[^`]*$/ end=/^\s*\z1`*\s*$/' . s:concealends
|
||||
execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/\(\([^\\]\|^\)\\\)\@<!\~\~/ end=/\(\([^\\]\|^\)\\\)\@<!\~\~/' . s:concealends
|
||||
execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/^\s*\z(\~\{3,}\)\s*[0-9A-Za-z_+-]*\s*$/ end=/^\s*\z1\~*\s*$/' . s:concealends
|
||||
execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start="<pre[^>]*\\\@<!>" end="</pre>"' . s:concealends
|
||||
execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start="<code[^>]*\\\@<!>" end="</code>"' . s:concealends
|
||||
syn region mkdFootnote start="\[^" end="\]"
|
||||
syn match mkdCode /^\s*\n\(\(\s\{8,}[^ ]\|\t\t\+[^\t]\).*\n\)\+/
|
||||
syn match mkdCode /\%^\(\(\s\{4,}[^ ]\|\t\+[^\t]\).*\n\)\+/
|
||||
|
@ -115,7 +115,7 @@ syn match mkdRule /^\s*_\s\{0,1}_\s\{0,1}_\(_\|\s\)*$/
|
|||
" YAML frontmatter
|
||||
if get(g:, 'vim_markdown_frontmatter', 0)
|
||||
syn include @yamlTop syntax/yaml.vim
|
||||
syn region Comment matchgroup=mkdDelimiter start="\%^---$" end="^---$" contains=@yamlTop keepend
|
||||
syn region Comment matchgroup=mkdDelimiter start="\%^---$" end="^\(---\|...\)$" contains=@yamlTop keepend
|
||||
unlet! b:current_syntax
|
||||
endif
|
||||
|
||||
|
@ -150,6 +150,7 @@ syn cluster mkdNonListItem contains=@htmlTop,htmlItalic,htmlBold,htmlBoldItalic,
|
|||
"highlighting for Markdown groups
|
||||
HtmlHiLink mkdString String
|
||||
HtmlHiLink mkdCode String
|
||||
HtmlHiLink mkdCodeDelimiter String
|
||||
HtmlHiLink mkdCodeStart String
|
||||
HtmlHiLink mkdCodeEnd String
|
||||
HtmlHiLink mkdFootnote Comment
|
||||
|
|
|
@ -1139,19 +1139,19 @@ Given markdown;
|
|||
###### h6
|
||||
|
||||
Execute (atx headers):
|
||||
AssertEqual SyntaxOf('# h1 space'), 'htmlH1'
|
||||
AssertEqual SyntaxOf('#h1 nospace'), 'htmlH1'
|
||||
AssertEqual SyntaxOf('# h1 2 spaces'), 'htmlH1'
|
||||
AssertEqual SyntaxOf('# h1 trailing hash #'), 'htmlH1'
|
||||
AssertEqual SyntaxOf('## h2 space'), 'htmlH2'
|
||||
AssertEqual SyntaxOf('##h2 nospace'), 'htmlH2'
|
||||
AssertEqual SyntaxOf('## h2 trailing hash ##'), 'htmlH2'
|
||||
AssertEqual SyntaxOf('### h3 space'), 'htmlH3'
|
||||
AssertEqual SyntaxOf('###h3 nospace'), 'htmlH3'
|
||||
AssertEqual SyntaxOf('### h3 trailing hash ###'), 'htmlH3'
|
||||
AssertEqual SyntaxOf('#### h4'), 'htmlH4'
|
||||
AssertEqual SyntaxOf('##### h5'), 'htmlH5'
|
||||
AssertEqual SyntaxOf('###### h6'), 'htmlH6'
|
||||
AssertEqual SyntaxOf(' h1 space'), 'htmlH1'
|
||||
AssertEqual SyntaxOf('h1 nospace'), 'htmlH1'
|
||||
AssertEqual SyntaxOf(' h1 2 spaces'), 'htmlH1'
|
||||
AssertEqual SyntaxOf(' h1 trailing hash '), 'htmlH1'
|
||||
AssertEqual SyntaxOf(' h2 space'), 'htmlH2'
|
||||
AssertEqual SyntaxOf('h2 nospace'), 'htmlH2'
|
||||
AssertEqual SyntaxOf(' h2 trailing hash '), 'htmlH2'
|
||||
AssertEqual SyntaxOf(' h3 space'), 'htmlH3'
|
||||
AssertEqual SyntaxOf('h3 nospace'), 'htmlH3'
|
||||
AssertEqual SyntaxOf(' h3 trailing hash '), 'htmlH3'
|
||||
AssertEqual SyntaxOf(' h4'), 'htmlH4'
|
||||
AssertEqual SyntaxOf(' h5'), 'htmlH5'
|
||||
AssertEqual SyntaxOf(' h6'), 'htmlH6'
|
||||
|
||||
Given markdown;
|
||||
# h1 before h2
|
||||
|
@ -1161,9 +1161,9 @@ Given markdown;
|
|||
# h1 after h2
|
||||
|
||||
Execute (atx headers relative positions):
|
||||
AssertEqual SyntaxOf('# h1 before h2'), 'htmlH1'
|
||||
AssertEqual SyntaxOf('## h2 between h1s'), 'htmlH2'
|
||||
AssertEqual SyntaxOf('# h1 after h2'), 'htmlH1'
|
||||
AssertEqual SyntaxOf(' h1 before h2'), 'htmlH1'
|
||||
AssertEqual SyntaxOf(' h2 between h1s'), 'htmlH2'
|
||||
AssertEqual SyntaxOf(' h1 after h2'), 'htmlH1'
|
||||
|
||||
Given markdown;
|
||||
setex h1
|
||||
|
@ -1214,9 +1214,9 @@ setex h2
|
|||
Execute (mixed atx and setex headers):
|
||||
AssertEqual SyntaxOf('setex h1 before atx'), 'htmlH1'
|
||||
AssertEqual SyntaxOf('==================='), 'htmlH1'
|
||||
AssertEqual SyntaxOf('## atx h2'), 'htmlH2'
|
||||
AssertEqual SyntaxOf('### atx h3'), 'htmlH3'
|
||||
AssertEqual SyntaxOf('# atx h1'), 'htmlH1'
|
||||
AssertEqual SyntaxOf(' atx h2'), 'htmlH2'
|
||||
AssertEqual SyntaxOf(' atx h3'), 'htmlH3'
|
||||
AssertEqual SyntaxOf(' atx h1'), 'htmlH1'
|
||||
AssertEqual SyntaxOf('setex h2'), 'htmlH2'
|
||||
AssertEqual SyntaxOf('------------------'), 'htmlH2'
|
||||
|
||||
|
|
|
@ -263,11 +263,16 @@ function! s:wrap(string,char,type,removed,special)
|
|||
elseif keeper =~ '\n$' && after =~ '^\n'
|
||||
let after = strpart(after,1)
|
||||
endif
|
||||
if before !~ '\n\s*$'
|
||||
if keeper !~ '^\n' && before !~ '\n\s*$'
|
||||
let before .= "\n"
|
||||
if a:special
|
||||
let before .= "\t"
|
||||
endif
|
||||
elseif keeper =~ '^\n' && before =~ '\n\s*$'
|
||||
let keeper = strcharpart(keeper,1)
|
||||
endif
|
||||
if type ==# 'V' && keeper =~ '\n\s*\n$'
|
||||
let keeper = strcharpart(keeper,0,strchars(keeper) - 1)
|
||||
endif
|
||||
endif
|
||||
if type ==# 'V'
|
||||
|
|
Loading…
Reference in a new issue