update all plugins

This commit is contained in:
phucleeuwu 2025-06-22 15:49:55 +07:00
parent 46294d589d
commit 84ae28807a
334 changed files with 12415 additions and 305431 deletions

View File

@ -0,0 +1,43 @@
" Description: named-checkzone for bindzone
call ale#Set('bindzone_checkzone_executable', 'named-checkzone')
call ale#Set('bindzone_checkzone_options', '-c IN')
function! ale_linters#bindzone#checkzone#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'bindzone_checkzone_options'))
\ . ' example.com %t'
endfunction
function! ale_linters#bindzone#checkzone#Handle(buffer, lines) abort
let l:warning_pattern = '\vzone example.com/IN: (.+)$'
let l:error_pattern = '\v:(\d+): (.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:error_pattern)
let l:lnum = l:match[1]
let l:text = l:match[2]
call add(l:output, {'text': l:text, 'lnum': l:lnum + 0, 'type': 'E'})
endfor
for l:match in ale#util#GetMatches(a:lines, l:warning_pattern)
let l:text = l:match[1]
" Ignore information messages
let l:scrub_match = matchlist(l:text, '\v(loaded serial|not loaded due to) ')
if empty(l:scrub_match)
call add(l:output, {'text': l:text, 'lnum': 0, 'type': 'W'})
endif
endfor
return l:output
endfunction
call ale#linter#Define('bindzone', {
\ 'name': 'checkzone',
\ 'executable': {b -> ale#Var(b, 'bindzone_checkzone_executable')},
\ 'command': function('ale_linters#bindzone#checkzone#GetCommand'),
\ 'callback': 'ale_linters#bindzone#checkzone#Handle',
\ 'read_buffer': 0,
\})

View File

@ -0,0 +1,22 @@
" Author: Koni Marti <koni.marti@gmail.com>
" Description: A Language Server implementation for C3
call ale#Set('c3_c3lsp_executable', 'c3lsp')
call ale#Set('c3_c3lsp_options', '')
call ale#Set('c3_c3lsp_init_options', {})
function! ale_linters#c3#c3lsp#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'c3_c3lsp_executable')
return ale#Escape(l:executable) . ale#Pad(ale#Var(a:buffer, 'c3_c3lsp_options'))
endfunction
call ale#linter#Define('c3', {
\ 'name': 'c3lsp',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'c3_c3lsp_executable')},
\ 'command': function('ale_linters#c3#c3lsp#GetCommand'),
\ 'project_root': function('ale#handlers#c3lsp#GetProjectRoot'),
\ 'lsp_config': {b -> ale#handlers#c3lsp#GetInitOpts(b, 'c3_c3lsp_init_options')},
\})

View File

@ -49,7 +49,6 @@ function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
if l:match[5] isnot# ''
let l:code = l:match[4] . l:match[5]
let l:link = ' ( ' . l:domain . l:code . ' )'
let l:text = l:code . ': ' . l:detail
let l:detail = l:code . l:link . "\n\n" . l:detail
else
let l:type = 'E'

View File

@ -53,4 +53,5 @@ call ale#linter#Define('erlang', {
\ 'command': function('s:GetCommand'),
\ 'lsp': 'stdio',
\ 'project_root': function('s:FindProjectRoot'),
\ 'aliases': ['erlang-ls'],
\})

View File

@ -5,11 +5,27 @@ call ale#Set('go_golangci_lint_options', '')
call ale#Set('go_golangci_lint_executable', 'golangci-lint')
call ale#Set('go_golangci_lint_package', 1)
function! ale_linters#go#golangci_lint#GetCommand(buffer) abort
function! ale_linters#go#golangci_lint#GetExecutable(buffer) abort
let l:executable = ale#Var(a:buffer, 'go_golangci_lint_executable')
return l:executable
endfunction
function! ale_linters#go#golangci_lint#GetCommand(buffer, version) abort
let l:filename = expand('#' . a:buffer . ':t')
let l:options = ale#Var(a:buffer, 'go_golangci_lint_options')
let l:lint_package = ale#Var(a:buffer, 'go_golangci_lint_package')
if ale#semver#GTE(a:version, [2, 0, 0])
let l:options = l:options
\ . ' --output.json.path stdout'
\ . ' --output.text.path stderr'
\ . ' --show-stats=0'
else
let l:options = l:options
\ . ' --out-format=json'
\ . ' --show-stats=0'
endif
if l:lint_package
return ale#go#EnvString(a:buffer)
@ -23,31 +39,29 @@ function! ale_linters#go#golangci_lint#GetCommand(buffer) abort
\ . ' ' . l:options
endfunction
function! ale_linters#go#golangci_lint#GetMatches(lines) abort
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:?:?:?\s\*?(.+)\s+\((.+)\)$'
return ale#util#GetMatches(a:lines, l:pattern)
endfunction
function! ale_linters#go#golangci_lint#Handler(buffer, lines) abort
let l:dir = expand('#' . a:buffer . ':p:h')
let l:output = []
for l:match in ale_linters#go#golangci_lint#GetMatches(a:lines)
if l:match[5] is# 'typecheck'
let l:matches = ale#util#FuzzyJSONDecode(a:lines, [])
if empty(l:matches)
return []
endif
for l:match in l:matches['Issues']
if l:match['FromLinter'] is# 'typecheck'
let l:msg_type = 'E'
else
let l:msg_type = 'W'
endif
" l:match[1] will already be an absolute path, output from
" golangci_lint
call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]),
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'filename': ale#path#GetAbsPath(l:dir, fnamemodify(l:match['Pos']['Filename'], ':t')),
\ 'lnum': l:match['Pos']['Line'] + 0,
\ 'col': l:match['Pos']['Column'] + 0,
\ 'type': l:msg_type,
\ 'text': l:match[4] . ' (' . l:match[5] . ')',
\ 'text': match['FromLinter'] . ' - ' . l:match['Text'],
\})
endfor
@ -56,9 +70,14 @@ endfunction
call ale#linter#Define('go', {
\ 'name': 'golangci-lint',
\ 'executable': {b -> ale#Var(b, 'go_golangci_lint_executable')},
\ 'executable': function('ale_linters#go#golangci_lint#GetExecutable'),
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#go#golangci_lint#GetCommand'),
\ 'command': {buffer -> ale#semver#RunWithVersionCheck(
\ buffer,
\ ale_linters#go#golangci_lint#GetExecutable(buffer),
\ '%e --version',
\ function('ale_linters#go#golangci_lint#GetCommand'),
\ )},
\ 'callback': 'ale_linters#go#golangci_lint#Handler',
\ 'lint_file': 1,
\})

View File

@ -0,0 +1,12 @@
" Author: Adrian Vollmer <computerfluesterer@protonmail.com>
" Description: djlint for Django HTML template files
call ale#Set('html_djlint_executable', 'djlint')
call ale#Set('html_djlint_options', '')
call ale#linter#Define('gohtmltmpl', {
\ 'name': 'djlint',
\ 'executable': function('ale#handlers#djlint#GetExecutable'),
\ 'command': function('ale#handlers#djlint#GetCommand'),
\ 'callback': 'ale#handlers#djlint#Handle',
\})

View File

@ -0,0 +1,12 @@
" Author: Adrian Vollmer <computerfluesterer@protonmail.com>
" Description: djlint for Django HTML template files
call ale#Set('html_djlint_executable', 'djlint')
call ale#Set('html_djlint_options', '')
call ale#linter#Define('handlebars', {
\ 'name': 'djlint',
\ 'executable': function('ale#handlers#djlint#GetExecutable'),
\ 'command': function('ale#handlers#djlint#GetCommand'),
\ 'callback': 'ale#handlers#djlint#Handle',
\})

View File

@ -0,0 +1,14 @@
" Author: Vivian De Smedt <vds2212@gmail.com>
" Description: Adds support for djlint
call ale#Set('html_djlint_executable', 'djlint')
call ale#Set('html_djlint_options', '')
call ale#linter#Define('html', {
\ 'name': 'djlint',
\ 'executable': function('ale#handlers#djlint#GetExecutable'),
\ 'command': function('ale#handlers#djlint#GetCommand'),
\ 'callback': 'ale#handlers#djlint#Handle',
\})
" vim:ts=4:sw=4:et:

View File

@ -0,0 +1,12 @@
" Author: Adrian Vollmer <computerfluesterer@protonmail.com>
" Description: djlint for Django HTML template files
call ale#Set('html_djlint_executable', 'djlint')
call ale#Set('html_djlint_options', '')
call ale#linter#Define('htmlangular', {
\ 'name': 'djlint',
\ 'executable': function('ale#handlers#djlint#GetExecutable'),
\ 'command': function('ale#handlers#djlint#GetCommand'),
\ 'callback': 'ale#handlers#djlint#Handle',
\})

View File

@ -0,0 +1,12 @@
" Author: Adrian Vollmer <computerfluesterer@protonmail.com>
" Description: djlint for Django HTML template files
call ale#Set('html_djlint_executable', 'djlint')
call ale#Set('html_djlint_options', '')
call ale#linter#Define('htmldjango', {
\ 'name': 'djlint',
\ 'executable': function('ale#handlers#djlint#GetExecutable'),
\ 'command': function('ale#handlers#djlint#GetCommand'),
\ 'callback': 'ale#handlers#djlint#Handle',
\})

View File

@ -0,0 +1,12 @@
" Author: Adrian Vollmer <computerfluesterer@protonmail.com>
" Description: djlint for Django HTML template files
call ale#Set('html_djlint_executable', 'djlint')
call ale#Set('html_djlint_options', '')
call ale#linter#Define('jinja', {
\ 'name': 'djlint',
\ 'executable': function('ale#handlers#djlint#GetExecutable'),
\ 'command': function('ale#handlers#djlint#GetCommand'),
\ 'callback': 'ale#handlers#djlint#Handle',
\})

View File

@ -5,7 +5,7 @@ call ale#Set('json_jq_filters', '.')
" Matches patterns like the following:
" parse error: Expected another key-value pair at line 4, column 3
let s:pattern = '^parse error: \(.\+\) at line \(\d\+\), column \(\d\+\)$'
let s:pattern = 'parse error: \(.\+\) at line \(\d\+\), column \(\d\+\)$'
function! ale_linters#json#jq#Handle(buffer, lines) abort
return ale#util#MapMatches(a:lines, s:pattern, {match -> {

View File

@ -0,0 +1,28 @@
" Author: Benjamin Block <https://github.com/benjamindblock>
" Description: A language server for Lean 4.
function! ale_linters#lean#lake#GetProjectRoot(buffer) abort
let l:lakefile_toml = ale#path#FindNearestFile(a:buffer, 'lakefile.toml')
let l:lakefile_lean = ale#path#FindNearestFile(a:buffer, 'lakefile.lean')
if !empty(l:lakefile_toml)
return fnamemodify(l:lakefile_toml, ':p:h')
elseif !empty(l:lakefile_lean)
return fnamemodify(l:lakefile_lean, ':p:h')
else
return fnamemodify('', ':h')
endif
endfunction
call ale#Set('lean_lake_executable', 'lake')
call ale#Set('lean_lake_config', {})
call ale#linter#Define('lean', {
\ 'name': 'lake',
\ 'lsp': 'stdio',
\ 'language': 'lean',
\ 'lsp_config': {b -> ale#Var(b, 'lean_lake_config')},
\ 'executable': {b -> ale#Var(b, 'lean_lake_executable')},
\ 'command': '%e serve',
\ 'project_root': function('ale_linters#lean#lake#GetProjectRoot'),
\})

View File

@ -0,0 +1,73 @@
call ale#Set('markdown_pymarkdown_executable', 'pymarkdown')
call ale#Set('markdown_pymarkdown_options', '')
call ale#Set('markdown_pymarkdown_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('markdown_pymarkdown_auto_pipenv', 0)
call ale#Set('markdown_pymarkdown_auto_poetry', 0)
call ale#Set('markdown_pymarkdown_auto_uv', 0)
function! ale_linters#markdown#pymarkdown#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'markdown_pymarkdown_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'markdown_pymarkdown_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
if (ale#Var(a:buffer, 'python_auto_uv') || ale#Var(a:buffer, 'markdown_pymarkdown_auto_uv'))
\ && ale#python#UvPresent(a:buffer)
return 'uv'
endif
return ale#python#FindExecutable(a:buffer, 'markdown_pymarkdown', ['pymarkdown'])
endfunction
function! ale_linters#markdown#pymarkdown#GetCommand(buffer) abort
let l:executable = ale_linters#markdown#pymarkdown#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
\ ? ' run pymarkdown'
\ : ''
return ale#Escape(l:executable) . l:exec_args
\ . ' '
\ . ale#Var(a:buffer, 'markdown_pymarkdown_options')
\ . 'scan-stdin'
endfunction
function! ale_linters#markdown#pymarkdown#Handle(buffer, lines) abort
let l:pattern = '\v^(\S*):(\d+):(\d+): ([A-Z]+\d+): (.*)$'
let l:output = []
" lines are formatted as follows:
" sample.md:1:1: MD022: Headings should be surrounded by blank lines. [Expected: 1; Actual: 0; Below] (blanks-around-headings,blanks-around-headers)
for l:match in ale#util#GetMatches(a:lines, l:pattern)
if(l:match[4] is# 'MD009')
\&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
let l:item = {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'type': l:match[4][0],
\ 'text': l:match[5],
\ 'code': l:match[4],
\}
call add(l:output, l:item)
endfor
return l:output
endfunction
call ale#linter#Define('markdown', {
\ 'name': 'pymarkdown',
\ 'executable': function('ale_linters#markdown#pymarkdown#GetExecutable'),
\ 'command': function('ale_linters#markdown#pymarkdown#GetCommand'),
\ 'callback': 'ale_linters#markdown#pymarkdown#Handle',
\})

View File

@ -29,7 +29,7 @@ function! ale_linters#nix#nix#Handle(buffer, lines) abort
\ 'type': 'E',
\ 'lnum': l:result.line,
\ 'col': l:result.column,
\ 'text': l:result.raw_msg
\ 'text': substitute(l:result.raw_msg, '\e\[[0-9;]*m', '', 'g'),
\})
endif
endif

View File

@ -0,0 +1,12 @@
" Author: Adrian Vollmer <computerfluesterer@protonmail.com>
" Description: djlint for Django HTML template files
call ale#Set('html_djlint_executable', 'djlint')
call ale#Set('html_djlint_options', '')
call ale#linter#Define('nunjucks', {
\ 'name': 'djlint',
\ 'executable': function('ale#handlers#djlint#GetExecutable'),
\ 'command': function('ale#handlers#djlint#GetCommand'),
\ 'callback': 'ale#handlers#djlint#Handle',
\})

View File

@ -22,7 +22,7 @@ function! ale_linters#php#phpstan#GetCommand(buffer, version) abort
let l:memory_limit = ale#Var(a:buffer, 'php_phpstan_memory_limit')
let l:memory_limit_option = !empty(l:memory_limit)
\ ? ' --memory-limit ' . ale#Escape(l:memory_limit)
\ ? ' --memory-limit=' . ale#Escape(l:memory_limit)
\ : ''
let l:level = ale#Var(a:buffer, 'php_phpstan_level')

View File

@ -45,7 +45,7 @@ function! ale_linters#python#bandit#GetCommand(buffer) abort
endif
endif
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run bandit'
\ : ''

View File

@ -63,7 +63,7 @@ function! ale_linters#python#flake8#GetCwd(buffer) abort
endif
if (l:change_directory is# 'project' && empty(l:cwd))
\|| l:change_directory is# 1
\|| l:change_directory
\|| l:change_directory is# 'file'
let l:cwd = '%s:h'
endif
@ -74,7 +74,7 @@ endfunction
function! ale_linters#python#flake8#GetCommand(buffer, version) abort
let l:executable = ale_linters#python#flake8#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run flake8'
\ : ''

View File

@ -63,7 +63,7 @@ function! ale_linters#python#flakehell#GetCwd(buffer) abort
endif
if (l:change_directory is# 'project' && empty(l:cwd))
\|| l:change_directory is# 1
\|| l:change_directory
\|| l:change_directory is# 'file'
let l:cwd = '%s:h'
endif
@ -74,7 +74,7 @@ endfunction
function! ale_linters#python#flakehell#GetCommand(buffer, version) abort
let l:executable = ale_linters#python#flakehell#GetExecutable(a:buffer)
if (l:executable =~? 'pipenv\|poetry\|uv$')
if (l:executable =~? '\(pipenv\|poetry\|uv\)$')
let l:exec_args = ' run flakehell'
elseif (l:executable is? 'python')
let l:exec_args = ' -m flakehell'

View File

@ -28,7 +28,7 @@ endfunction
function! ale_linters#python#jedils#GetCommand(buffer) abort
let l:executable = ale_linters#python#jedils#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run jedi-language-server'
\ : ''
let l:env_string = ''

View File

@ -49,7 +49,7 @@ endfunction
function! ale_linters#python#mypy#GetCommand(buffer) abort
let l:executable = ale_linters#python#mypy#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run mypy'
\ : ''

View File

@ -35,7 +35,7 @@ endfunction
function! ale_linters#python#prospector#GetCommand(buffer) abort
let l:executable = ale_linters#python#prospector#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run prospector'
\ : ''

View File

@ -42,7 +42,7 @@ endfunction
function! ale_linters#python#pycln#GetCommand(buffer, version) abort
let l:executable = ale_linters#python#pycln#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run pycln'
\ : ''

View File

@ -30,7 +30,7 @@ endfunction
function! ale_linters#python#pycodestyle#GetCommand(buffer) abort
let l:executable = ale_linters#python#pycodestyle#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run pycodestyle'
\ : ''

View File

@ -29,7 +29,7 @@ endfunction
function! ale_linters#python#pydocstyle#GetCommand(buffer) abort
let l:executable = ale_linters#python#pydocstyle#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run pydocstyle'
\ : ''

View File

@ -29,7 +29,7 @@ endfunction
function! ale_linters#python#pyflakes#GetCommand(buffer) abort
let l:executable = ale_linters#python#pyflakes#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run pyflakes'
\ : ''

View File

@ -30,7 +30,7 @@ endfunction
function! ale_linters#python#pylama#RunWithVersionCheck(buffer) abort
let l:executable = ale_linters#python#pylama#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run pylama'
\ : ''
@ -59,7 +59,7 @@ endfunction
function! ale_linters#python#pylama#GetCommand(buffer, version) abort
let l:executable = ale_linters#python#pylama#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run pylama'
\ : ''

View File

@ -44,7 +44,7 @@ endfunction
function! ale_linters#python#pylint#GetCommand(buffer, version) abort
let l:executable = ale_linters#python#pylint#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run pylint'
\ : ''
@ -82,7 +82,7 @@ function! ale_linters#python#pylint#Handle(buffer, lines) abort
continue
endif
if ale#Var(a:buffer, 'python_pylint_use_msg_id') is# 1
if ale#Var(a:buffer, 'python_pylint_use_msg_id')
let l:code_out = l:code
else
let l:code_out = l:match[4]

View File

@ -43,7 +43,7 @@ endfunction
function! ale_linters#python#pylsp#GetCommand(buffer) abort
let l:executable = ale_linters#python#pylsp#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run pylsp'
\ : ''
let l:env_string = ''

View File

@ -28,7 +28,7 @@ endfunction
function! ale_linters#python#pyre#GetCommand(buffer) abort
let l:executable = ale_linters#python#pyre#GetExecutable(a:buffer)
let l:exec_args = (l:executable =~? 'pipenv\|poetry\|uv$' ? ' run pyre' : '') . ' persistent'
let l:exec_args = (l:executable =~? '\(pipenv\|poetry\|uv\)$' ? ' run pyre' : '') . ' persistent'
return ale#Escape(l:executable) . l:exec_args
endfunction

View File

@ -0,0 +1,57 @@
" Author: oliverralbertini <oliver.albertini@gmail.com>
" Description: A performant type-checker supporting LSP for Python 3 created by Facebook
call ale#Set('python_pyrefly_executable', 'pyrefly')
call ale#Set('python_pyrefly_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_pyrefly_auto_pipenv', 0)
call ale#Set('python_pyrefly_auto_poetry', 0)
call ale#Set('python_pyrefly_auto_uv', 0)
function! ale_linters#python#pyrefly#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pyrefly_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_pyrefly_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
if (ale#Var(a:buffer, 'python_auto_uv') || ale#Var(a:buffer, 'python_pyrefly_auto_uv'))
\ && ale#python#UvPresent(a:buffer)
return 'uv'
endif
return ale#python#FindExecutable(a:buffer, 'python_pyrefly', ['pyrefly'])
endfunction
function! ale_linters#python#pyrefly#GetCommand(buffer) abort
let l:executable = ale_linters#python#pyrefly#GetExecutable(a:buffer)
let l:exec_args = [
\ ale#Escape(l:executable)
\ ]
\ + (l:executable =~? '\(pipenv\|poetry\|uv\)$' ? ['run', 'pyrefly'] : [])
\ + [
\ 'lsp',
\ ]
return join(l:exec_args, ' ')
endfunction
function! ale_linters#python#pyrefly#GetCwd(buffer) abort
" Run from project root if found, else from buffer dir.
let l:project_root = ale#python#FindProjectRoot(a:buffer)
return !empty(l:project_root) ? l:project_root : '%s:h'
endfunction
call ale#linter#Define('python', {
\ 'name': 'pyrefly',
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#python#pyrefly#GetExecutable'),
\ 'command': function('ale_linters#python#pyrefly#GetCommand'),
\ 'project_root': function('ale#python#FindProjectRoot'),
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
\ 'cwd': function('ale_linters#python#pyrefly#GetCwd'),
\})

View File

@ -70,7 +70,7 @@ endfunction
function! ale_linters#python#pyright#GetCommand(buffer) abort
let l:executable = ale_linters#python#pyright#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run pyright-langserver'
\ : ''
let l:env_string = ''

View File

@ -41,7 +41,7 @@ endfunction
function! ale_linters#python#refurb#GetCommand(buffer) abort
let l:executable = ale_linters#python#refurb#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run refurb'
\ : ''

View File

@ -47,7 +47,7 @@ endfunction
function! ale_linters#python#ruff#GetCommand(buffer, version) abort
let l:executable = ale_linters#python#ruff#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run ruff'
\ : ''
@ -72,10 +72,22 @@ function! ale_linters#python#ruff#Handle(buffer, lines) abort
try
let l:item = json_decode(l:line)
catch
let l:item = v:null
" If we can't decode a line, skip it.
continue
endtry
if !empty(l:item)
if (l:item.code is# 'W291' || l:item.code is# 'W293')
\&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
if l:item.code is# 'W391'
\&& !ale#Var(a:buffer, 'warn_about_trailing_blank_lines')
" Skip warnings for trailing blank lines if the option is off
continue
endif
call add(l:output, {
\ 'lnum': l:item.location.row,
\ 'col': l:item.location.column,
@ -85,7 +97,6 @@ function! ale_linters#python#ruff#Handle(buffer, lines) abort
\ 'text': l:item.message,
\ 'type': l:item.code =~? '\vE\d+' ? 'E' : 'W',
\})
endif
endfor
return l:output

View File

@ -28,7 +28,7 @@ endfunction
function! ale_linters#python#unimport#GetCommand(buffer) abort
let l:executable = ale_linters#python#unimport#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run unimport'
\ : ''

View File

@ -47,7 +47,7 @@ endfunction
function! ale_linters#python#vulture#GetCommand(buffer) abort
let l:executable = ale_linters#python#vulture#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run vulture'
\ : ''
let l:lint_dest = ale#Var(a:buffer, 'python_vulture_change_directory')

View File

@ -11,7 +11,7 @@ function! ale_linters#rego#opacheck#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'rego_opacheck_options')
return ale#Escape(ale_linters#rego#opacheck#GetExecutable(a:buffer))
\ . ' check %s --format json '
\ . ' check %s:h --format json '
\ . (!empty(l:options) ? ' ' . l:options : '')
endfunction

View File

@ -0,0 +1,25 @@
" Author: Benjamin Block <https://github.com/benjamindblock>
" Description: A language server for Roc.
function! ale_linters#roc#roc_language_server#GetProjectRoot(buffer) abort
let l:roc_main_file = ale#path#FindNearestFile(a:buffer, 'main.roc')
if !empty(l:roc_main_file)
return fnamemodify(l:roc_main_file, ':p:h')
else
return fnamemodify('', ':h')
endif
endfunction
call ale#Set('roc_roc_language_server_executable', 'roc_language_server')
call ale#Set('roc_roc_language_server_config', {})
call ale#linter#Define('roc', {
\ 'name': 'roc_language_server',
\ 'lsp': 'stdio',
\ 'language': 'roc',
\ 'lsp_config': {b -> ale#Var(b, 'roc_roc_language_server_config')},
\ 'executable': {b -> ale#Var(b, 'roc_roc_language_server_executable')},
\ 'command': '%e',
\ 'project_root': function('ale_linters#roc#roc_language_server#GetProjectRoot'),
\})

View File

@ -1,7 +1,7 @@
" Author: Jeffrey Lau - https://github.com/zoonfafer
" Description: Metals Language Server for Scala https://scalameta.org/metals/
call ale#Set('scala_metals_executable', 'metals-vim')
call ale#Set('scala_metals_executable', 'metals')
call ale#Set('scala_metals_project_root', '')
function! ale_linters#scala#metals#GetProjectRoot(buffer) abort

View File

@ -25,6 +25,7 @@ endfunction
call ale#linter#Define('sh', {
\ 'name': 'language_server',
\ 'aliases': ['bash-language-server'],
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#sh#language_server#GetExecutable'),
\ 'command': function('ale_linters#sh#language_server#GetCommand'),

View File

@ -52,16 +52,24 @@ function! ale_linters#sql#sqlfluff#Handle(buffer, version, lines) abort
if ale#semver#GTE(a:version, [3, 0, 0])
for l:violation in get(l:json, 'violations', [])
call add(l:output, {
let l:err = {
\ 'filename': l:json.filepath,
\ 'lnum': l:violation.start_line_no,
\ 'end_lnum': l:violation.end_line_no,
\ 'col': l:violation.start_line_pos,
\ 'end_col': l:violation.end_line_pos,
\ 'text': l:violation.description,
\ 'code': l:violation.code,
\ 'type': 'W',
\})
\}
if has_key(l:violation, 'end_line_no')
let l:err.end_lnum = l:violation.end_line_no
endif
if has_key(l:violation, 'end_line_pos')
let l:err.end_col = l:violation.end_line_pos
endif
call add(l:output, l:err)
endfor
else
for l:violation in get(l:json, 'violations', [])

View File

@ -5,6 +5,7 @@ call ale#Set('verilog_iverilog_options', '')
function! ale_linters#verilog#iverilog#GetCommand(buffer) abort
return 'iverilog -t null -Wall '
\ . '-y%s:h '
\ . ale#Var(a:buffer, 'verilog_iverilog_options')
\ . ' %t'
endfunction

View File

@ -20,9 +20,32 @@ function! ale_linters#yaml#actionlint#GetCommand(buffer) abort
let l:options .= ale#Pad('-oneline')
endif
let l:configfile = ale_linters#yaml#actionlint#GitRepoHasConfig(a:buffer)
if !empty(l:configfile)
let l:options .= ale#Pad('-config-file ' . l:configfile)
endif
return '%e' . ale#Pad(l:options) . ' - '
endfunction
" If we have a actionlint.yml or actionlint.yaml in our github directory
" use that as our config file.
function! ale_linters#yaml#actionlint#GitRepoHasConfig(buffer) abort
let l:filename = expand('#' . a:buffer . ':p')
let l:configfilebase = substitute(l:filename, '\.github/.*', '.github/actionlint.','')
for l:ext in ['yml', 'yaml']
let l:configfile = l:configfilebase . l:ext
if filereadable(l:configfile)
return l:configfile
endif
endfor
return ''
endfunction
function! ale_linters#yaml#actionlint#Handle(buffer, lines) abort
" Matches patterns line the following:
".github/workflows/main.yml:19:0: could not parse as YAML: yaml: line 19: mapping values are not allowed in this context [yaml-syntax]

View File

@ -0,0 +1,22 @@
" Author: axhav <william@axhav.se>
call ale#Set('yaml_yq_executable', 'yq')
call ale#Set('yaml_yq_options', '')
call ale#Set('yaml_yq_filters', '.')
" Matches patterns like the following:
let s:pattern = '^Error\:.* line \(\d\+\)\: \(.\+\)$'
function! ale_linters#yaml#yq#Handle(buffer, lines) abort
return ale#util#MapMatches(a:lines, s:pattern, {match -> {
\ 'lnum': match[1] + 0,
\ 'text': match[2],
\}})
endfunction
call ale#linter#Define('yaml', {
\ 'name': 'yq',
\ 'executable': {b -> ale#Var(b, 'yaml_yq_executable')},
\ 'output_stream': 'stderr',
\ 'command': '%e',
\ 'callback': 'ale_linters#yaml#yq#Handle',
\})

View File

@ -0,0 +1,18 @@
" Author: TcM1911
" Description: A language server for Yara.
call ale#Set('yara_yls_executable', 'yls')
function! ale_linters#yara#yls#FindProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestDirectory(a:buffer, '.git')
return !empty(l:project_root) ? (ale#path#Upwards(l:project_root)[1]) : ''
endfunction
call ale#linter#Define('yara', {
\ 'name': 'yls',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'yara_yls_executable')},
\ 'command': '%e -v',
\ 'project_root': function('ale_linters#yara#yls#FindProjectRoot'),
\})

View File

@ -4,11 +4,12 @@
call ale#Set('zeek_zeek_executable', 'zeek')
function! ale_linters#zeek#zeek#HandleErrors(buffer, lines) abort
let l:pattern = 'error in \v.*, line (\d+): (.*)$'
let l:pattern = '\(error\|warning\) in \v.*, line (\d+): (.*)$'
return map(ale#util#GetMatches(a:lines, l:pattern), "{
\ 'lnum': str2nr(v:val[1]),
\ 'text': v:val[2],
\ 'lnum': str2nr(v:val[2]),
\ 'text': v:val[3],
\ 'type': (v:val[1] is# 'error') ? 'E': 'W',
\}")
endfunction

View File

@ -0,0 +1,30 @@
" Author: Don Isaac
" Description: A linter for the Zig programming language
call ale#Set('zig_zlint_executable', 'zlint')
function! ale_linters#zig#zlint#Handle(buffer, lines) abort
" GitHub Actions format: ::severity file=file,line=line,col=col,title=code::message
let l:pattern = '::\([a-z]\+\) file=\([^,]\+\),line=\(\d\+\),col=\(\d\+\),title=\([^:]\+\)::\(.*\)'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'filename': l:match[2],
\ 'lnum': str2nr(l:match[3]),
\ 'col': str2nr(l:match[4]),
\ 'text': l:match[6],
\ 'type': l:match[1] =~? 'error\|fail' ? 'E' : 'W',
\ 'code': l:match[5],
\})
endfor
return l:output
endfunction
call ale#linter#Define('zig', {
\ 'name': 'zlint',
\ 'executable': {b -> ale#Var(b, "zig_zlint_executable")},
\ 'command': '%e %s -f gh',
\ 'callback': 'ale_linters#zig#zlint#Handle',
\})

View File

@ -171,7 +171,7 @@ function! ale#Queue(delay, ...) abort
endif
endfunction
let s:current_ale_version = [3, 3, 0]
let s:current_ale_version = [4, 0, 0]
" A function used to check for ALE features in files outside of the project.
function! ale#Has(feature) abort

View File

@ -205,7 +205,10 @@ endfunction
function! ale#assert#LSPLanguage(expected_language) abort
let l:buffer = bufnr('')
let l:linter = s:GetLinter()
let l:language = ale#linter#GetLanguage(l:buffer, l:linter)
let l:Language = l:linter.language
let l:language = type(l:Language) is v:t_func
\ ? l:Language(l:buffer)
\ : l:Language
AssertEqual a:expected_language, l:language
endfunction

View File

@ -16,7 +16,7 @@ onoremap <silent> <Plug>(ale_show_completion_menu) <Nop>
let g:ale_completion_delay = get(g:, 'ale_completion_delay', 100)
let g:ale_completion_excluded_words = get(g:, 'ale_completion_excluded_words', [])
let g:ale_completion_max_suggestions = get(g:, 'ale_completion_max_suggestions', 50)
let g:ale_completion_autoimport = get(g:, 'ale_completion_autoimport', 1)
let g:ale_completion_autoimport = get(g:, 'ale_completion_autoimport', v:true)
let g:ale_completion_tsserver_remove_warnings = get(g:, 'ale_completion_tsserver_remove_warnings', 0)
let s:timer_id = -1
@ -394,6 +394,7 @@ function! ale#completion#Show(result) abort
if g:ale_enabled
\&& (
\ l:text_changed is# '1'
\ || g:ale_lint_on_text_changed is v:true
\ || l:text_changed is# 'always'
\ || l:text_changed is# 'normal'
\ || l:text_changed is# 'insert'
@ -510,7 +511,7 @@ function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort
\ 'icase': 1,
\ 'menu': join(l:displayParts, ''),
\ 'dup': get(l:info, 'additional_edits_only', 0)
\ || g:ale_completion_autoimport,
\ || (g:ale_completion_autoimport + 0),
\ 'info': join(l:documentationParts, ''),
\}
" This flag is used to tell if this completion came from ALE or not.
@ -625,7 +626,7 @@ function! ale#completion#ParseLSPCompletions(response) abort
\ 'icase': 1,
\ 'menu': l:detail,
\ 'dup': get(l:info, 'additional_edits_only', 0)
\ || g:ale_completion_autoimport,
\ || (g:ale_completion_autoimport + 0),
\ 'info': (type(l:doc) is v:t_string ? l:doc : ''),
\}
" This flag is used to tell if this completion came from ALE or not.
@ -779,18 +780,15 @@ function! s:OnReady(linter, lsp_details) abort
call ale#lsp#RegisterCallback(l:id, l:Callback)
if a:linter.lsp is# 'tsserver'
if get(g:, 'ale_completion_tsserver_autoimport') is 1
" no-custom-checks
echom '`g:ale_completion_tsserver_autoimport` is deprecated. Use `g:ale_completion_autoimport` instead.'
endif
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,
\ (
\ get(b:ale_completion_info, 'additional_edits_only', 0)
\ || g:ale_completion_autoimport,
\ || g:ale_completion_autoimport
\ ) ? v:true : v:false,
\)
else
" Send a message saying the buffer has changed first, otherwise

View File

@ -340,6 +340,11 @@ function! ale#debugging#InfoCommand(...) abort
return
endif
" Do not show info for the info window itself.
if &filetype is# 'ale-info'
return
endif
" Get 'echo' from '-echo', if there's an argument.
let l:mode = get(a:000, '')[1:]

View File

@ -4,7 +4,7 @@
let s:go_to_definition_map = {}
" Enable automatic updates of the tagstack
let g:ale_update_tagstack = get(g:, 'ale_update_tagstack', 1)
let g:ale_update_tagstack = get(g:, 'ale_update_tagstack', v:true)
let g:ale_default_navigation = get(g:, 'ale_default_navigation', 'buffer')
" Used to get the definition map in tests.

View File

@ -68,7 +68,7 @@ function! ale#engine#IsExecutable(buffer, executable) abort
" Cache the executable check if we found it, or if the option to cache
" failing checks is on.
if l:result || get(g:, 'ale_cache_executable_check_failures', 0)
if l:result || get(g:, 'ale_cache_executable_check_failures')
let s:executable_cache_map[a:executable] = l:result
endif
@ -178,6 +178,12 @@ function! s:HandleExit(job_info, buffer, output, data) abort
let l:loclist = []
endtry
if type(l:loclist) isnot# v:t_list
" we only expect the list type; don't pass anything else down to
" `ale#engine#HandleLoclist` since it won't understand it
let l:loclist = []
endif
call ale#engine#HandleLoclist(l:linter.name, a:buffer, l:loclist, 0)
endfunction
@ -253,7 +259,7 @@ function! ale#engine#SendResultsToNeovimDiagnostics(buffer, loclist) abort
" Keep the Lua surface area really small in the VimL part of ALE,
" and just require the diagnostics.lua module on demand.
let l:SendDiagnostics = luaeval('require("ale.diagnostics").sendAleResultsToDiagnostics')
let l:SendDiagnostics = luaeval('require("ale.diagnostics").send')
call l:SendDiagnostics(a:buffer, a:loclist)
endfunction

View File

@ -100,6 +100,10 @@ if !exists('s:insert_leave_timer')
let s:insert_leave_timer = -1
endif
" True if the ModeChanged event exists.
" In this case, ModeChanged will be used instead of InsertLeave emulation.
let s:mode_changed_exists = exists('##ModeChanged')
function! ale#events#EmulateInsertLeave(buffer) abort
if mode() is# 'n'
call timer_stop(s:insert_leave_timer)
@ -114,8 +118,12 @@ function! ale#events#InsertEnterEvent(buffer) abort
" Start a repeating timer if the use might not trigger InsertLeave, so we
" can emulate its behavior.
" If the ModeChanged autocmd exists, it will be used instead of this
" timer; as ModeChanged will be sent regardless of how the insert mode is
" exited, including <Esc>, <C-c> and <C-]>.
if ale#Var(a:buffer, 'lint_on_insert_leave')
\&& maparg("\<C-c>", 'i') isnot# '<Esc>'
\&& !s:mode_changed_exists
call timer_stop(s:insert_leave_timer)
let s:insert_leave_timer = timer_start(
\ 100,
@ -126,10 +134,15 @@ function! ale#events#InsertEnterEvent(buffer) abort
endfunction
function! ale#events#InsertLeaveEvent(buffer) abort
if ale#Var(a:buffer, 'lint_on_insert_leave')
" Kill the InsertLeave emulation if the event fired.
" If the ModeChanged event is available, it will be used instead of
" a timer.
if !s:mode_changed_exists
call timer_stop(s:insert_leave_timer)
call ale#Queue(0)
endif
if ale#Var(a:buffer, 'lint_on_insert_leave')
call ale#Queue(0, '', a:buffer)
endif
" Look for a warning to echo as soon as we leave Insert mode.
@ -160,7 +173,9 @@ function! ale#events#Init() abort
autocmd BufWritePost * call ale#events#SaveEvent(str2nr(expand('<abuf>')))
if g:ale_enabled
if l:text_changed is? 'always' || l:text_changed is# '1'
if l:text_changed is? 'always'
\|| l:text_changed is# '1'
\|| g:ale_lint_on_text_changed is v:true
autocmd TextChanged,TextChangedI * call ale#Queue(ale#Var(str2nr(expand('<abuf>')), 'lint_delay'))
elseif l:text_changed is? 'normal'
autocmd TextChanged * call ale#Queue(ale#Var(str2nr(expand('<abuf>')), 'lint_delay'))
@ -189,8 +204,11 @@ function! ale#events#Init() abort
"
" We will emulate leaving insert mode for users that might not
" trigger InsertLeave.
"
" If the ModeChanged event is available, this timer will not
" be used.
if g:ale_close_preview_on_insert
\|| (g:ale_lint_on_insert_leave && maparg("\<C-c>", 'i') isnot# '<Esc>')
\|| (g:ale_lint_on_insert_leave && maparg("\<C-c>", 'i') isnot# '<Esc>' && !s:mode_changed_exists)
autocmd InsertEnter * call ale#events#InsertEnterEvent(str2nr(expand('<abuf>')))
endif
@ -211,8 +229,15 @@ function! ale#events#Init() abort
endif
if l:add_insert_leave_event
if s:mode_changed_exists
" If the ModeChanged event is available, handle any
" transition from the Insert mode to any other mode.
autocmd ModeChanged i*:* call ale#events#InsertLeaveEvent(str2nr(expand('<abuf>')))
else
" If ModeChanged is not available, handle InsertLeave events.
autocmd InsertLeave * call ale#events#InsertLeaveEvent(str2nr(expand('<abuf>')))
endif
endif
if g:ale_hover_cursor
autocmd CursorHold * if exists('*ale#lsp#Send') | call ale#hover#ShowTruncatedMessageAtCursor() | endif

View File

@ -78,7 +78,7 @@ function! ale#fix#ApplyFixes(buffer, output) abort
if !l:data.ignore_file_changed_errors
" no-custom-checks
echoerr 'The file was changed before fixing finished'
echom 'The file was changed before fixing finished'
endif
return

View File

@ -17,6 +17,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['help'],
\ 'description': 'Align help tags to the right margin',
\ },
\ 'apkbuild-fixer': {
\ 'function': 'ale#fixers#apkbuild_fixer#Fix',
\ 'suggested_filetypes': ['apkbuild'],
\ 'description': 'Fix policy violations found by apkbuild-lint in APKBUILDs',
\ },
\ 'autoimport': {
\ 'function': 'ale#fixers#autoimport#Fix',
\ 'suggested_filetypes': ['python'],
@ -39,7 +44,7 @@ let s:default_registry = {
\ },
\ 'biome': {
\ 'function': 'ale#fixers#biome#Fix',
\ 'suggested_filetypes': ['javascript', 'typescript', 'json', 'jsonc'],
\ 'suggested_filetypes': ['javascript', 'typescript', 'json', 'jsonc', 'css', 'graphql'],
\ 'description': 'Fix JavaScript and TypeScript using biome.',
\ },
\ 'black': {
@ -93,11 +98,27 @@ let s:default_registry = {
\ 'suggested_filetypes': ['dhall'],
\ 'description': 'Standard code formatter for the Dhall language and removing dead code',
\ },
\ 'djlint': {
\ 'function': 'ale#fixers#djlint#Fix',
\ 'suggested_filetypes': ['html', 'htmldjango', 'htmlangular', 'jinja', 'handlebars', 'nunjucks', 'gohtmltmpl'],
\ 'description': 'Fix HTML templates with `djlint --reformat`.',
\ },
\ 'dune': {
\ 'function': 'ale#fixers#dune#Fix',
\ 'suggested_filetypes': ['dune'],
\ 'description': 'Fix dune files with dune format',
\ },
\ 'erlang_mode': {
\ 'function': 'ale#fixers#erlang_mode#Fix',
\ 'suggested_filetypes': ['erlang'],
\ 'description': 'Indent with the Erlang mode for Emacs',
\ 'aliases': ['erlang-mode'],
\ },
\ 'erlfmt': {
\ 'function': 'ale#fixers#erlfmt#Fix',
\ 'suggested_filetypes': ['erlang'],
\ 'description': 'Format Erlang code with erlfmt',
\ },
\ 'fecs': {
\ 'function': 'ale#fixers#fecs#Fix',
\ 'suggested_filetypes': ['javascript', 'css', 'html'],
@ -108,6 +129,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['hurl'],
\ 'description': 'Fix hurl files with hurlfmt.',
\ },
\ 'kulala_fmt': {
\ 'function': 'ale#fixers#kulala_fmt#Fix',
\ 'suggested_filetypes': ['http', 'rest'],
\ 'description': 'Fix http and rest files with kulala_fmt.',
\ },
\ 'tidy': {
\ 'function': 'ale#fixers#tidy#Fix',
\ 'suggested_filetypes': ['html'],
@ -201,6 +227,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['python'],
\ 'description': 'Fix Python files with yapf.',
\ },
\ 'yq': {
\ 'function': 'ale#fixers#yq#Fix',
\ 'suggested_filetypes': ['yaml'],
\ 'description': 'Fix YAML files with yq.',
\ },
\ 'rubocop': {
\ 'function': 'ale#fixers#rubocop#Fix',
\ 'suggested_filetypes': ['ruby'],
@ -321,6 +352,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['go'],
\ 'description': 'Fix Go files imports with goimports.',
\ },
\ 'golangci_lint': {
\ 'function': 'ale#fixers#golangci_lint#Fix',
\ 'suggested_filetypes': ['go'],
\ 'description': 'Fix Go files with golangci-lint.',
\ },
\ 'golines': {
\ 'function': 'ale#fixers#golines#Fix',
\ 'suggested_filetypes': ['go'],
@ -451,6 +487,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['json'],
\ 'description': 'Fix JSON files with jq.',
\ },
\ 'json_pytool': {
\ 'function': 'ale#fixers#json_pytool#Fix',
\ 'suggested_filetypes': ['json'],
\ 'description': "Fix JSON files with python's built-in json.tool module.",
\ },
\ 'protolint': {
\ 'function': 'ale#fixers#protolint#Fix',
\ 'suggested_filetypes': ['proto'],
@ -666,6 +707,31 @@ let s:default_registry = {
\ 'suggested_filetypes': ['ruby'],
\ 'description': 'A formatter for Ruby source code',
\ },
\ 'scadformat': {
\ 'function': 'ale#fixers#scadformat#Fix',
\ 'suggested_filetypes': ['openscad'],
\ 'description': 'Formatter for scad files',
\ },
\ 'cljfmt': {
\ 'function': 'ale#fixers#cljfmt#Fix',
\ 'suggested_filetypes': ['clojure'],
\ 'description': 'formatter and linter for clojure files',
\ },
\ 'typstyle': {
\ 'function': 'ale#fixers#typstyle#Fix',
\ 'suggested_filetypes': ['typst'],
\ 'description': 'A formatter for Typst files',
\ },
\ 'roc_format': {
\ 'function': 'ale#fixers#roc_format#Fix',
\ 'suggested_filetypes': ['roc'],
\ 'description': 'Formats Roc files.',
\ },
\ 'roc_annotate': {
\ 'function': 'ale#fixers#roc_annotate#Fix',
\ 'suggested_filetypes': ['roc'],
\ 'description': 'Annotates all top-level definitions in Roc files.',
\ },
\}
" Reset the function registry to the default entries.

View File

@ -0,0 +1,19 @@
" Author: Leo <thinkabit.ukim@gmail.com>
" Description: Fix policy violations found by apkbuild-lint
call ale#Set('apkbuild_apkbuild_fixer_executable', 'apkbuild-fixer')
call ale#Set('apkbuild_apkbuild_fixer_lint_executable', get(g:, 'ale_apkbuild_apkbuild_lint_executable'))
call ale#Set('apkbuild_apkbuild_fixer_options', '')
function! ale#fixers#apkbuild_fixer#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'apkbuild_apkbuild_fixer_executable')
let l:options = ale#Var(a:buffer, 'apkbuild_apkbuild_fixer_options')
return {
\ 'command': ale#Escape(l:executable)
\ . ' -p ' . ale#Var(a:buffer, 'apkbuild_apkbuild_fixer_lint_executable')
\ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -30,7 +30,7 @@ endfunction
function! ale#fixers#autoflake#Fix(buffer) abort
let l:executable = ale#fixers#autoflake#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run autoflake'
\ : ''

View File

@ -30,7 +30,7 @@ endfunction
function! ale#fixers#autoimport#Fix(buffer) abort
let l:executable = ale#fixers#autoimport#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run autoimport'
\ : ''

View File

@ -30,7 +30,7 @@ endfunction
function! ale#fixers#autopep8#Fix(buffer) abort
let l:executable = ale#fixers#autopep8#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run autopep8'
\ : ''

View File

@ -1,7 +1,7 @@
function! ale#fixers#biome#Fix(buffer) abort
let l:executable = ale#handlers#biome#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'biome_options')
let l:apply = ale#Var(a:buffer, 'biome_fixer_apply_unsafe') ? '--apply-unsafe' : '--apply'
let l:apply = ale#Var(a:buffer, 'biome_fixer_apply_unsafe') ? '--write --unsafe' : '--write'
return {
\ 'read_temporary_file': 1,

View File

@ -32,7 +32,7 @@ function! ale#fixers#black#Fix(buffer) abort
let l:executable = ale#fixers#black#GetExecutable(a:buffer)
let l:cmd = [ale#Escape(l:executable)]
if l:executable =~? 'pipenv\|poetry\|uv$'
if l:executable =~? '\(pipenv\|poetry\|uv\)$'
call extend(l:cmd, ['run', 'black'])
endif
@ -42,6 +42,9 @@ function! ale#fixers#black#Fix(buffer) abort
call add(l:cmd, l:options)
endif
let l:fname = expand('#' . a:buffer . '...')
call add(l:cmd, '--stdin-filename '.ale#Escape(ale#path#Simplify(l:fname)))
if expand('#' . a:buffer . ':e') is? 'pyi'
call add(l:cmd, '--pyi')
endif

View File

@ -22,7 +22,7 @@ function! ale#fixers#clangformat#Fix(buffer) abort
let l:use_local_file = ale#Var(a:buffer, 'c_clangformat_use_local_file')
if l:style_option isnot# ''
let l:style_option = '-style=' . "'" . l:style_option . "'"
let l:style_option = '-style=' . ale#Escape(l:style_option)
endif
if l:use_local_file

View File

@ -0,0 +1,14 @@
" Author: rudolf ordoyne <rudolfordoyne@protonmail.com>
" Description: Support for cljfmt https://github.com/weavejester/cljfmt
call ale#Set('clojure_cljfmt_executable', 'cljfmt')
function! ale#fixers#cljfmt#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'clojure_cljfmt_executable')
return {
\ 'command': ale#Escape(l:executable) . ' fix %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -0,0 +1,48 @@
" Author: Adrian Vollmer (computerfluesterer@protonmail.com)
" Description: HTML template formatter using `djlint --reformat`
call ale#Set('html_djlint_executable', 'djlint')
call ale#Set('html_djlint_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('html_djlint_options', '')
function! ale#fixers#djlint#Fix(buffer) abort
let l:executable = ale#python#FindExecutable(
\ a:buffer,
\ 'html_djlint',
\ ['djlint']
\)
let l:options = ale#Var(a:buffer, 'html_djlint_options')
let l:profile = ''
let l:filetypes = split(getbufvar(a:buffer, '&filetype'), '\.')
" Append the --profile flag depending on the current filetype (unless it's
" already set in g:html_djlint_options).
if match(l:options, '--profile') == -1
let l:djlint_profiles = {
\ 'html': 'html',
\ 'htmldjango': 'django',
\ 'jinja': 'jinja',
\ 'nunjucks': 'nunjucks',
\ 'handlebars': 'handlebars',
\ 'gohtmltmpl': 'golang',
\ 'htmlangular': 'angular',
\}
for l:filetype in l:filetypes
if has_key(l:djlint_profiles, l:filetype)
let l:profile = l:djlint_profiles[l:filetype]
break
endif
endfor
endif
if !empty(l:profile)
let l:options = (!empty(l:options) ? l:options . ' ' : '') . '--profile ' . l:profile
endif
return {
\ 'command': ale#Escape(l:executable) . ' --reformat ' . l:options . ' -',
\}
endfunction

View File

@ -0,0 +1,50 @@
" Author: Dmitri Vereshchagin <dmitri.vereshchagin@gmail.com>
" Description: Indent with the Erlang mode for Emacs
call ale#Set('erlang_erlang_mode_emacs_executable', 'emacs')
call ale#Set('erlang_erlang_mode_indent_level', 4)
call ale#Set('erlang_erlang_mode_icr_indent', 'nil')
call ale#Set('erlang_erlang_mode_indent_guard', 2)
call ale#Set('erlang_erlang_mode_argument_indent', 2)
call ale#Set('erlang_erlang_mode_indent_tabs_mode', 'nil')
let s:variables = {
\ 'erlang-indent-level': 'erlang_erlang_mode_indent_level',
\ 'erlang-icr-indent': 'erlang_erlang_mode_icr_indent',
\ 'erlang-indent-guard': 'erlang_erlang_mode_indent_guard',
\ 'erlang-argument-indent': 'erlang_erlang_mode_argument_indent',
\ 'indent-tabs-mode': 'erlang_erlang_mode_indent_tabs_mode',
\}
function! ale#fixers#erlang_mode#Fix(buffer) abort
let l:emacs_executable =
\ ale#Var(a:buffer, 'erlang_erlang_mode_emacs_executable')
let l:exprs = [
\ '(setq enable-local-variables :safe)',
\ s:SetqDefault(a:buffer, s:variables),
\ '(erlang-mode)',
\ '(font-lock-fontify-region (point-min) (point-max))',
\ '(indent-region (point-min) (point-max))',
\ '(funcall (if indent-tabs-mode ''tabify ''untabify)'
\ . ' (point-min) (point-max))',
\ '(save-buffer 0)',
\]
let l:command = ale#Escape(l:emacs_executable)
\ . ' --batch'
\ . ' --find-file=%t'
\ . join(map(l:exprs, '" --eval=" . ale#Escape(v:val)'), '')
return {'command': l:command, 'read_temporary_file': 1}
endfunction
function! s:SetqDefault(buffer, variables) abort
let l:args = []
for [l:emacs_name, l:ale_name] in items(a:variables)
let l:args += [l:emacs_name, ale#Var(a:buffer, l:ale_name)]
endfor
return '(setq-default ' . join(l:args) . ')'
endfunction

View File

@ -13,9 +13,7 @@ function! ale#fixers#erlfmt#Fix(buffer) abort
let l:options = ale#Var(a:buffer, 'erlang_erlfmt_options')
let l:executable = ale#fixers#erlfmt#GetExecutable(a:buffer)
let l:command = ale#Escape(l:executable) . (empty(l:options) ? '' : ' ' . l:options) . ' %s'
let l:command = ale#Escape(l:executable) . ale#Pad(l:options) . ' -'
return {
\ 'command': l:command
\}
return {'command': l:command}
endfunction

View File

@ -0,0 +1,48 @@
" Author: Ian Stapleton Cordasco <graffatcolmingov@gmail.com>
" Description: Run golangci-lint with the --fix flag to autofix some issues
call ale#Set('go_golangci_formatter_options', '')
call ale#Set('go_golangci_formatter_executable', 'golangci-lint')
function! ale#fixers#golangci_lint#GetExecutable(buffer) abort
let l:executable = ale#Var(a:buffer, 'go_golangci_formatter_executable')
return l:executable
endfunction
function! ale#fixers#golangci_lint#GetCommand(buffer, version) abort
let l:filename = expand('#' . a:buffer . ':t')
let l:executable = ale#fixers#golangci_lint#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'go_golangci_formatter_options')
let l:env = ale#go#EnvString(a:buffer)
if ale#semver#GTE(a:version, [2, 0, 0])
return l:env . ale#Escape(l:executable)
\ . ' fmt --stdin '
\ . l:options
else
return l:env . ale#Escape(l:executable)
\ . ' run --fix '
\ . l:options
\ . ' '
\ . ale#Escape(l:filename)
endif
endfunction
function! ale#fixers#golangci_lint#GetCommandForVersion(buffer, version) abort
return {
\ 'command': ale#fixers#golangci_lint#GetCommand(a:buffer, a:version)
\}
endfunction
function! ale#fixers#golangci_lint#Fix(buffer) abort
let l:executable = ale#fixers#golangci_lint#GetExecutable(a:buffer)
let l:command = ale#fixers#golangci_lint#GetExecutable(a:buffer) . ale#Pad('--version')
return ale#semver#RunWithVersionCheck(
\ a:buffer,
\ l:executable,
\ l:command,
\ function('ale#fixers#golangci_lint#GetCommandForVersion'),
\)
endfunction

View File

@ -31,7 +31,7 @@ function! ale#fixers#isort#GetCmd(buffer) abort
let l:executable = ale#fixers#isort#GetExecutable(a:buffer)
let l:cmd = [ale#Escape(l:executable)]
if l:executable =~? 'pipenv\|poetry\|uv$'
if l:executable =~? '\(pipenv\|poetry\|uv\)$'
call extend(l:cmd, ['run', 'isort'])
endif
@ -42,7 +42,7 @@ function! ale#fixers#isort#FixForVersion(buffer, version) abort
let l:executable = ale#fixers#isort#GetExecutable(a:buffer)
let l:cmd = [ale#Escape(l:executable)]
if l:executable =~? 'pipenv\|poetry\|uv$'
if l:executable =~? '\(pipenv\|poetry\|uv\)$'
call extend(l:cmd, ['run', 'isort'])
endif

View File

@ -0,0 +1,20 @@
" Author: idbrii
" Description: json formatter as ALE fixer using python's json.tool
call ale#Set('json_pytool_executable', 'python')
call ale#Set('json_pytool_options', '')
call ale#Set('json_pytool_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale#fixers#json_pytool#GetExecutable(buffer) abort
return ale#path#FindExecutable(a:buffer, 'json_pytool', ['python'])
endfunction
function! ale#fixers#json_pytool#Fix(buffer) abort
let l:executable = ale#Escape(ale#fixers#json_pytool#GetExecutable(a:buffer))
let l:opts = ale#Var(a:buffer, 'json_pytool_options')
let l:command = printf('%s -m json.tool %s -', l:executable, l:opts)
return {
\ 'command': l:command
\ }
endfunction

View File

@ -0,0 +1,11 @@
" Author: hsanson <hsanson@gmail.com>
" Description: kulala_fmt fixer for http and rest files.
call ale#Set('http_kulala_fmt_executable', 'kulala-fmt')
function! ale#fixers#kulala_fmt#Fix(buffer) abort
return {
\ 'command': ale#Escape(ale#Var(a:buffer, 'http_kulala_fmt_executable')) . ' format %t > /dev/null',
\ 'read_temporary_file': 1
\ }
endfunction

View File

@ -42,7 +42,7 @@ endfunction
function! ale#fixers#pycln#GetCommand(buffer) abort
let l:executable = ale#fixers#pycln#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run pycln'
\ : ''
@ -53,7 +53,7 @@ function! ale#fixers#pycln#FixForVersion(buffer, version) abort
let l:executable = ale#fixers#pycln#GetExecutable(a:buffer)
let l:cmd = [ale#Escape(l:executable)]
if l:executable =~? 'pipenv\|poetry\|uv$'
if l:executable =~? '\(pipenv\|poetry\|uv\)$'
call extend(l:cmd, ['run', 'pycln'])
endif

View File

@ -33,7 +33,7 @@ function! ale#fixers#pyflyby#Fix(buffer) abort
let l:executable = ale#fixers#pyflyby#GetExecutable(a:buffer)
let l:cmd = [ale#Escape(l:executable)]
if l:executable =~? 'pipenv\|poetry\|uv$'
if l:executable =~? '\(pipenv\|poetry\|uv\)$'
call extend(l:cmd, ['run', 'tidy-imports'])
endif

View File

@ -30,7 +30,7 @@ endfunction
function! ale#fixers#reorder_python_imports#Fix(buffer) abort
let l:executable = ale#fixers#reorder_python_imports#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run reorder-python-imports'
\ : ''

View File

@ -0,0 +1,21 @@
" Author: Benjamin Block <https://github.com/benjamindblock>
" Description: Official type annotation tool for Roc.
call ale#Set('roc_roc_annotate_executable', 'roc')
call ale#Set('roc_roc_annotate_options', '')
function! ale#fixers#roc_annotate#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'roc_roc_annotate_executable')
let l:command = l:executable . ' format annotate'
let l:options = ale#Var(a:buffer, 'roc_roc_annotate_options')
if l:options isnot# ''
let l:command .= ' ' . l:options
endif
return {
\ 'command': l:command . ' %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -0,0 +1,20 @@
" Author: Benjamin Block <https://github.com/benjamindblock>
" Description: Official formatter for Roc.
call ale#Set('roc_roc_format_executable', 'roc')
call ale#Set('roc_roc_format_options', '')
function! ale#fixers#roc_format#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'roc_roc_format_executable')
let l:command = l:executable . ' format'
let l:options = ale#Var(a:buffer, 'roc_roc_format_options')
if l:options isnot# ''
let l:command .= ' ' . l:options
endif
return {
\ 'command': l:command . ' %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -41,7 +41,7 @@ endfunction
function! ale#fixers#ruff#GetCommand(buffer) abort
let l:executable = ale#fixers#ruff#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run ruff'
\ : ''
@ -52,7 +52,7 @@ function! ale#fixers#ruff#FixForVersion(buffer, version) abort
let l:executable = ale#fixers#ruff#GetExecutable(a:buffer)
let l:cmd = [ale#Escape(l:executable)]
if l:executable =~? 'pipenv\|poetry\|uv$'
if l:executable =~? '\(pipenv\|poetry\|uv\)$'
call extend(l:cmd, ['run', 'ruff'])
endif

View File

@ -41,7 +41,7 @@ endfunction
function! ale#fixers#ruff_format#GetCommand(buffer) abort
let l:executable = ale#fixers#ruff_format#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run ruff'
\ : ''
@ -52,7 +52,7 @@ function! ale#fixers#ruff_format#Fix(buffer) abort
let l:executable = ale#fixers#ruff_format#GetExecutable(a:buffer)
let l:cmd = [ale#Escape(l:executable)]
if l:executable =~? 'pipenv\|poetry\|uv$'
if l:executable =~? '\(pipenv\|poetry\|uv\)$'
call extend(l:cmd, ['run', 'ruff'])
endif

View File

@ -0,0 +1,15 @@
" Author: tony o'dell <tony.odell@live.com>
" Description: Fix scad files with scadformat
call ale#Set('openscad_scadformat_executable', 'scadformat')
call ale#Set('openscad_scadformat_options', '')
function! ale#fixers#scadformat#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'openscad_scadformat_executable')
let l:options = ale#Var(a:buffer, 'openscad_scadformat_options')
return {
\ 'command': ale#Escape(l:executable)
\ . (empty(l:options) ? '' : ' ' . l:options),
\}
endfunction

View File

@ -4,11 +4,24 @@
call ale#Set('lua_stylua_executable', 'stylua')
call ale#Set('lua_stylua_options', '')
function! ale#fixers#stylua#GetCwd(buffer) abort
for l:possible_configfile in ['stylua.toml', '.stylua.toml']
let l:config = ale#path#FindNearestFile(a:buffer, l:possible_configfile)
if !empty(l:config)
return fnamemodify(l:config, ':h')
endif
endfor
return '%s:h'
endfunction
function! ale#fixers#stylua#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'lua_stylua_executable')
let l:options = ale#Var(a:buffer, 'lua_stylua_options')
return {
\ 'command': ale#Escape(l:executable) . ale#Pad(l:options) . ' -',
\ 'cwd': ale#fixers#stylua#GetCwd(a:buffer),
\ 'command': ale#Escape(l:executable) . ale#Pad(l:options) . ' --stdin-filepath %s -',
\}
endfunction

View File

@ -6,7 +6,7 @@ function! ale#fixers#syntax_tree#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'ruby_syntax_tree_options')
return ale#ruby#EscapeExecutable(l:executable, 'stree')
\ . ' write'
\ . ' format'
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %t'
endfunction
@ -14,6 +14,5 @@ endfunction
function! ale#fixers#syntax_tree#Fix(buffer) abort
return {
\ 'command': ale#fixers#syntax_tree#GetCommand(a:buffer),
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -0,0 +1,20 @@
" Author: Adrian Vollmer (computerfluesterer@protonmail.com)
" Description: Typst formatter using typstyle
call ale#Set('typst_typstyle_executable', 'typstyle')
call ale#Set('typst_typstyle_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('typst_typstyle_options', '')
function! ale#fixers#typstyle#Fix(buffer) abort
let l:executable = ale#path#FindExecutable(
\ a:buffer,
\ 'typst_typstyle',
\ ['typstyle']
\)
let l:options = ale#Var(a:buffer, 'typst_typstyle_options')
return {
\ 'command': ale#Escape(l:executable) . ' ' . l:options,
\}
endfunction

View File

@ -7,15 +7,8 @@ call ale#Set('xml_xmllint_indentsize', 2)
function! ale#fixers#xmllint#Fix(buffer) abort
let l:executable = ale#Escape(ale#Var(a:buffer, 'xml_xmllint_executable'))
let l:filename = bufname(a:buffer)
if empty(l:filename)
let l:filename = '%t'
else
let l:filename = ale#Escape(l:filename)
endif
let l:command = l:executable . ' --format ' . l:filename
let l:command = l:executable . ' --format'
let l:indent = ale#Var(a:buffer, 'xml_xmllint_indentsize')
@ -31,6 +24,6 @@ function! ale#fixers#xmllint#Fix(buffer) abort
endif
return {
\ 'command': l:command
\ 'command': l:command . ' -'
\}
endfunction

View File

@ -29,7 +29,7 @@ endfunction
function! ale#fixers#yapf#Fix(buffer) abort
let l:executable = ale#fixers#yapf#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry\|uv$'
let l:exec_args = l:executable =~? '\(pipenv\|poetry\|uv\)$'
\ ? ' run yapf'
\ : ''

View File

@ -0,0 +1,22 @@
call ale#Set('yaml_yq_executable', 'yq')
call ale#Set('yaml_yq_options', '')
call ale#Set('yaml_yq_filters', '.')
function! ale#fixers#yq#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'yaml_yq_executable')
endfunction
function! ale#fixers#yq#Fix(buffer) abort
let l:options = ale#Var(a:buffer, 'yaml_yq_options')
let l:filters = ale#Var(a:buffer, 'yaml_yq_filters')
if empty(l:filters)
return 0
endif
return {
\ 'command': ale#Escape(ale#fixers#yq#GetExecutable(a:buffer))
\ . ' ' . l:filters . ' '
\ . l:options,
\}
endfunction

View File

@ -21,6 +21,8 @@ function! ale#floating_preview#Show(lines, ...) abort
else
call s:VimShow(a:lines, l:options)
endif
return w:preview.id
endfunction
function! s:NvimShow(lines, options) abort

View File

@ -0,0 +1,19 @@
scriptencoding utf-8
" Author: Koni Marti <koni.marti@gmail.com>
" Description: Utilities for c3lsp
function! ale#handlers#c3lsp#GetProjectRoot(buffer) abort
let l:config = ale#path#FindNearestFile(a:buffer, 'project.json')
if !empty(l:config)
return fnamemodify(l:config, ':h')
endif
return expand('#' . a:buffer . ':p:h')
endfunction
function! ale#handlers#c3lsp#GetInitOpts(buffer, init_options_var) abort
let l:init_options = {}
return extend(l:init_options, ale#Var(a:buffer, a:init_options_var))
endfunction

View File

@ -0,0 +1,64 @@
" Author: Vivian De Smedt <vds2212@gmail.com>, Adrian Vollmer <computerfluesterer@protonmail.com>
" Description: Adds support for djlint
"
function! ale#handlers#djlint#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'html_djlint_executable')
endfunction
function! ale#handlers#djlint#GetCommand(buffer) abort
let l:executable = ale#handlers#djlint#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'html_djlint_options')
let l:profile = ''
let l:filetypes = split(getbufvar(a:buffer, '&filetype'), '\.')
" Append the --profile flag depending on the current filetype (unless it's
" already set in g:html_djlint_options).
if match(l:options, '--profile') == -1
let l:djlint_profiles = {
\ 'html': 'html',
\ 'htmldjango': 'django',
\ 'jinja': 'jinja',
\ 'nunjucks': 'nunjucks',
\ 'handlebars': 'handlebars',
\ 'gohtmltmpl': 'golang',
\ 'htmlangular': 'angular',
\}
for l:filetype in l:filetypes
if has_key(l:djlint_profiles, l:filetype)
let l:profile = l:djlint_profiles[l:filetype]
break
endif
endfor
endif
if !empty(l:profile)
let l:options = (!empty(l:options) ? l:options . ' ' : '') . '--profile ' . l:profile
endif
return ale#Escape(l:executable)
\ . (!empty(l:options) ? ' ' . l:options : '') . ' %s'
endfunction
function! ale#handlers#djlint#Handle(buffer, lines) abort
let l:output = []
let l:pattern = '\v^([A-Z]\d+) (\d+):(\d+) (.*)$'
let l:i = 0
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:i += 1
let l:item = {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'vcol': 1,
\ 'text': l:match[4],
\ 'code': l:match[1],
\ 'type': 'W',
\}
call add(l:output, l:item)
endfor
return l:output
endfunction

View File

@ -11,6 +11,7 @@ let s:linters = {}
" NOTE: Update the g:ale_linter_aliases documentation when modifying this.
let s:default_ale_linter_aliases = {
\ 'Dockerfile': 'dockerfile',
\ 'bash': 'sh',
\ 'csh': 'sh',
\ 'javascriptreact': ['javascript', 'jsx'],
\ 'plaintex': 'tex',
@ -446,9 +447,3 @@ function! ale#linter#GetAddress(buffer, linter) abort
return type(l:Address) is v:t_func ? l:Address(a:buffer) : l:Address
endfunction
function! ale#linter#GetLanguage(buffer, linter) abort
let l:Language = a:linter.language
return type(l:Language) is v:t_func ? l:Language(a:buffer) : l:Language
endfunction

View File

@ -2,11 +2,11 @@
" Description: Manages the loclist and quickfix lists
" This flag dictates if ale open the configured loclist
let g:ale_open_list = get(g:, 'ale_open_list', 0)
let g:ale_open_list = get(g:, 'ale_open_list', v:false)
" This flag dictates if ale keeps open loclist even if there is no error in loclist
let g:ale_keep_list_window_open = get(g:, 'ale_keep_list_window_open', 0)
" This flag dictates that quickfix windows should be opened vertically
let g:ale_list_vertical = get(g:, 'ale_list_vertical', 0)
let g:ale_list_vertical = get(g:, 'ale_list_vertical', v:false)
" The window size to set for the quickfix and loclist windows
let g:ale_list_window_size = get(g:, 'ale_list_window_size', 10)
" A string format for the loclist messages.

View File

@ -5,9 +5,10 @@
let s:connections = get(s:, 'connections', {})
let g:ale_lsp_next_message_id = 1
" Given an id, which can be an executable or address, and a project path,
" Given an id, which can be an executable or address, a project path,
" and a language string or (bufnr) -> string function
" create a new connection if needed. Return a unique ID for the connection.
function! ale#lsp#Register(executable_or_address, project, init_options) abort
function! ale#lsp#Register(executable_or_address, project, language, init_options) abort
let l:conn_id = a:executable_or_address . ':' . a:project
if !has_key(s:connections, l:conn_id)
@ -28,6 +29,7 @@ function! ale#lsp#Register(executable_or_address, project, init_options) abort
\ 'is_tsserver': 0,
\ 'data': '',
\ 'root': a:project,
\ 'language': a:language,
\ 'open_documents': {},
\ 'initialized': 0,
\ 'init_request_id': 0,
@ -45,6 +47,7 @@ function! ale#lsp#Register(executable_or_address, project, init_options) abort
\ 'definition': 0,
\ 'typeDefinition': 0,
\ 'implementation': 0,
\ 'pull_model': 0,
\ 'symbol_search': 0,
\ 'code_actions': 0,
\ 'did_save': 0,
@ -195,101 +198,114 @@ endfunction
" Update capabilities from the server, so we know which features the server
" supports.
function! s:UpdateCapabilities(conn, capabilities) abort
function! ale#lsp#UpdateCapabilities(conn_id, capabilities) abort
let l:conn = get(s:connections, a:conn_id, {})
if empty(l:conn)
return
endif
if type(a:capabilities) isnot v:t_dict
return
endif
if get(a:capabilities, 'hoverProvider') is v:true
let a:conn.capabilities.hover = 1
let l:conn.capabilities.hover = 1
endif
if type(get(a:capabilities, 'hoverProvider')) is v:t_dict
let a:conn.capabilities.hover = 1
let l:conn.capabilities.hover = 1
endif
if get(a:capabilities, 'referencesProvider') is v:true
let a:conn.capabilities.references = 1
let l:conn.capabilities.references = 1
endif
if type(get(a:capabilities, 'referencesProvider')) is v:t_dict
let a:conn.capabilities.references = 1
let l:conn.capabilities.references = 1
endif
if get(a:capabilities, 'renameProvider') is v:true
let a:conn.capabilities.rename = 1
let l:conn.capabilities.rename = 1
endif
if type(get(a:capabilities, 'renameProvider')) is v:t_dict
let a:conn.capabilities.rename = 1
let l:conn.capabilities.rename = 1
endif
if get(a:capabilities, 'codeActionProvider') is v:true
let a:conn.capabilities.code_actions = 1
let l:conn.capabilities.code_actions = 1
endif
if type(get(a:capabilities, 'codeActionProvider')) is v:t_dict
let a:conn.capabilities.code_actions = 1
let l:conn.capabilities.code_actions = 1
endif
if !empty(get(a:capabilities, 'completionProvider'))
let a:conn.capabilities.completion = 1
let l: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
let l:conn.capabilities.completion_trigger_characters = l:chars
endif
endif
if get(a:capabilities, 'definitionProvider') is v:true
let a:conn.capabilities.definition = 1
let l:conn.capabilities.definition = 1
endif
if type(get(a:capabilities, 'definitionProvider')) is v:t_dict
let a:conn.capabilities.definition = 1
let l:conn.capabilities.definition = 1
endif
if get(a:capabilities, 'typeDefinitionProvider') is v:true
let a:conn.capabilities.typeDefinition = 1
let l:conn.capabilities.typeDefinition = 1
endif
if type(get(a:capabilities, 'typeDefinitionProvider')) is v:t_dict
let a:conn.capabilities.typeDefinition = 1
let l:conn.capabilities.typeDefinition = 1
endif
if get(a:capabilities, 'implementationProvider') is v:true
let a:conn.capabilities.implementation = 1
let l:conn.capabilities.implementation = 1
endif
if type(get(a:capabilities, 'implementationProvider')) is v:t_dict
let a:conn.capabilities.implementation = 1
let l:conn.capabilities.implementation = 1
endif
" Check if the language server supports pull model diagnostics.
if type(get(a:capabilities, 'diagnosticProvider')) is v:t_dict
if type(get(a:capabilities.diagnosticProvider, 'interFileDependencies')) is v:t_bool
let l:conn.capabilities.pull_model = 1
endif
endif
if get(a:capabilities, 'workspaceSymbolProvider') is v:true
let a:conn.capabilities.symbol_search = 1
let l:conn.capabilities.symbol_search = 1
endif
if type(get(a:capabilities, 'workspaceSymbolProvider')) is v:t_dict
let a:conn.capabilities.symbol_search = 1
let l:conn.capabilities.symbol_search = 1
endif
if type(get(a:capabilities, 'textDocumentSync')) is v:t_dict
let l:syncOptions = get(a:capabilities, 'textDocumentSync')
if get(l:syncOptions, 'save') is v:true
let a:conn.capabilities.did_save = 1
let l:conn.capabilities.did_save = 1
endif
if type(get(l:syncOptions, 'save')) is v:t_dict
let a:conn.capabilities.did_save = 1
let l:conn.capabilities.did_save = 1
let l:saveOptions = get(l:syncOptions, 'save')
if get(l:saveOptions, 'includeText') is v:true
let a:conn.capabilities.includeText = 1
let l:conn.capabilities.includeText = 1
endif
endif
endif
@ -313,13 +329,30 @@ function! ale#lsp#UpdateConfig(conn_id, buffer, config) abort
return 1
endfunction
function! ale#lsp#CallInitCallbacks(conn_id) abort
let l:conn = get(s:connections, a:conn_id, {})
if !empty(l:conn)
" Ensure the connection is marked as initialized.
" For integration with Neovim's LSP tooling this ensures immediately
" call OnInit functions in Vim after the `on_init` callback is called.
let l:conn.initialized = 1
" Call capabilities callbacks queued for the project.
for l:Callback in l:conn.init_queue
call l:Callback()
endfor
let l:conn.init_queue = []
endif
endfunction
function! ale#lsp#HandleInitResponse(conn, response) abort
if get(a:response, 'method', '') is# 'initialize'
let a:conn.initialized = 1
elseif type(get(a:response, 'result')) is v:t_dict
\&& has_key(a:response.result, 'capabilities')
call s:UpdateCapabilities(a:conn, a:response.result.capabilities)
call ale#lsp#UpdateCapabilities(a:conn.id, a:response.result.capabilities)
let a:conn.initialized = 1
endif
@ -331,12 +364,7 @@ function! ale#lsp#HandleInitResponse(conn, response) abort
" The initialized message must be sent before everything else.
call ale#lsp#Send(a:conn.id, ale#lsp#message#Initialized())
" Call capabilities callbacks queued for the project.
for l:Callback in a:conn.init_queue
call l:Callback()
endfor
let a:conn.init_queue = []
call ale#lsp#CallInitCallbacks(a:conn.id)
endfunction
function! ale#lsp#HandleMessage(conn_id, message) abort
@ -375,6 +403,20 @@ function! ale#lsp#HandleMessage(conn_id, message) abort
endif
endfunction
" Handle a JSON response from a language server.
" This is called from Lua for integration with Neovim's LSP API.
function! ale#lsp#HandleResponse(conn_id, response) abort
let l:conn = get(s:connections, a:conn_id, {})
if empty(l:conn)
return
endif
for l:Callback in l:conn.callback_list
call ale#util#GetFunction(l:Callback)(a:conn_id, a:response)
endfor
endfunction
" Given a connection ID, mark it as a tsserver connection, so it will be
" handled that way.
function! ale#lsp#MarkConnectionAsTsserver(conn_id) abort
@ -452,6 +494,10 @@ function! s:SendInitMessage(conn) abort
\ 'dynamicRegistration': v:false,
\ 'linkSupport': v:false,
\ },
\ 'diagnostic': {
\ 'dynamicRegistration': v:true,
\ 'relatedDocumentSupport': v:true,
\ },
\ 'publishDiagnostics': {
\ 'relatedInformation': v:true,
\ },
@ -482,6 +528,29 @@ function! ale#lsp#StartProgram(conn_id, executable, command) abort
let l:conn = s:connections[a:conn_id]
let l:started = 0
if g:ale_use_neovim_lsp_api && !l:conn.is_tsserver
" For Windows from 'cmd /s/c "foo bar"' we need 'foo bar'
let l:lsp_cmd = has('win32') && type(a:command) is v:t_string
\ ? ['cmd', '/s/c/', a:command[10:-2]]
\ : a:command
" Always call lsp.start, which will either create or re-use a
" connection. We'll set `attach` to `false` so we can later use
" our OpenDocument function to attach the buffer separately.
let l:client_id = luaeval('require("ale.lsp").start(_A)', {
\ 'name': a:conn_id,
\ 'cmd': l:lsp_cmd,
\ 'root_dir': l:conn.root,
\ 'init_options': l:conn.init_options,
\})
if l:client_id > 0
let l:conn.client_id = l:client_id
endif
return l:client_id > 0
endif
if !has_key(l:conn, 'job_id') || !ale#job#HasOpenChannel(l:conn.job_id)
let l:options = {
\ 'mode': 'raw',
@ -512,6 +581,21 @@ function! ale#lsp#StartProgram(conn_id, executable, command) abort
return l:job_id > 0
endfunction
" Split an address into [host, port].
" The port will either be a number or v:null.
function! ale#lsp#SplitAddress(address) abort
let l:port_match = matchlist(a:address, '\v:(\d+)$')
if !empty(l:port_match)
let l:host = a:address[:-len(l:port_match[1]) - 2]
let l:port = l:port_match[1] + 0
return [l:host, l:port ? l:port : v:null]
endif
return [a:address, v:null]
endfunction
" Connect to an LSP server via TCP.
"
" 1 will be returned if the connection is running, or 0 if the connection could
@ -520,7 +604,23 @@ function! ale#lsp#ConnectToAddress(conn_id, address) abort
let l:conn = s:connections[a:conn_id]
let l:started = 0
if !has_key(l:conn, 'channel_id') || !ale#socket#IsOpen(l:conn.channel_id)
if g:ale_use_neovim_lsp_api && !l:conn.is_tsserver
let [l:host, l:port] = ale#lsp#SplitAddress(a:address)
let l:client_id = luaeval('require("ale.lsp").start(_A)', {
\ 'name': a:conn_id,
\ 'host': l:host,
\ 'port': l:port,
\ 'root_dir': l:conn.root,
\ 'init_options': l:conn.init_options,
\})
if l:client_id > 0
let l:conn.client_id = l:client_id
endif
return l:client_id > 0
elseif !has_key(l:conn, 'channel_id') || !ale#socket#IsOpen(l:conn.channel_id)
let l:channel_id = ale#socket#Open(a:address, {
\ 'callback': {_, mess -> ale#lsp#HandleMessage(a:conn_id, mess)},
\})
@ -606,26 +706,53 @@ function! ale#lsp#Send(conn_id, message) abort
throw 'LSP server not initialized yet!'
endif
if g:ale_use_neovim_lsp_api && !l:conn.is_tsserver
return luaeval('require("ale.lsp").send_message(_A)', {
\ 'client_id': l:conn.client_id,
\ 'is_notification': a:message[0] == 1 ? v:true : v:false,
\ 'method': a:message[1],
\ 'params': get(a:message, 2, v:null)
\})
endif
let [l:id, l:data] = ale#lsp#CreateMessageData(a:message)
call s:SendMessageData(l:conn, l:data)
return l:id == 0 ? -1 : l:id
endfunction
function! ale#lsp#GetLanguage(conn_id, buffer) abort
let l:conn = get(s:connections, a:conn_id, {})
let l:Language = get(l:conn, 'language')
if empty(l:Language)
return getbufvar(a:buffer, '&filetype')
endif
return type(l:Language) is v:t_func ? l:Language(a:buffer) : l:Language
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(conn_id, buffer, language_id) abort
function! ale#lsp#OpenDocument(conn_id, buffer) abort
let l:conn = get(s:connections, a:conn_id, {})
let l:opened = 0
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)
call ale#lsp#Send(a:conn_id, l:message)
elseif g:ale_use_neovim_lsp_api
call luaeval('require("ale.lsp").buf_attach(_A)', {
\ 'bufnr': a:buffer,
\ 'client_id': l:conn.client_id,
\})
else
let l:message = ale#lsp#message#DidOpen(a:buffer, a:language_id)
let l:language_id = ale#lsp#GetLanguage(a:conn_id, a:buffer)
let l:message = ale#lsp#message#DidOpen(a:buffer, l:language_id)
call ale#lsp#Send(a:conn_id, l:message)
endif
call ale#lsp#Send(a:conn_id, l:message)
let l:conn.open_documents[a:buffer] = getbufvar(a:buffer, 'changedtick')
let l:opened = 1
endif
@ -649,11 +776,17 @@ function! ale#lsp#CloseDocument(buffer) abort
if l:conn.initialized && has_key(l:conn.open_documents, a:buffer)
if l:conn.is_tsserver
let l:message = ale#lsp#tsserver_message#Close(a:buffer)
call ale#lsp#Send(l:conn_id, l:message)
elseif g:ale_use_neovim_lsp_api
call luaeval('require("ale.lsp").buf_detach(_A)', {
\ 'bufnr': a:buffer,
\ 'client_id': l:conn.client_id,
\})
else
let l:message = ale#lsp#message#DidClose(a:buffer)
call ale#lsp#Send(l:conn_id, l:message)
endif
call ale#lsp#Send(l:conn_id, l:message)
call remove(l:conn.open_documents, a:buffer)
let l:closed = 1
endif

View File

@ -200,6 +200,14 @@ function! ale#lsp#message#CodeAction(buffer, line, column, end_line, end_column,
\}]
endfunction
function! ale#lsp#message#Diagnostic(buffer) abort
return [0, 'textDocument/diagnostic', {
\ 'textDocument': {
\ 'uri': ale#util#ToURI(expand('#' . a:buffer . ':p')),
\ },
\}]
endfunction
function! ale#lsp#message#ExecuteCommand(command, arguments) abort
return [0, 'workspace/executeCommand', {
\ 'command': a:command,

View File

@ -21,11 +21,11 @@ let s:SEVERITY_WARNING = 2
let s:SEVERITY_INFORMATION = 3
let s:SEVERITY_HINT = 4
" Parse the message for textDocument/publishDiagnostics
function! ale#lsp#response#ReadDiagnostics(response) abort
" Convert Diagnostic[] data from a language server to an ALE loclist.
function! ale#lsp#response#ReadDiagnostics(diagnostics) abort
let l:loclist = []
for l:diagnostic in a:response.params.diagnostics
for l:diagnostic in a:diagnostics
let l:severity = get(l:diagnostic, 'severity', 0)
let l:loclist_item = {
\ 'text': substitute(l:diagnostic.message, '\(\r\n\|\n\|\r\)', ' ', 'g'),

View File

@ -23,6 +23,26 @@ function! ale#lsp_linter#SetLSPLinterMap(replacement_map) abort
let s:lsp_linter_map = a:replacement_map
endfunction
" A map for tracking URIs for diagnostic request IDs
if !has_key(s:, 'diagnostic_uri_map')
let s:diagnostic_uri_map = {}
endif
" For internal use only.
function! ale#lsp_linter#ClearDiagnosticURIMap() abort
let s:diagnostic_uri_map = {}
endfunction
" For internal use only.
function! ale#lsp_linter#GetDiagnosticURIMap() abort
return s:diagnostic_uri_map
endfunction
" Just for tests.
function! ale#lsp_linter#SetDiagnosticURIMap(replacement_map) abort
let s:diagnostic_uri_map = a:replacement_map
endfunction
" Get all enabled LSP linters.
" This list still includes linters ignored with `ale_linters_ignore`.
"
@ -77,14 +97,17 @@ function! s:ShouldIgnoreDiagnostics(buffer, linter) abort
return 0
endfunction
function! s:HandleLSPDiagnostics(conn_id, response) abort
" Handle LSP diagnostics for a given URI.
" The special value 'unchanged' can be used for diagnostics to indicate
" that diagnostics haven't changed since we last checked.
function! ale#lsp_linter#HandleLSPDiagnostics(conn_id, uri, diagnostics) abort
let l:linter = get(s:lsp_linter_map, a:conn_id)
if empty(l:linter)
return
endif
let l:filename = ale#util#ToResource(a:response.params.uri)
let l:filename = ale#util#ToResource(a:uri)
let l:escaped_name = escape(
\ fnameescape(l:filename),
\ has('win32') ? '^' : '^,}]'
@ -100,9 +123,12 @@ function! s:HandleLSPDiagnostics(conn_id, response) abort
return
endif
let l:loclist = ale#lsp#response#ReadDiagnostics(a:response)
if a:diagnostics is# 'unchanged'
call ale#engine#MarkLinterInactive(l:info, l:linter)
else
let l:loclist = ale#lsp#response#ReadDiagnostics(a:diagnostics)
call ale#engine#HandleLoclist(l:linter.name, l:buffer, l:loclist, 0)
endif
endfunction
function! s:HandleTSServerDiagnostics(response, error_type) abort
@ -204,7 +230,17 @@ function! ale#lsp_linter#HandleLSPResponse(conn_id, response) abort
call s:HandleLSPErrorMessage(l:linter, a:response)
elseif l:method is# 'textDocument/publishDiagnostics'
call s:HandleLSPDiagnostics(a:conn_id, a:response)
let l:uri = a:response.params.uri
let l:diagnostics = a:response.params.diagnostics
call ale#lsp_linter#HandleLSPDiagnostics(a:conn_id, l:uri, l:diagnostics)
elseif has_key(s:diagnostic_uri_map, get(a:response, 'id'))
let l:uri = remove(s:diagnostic_uri_map, a:response.id)
let l:diagnostics = a:response.result.kind is# 'unchanged'
\ ? 'unchanged'
\ : a:response.result.items
call ale#lsp_linter#HandleLSPDiagnostics(a:conn_id, l:uri, l:diagnostics)
elseif l:method is# 'window/showMessage'
call ale#lsp_window#HandleShowMessage(
\ s:lsp_linter_map[a:conn_id].name,
@ -219,7 +255,7 @@ function! ale#lsp_linter#HandleLSPResponse(conn_id, response) abort
call s:HandleTSServerDiagnostics(a:response, 'syntax')
elseif get(a:response, 'type', '') is# 'event'
\&& get(a:response, 'event', '') is# 'suggestionDiag'
\&& get(g:, 'ale_lsp_suggestions', '1') == 1
\&& get(g:, 'ale_lsp_suggestions')
call s:HandleTSServerDiagnostics(a:response, 'suggestion')
endif
endfunction
@ -306,11 +342,10 @@ function! ale#lsp_linter#OnInit(linter, details, Callback) abort
let l:command = a:details.command
let l:config = ale#lsp_linter#GetConfig(l:buffer, a:linter)
let l:language_id = ale#linter#GetLanguage(l:buffer, a:linter)
call ale#lsp#UpdateConfig(l:conn_id, l:buffer, l:config)
if ale#lsp#OpenDocument(l:conn_id, l:buffer, l:language_id)
if ale#lsp#OpenDocument(l:conn_id, l:buffer)
if g:ale_history_enabled && !empty(l:command)
call ale#history#Add(l:buffer, 'started', l:conn_id, l:command)
endif
@ -357,11 +392,21 @@ function! s:StartLSP(options, address, executable, command) abort
let l:init_options = ale#lsp_linter#GetOptions(l:buffer, l:linter)
if l:linter.lsp is# 'socket'
let l:conn_id = ale#lsp#Register(a:address, l:root, l:init_options)
let l:conn_id = ale#lsp#Register(
\ a:address,
\ l:root,
\ l:linter.language,
\ l:init_options
\)
let l:ready = ale#lsp#ConnectToAddress(l:conn_id, a:address)
let l:command = ''
else
let l:conn_id = ale#lsp#Register(a:executable, l:root, l:init_options)
let l:conn_id = ale#lsp#Register(
\ a:executable,
\ l:root,
\ l:linter.language,
\ l:init_options
\)
" tsserver behaves differently, so tell the LSP API that it is tsserver.
if l:linter.lsp is# 'tsserver'
@ -511,18 +556,34 @@ function! s:CheckWithLSP(linter, details) abort
if l:notified
call ale#engine#MarkLinterActive(l:info, a:linter)
endif
else
elseif !g:ale_use_neovim_lsp_api
let l:notified = ale#lsp#NotifyForChanges(l:id, l:buffer)
endif
" If this was a file save event, also notify the server of that.
if a:linter.lsp isnot# 'tsserver'
\&& getbufvar(l:buffer, 'ale_save_event_fired', 0)
if getbufvar(l:buffer, 'ale_save_event_fired', 0)
\&& ale#lsp#HasCapability(l:id, 'did_save')
let l:include_text = ale#lsp#HasCapability(l:id, 'includeText')
let l:save_message = ale#lsp#message#DidSave(l:buffer, l:include_text)
let l:notified = ale#lsp#Send(l:id, l:save_message) != 0
endif
let l:diagnostic_request_id = 0
" If the document is updated and we can pull diagnostics, try to.
if ale#lsp#HasCapability(l:id, 'pull_model')
let l:diagnostic_message = ale#lsp#message#Diagnostic(l:buffer)
let l:diagnostic_request_id = ale#lsp#Send(l:id, l:diagnostic_message)
endif
" If we are going to pull diagnostics, then mark the linter as active,
" and remember the URI we sent the request for.
if l:diagnostic_request_id
call ale#engine#MarkLinterActive(l:info, a:linter)
let s:diagnostic_uri_map[l:diagnostic_request_id] =
\ l:diagnostic_message[2].textDocument.uri
endif
endif
endfunction
function! ale#lsp_linter#CheckWithLSP(buffer, linter) abort

View File

@ -4,6 +4,7 @@
" Find project root for a Lua language server.
function! ale#lua#FindProjectRoot(buffer) abort
let l:possible_project_roots = [
\ '.luarc.json',
\ '.git',
\ bufname(a:buffer),
\]

View File

@ -124,11 +124,16 @@ function! ale#path#IsAbsolute(filename) abort
endfunction
let s:temp_dir = ale#path#Simplify(fnamemodify(ale#util#Tempname(), ':h:h'))
let s:resolved_temp_dir = resolve(s:temp_dir)
" Given a filename, return 1 if the file represents some temporary file
" created by Vim.
" created by Vim. If the temporary location is symlinked (e.g. macOS), some
" linters may report the resolved version of the path, so both are checked.
function! ale#path#IsTempName(filename) abort
return ale#path#Simplify(a:filename)[:len(s:temp_dir) - 1] is# s:temp_dir
let l:filename = ale#path#Simplify(a:filename)
return l:filename[:len(s:temp_dir) - 1] is# s:temp_dir
\|| l:filename[:len(s:resolved_temp_dir) - 1] is# s:resolved_temp_dir
endfunction
" Given a base directory, which must not have a trailing slash, and a

View File

@ -108,12 +108,17 @@ function! ale#python#AutoVirtualenvEnvString(buffer) abort
if !empty(l:venv_dir)
let l:strs = [ ]
" venv/bin directory
let l:pathdir = join([l:venv_dir, s:bin_dir], s:sep)
" expand PATH correctly inside of the appropriate shell.
" set VIRTUAL_ENV to point to venv
if has('win32')
call add(l:strs, 'set PATH=' . ale#Escape(l:venv_dir) . ';%PATH% && ')
call add(l:strs, 'set PATH=' . ale#Escape(l:pathdir) . ';%PATH% && ')
call add(l:strs, 'set VIRTUAL_ENV=' . ale#Escape(l:venv_dir) . ' && ')
else
call add(l:strs, 'PATH=' . ale#Escape(l:venv_dir) . '":$PATH" ')
call add(l:strs, 'PATH=' . ale#Escape(l:pathdir) . '":$PATH" ')
call add(l:strs, 'VIRTUAL_ENV=' . ale#Escape(l:venv_dir) . ' ')
endif
return join(l:strs, '')

View File

@ -17,18 +17,21 @@ function! ale#references#ClearLSPData() abort
endfunction
function! ale#references#FormatTSResponseItem(response_item, options) abort
let l:match = substitute(a:response_item.lineText, '^\s*\(.\{-}\)\s*$', '\1', '')
if get(a:options, 'open_in') is# 'quickfix'
return {
\ 'filename': a:response_item.file,
\ 'lnum': a:response_item.start.line,
\ 'col': a:response_item.start.offset,
\ 'text': l:match,
\}
else
return {
\ 'filename': a:response_item.file,
\ 'line': a:response_item.start.line,
\ 'column': a:response_item.start.offset,
\ 'match': substitute(a:response_item.lineText, '^\s*\(.\{-}\)\s*$', '\1', ''),
\ 'match': l:match,
\}
endif
endfunction

View File

@ -17,8 +17,8 @@ function! ale#rename#ClearLSPData() abort
let s:rename_map = {}
endfunction
let g:ale_rename_tsserver_find_in_comments = get(g:, 'ale_rename_tsserver_find_in_comments')
let g:ale_rename_tsserver_find_in_strings = get(g:, 'ale_rename_tsserver_find_in_strings')
let g:ale_rename_tsserver_find_in_comments = get(g:, 'ale_rename_tsserver_find_in_comments', v:false)
let g:ale_rename_tsserver_find_in_strings = get(g:, 'ale_rename_tsserver_find_in_strings', v:false)
function! s:message(message) abort
call ale#util#Execute('echom ' . string(a:message))

Some files were not shown because too many files have changed in this diff Show More