mirror of
1
0
Fork 0

Merge branch 'master' of git://github.com/amix/vimrc into amix-master

This commit is contained in:
emmanueldiaz 2021-09-19 23:04:47 -05:00
commit 5a67ab85bb
524 changed files with 22474 additions and 5437 deletions

View File

@ -31,7 +31,7 @@ Naturally, `/opt/vim_runtime` can be any directory, as long as all the users spe
## Fonts
I recommend using [IBM Plex Mono font](https://github.com/IBM/plex) (it's an open-source and awesome font that can make your code beautiful). The Awesome vimrc is already setup to try to use it.
I recommend using [IBM Plex Mono font](https://github.com/IBM/plex) (it's an open-source and awesome font that can make your code look beautiful). The Awesome vimrc is already setup to try to use it.
Some other fonts that Awesome will try to use:
@ -63,9 +63,14 @@ If you have vim aliased as `vi` instead of `vim`, make sure to either alias it:
Just do a git rebase!
cd ~/.vim_runtime
git reset --hard
git clean -d --force
git pull --rebase
python update_plugins.py
python update_plugins.py # use python3 if python is unavailable
NOTE: If you get `ModuleNotFoundError: No module named 'requests'`, you must first install the `requests` python module using `pip`, `pip3`, or `easy_install`.
pip install requests
## Some screenshots
@ -102,11 +107,14 @@ I recommend reading the docs of these plugins to understand them better. Each pl
* [vim-yankstack](https://github.com/maxbrunsfeld/vim-yankstack): Maintains a history of previous yanks, changes and deletes
* [vim-zenroom2](https://github.com/amix/vim-zenroom2) Remove all clutter and focus only on the essential. Similar to iA Writer or Write Room
* [gist-vim](https://github.com/mattn/gist-vim) Easily create gists from Vim using the `:Gist` command
* [vim-indent-guides](https://github.com/nathanaelkane/vim-indent-guides) Is a plugin for visually displaying indent levels in Vim
* [editorconfig-vim](https://github.com/editorconfig/editorconfig-vim) EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs.
## Included color schemes
* [peaksea](https://github.com/vim-scripts/peaksea): The default
* [dracula](https://github.com/dracula/vim)
* [vim-colors-solarized](https://github.com/altercation/vim-colors-solarized)
* [vim-irblack](https://github.com/wgibbs/vim-irblack)
* [mayansmoke](https://github.com/vim-scripts/mayansmoke)
@ -140,6 +148,13 @@ You can also install your plugins, for instance, via pathogen you can install [v
cd ~/.vim_runtime
git clone git://github.com/tpope/vim-rails.git my_plugins/vim-rails
You can also install plugins without any plugin manager (vim 8+ required):
Add `packloadall` to your .vimrc file
Create pack plugin directory:
`mkdir -p ~/.vim/pack/plugins/start`
Clone the plugin that you want in that directory, for example:
`git clone --depth=1 git://github.com/maxmellon/vim-jsx-pretty ~/.vim/pack/plugins/vim-jsx-pretty`
## Key Mappings
@ -330,6 +345,13 @@ Open [ctrlp.vim](https://github.com/kien/ctrlp.vim) plugin to quickly find a fil
nmap <silent> <leader>a <Plug>(ale_next_wrap)
[vim-indent-guides](https://github.com/nathanaelkane/vim-indent-guides) the default mapping to toggle the plugin is (`<leader>ig`)
You can also use the following commands inside Vim:
:IndentGuidesEnable
:IndentGuidesDisable
:IndentGuidesToggle
### Spell checking
Pressing `<leader>ss` will toggle spell checking:
@ -343,6 +365,13 @@ Shortcuts using `<leader>` instead of special characters:
map <leader>sa zg
map <leader>s? z=
### Running Code
To run code directly from vim, press `F5`. The currently open code will execute without you having to type anything.
Can be used to execute code written in C, C++, Java, Python, Go, Octave, Bash scripts and HTML. To edit how you want your code to be executed, make changes in the file
```
~/vim_runtime/vimrcs/extended.vim
```
### Cope
Query `:help cope` if you are unsure what cope is. It's super useful!
@ -375,3 +404,4 @@ Just do following:
Maintaining this Vim configuration isn't my day job. Daily I am the founder/CEO of [Doist](https://doist.com/). You could come and help us build the workplace of the future while living a balanced life (anywhere in the world 🌍🌎🌏).
PS: Using Vim isn't a requirement 😄

View File

@ -4,7 +4,10 @@ set -e
echo 'Installing Awesome Vim from '$1
cd $1
VIMRC="set runtimepath+=$1
VIMRC="\" DO NOT EDIT THIS FILE
\" Add your own customizations in $1/my_configs.vim
set runtimepath+=$1
source $1/vimrcs/basic.vim
source $1/vimrcs/filetypes.vim
@ -12,7 +15,7 @@ source $1/vimrcs/plugins_config.vim
source $1/vimrcs/extended.vim
try
source $1/my_configs.vim
source $1/my_configs.vim
catch
endtry"

View File

@ -3,15 +3,17 @@ set -e
cd ~/.vim_runtime
echo 'set runtimepath+=~/.vim_runtime
echo '" DO NOT EDIT THIS FILE
" Add your own customizations in ~/.vim_runtime/my_configs.vim
set runtimepath+=~/.vim_runtime
source ~/.vim_runtime/vimrcs/basic.vim
source ~/.vim_runtime/vimrcs/filetypes.vim
source ~/.vim_runtime/vimrcs/plugins_config.vim
source ~/.vim_runtime/vimrcs/extended.vim
try
source ~/.vim_runtime/my_configs.vim
source ~/.vim_runtime/my_configs.vim
catch
endtry' > ~/.vimrc

View File

@ -0,0 +1,26 @@
" Author: Bartek Jasicki http://github.com/thindil
" Description: Support for Ada Language Server
call ale#Set('ada_adals_executable', 'ada_language_server')
call ale#Set('ada_adals_project', 'default.gpr')
call ale#Set('ada_adals_encoding', 'utf-8')
function! ale_linters#ada#adals#GetAdaLSConfig(buffer) abort
return {
\ 'ada.projectFile': ale#Var(a:buffer, 'ada_adals_project'),
\ 'ada.defaultCharset': ale#Var(a:buffer, 'ada_adals_encoding')
\}
endfunction
function! ale_linters#ada#adals#GetRootDirectory(buffer) abort
return fnamemodify(bufname(a:buffer), ':p:h')
endfunction
call ale#linter#Define('ada', {
\ 'name': 'adals',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'ada_adals_executable')},
\ 'command': '%e',
\ 'project_root': function('ale_linters#ada#adals#GetRootDirectory'),
\ 'lsp_config': function('ale_linters#ada#adals#GetAdaLSConfig')
\})

View File

@ -1,4 +1,4 @@
" Author: Bjorn Neergaard <bjorn@neersighted.com>
" Authors: Bjorn Neergaard <bjorn@neersighted.com>, Vytautas Macionis <vytautas.macionis@manomail.de>
" Description: ansible-lint for ansible-yaml files
call ale#Set('ansible_ansible_lint_executable', 'ansible-lint')
@ -7,7 +7,7 @@ function! ale_linters#ansible#ansible_lint#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'ansible_ansible_lint_executable')
endfunction
function! ale_linters#ansible#ansible_lint#Handle(buffer, lines) abort
function! ale_linters#ansible#ansible_lint#Handle(buffer, version, lines) abort
for l:line in a:lines[:10]
if match(l:line, '^Traceback') >= 0
return [{
@ -18,39 +18,87 @@ function! ale_linters#ansible#ansible_lint#Handle(buffer, lines) abort
endif
endfor
" Matches patterns line the following:
"
" test.yml:35: [EANSIBLE0002] Trailing whitespace
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?: \[?([[:alnum:]]+)\]? (.*)$'
let l:version_group = ale#semver#GTE(a:version, [5, 0, 0]) ? '>=5.0.0' : '<5.0.0'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:code = l:match[4]
if '>=5.0.0' is# l:version_group
" Matches patterns line the following:
" test.yml:3:148: syntax-check 'var' is not a valid attribute for a Play
" roles/test/tasks/test.yml:8: [package-latest] [VERY_LOW] Package installs should not use latest
" D:\test\tasks\test.yml:8: [package-latest] [VERY_LOW] package installs should not use latest
let l:pattern = '\v^(%([a-zA-Z]:)?[^:]+):(\d+):%((\d+):)? %(\[([-[:alnum:]]+)\]) %(\[([_[:alnum:]]+)\]) (.*)$'
let l:error_codes = { 'VERY_HIGH': 'E', 'HIGH': 'E', 'MEDIUM': 'W', 'LOW': 'W', 'VERY_LOW': 'W', 'INFO': 'I' }
if l:code is# 'EANSIBLE0002'
\&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
for l:match in ale#util#GetMatches(a:lines, l:pattern)
if ale#path#IsBufferPath(a:buffer, l:match[1])
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'text': l:match[6],
\ 'code': l:match[4],
\ 'type': l:error_codes[l:match[5]],
\})
endif
endfor
endif
if ale#path#IsBufferPath(a:buffer, l:match[1])
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'text': l:match[5],
\ 'code': l:code,
\ 'type': l:code[:0] is# 'E' ? 'E' : 'W',
\})
endif
endfor
if '<5.0.0' is# l:version_group
" Matches patterns line the following:
" test.yml:35: [EANSIBLE0002] Trailing whitespace
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?: \[?([[:alnum:]]+)\]? (.*)$'
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:code = l:match[4]
if l:code is# 'EANSIBLE0002'
\&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
if ale#path#IsBufferPath(a:buffer, l:match[1])
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'text': l:match[5],
\ 'code': l:code,
\ 'type': l:code[:0] is# 'E' ? 'E' : 'W',
\})
endif
endfor
endif
return l:output
endfunction
function! ale_linters#ansible#ansible_lint#GetCommand(buffer, version) abort
let l:commands = {
\ '>=5.0.0': '%e --nocolor --parseable-severity -x yaml %s',
\ '<5.0.0': '%e --nocolor -p %t'
\}
let l:command = ale#semver#GTE(a:version, [5, 0]) ? l:commands['>=5.0.0'] : l:commands['<5.0.0']
return l:command
endfunction
call ale#linter#Define('ansible', {
\ 'name': 'ansible_lint',
\ 'aliases': ['ansible', 'ansible-lint'],
\ 'executable': function('ale_linters#ansible#ansible_lint#GetExecutable'),
\ 'command': '%e -p %t',
\ 'callback': 'ale_linters#ansible#ansible_lint#Handle',
\ 'command': {buffer -> ale#semver#RunWithVersionCheck(
\ buffer,
\ ale_linters#ansible#ansible_lint#GetExecutable(buffer),
\ '%e --version',
\ function('ale_linters#ansible#ansible_lint#GetCommand'),
\ )},
\ 'lint_file': 1,
\ 'callback': {buffer, lines -> ale#semver#RunWithVersionCheck(
\ buffer,
\ ale_linters#ansible#ansible_lint#GetExecutable(buffer),
\ '%e --version',
\ {buffer, version -> ale_linters#ansible#ansible_lint#Handle(
\ buffer,
\ l:version,
\ lines)},
\ )},
\})

View File

@ -0,0 +1,12 @@
" Author: Leo <thinkabit.ukim@gmail.com>
" Description: apkbuild-lint from atools linter for APKBUILDs
call ale#Set('apkbuild_apkbuild_lint_executable', 'apkbuild-lint')
call ale#linter#Define('apkbuild', {
\ 'name': 'apkbuild_lint',
\ 'output_stream': 'stdout',
\ 'executable': {b -> ale#Var(b, 'apkbuild_apkbuild_lint_executable')},
\ 'command': '%e %t',
\ 'callback': 'ale#handlers#atools#Handle',
\})

View File

@ -0,0 +1,12 @@
" Author: Leo <thinkabit.ukim@gmail.com>
" Description: secfixes-check from atools linter for APKBUILDs
call ale#Set('apkbuild_secfixes_check_executable', 'secfixes-check')
call ale#linter#Define('apkbuild', {
\ 'name': 'secfixes_check',
\ 'output_stream': 'stdout',
\ 'executable': {b -> ale#Var(b, 'apkbuild_secfixes_check_executable')},
\ 'command': '%e %t',
\ 'callback': 'ale#handlers#atools#Handle',
\})

View File

@ -5,15 +5,13 @@ call ale#Set('c_cppcheck_executable', 'cppcheck')
call ale#Set('c_cppcheck_options', '--enable=style')
function! ale_linters#c#cppcheck#GetCommand(buffer) abort
let l:cd_command = ale#handlers#cppcheck#GetCdCommand(a:buffer)
let l:compile_commands_option = ale#handlers#cppcheck#GetCompileCommandsOptions(a:buffer)
let l:buffer_path_include = empty(l:compile_commands_option)
\ ? ale#handlers#cppcheck#GetBufferPathIncludeOptions(a:buffer)
\ : ''
let l:template = ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
let l:template = ' --template=' . ale#Escape('{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}')
return l:cd_command
\ . '%e -q --language=c'
return '%e -q --language=c'
\ . l:template
\ . ale#Pad(l:compile_commands_option)
\ . ale#Pad(ale#Var(a:buffer, 'c_cppcheck_options'))
@ -25,6 +23,7 @@ call ale#linter#Define('c', {
\ 'name': 'cppcheck',
\ 'output_stream': 'both',
\ 'executable': {b -> ale#Var(b, 'c_cppcheck_executable')},
\ 'cwd': function('ale#handlers#cppcheck#GetCwd'),
\ 'command': function('ale_linters#c#cppcheck#GetCommand'),
\ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat',
\})

View File

@ -1,6 +1,18 @@
" Author: Masashi Iizuka <liquidz.uo@gmail.com>
" Description: linter for clojure using clj-kondo https://github.com/borkdude/clj-kondo
call ale#Set('clojure_clj_kondo_options', '--cache')
function! ale_linters#clojure#clj_kondo#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'clojure_clj_kondo_options')
let l:command = 'clj-kondo'
\ . ale#Pad(l:options)
\ . ' --lint %t'
return l:command
endfunction
function! ale_linters#clojure#clj_kondo#HandleCljKondoFormat(buffer, lines) abort
" output format
" <filename>:<line>:<column>: <issue type>: <message>
@ -29,6 +41,6 @@ call ale#linter#Define('clojure', {
\ 'name': 'clj-kondo',
\ 'output_stream': 'stdout',
\ 'executable': 'clj-kondo',
\ 'command': 'clj-kondo --cache --lint %t',
\ 'command': function('ale_linters#clojure#clj_kondo#GetCommand'),
\ 'callback': 'ale_linters#clojure#clj_kondo#HandleCljKondoFormat',
\})

View File

@ -29,6 +29,7 @@ endfunction
call ale#linter#Define('cloudformation', {
\ 'name': 'cloudformation',
\ 'aliases': ['cfn-lint'],
\ 'executable': 'cfn-lint',
\ 'command': 'cfn-lint --template %t --format parseable',
\ 'callback': 'ale_linters#cloudformation#cfn_python_lint#Handle',

View File

@ -23,11 +23,13 @@ function! ale_linters#cpp#clangtidy#GetCommand(buffer, output) abort
let l:options = ale#Var(a:buffer, 'cpp_clangtidy_options')
let l:cflags = ale#c#GetCFlags(a:buffer, a:output)
let l:options .= !empty(l:options) ? ale#Pad(l:cflags) : l:cflags
endif
" Tell clang-tidy a .h header with a C++ filetype in Vim is a C++ file.
if expand('#' . a:buffer) =~# '\.h$'
let l:options .= !empty(l:options) ? ' -x c++' : '-x c++'
" Tell clang-tidy a .h header with a C++ filetype in Vim is a C++ file
" only when compile-commands.json file is not there. Adding these
" flags makes clang-tidy completely ignore compile commmands.
if expand('#' . a:buffer) =~# '\.h$'
let l:options .= !empty(l:options) ? ' -x c++' : '-x c++'
endif
endif
" Get the options to pass directly to clang-tidy

View File

@ -5,15 +5,13 @@ call ale#Set('cpp_cppcheck_executable', 'cppcheck')
call ale#Set('cpp_cppcheck_options', '--enable=style')
function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort
let l:cd_command = ale#handlers#cppcheck#GetCdCommand(a:buffer)
let l:compile_commands_option = ale#handlers#cppcheck#GetCompileCommandsOptions(a:buffer)
let l:buffer_path_include = empty(l:compile_commands_option)
\ ? ale#handlers#cppcheck#GetBufferPathIncludeOptions(a:buffer)
\ : ''
let l:template = ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
let l:template = ' --template=' . ale#Escape('{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}')
return l:cd_command
\ . '%e -q --language=c++'
return '%e -q --language=c++'
\ . l:template
\ . ale#Pad(l:compile_commands_option)
\ . ale#Pad(ale#Var(a:buffer, 'cpp_cppcheck_options'))
@ -25,6 +23,7 @@ call ale#linter#Define('cpp', {
\ 'name': 'cppcheck',
\ 'output_stream': 'both',
\ 'executable': {b -> ale#Var(b, 'cpp_cppcheck_executable')},
\ 'cwd': function('ale#handlers#cppcheck#GetCwd'),
\ 'command': function('ale_linters#cpp#cppcheck#GetCommand'),
\ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat',
\})

View File

@ -3,14 +3,10 @@ call ale#Set('cs_csc_source', '')
call ale#Set('cs_csc_assembly_path', [])
call ale#Set('cs_csc_assemblies', [])
function! s:GetWorkingDirectory(buffer) abort
let l:working_directory = ale#Var(a:buffer, 'cs_csc_source')
function! ale_linters#cs#csc#GetCwd(buffer) abort
let l:cwd = ale#Var(a:buffer, 'cs_csc_source')
if !empty(l:working_directory)
return l:working_directory
endif
return expand('#' . a:buffer . ':p:h')
return !empty(l:cwd) ? l:cwd : expand('#' . a:buffer . ':p:h')
endfunction
function! ale_linters#cs#csc#GetCommand(buffer) abort
@ -34,8 +30,7 @@ function! ale_linters#cs#csc#GetCommand(buffer) abort
" The code is compiled as a module and the output is redirected to a
" temporary file.
return ale#path#CdString(s:GetWorkingDirectory(a:buffer))
\ . 'csc /unsafe'
return 'csc /unsafe'
\ . ale#Pad(ale#Var(a:buffer, 'cs_csc_options'))
\ . ale#Pad(l:lib_option)
\ . ale#Pad(l:r_option)
@ -57,8 +52,7 @@ function! ale_linters#cs#csc#Handle(buffer, lines) abort
\ '^\v([^ ]+)\s+([Cc][sS][^ ]+):\s+(.+)$',
\]
let l:output = []
let l:dir = s:GetWorkingDirectory(a:buffer)
let l:dir = ale_linters#cs#csc#GetCwd(a:buffer)
for l:match in ale#util#GetMatches(a:lines, l:patterns)
if len(l:match) > 6 && strlen(l:match[5]) > 2 && l:match[5][:1] is? 'CS'
@ -89,6 +83,7 @@ call ale#linter#Define('cs',{
\ 'name': 'csc',
\ 'output_stream': 'stdout',
\ 'executable': 'csc',
\ 'cwd': function('ale_linters#cs#csc#GetCwd'),
\ 'command': function('ale_linters#cs#csc#GetCommand'),
\ 'callback': 'ale_linters#cs#csc#Handle',
\ 'lint_file': 1

View File

@ -3,14 +3,10 @@ call ale#Set('cs_mcsc_source', '')
call ale#Set('cs_mcsc_assembly_path', [])
call ale#Set('cs_mcsc_assemblies', [])
function! s:GetWorkingDirectory(buffer) abort
let l:working_directory = ale#Var(a:buffer, 'cs_mcsc_source')
function! ale_linters#cs#mcsc#GetCwd(buffer) abort
let l:cwd = ale#Var(a:buffer, 'cs_mcsc_source')
if !empty(l:working_directory)
return l:working_directory
endif
return expand('#' . a:buffer . ':p:h')
return !empty(l:cwd) ? l:cwd : expand('#' . a:buffer . ':p:h')
endfunction
function! ale_linters#cs#mcsc#GetCommand(buffer) abort
@ -34,8 +30,7 @@ function! ale_linters#cs#mcsc#GetCommand(buffer) abort
" The code is compiled as a module and the output is redirected to a
" temporary file.
return ale#path#CdString(s:GetWorkingDirectory(a:buffer))
\ . 'mcs -unsafe'
return 'mcs -unsafe'
\ . ale#Pad(ale#Var(a:buffer, 'cs_mcsc_options'))
\ . ale#Pad(l:lib_option)
\ . ale#Pad(l:r_option)
@ -58,7 +53,7 @@ function! ale_linters#cs#mcsc#Handle(buffer, lines) abort
\]
let l:output = []
let l:dir = s:GetWorkingDirectory(a:buffer)
let l:dir = ale_linters#cs#mcsc#GetCwd(a:buffer)
for l:match in ale#util#GetMatches(a:lines, l:patterns)
if len(l:match) > 6 && strlen(l:match[5]) > 2 && l:match[5][:1] is? 'CS'
@ -89,6 +84,7 @@ call ale#linter#Define('cs',{
\ 'name': 'mcsc',
\ 'output_stream': 'stderr',
\ 'executable': 'mcs',
\ 'cwd': function('ale_linters#cs#mcsc#GetCwd'),
\ 'command': function('ale_linters#cs#mcsc#GetCommand'),
\ 'callback': 'ale_linters#cs#mcsc#Handle',
\ 'lint_file': 1

View File

@ -11,7 +11,7 @@ endfunction
call ale#linter#Define('css', {
\ 'name': 'stylelint',
\ 'executable': {b -> ale#node#FindExecutable(b, 'css_stylelint', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'css_stylelint', [
\ 'node_modules/.bin/stylelint',
\ ])},
\ 'command': function('ale_linters#css#stylelint#GetCommand'),

View File

@ -0,0 +1,23 @@
" Author: Tommy Chiang <ty1208chiang@gmail.com>
" Description: Clangd language server for CUDA (modified from Andrey
" Melentyev's implementation for C++)
call ale#Set('cuda_clangd_executable', 'clangd')
call ale#Set('cuda_clangd_options', '')
call ale#Set('c_build_dir', '')
function! ale_linters#cuda#clangd#GetCommand(buffer) abort
let l:build_dir = ale#c#GetBuildDirectory(a:buffer)
return '%e'
\ . ale#Pad(ale#Var(a:buffer, 'cuda_clangd_options'))
\ . (!empty(l:build_dir) ? ' -compile-commands-dir=' . ale#Escape(l:build_dir) : '')
endfunction
call ale#linter#Define('cuda', {
\ 'name': 'clangd',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'cuda_clangd_executable')},
\ 'command': function('ale_linters#cuda#clangd#GetCommand'),
\ 'project_root': function('ale#c#FindProjectRoot'),
\})

View File

@ -1,64 +1,106 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: "dmd for D files"
function! ale_linters#d#dmd#GetDUBCommand(buffer) abort
function! s:GetDUBCommand(buffer) abort
" If we can't run dub, then skip this command.
if !executable('dub')
if executable('dub')
" Returning an empty string skips to the DMD command.
return ''
let l:config = ale#d#FindDUBConfig(a:buffer)
" To support older dub versions, we just change the directory to the
" directory where we found the dub config, and then run `dub describe`
" from that directory.
if !empty(l:config)
return [fnamemodify(l:config, ':h'), 'dub describe --data-list
\ --data=import-paths
\ --data=string-import-paths
\ --data=versions
\ --data=debug-versions
\']
endif
endif
let l:dub_file = ale#d#FindDUBConfig(a:buffer)
if empty(l:dub_file)
return ''
endif
" To support older dub versions, we just change the directory to
" the directory where we found the dub config, and then run `dub describe`
" from that directory.
return 'cd ' . ale#Escape(fnamemodify(l:dub_file, ':h'))
\ . ' && dub describe --import-paths'
return ['', '']
endfunction
function! ale_linters#d#dmd#RunDUBCommand(buffer) abort
let l:command = ale_linters#d#dmd#GetDUBCommand(a:buffer)
let [l:cwd, l:command] = s:GetDUBCommand(a:buffer)
if empty(l:command)
" If we can't run DUB, just run DMD.
return ale_linters#d#dmd#DMDCommand(a:buffer, [], {})
endif
return ale#command#Run(a:buffer, l:command, function('ale_linters#d#dmd#DMDCommand'))
return ale#command#Run(
\ a:buffer,
\ l:command,
\ function('ale_linters#d#dmd#DMDCommand'),
\ {'cwd': l:cwd},
\)
endfunction
function! ale_linters#d#dmd#DMDCommand(buffer, dub_output, meta) abort
let l:import_list = []
let l:str_import_list = []
let l:versions_list = []
let l:deb_versions_list = []
let l:list_ind = 1
let l:seen_line = 0
" Build a list of import paths generated from DUB, if available.
" Build a list of options generated from DUB, if available.
" DUB output each path or version on a single line.
" Each list is separated by a blank line.
" Empty list are represented by a blank line (followed and/or
" preceded by a separation blank line)
for l:line in a:dub_output
" line still has end of line char on windows
let l:line = substitute(l:line, '[\r\n]*$', '', '')
if !empty(l:line)
" The arguments must be '-Ifilename', not '-I filename'
call add(l:import_list, '-I' . ale#Escape(l:line))
if l:list_ind == 1
call add(l:import_list, '-I' . ale#Escape(l:line))
elseif l:list_ind == 2
call add(l:str_import_list, '-J' . ale#Escape(l:line))
elseif l:list_ind == 3
call add(l:versions_list, '-version=' . ale#Escape(l:line))
elseif l:list_ind == 4
call add(l:deb_versions_list, '-debug=' . ale#Escape(l:line))
endif
let l:seen_line = 1
elseif !l:seen_line
" if list is empty must skip one empty line
let l:seen_line = 1
else
let l:seen_line = 0
let l:list_ind += 1
endif
endfor
return 'dmd '. join(l:import_list) . ' -o- -wi -vcolumns -c %t'
return 'dmd ' . join(l:import_list) . ' ' .
\ join(l:str_import_list) . ' ' .
\ join(l:versions_list) . ' ' .
\ join(l:deb_versions_list) . ' -o- -wi -vcolumns -c %t'
endfunction
function! ale_linters#d#dmd#Handle(buffer, lines) abort
" Matches patterns lines like the following:
" /tmp/tmp.qclsa7qLP7/file.d(1): Error: function declaration without return type. (Note that constructors are always named 'this')
" /tmp/tmp.G1L5xIizvB.d(8,8): Error: module weak_reference is in file 'dstruct/weak_reference.d' which cannot be read
let l:pattern = '^[^(]\+(\([0-9]\+\)\,\?\([0-9]*\)): \([^:]\+\): \(.\+\)'
let l:pattern = '\v^(\f+)\((\d+)(,(\d+))?\): (\w+): (.+)$'
let l:output = []
let l:dir = expand('#' . a:buffer . ':p:h')
for l:match in ale#util#GetMatches(a:lines, l:pattern)
" If dmd was invoked with relative path, match[1] is relative, otherwise it is absolute.
" As we invoke dmd with the buffer path (in /tmp), this will generally be absolute already
let l:fname = ale#path#GetAbsPath(l:dir, l:match[1])
call add(l:output, {
\ 'lnum': l:match[1],
\ 'col': l:match[2],
\ 'type': l:match[3] is# 'Warning' ? 'W' : 'E',
\ 'text': l:match[4],
\ 'filename': l:fname,
\ 'lnum': l:match[2],
\ 'col': l:match[4],
\ 'type': l:match[5] is# 'Warning' || l:match[5] is# 'Deprecation' ? 'W' : 'E',
\ 'text': l:match[6],
\})
endfor

View File

@ -6,7 +6,7 @@ function! ale_linters#dafny#dafny#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'filename': l:match[1],
\ 'col': l:match[3] + 0,
\ 'lnum': l:match[2] + 0,
\ 'text': l:match[5],
@ -14,13 +14,28 @@ function! ale_linters#dafny#dafny#Handle(buffer, lines) abort
\ })
endfor
for l:match in ale#util#GetMatches(a:lines, '\v(.*)\((\d+),(\d+)\): (Verification of .{-} timed out after \d+ seconds)')
call add(l:output, {
\ 'filename': l:match[1],
\ 'col': l:match[3] + 0,
\ 'lnum': l:match[2] + 0,
\ 'text': l:match[4],
\ 'type': 'E',
\ })
endfor
return l:output
endfunction
function! ale_linters#dafny#dafny#GetCommand(buffer) abort
return printf('dafny %%s /compile:0 /timeLimit:%d', ale#Var(a:buffer, 'dafny_dafny_timelimit'))
endfunction
call ale#Set('dafny_dafny_timelimit', 10)
call ale#linter#Define('dafny', {
\ 'name': 'dafny',
\ 'executable': 'dafny',
\ 'command': 'dafny %s /compile:0',
\ 'command': function('ale_linters#dafny#dafny#GetCommand'),
\ 'callback': 'ale_linters#dafny#dafny#Handle',
\ 'lint_file': 1,
\ })

View File

@ -0,0 +1,29 @@
" Author: Nelson Yeung <nelsyeung@gmail.com>
" Description: Check Dart files with dart analysis server LSP
call ale#Set('dart_analysis_server_executable', 'dart')
function! ale_linters#dart#analysis_server#GetProjectRoot(buffer) abort
" Note: pub only looks for pubspec.yaml, there's no point in adding
" support for pubspec.yml
let l:pubspec = ale#path#FindNearestFile(a:buffer, 'pubspec.yaml')
return !empty(l:pubspec) ? fnamemodify(l:pubspec, ':h:h') : '.'
endfunction
function! ale_linters#dart#analysis_server#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'dart_analysis_server_executable')
let l:dart = resolve(exepath(l:executable))
return '%e '
\ . fnamemodify(l:dart, ':h') . '/snapshots/analysis_server.dart.snapshot'
\ . ' --lsp'
endfunction
call ale#linter#Define('dart', {
\ 'name': 'analysis_server',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'dart_analysis_server_executable')},
\ 'command': function('ale_linters#dart#analysis_server#GetCommand'),
\ 'project_root': function('ale_linters#dart#analysis_server#GetProjectRoot'),
\})

View File

@ -0,0 +1,28 @@
" Author: ghsang <gwonhyuksang@gmail.com>
" Description: Check Dart files with dart analyze
call ale#Set('dart_analyze_executable', 'dart')
function! ale_linters#dart#dart_analyze#Handle(buffer, lines) abort
let l:pattern = '\v^ ([a-z]+) - (.+):(\d+):(\d+) - (.+) - (.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'type': l:match[1] is# 'error' ? 'E' : 'W',
\ 'text': l:match[6] . ': ' . l:match[5],
\ 'lnum': str2nr(l:match[3]),
\ 'col': str2nr(l:match[4]),
\})
endfor
return l:output
endfunction
call ale#linter#Define('dart', {
\ 'name': 'dart_analyze',
\ 'executable': {b -> ale#Var(b, 'dart_analyze_executable')},
\ 'command': '%e analyze %s',
\ 'callback': 'ale_linters#dart#dart_analyze#Handle',
\ 'lint_file': 1,
\})

View File

@ -0,0 +1,31 @@
call ale#Set('desktop_desktop_file_validate_options', '')
" Example matches for pattern:
"
" foo.desktop: warning: key "TerminalOptions" in group ...
" foo.desktop: error: action "new-private-window" is defined, ...
let s:pattern = '\v^(.+): ([a-z]+): (.+)$'
function! ale_linters#desktop#desktop_file_validate#Handle(buffer, lines) abort
" The error format doesn't specify lines, so we can just put all of the
" errors on line 1.
return ale#util#MapMatches(a:lines, s:pattern, {match -> {
\ 'lnum': 1,
\ 'col': 1,
\ 'type': match[2] is? 'error' ? 'E' : 'W',
\ 'text': match[3],
\}})
endfunction
call ale#linter#Define('desktop', {
\ 'name': 'desktop_file_validate',
\ 'aliases': ['desktop-file-validate'],
\ 'executable': 'desktop-file-validate',
\ 'command': {b ->
\ '%e'
\ . ale#Pad(ale#Var(b, 'desktop_desktop_file_validate_options'))
\ . ' %t'
\ },
\ 'callback': 'ale_linters#desktop#desktop_file_validate#Handle',
\ 'output_stream': 'both',
\})

View File

@ -7,9 +7,9 @@ call ale#Set('dockerfile_hadolint_docker_image', 'hadolint/hadolint')
function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
" Matches patterns line the following:
"
" /dev/stdin:19 DL3001 Pipe chain should start with a raw value.
" -:19 DL3001 warning: Pipe chain should start with a raw value.
" /dev/stdin:19:3 unexpected thing
let l:pattern = '\v^/dev/stdin:(\d+):?(\d+)? ((DL|SC)(\d+) )?(.+)$'
let l:pattern = '\v^%(/dev/stdin|-):(\d+):?(\d+)? ((DL|SC)(\d+) )?((.+)?: )?(.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
@ -24,10 +24,22 @@ function! ale_linters#dockerfile#hadolint#Handle(buffer, lines) abort
let l:colnum = l:match[2] + 0
endif
let l:type = 'W'
let l:text = l:match[6]
let l:detail = l:match[6]
" Shellcheck knows a 'style' severity - pin it to info level as well.
if l:match[7] is# 'style'
let l:type = 'I'
elseif l:match[7] is# 'info'
let l:type = 'I'
elseif l:match[7] is# 'warning'
let l:type = 'W'
else
let l:type = 'E'
endif
let l:text = l:match[8]
let l:detail = l:match[8]
let l:domain = 'https://github.com/hadolint/hadolint/wiki/'
let l:code = ''
let l:link = ''
if l:match[4] is# 'SC'
let l:domain = 'https://github.com/koalaman/shellcheck/wiki/'
@ -36,9 +48,11 @@ 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'
let l:detail = 'hadolint could not parse the file because of a syntax error.'
endif
call add(l:output, {
@ -82,12 +96,15 @@ endfunction
function! ale_linters#dockerfile#hadolint#GetCommand(buffer) abort
let l:command = ale_linters#dockerfile#hadolint#GetExecutable(a:buffer)
let l:opts = '--no-color -'
if l:command is# 'docker'
return 'docker run --rm -i ' . ale#Var(a:buffer, 'dockerfile_hadolint_docker_image')
return printf('docker run --rm -i %s hadolint %s',
\ ale#Var(a:buffer, 'dockerfile_hadolint_docker_image'),
\ l:opts)
endif
return 'hadolint -'
return 'hadolint ' . l:opts
endfunction

View File

@ -45,19 +45,27 @@ function! ale_linters#elixir#credo#GetMode() abort
endif
endfunction
function! ale_linters#elixir#credo#GetCommand(buffer) abort
let l:project_root = ale#handlers#elixir#FindMixUmbrellaRoot(a:buffer)
let l:mode = ale_linters#elixir#credo#GetMode()
function! ale_linters#elixir#credo#GetConfigFile() abort
let l:config_file = get(g:, 'ale_elixir_credo_config_file', '')
return ale#path#CdString(l:project_root)
\ . 'mix help credo && '
if empty(l:config_file)
return ''
endif
return ' --config-file ' . l:config_file
endfunction
function! ale_linters#elixir#credo#GetCommand(buffer) abort
return 'mix help credo && '
\ . 'mix credo ' . ale_linters#elixir#credo#GetMode()
\ . ale_linters#elixir#credo#GetConfigFile()
\ . ' --format=flycheck --read-from-stdin %s'
endfunction
call ale#linter#Define('elixir', {
\ 'name': 'credo',
\ 'executable': 'mix',
\ 'cwd': function('ale#handlers#elixir#FindMixUmbrellaRoot'),
\ 'command': function('ale_linters#elixir#credo#GetCommand'),
\ 'callback': 'ale_linters#elixir#credo#Handle',
\})

View File

@ -25,17 +25,10 @@ function! ale_linters#elixir#dialyxir#Handle(buffer, lines) abort
return l:output
endfunction
function! ale_linters#elixir#dialyxir#GetCommand(buffer) abort
let l:project_root = ale#handlers#elixir#FindMixProjectRoot(a:buffer)
return ale#path#CdString(l:project_root)
\ . ' mix help dialyzer && mix dialyzer'
endfunction
call ale#linter#Define('elixir', {
\ 'name': 'dialyxir',
\ 'executable': 'mix',
\ 'command': function('ale_linters#elixir#dialyxir#GetCommand'),
\ 'cwd': function('ale#handlers#elixir#FindMixProjectRoot'),
\ 'command': 'mix help dialyzer && mix dialyzer',
\ 'callback': 'ale_linters#elixir#dialyxir#Handle',
\})

View File

@ -29,17 +29,11 @@ function! ale_linters#elixir#dogma#Handle(buffer, lines) abort
return l:output
endfunction
function! ale_linters#elixir#dogma#GetCommand(buffer) abort
let l:project_root = ale#handlers#elixir#FindMixProjectRoot(a:buffer)
return ale#path#CdString(l:project_root)
\ . ' mix help dogma && mix dogma %s --format=flycheck'
endfunction
call ale#linter#Define('elixir', {
\ 'name': 'dogma',
\ 'executable': 'mix',
\ 'command': function('ale_linters#elixir#dogma#GetCommand'),
\ 'cwd': function('ale#handlers#elixir#FindMixProjectRoot'),
\ 'command': 'mix help dogma && mix dogma %s --format=flycheck',
\ 'lint_file': 1,
\ 'callback': 'ale_linters#elixir#dogma#Handle',
\})

View File

@ -30,22 +30,15 @@ function! ale_linters#elixir#mix#Handle(buffer, lines) abort
endfunction
function! ale_linters#elixir#mix#GetCommand(buffer) abort
let l:project_root = ale#handlers#elixir#FindMixProjectRoot(a:buffer)
let l:temp_dir = ale#command#CreateDirectory(a:buffer)
let l:mix_build_path = has('win32')
\ ? 'set MIX_BUILD_PATH=' . ale#Escape(l:temp_dir) . ' &&'
\ : 'MIX_BUILD_PATH=' . ale#Escape(l:temp_dir)
return ale#path#CdString(l:project_root)
\ . l:mix_build_path
\ . ' mix compile %s'
return ale#Env('MIX_BUILD_PATH', l:temp_dir) . 'mix compile %s'
endfunction
call ale#linter#Define('elixir', {
\ 'name': 'mix',
\ 'executable': 'mix',
\ 'cwd': function('ale#handlers#elixir#FindMixProjectRoot'),
\ 'command': function('ale_linters#elixir#mix#GetCommand'),
\ 'callback': 'ale_linters#elixir#mix#Handle',
\ 'lint_file': 1,

View File

@ -28,7 +28,7 @@ endfunction
call ale#linter#Define('elm', {
\ 'name': 'elm_ls',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#node#FindExecutable(b, 'elm_ls', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'elm_ls', [
\ 'node_modules/.bin/elm-language-server',
\ 'node_modules/.bin/elm-lsp',
\ 'elm-lsp'

View File

@ -186,24 +186,23 @@ function! ale_linters#elm#make#IsTest(buffer) abort
endif
endfunction
function! ale_linters#elm#make#GetCwd(buffer) abort
let l:root_dir = ale_linters#elm#make#GetRootDir(a:buffer)
return !empty(l:root_dir) ? l:root_dir : ''
endfunction
" Return the command to execute the linter in the projects directory.
" If it doesn't, then this will fail when imports are needed.
function! ale_linters#elm#make#GetCommand(buffer) abort
let l:executable = ale_linters#elm#make#GetExecutable(a:buffer)
let l:root_dir = ale_linters#elm#make#GetRootDir(a:buffer)
let l:is_v19 = ale_linters#elm#make#IsVersionGte19(a:buffer)
let l:is_using_elm_test = l:executable =~# 'elm-test$'
if empty(l:root_dir)
let l:dir_set_cmd = ''
else
let l:dir_set_cmd = 'cd ' . ale#Escape(l:root_dir) . ' && '
endif
" elm-test needs to know the path of elm-make if elm isn't installed globally.
" https://github.com/rtfeldman/node-test-runner/blob/57728f10668f2d2ab3179e7e3208bcfa9a1f19aa/README.md#--compiler
if l:is_v19 && l:is_using_elm_test
let l:elm_make_executable = ale#node#FindExecutable(a:buffer, 'elm_make', ['node_modules/.bin/elm'])
let l:elm_make_executable = ale#path#FindExecutable(a:buffer, 'elm_make', ['node_modules/.bin/elm'])
let l:elm_test_compiler_flag = ' --compiler ' . l:elm_make_executable . ' '
else
let l:elm_test_compiler_flag = ' '
@ -213,7 +212,9 @@ function! ale_linters#elm#make#GetCommand(buffer) abort
" a sort of flag to tell the compiler not to generate an output file,
" which is why this is hard coded here.
" Source: https://github.com/elm-lang/elm-compiler/blob/19d5a769b30ec0b2fc4475985abb4cd94cd1d6c3/builder/src/Generate/Output.hs#L253
return l:dir_set_cmd . '%e make --report=json --output=/dev/null' . l:elm_test_compiler_flag . '%t'
return '%e make --report=json --output=/dev/null'
\ . l:elm_test_compiler_flag
\ . '%t'
endfunction
function! ale_linters#elm#make#GetExecutable(buffer) abort
@ -221,13 +222,13 @@ function! ale_linters#elm#make#GetExecutable(buffer) abort
let l:is_v19 = ale_linters#elm#make#IsVersionGte19(a:buffer)
if l:is_test && l:is_v19
return ale#node#FindExecutable(
return ale#path#FindExecutable(
\ a:buffer,
\ 'elm_make',
\ ['node_modules/.bin/elm-test', 'node_modules/.bin/elm']
\)
else
return ale#node#FindExecutable(a:buffer, 'elm_make', ['node_modules/.bin/elm'])
return ale#path#FindExecutable(a:buffer, 'elm_make', ['node_modules/.bin/elm'])
endif
endfunction
@ -235,6 +236,7 @@ call ale#linter#Define('elm', {
\ 'name': 'make',
\ 'executable': function('ale_linters#elm#make#GetExecutable'),
\ 'output_stream': 'both',
\ 'cwd': function('ale_linters#elm#make#GetCwd'),
\ 'command': function('ale_linters#elm#make#GetCommand'),
\ 'callback': 'ale_linters#elm#make#Handle'
\})

View File

@ -3,6 +3,11 @@
let g:ale_erlang_dialyzer_executable =
\ get(g:, 'ale_erlang_dialyzer_executable', 'dialyzer')
let g:ale_erlang_dialyzer_options =
\ get(g:, 'ale_erlang_dialyzer_options', '-Wunmatched_returns'
\ . ' -Werror_handling'
\ . ' -Wrace_conditions'
\ . ' -Wunderspecs')
let g:ale_erlang_dialyzer_plt_file =
\ get(g:, 'ale_erlang_dialyzer_plt_file', '')
let g:ale_erlang_dialyzer_rebar3_profile =
@ -47,13 +52,12 @@ function! ale_linters#erlang#dialyzer#GetExecutable(buffer) abort
endfunction
function! ale_linters#erlang#dialyzer#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'erlang_dialyzer_options')
let l:command = ale#Escape(ale_linters#erlang#dialyzer#GetExecutable(a:buffer))
\ . ' -n'
\ . ' --plt ' . ale#Escape(ale_linters#erlang#dialyzer#GetPlt(a:buffer))
\ . ' -Wunmatched_returns'
\ . ' -Werror_handling'
\ . ' -Wrace_conditions'
\ . ' -Wunderspecs'
\ . ' ' . l:options
\ . ' %s'
return l:command

View File

@ -1,14 +1,22 @@
" Author: Magnus Ottenklinger - https://github.com/evnu
let g:ale_erlang_erlc_executable = get(g:, 'ale_erlang_erlc_executable', 'erlc')
let g:ale_erlang_erlc_options = get(g:, 'ale_erlang_erlc_options', '')
function! ale_linters#erlang#erlc#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'erlang_erlc_executable')
endfunction
function! ale_linters#erlang#erlc#GetCommand(buffer) abort
let l:output_file = ale#util#Tempname()
call ale#command#ManageFile(a:buffer, l:output_file)
return 'erlc -o ' . ale#Escape(l:output_file)
\ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options')
\ . ' %t'
let l:command = ale#Escape(ale_linters#erlang#erlc#GetExecutable(a:buffer))
\ . ' -o ' . ale#Escape(l:output_file)
\ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options')
\ . ' %t'
return l:command
endfunction
function! ale_linters#erlang#erlc#Handle(buffer, lines) abort
@ -17,7 +25,7 @@ function! ale_linters#erlang#erlc#Handle(buffer, lines) abort
" error.erl:4: variable 'B' is unbound
" error.erl:3: Warning: function main/0 is unused
" error.erl:4: Warning: variable 'A' is unused
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+): (Warning: )?(.+)$'
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+:)? (Warning: )?(.+)$'
" parse_transforms are a special case. The error message does not indicate a location:
" error.erl: undefined parse transform 'some_parse_transform'
@ -57,8 +65,8 @@ function! ale_linters#erlang#erlc#Handle(buffer, lines) abort
endif
let l:line = l:match[2]
let l:warning_or_text = l:match[3]
let l:text = l:match[4]
let l:warning_or_text = l:match[4]
let l:text = l:match[5]
" If this file is a header .hrl, ignore the following expected messages:
" - 'no module definition'
@ -90,7 +98,7 @@ endfunction
call ale#linter#Define('erlang', {
\ 'name': 'erlc',
\ 'executable': 'erlc',
\ 'executable': function('ale_linters#erlang#erlc#GetExecutable'),
\ 'command': function('ale_linters#erlang#erlc#GetCommand'),
\ 'callback': 'ale_linters#erlang#erlc#Handle',
\})

View File

@ -10,8 +10,7 @@ function! ale_linters#go#gobuild#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'go_gobuild_options')
" Run go test in local directory with relative path
return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer)
return ale#go#EnvString(a:buffer)
\ . ale#Var(a:buffer, 'go_go_executable') . ' test'
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' -c -o /dev/null ./'
@ -50,6 +49,7 @@ call ale#linter#Define('go', {
\ 'name': 'gobuild',
\ 'aliases': ['go build'],
\ 'executable': {b -> ale#Var(b, 'go_go_executable')},
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#go#gobuild#GetCommand'),
\ 'output_stream': 'stderr',
\ 'callback': 'ale_linters#go#gobuild#Handler',

View File

@ -12,14 +12,12 @@ function! ale_linters#go#golangci_lint#GetCommand(buffer) abort
if l:lint_package
return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer)
return ale#go#EnvString(a:buffer)
\ . '%e run '
\ . l:options
endif
return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer)
return ale#go#EnvString(a:buffer)
\ . '%e run '
\ . ale#Escape(l:filename)
\ . ' ' . l:options
@ -53,6 +51,7 @@ endfunction
call ale#linter#Define('go', {
\ 'name': 'golangci-lint',
\ 'executable': {b -> ale#Var(b, 'go_golangci_lint_executable')},
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#go#golangci_lint#GetCommand'),
\ 'callback': 'ale_linters#go#golangci_lint#Handler',
\ 'lint_file': 1,

View File

@ -13,14 +13,12 @@ function! ale_linters#go#gometalinter#GetCommand(buffer) abort
" BufferCdString is used so that we can be sure the paths output from gometalinter can
" be calculated to absolute paths in the Handler
if l:lint_package
return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer)
return ale#go#EnvString(a:buffer)
\ . '%e'
\ . (!empty(l:options) ? ' ' . l:options : '') . ' .'
endif
return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer)
return ale#go#EnvString(a:buffer)
\ . '%e'
\ . ' --include=' . ale#Escape(ale#util#EscapePCRE(l:filename))
\ . (!empty(l:options) ? ' ' . l:options : '') . ' .'
@ -53,6 +51,7 @@ endfunction
call ale#linter#Define('go', {
\ 'name': 'gometalinter',
\ 'executable': {b -> ale#Var(b, 'go_gometalinter_executable')},
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#go#gometalinter#GetCommand'),
\ 'callback': 'ale_linters#go#gometalinter#Handler',
\ 'lint_file': 1,

View File

@ -4,6 +4,8 @@
call ale#Set('go_gopls_executable', 'gopls')
call ale#Set('go_gopls_options', '--mode stdio')
call ale#Set('go_gopls_init_options', {})
call ale#Set('go_gopls_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#go#gopls#GetCommand(buffer) abort
return ale#go#EnvString(a:buffer)
@ -28,7 +30,10 @@ endfunction
call ale#linter#Define('go', {
\ 'name': 'gopls',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'go_gopls_executable')},
\ 'executable': {b -> ale#path#FindExecutable(b, 'go_gopls', [
\ ale#go#GetGoPathExecutable('bin/gopls'),
\ ])},
\ 'command': function('ale_linters#go#gopls#GetCommand'),
\ 'project_root': function('ale_linters#go#gopls#FindProjectRoot'),
\ 'initialization_options': {b -> ale#Var(b, 'go_gopls_init_options')},
\})

View File

@ -1,15 +1,11 @@
" Author: Ben Reedy <https://github.com/breed808>
" Description: gosimple for Go files
function! ale_linters#go#gosimple#GetCommand(buffer) abort
return ale#path#BufferCdString(a:buffer) . ' '
\ . ale#go#EnvString(a:buffer) . 'gosimple .'
endfunction
call ale#linter#Define('go', {
\ 'name': 'gosimple',
\ 'executable': 'gosimple',
\ 'command': function('ale_linters#go#gosimple#GetCommand'),
\ 'cwd': '%s:h',
\ 'command': {b -> ale#go#EnvString(b) . 'gosimple .'},
\ 'callback': 'ale#handlers#go#Handler',
\ 'output_stream': 'both',
\ 'lint_file': 1,

View File

@ -1,19 +1,23 @@
" Author: Jelte Fennema <github-public@jeltef.nl>
" Description: gotype for Go files
function! ale_linters#go#gotype#GetCommand(buffer) abort
function! ale_linters#go#gotype#GetExecutable(buffer) abort
if expand('#' . a:buffer . ':p') =~# '_test\.go$'
return ''
endif
return ale#path#BufferCdString(a:buffer) . ' '
\ . ale#go#EnvString(a:buffer) . 'gotype -e .'
return 'gotype'
endfunction
function! ale_linters#go#gotype#GetCommand(buffer) abort
return ale#go#EnvString(a:buffer) . 'gotype -e .'
endfunction
call ale#linter#Define('go', {
\ 'name': 'gotype',
\ 'output_stream': 'stderr',
\ 'executable': 'gotype',
\ 'executable': function('ale_linters#go#gotype#GetExecutable'),
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#go#gotype#GetCommand'),
\ 'callback': 'ale#handlers#go#Handler',
\ 'lint_file': 1,

View File

@ -10,8 +10,7 @@ call ale#Set('go_govet_options', '')
function! ale_linters#go#govet#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'go_govet_options')
return ale#path#BufferCdString(a:buffer) . ' '
\ . ale#go#EnvString(a:buffer)
return ale#go#EnvString(a:buffer)
\ . ale#Var(a:buffer, 'go_go_executable') . ' vet '
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' .'
@ -22,6 +21,7 @@ call ale#linter#Define('go', {
\ 'aliases': ['go vet'],
\ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'go_go_executable')},
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#go#govet#GetCommand'),
\ 'callback': 'ale#handlers#go#Handler',
\ 'lint_file': 1,

View File

@ -1,32 +1,32 @@
" Author: Ben Reedy <https://github.com/breed808>
" Description: staticcheck for Go files
call ale#Set('go_staticcheck_executable', 'staticcheck')
call ale#Set('go_staticcheck_options', '')
call ale#Set('go_staticcheck_lint_package', 0)
call ale#Set('go_staticcheck_lint_package', 1)
call ale#Set('go_staticcheck_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#go#staticcheck#GetCommand(buffer) abort
let l:filename = expand('#' . a:buffer . ':t')
let l:options = ale#Var(a:buffer, 'go_staticcheck_options')
let l:lint_package = ale#Var(a:buffer, 'go_staticcheck_lint_package')
let l:env = ale#go#EnvString(a:buffer)
" BufferCdString is used so that we can be sure the paths output from
" staticcheck can be calculated to absolute paths in the Handler
if l:lint_package
return ale#path#BufferCdString(a:buffer)
\ . l:env . 'staticcheck'
return l:env . '%e'
\ . (!empty(l:options) ? ' ' . l:options : '') . ' .'
endif
return ale#path#BufferCdString(a:buffer)
\ . l:env . 'staticcheck'
return l:env . '%e'
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' ' . ale#Escape(l:filename)
\ . ' %s:t'
endfunction
call ale#linter#Define('go', {
\ 'name': 'staticcheck',
\ 'executable': 'staticcheck',
\ 'executable': {b -> ale#path#FindExecutable(b, 'go_staticcheck', [
\ ale#go#GetGoPathExecutable('bin/staticcheck'),
\ ])},
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#go#staticcheck#GetCommand'),
\ 'callback': 'ale#handlers#go#Handler',
\ 'output_stream': 'both',

View File

@ -4,6 +4,7 @@
call ale#linter#Define('graphql', {
\ 'name': 'eslint',
\ 'executable': function('ale#handlers#eslint#GetExecutable'),
\ 'cwd': function('ale#handlers#eslint#GetCwd'),
\ 'command': function('ale#handlers#eslint#GetCommand'),
\ 'callback': 'ale#handlers#eslint#HandleJSON',
\})

View File

@ -1,15 +1,10 @@
" Author: Michiel Westerbeek <happylinks@gmail.com>
" Description: Linter for GraphQL Schemas
function! ale_linters#graphql#gqlint#GetCommand(buffer) abort
return ale#path#BufferCdString(a:buffer)
\ . 'gqlint'
\ . ' --reporter=simple %t'
endfunction
call ale#linter#Define('graphql', {
\ 'name': 'gqlint',
\ 'executable': 'gqlint',
\ 'command': function('ale_linters#graphql#gqlint#GetCommand'),
\ 'cwd': '%s:h',
\ 'command': 'gqlint --reporter=simple %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning',
\})

View File

@ -5,7 +5,7 @@ call ale#Set('handlebars_embertemplatelint_executable', 'ember-template-lint')
call ale#Set('handlebars_embertemplatelint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#handlebars#embertemplatelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'handlebars_embertemplatelint', [
return ale#path#FindExecutable(a:buffer, 'handlebars_embertemplatelint', [
\ 'node_modules/.bin/ember-template-lint',
\])
endfunction

View File

@ -4,8 +4,7 @@
call ale#Set('haskell_cabal_ghc_options', '-fno-code -v0')
function! ale_linters#haskell#cabal_ghc#GetCommand(buffer) abort
return ale#path#BufferCdString(a:buffer)
\ . 'cabal exec -- ghc '
return 'cabal exec -- ghc '
\ . ale#Var(a:buffer, 'haskell_cabal_ghc_options')
\ . ' %t'
endfunction
@ -15,6 +14,7 @@ call ale#linter#Define('haskell', {
\ 'aliases': ['cabal-ghc'],
\ 'output_stream': 'stderr',
\ 'executable': 'cabal',
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#haskell#cabal_ghc#GetCommand'),
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})

View File

@ -0,0 +1,63 @@
" Author: Yen3 <yen3rc@gmail.com>
" Description: A language server for haskell
" The file is based on hie.vim (author: Luxed
" <devildead13@gmail.com>). It search more project root files.
"
call ale#Set('haskell_hls_executable', 'haskell-language-server-wrapper')
function! ale_linters#haskell#hls#FindRootFile(buffer) abort
let l:serach_root_files = [
\ 'stack.yaml',
\ 'cabal.project',
\ 'package.yaml',
\ 'hie.yaml'
\ ]
for l:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h'))
for l:root_file in l:serach_root_files
if filereadable(l:path . l:root_file)
return l:path
endif
endfor
endfor
return ''
endfunction
function! ale_linters#haskell#hls#GetProjectRoot(buffer) abort
" Search for the project file first
let l:project_file = ale_linters#haskell#hls#FindRootFile(a:buffer)
" If it's empty, search for the cabal file
if empty(l:project_file)
" Search all of the paths except for the root filesystem path.
let l:paths = join(
\ ale#path#Upwards(expand('#' . a:buffer . ':p:h'))[:-2],
\ ','
\)
let l:project_file = globpath(l:paths, '*.cabal')
endif
" If we still can't find one, use the current file.
if empty(l:project_file)
let l:project_file = expand('#' . a:buffer . ':p')
endif
return fnamemodify(l:project_file, ':h')
endfunction
function! ale_linters#haskell#hls#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'haskell_hls_executable')
return ale#handlers#haskell_stack#EscapeExecutable(l:executable,
\ 'haskell-language-server-wrapper')
\ . ' --lsp'
endfunction
call ale#linter#Define('haskell', {
\ 'name': 'hls',
\ 'lsp': 'stdio',
\ 'command': function('ale_linters#haskell#hls#GetCommand'),
\ 'executable': {b -> ale#Var(b, 'haskell_hls_executable')},
\ 'project_root': function('ale_linters#haskell#hls#GetProjectRoot'),
\})

View File

@ -4,8 +4,7 @@
call ale#Set('haskell_stack_ghc_options', '-fno-code -v0')
function! ale_linters#haskell#stack_ghc#GetCommand(buffer) abort
return ale#path#BufferCdString(a:buffer)
\ . ale#handlers#haskell#GetStackExecutable(a:buffer)
return ale#handlers#haskell#GetStackExecutable(a:buffer)
\ . ' ghc -- '
\ . ale#Var(a:buffer, 'haskell_stack_ghc_options')
\ . ' %t'
@ -16,6 +15,7 @@ call ale#linter#Define('haskell', {
\ 'aliases': ['stack-ghc'],
\ 'output_stream': 'stderr',
\ 'executable': function('ale#handlers#haskell#GetStackExecutable'),
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#haskell#stack_ghc#GetCommand'),
\ 'callback': 'ale#handlers#haskell#HandleGHCFormat',
\})

View File

@ -0,0 +1,52 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: tsserver integration for ALE
call ale#Set('html_angular_executable', 'ngserver')
call ale#Set('html_angular_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#html#angular#GetProjectRoot(buffer) abort
return ale#path#Dirname(
\ ale#path#FindNearestDirectory(a:buffer, 'node_modules')
\)
endfunction
function! ale_linters#html#angular#GetExecutable(buffer) abort
return ale#path#FindExecutable(a:buffer, 'html_angular', [
\ 'node_modules/@angular/language-server/bin/ngserver',
\ 'node_modules/@angular/language-server/index.js',
\])
endfunction
function! ale_linters#html#angular#GetCommand(buffer) abort
let l:language_service_dir = ale#path#Simplify(
\ ale#path#FindNearestDirectory(
\ a:buffer,
\ 'node_modules/@angular/language-service'
\ )
\)
if empty(l:language_service_dir)
return ''
endif
let l:language_service_dir = fnamemodify(l:language_service_dir, ':h')
let l:typescript_dir = ale#path#Simplify(
\ fnamemodify(l:language_service_dir, ':h:h')
\ . '/typescript'
\)
let l:executable = ale_linters#html#angular#GetExecutable(a:buffer)
return ale#node#Executable(a:buffer, l:executable)
\ . ' --ngProbeLocations ' . ale#Escape(l:language_service_dir)
\ . ' --tsProbeLocations ' . ale#Escape(l:typescript_dir)
\ . ' --stdio'
endfunction
call ale#linter#Define('html', {
\ 'name': 'angular',
\ 'aliases': ['angular-language-server'],
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#html#angular#GetExecutable'),
\ 'command': function('ale_linters#html#angular#GetCommand'),
\ 'project_root': function('ale_linters#html#angular#GetProjectRoot'),
\})

View File

@ -24,7 +24,7 @@ endfunction
call ale#linter#Define('html', {
\ 'name': 'htmlhint',
\ 'executable': {b -> ale#node#FindExecutable(b, 'html_htmlhint', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'html_htmlhint', [
\ 'node_modules/.bin/htmlhint',
\ ])},
\ 'command': function('ale_linters#html#htmlhint#GetCommand'),

View File

@ -5,7 +5,7 @@ call ale#Set('html_stylelint_options', '')
call ale#Set('html_stylelint_use_global', 0)
function! ale_linters#html#stylelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'html_stylelint', [
return ale#path#FindExecutable(a:buffer, 'html_stylelint', [
\ 'node_modules/.bin/stylelint',
\])
endfunction

View File

@ -6,7 +6,7 @@ call ale#Set('ink_ls_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('ink_ls_initialization_options', {})
function! ale_linters#ink#ls#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'ink_ls', [
return ale#path#FindExecutable(a:buffer, 'ink_ls', [
\ 'ink-language-server',
\ 'node_modules/.bin/ink-language-server',
\])

View File

@ -0,0 +1,33 @@
" Author: Yorick Peterse <yorick@yorickpeterse.com>
" Description: linting of Inko source code using the Inko compiler
call ale#Set('inko_inko_executable', 'inko')
function! ale_linters#inko#inko#GetCommand(buffer) abort
let l:include = ''
" Include the tests source directory, but only for test files.
if expand('#' . a:buffer . ':p') =~? '\vtests[/\\]test[/\\]'
let l:test_dir = ale#path#FindNearestDirectory(a:buffer, 'tests')
if isdirectory(l:test_dir)
let l:include = '--include ' . ale#Escape(l:test_dir)
endif
endif
" We use %s instead of %t so the compiler determines the correct module
" names for the file being edited. Not doing so may lead to errors in
" certain cases.
return '%e build --check --format=json'
\ . ale#Pad(l:include)
\ . ' %s'
endfunction
call ale#linter#Define('inko', {
\ 'name': 'inko',
\ 'executable': {b -> ale#Var(b, 'inko_inko_executable')},
\ 'command': function('ale_linters#inko#inko#GetCommand'),
\ 'callback': 'ale#handlers#inko#Handle',
\ 'output_stream': 'stderr',
\ 'lint_file': 1
\})

View File

@ -9,11 +9,12 @@ function! ale_linters#java#checkstyle#Handle(buffer, lines) abort
let l:output = []
" modern checkstyle versions
let l:pattern = '\v\[(WARN|ERROR)\] [a-zA-Z]?:?[^:]+:(\d+):(\d+)?:? (.*) \[(.+)\]$'
let l:pattern = '\v\[(WARN|ERROR)\] [a-zA-Z]?:?[^:]+:(\d+):(\d+)?:? (.*) \[(.+)\]'
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'type': l:match[1] is? 'WARN' ? 'W' : 'E',
\ 'sub_type': 'style',
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'text': l:match[4],
@ -31,6 +32,7 @@ function! ale_linters#java#checkstyle#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'type': l:match[3] is? 'warning' ? 'W' : 'E',
\ 'sub_type': 'style',
\ 'lnum': l:match[2] + 0,
\ 'text': l:match[4],
\})

View File

@ -29,28 +29,28 @@ function! ale_linters#java#eclipselsp#JarPath(buffer) abort
endif
" Search jar file within repository path when manually built using mvn
let l:files = globpath(l:path, '**/'.l:platform.'/**/plugins/org.eclipse.equinox.launcher_\d\.\d\.\d\d\d\.*\.jar', 1, 1)
let l:files = globpath(l:path, '**/'.l:platform.'/**/plugins/org.eclipse.equinox.launcher_*\.jar', 1, 1)
if len(l:files) >= 1
return l:files[0]
endif
" Search jar file within VSCode extensions folder.
let l:files = globpath(l:path, '**/'.l:platform.'/plugins/org.eclipse.equinox.launcher_\d\.\d\.\d\d\d\.*\.jar', 1, 1)
let l:files = globpath(l:path, '**/'.l:platform.'/plugins/org.eclipse.equinox.launcher_*\.jar', 1, 1)
if len(l:files) >= 1
return l:files[0]
endif
" Search jar file within unzipped tar.gz file
let l:files = globpath(l:path, 'plugins/org.eclipse.equinox.launcher_\d\.\d\.\d\d\d\.*\.jar', 1, 1)
let l:files = globpath(l:path, 'plugins/org.eclipse.equinox.launcher_*\.jar', 1, 1)
if len(l:files) >= 1
return l:files[0]
endif
" Search jar file within system package path
let l:files = globpath('/usr/share/java/jdtls/plugins', 'org.eclipse.equinox.launcher_\d\.\d\.\d\d\d\.*\.jar', 1, 1)
let l:files = globpath('/usr/share/java/jdtls/plugins', 'org.eclipse.equinox.launcher_*\.jar', 1, 1)
if len(l:files) >= 1
return l:files[0]

View File

@ -9,16 +9,16 @@ call ale#Set('java_javac_classpath', '')
call ale#Set('java_javac_sourcepath', '')
function! ale_linters#java#javac#RunWithImportPaths(buffer) abort
let l:command = ale#maven#BuildClasspathCommand(a:buffer)
let [l:cwd, l:command] = ale#maven#BuildClasspathCommand(a:buffer)
" Try to use Gradle if Maven isn't available.
if empty(l:command)
let l:command = ale#gradle#BuildClasspathCommand(a:buffer)
let [l:cwd, l:command] = ale#gradle#BuildClasspathCommand(a:buffer)
endif
" Try to use Ant if Gradle and Maven aren't available
if empty(l:command)
let l:command = ale#ant#BuildClasspathCommand(a:buffer)
let [l:cwd, l:command] = ale#ant#BuildClasspathCommand(a:buffer)
endif
if empty(l:command)
@ -28,7 +28,8 @@ function! ale_linters#java#javac#RunWithImportPaths(buffer) abort
return ale#command#Run(
\ a:buffer,
\ l:command,
\ function('ale_linters#java#javac#GetCommand')
\ function('ale_linters#java#javac#GetCommand'),
\ {'cwd': l:cwd},
\)
endfunction
@ -110,8 +111,7 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths, meta) abort
" Always run javac from the directory the file is in, so we can resolve
" relative paths correctly.
return ale#path#BufferCdString(a:buffer)
\ . '%e -Xlint'
return '%e -Xlint'
\ . ale#Pad(l:cp_option)
\ . ale#Pad(l:sp_option)
\ . ' -d ' . ale#Escape(l:class_file_directory)
@ -132,7 +132,9 @@ function! ale_linters#java#javac#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, [l:pattern, l:col_pattern, l:symbol_pattern])
if empty(l:match[2]) && empty(l:match[3])
let l:output[-1].col = len(l:match[1])
if !empty(l:match[1]) && !empty(l:output)
let l:output[-1].col = len(l:match[1])
endif
elseif empty(l:match[3])
" Add symbols to 'cannot find symbol' errors.
if l:output[-1].text is# 'error: cannot find symbol'
@ -154,6 +156,7 @@ endfunction
call ale#linter#Define('java', {
\ 'name': 'javac',
\ 'executable': {b -> ale#Var(b, 'java_javac_executable')},
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#java#javac#RunWithImportPaths'),
\ 'output_stream': 'stderr',
\ 'callback': 'ale_linters#java#javac#Handle',

View File

@ -5,6 +5,7 @@ call ale#linter#Define('javascript', {
\ 'name': 'eslint',
\ 'output_stream': 'both',
\ 'executable': function('ale#handlers#eslint#GetExecutable'),
\ 'cwd': function('ale#handlers#eslint#GetCwd'),
\ 'command': function('ale#handlers#eslint#GetCommand'),
\ 'callback': 'ale#handlers#eslint#HandleJSON',
\})

View File

@ -22,7 +22,7 @@ function! ale_linters#javascript#flow#GetExecutable(buffer) abort
return ''
endif
return ale#node#FindExecutable(a:buffer, 'javascript_flow', [
return ale#path#FindExecutable(a:buffer, 'javascript_flow', [
\ 'node_modules/.bin/flow',
\])
endfunction

View File

@ -19,7 +19,7 @@ endfunction
call ale#linter#Define('javascript', {
\ 'name': 'flow-language-server',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#node#FindExecutable(b, 'javascript_flow_ls', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'javascript_flow_ls', [
\ 'node_modules/.bin/flow',
\ ])},
\ 'command': '%e lsp --from ale-lsp',

View File

@ -53,7 +53,7 @@ endfunction
call ale#linter#Define('javascript', {
\ 'name': 'jscs',
\ 'executable': {b -> ale#node#FindExecutable(b, 'javascript_jscs', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'javascript_jscs', [
\ 'node_modules/.bin/jscs',
\ ])},
\ 'command': function('ale_linters#javascript#jscs#GetCommand'),

View File

@ -25,7 +25,7 @@ endfunction
call ale#linter#Define('javascript', {
\ 'name': 'jshint',
\ 'executable': {b -> ale#node#FindExecutable(b, 'javascript_jshint', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'javascript_jshint', [
\ 'node_modules/.bin/jshint',
\ ])},
\ 'command': function('ale_linters#javascript#jshint#GetCommand'),

View File

@ -6,7 +6,7 @@ call ale#Set('javascript_standard_use_global', get(g:, 'ale_use_global_executabl
call ale#Set('javascript_standard_options', '')
function! ale_linters#javascript#standard#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_standard', [
return ale#path#FindExecutable(a:buffer, 'javascript_standard', [
\ 'node_modules/standardx/bin/cmd.js',
\ 'node_modules/standard/bin/cmd.js',
\ 'node_modules/semistandard/bin/cmd.js',

View File

@ -8,7 +8,7 @@ call ale#Set('javascript_tsserver_use_global', get(g:, 'ale_use_global_executabl
call ale#linter#Define('javascript', {
\ 'name': 'tsserver',
\ 'lsp': 'tsserver',
\ 'executable': {b -> ale#node#FindExecutable(b, 'javascript_tsserver', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'javascript_tsserver', [
\ 'node_modules/.bin/tsserver',
\ ])},
\ 'command': '%e',

View File

@ -1,26 +1,9 @@
" Author: Daniel Lupu <lupu.daniel.f@gmail.com>
" Description: xo for JavaScript files
call ale#Set('javascript_xo_executable', 'xo')
call ale#Set('javascript_xo_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('javascript_xo_options', '')
function! ale_linters#javascript#xo#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_xo', [
\ 'node_modules/.bin/xo',
\])
endfunction
function! ale_linters#javascript#xo#GetCommand(buffer) abort
return ale#Escape(ale_linters#javascript#xo#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'javascript_xo_options')
\ . ' --reporter json --stdin --stdin-filename %s'
endfunction
" xo uses eslint and the output format is the same
call ale#linter#Define('javascript', {
\ 'name': 'xo',
\ 'executable': function('ale_linters#javascript#xo#GetExecutable'),
\ 'command': function('ale_linters#javascript#xo#GetCommand'),
\ 'callback': 'ale#handlers#eslint#HandleJSON',
\ 'executable': function('ale#handlers#xo#GetExecutable'),
\ 'command': function('ale#handlers#xo#GetLintCommand'),
\ 'callback': 'ale#handlers#xo#HandleJSON',
\})

View File

@ -0,0 +1,24 @@
" Author: jD91mZM2 <me@krake.one>
call ale#Set('json_jq_executable', 'jq')
call ale#Set('json_jq_options', '')
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\+\)$'
function! ale_linters#json#jq#Handle(buffer, lines) abort
return ale#util#MapMatches(a:lines, s:pattern, {match -> {
\ 'text': match[1],
\ 'lnum': match[2] + 0,
\ 'col': match[3] + 0,
\}})
endfunction
call ale#linter#Define('json', {
\ 'name': 'jq',
\ 'executable': {b -> ale#Var(b, 'json_jq_executable')},
\ 'output_stream': 'stderr',
\ 'command': '%e',
\ 'callback': 'ale_linters#json#jq#Handle',
\})

View File

@ -4,7 +4,7 @@ call ale#Set('json_jsonlint_executable', 'jsonlint')
call ale#Set('json_jsonlint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#json#jsonlint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'json_jsonlint', [
return ale#path#FindExecutable(a:buffer, 'json_jsonlint', [
\ 'node_modules/.bin/jsonlint',
\ 'node_modules/jsonlint/lib/cli.js',
\])

View File

@ -0,0 +1,14 @@
" Author: t2h5 <https://github.com/t2h5>
" Description: Integration of Stoplight Spectral CLI with ALE.
call ale#Set('json_spectral_executable', 'spectral')
call ale#Set('json_spectral_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#linter#Define('json', {
\ 'name': 'spectral',
\ 'executable': {b -> ale#path#FindExecutable(b, 'json_spectral', [
\ 'node_modules/.bin/spectral',
\ ])},
\ 'command': '%e lint --ignore-unknown-format -q -f text %t',
\ 'callback': 'ale#handlers#spectral#HandleSpectralOutput'
\})

View File

@ -6,9 +6,9 @@ call ale#Set('julia_executable', 'julia')
function! ale_linters#julia#languageserver#GetCommand(buffer) abort
let l:julia_executable = ale#Var(a:buffer, 'julia_executable')
let l:cmd_string = 'using LanguageServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, false); server.runlinter = true; run(server);'
let l:cmd_string = 'using LanguageServer; using Pkg; import StaticLint; import SymbolServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, dirname(Pkg.Types.Context().env.project_file)); server.runlinter = true; run(server);'
return ale#Escape(l:julia_executable) . ' --startup-file=no --history-file=no -e ' . ale#Escape(l:cmd_string)
return ale#Escape(l:julia_executable) . ' --project=@. --startup-file=no --history-file=no -e ' . ale#Escape(l:cmd_string)
endfunction
call ale#linter#Define('julia', {

View File

@ -15,20 +15,15 @@ function! ale_linters#kotlin#kotlinc#RunWithImportPaths(buffer) abort
let l:command = ''
" exec maven/gradle only if classpath is not set
if ale#Var(a:buffer, 'kotlin_kotlinc_classpath') isnot# ''
if !empty(ale#Var(a:buffer, 'kotlin_kotlinc_classpath'))
return ale_linters#kotlin#kotlinc#GetCommand(a:buffer, [], {})
endif
let l:pom_path = ale#path#FindNearestFile(a:buffer, 'pom.xml')
if !empty(l:pom_path) && executable('mvn')
let l:command = ale#path#CdString(fnamemodify(l:pom_path, ':h'))
\ . 'mvn dependency:build-classpath'
endif
let [l:cwd, l:command] = ale#maven#BuildClasspathCommand(a:buffer)
" Try to use Gradle if Maven isn't available.
if empty(l:command)
let l:command = ale#gradle#BuildClasspathCommand(a:buffer)
let [l:cwd, l:command] = ale#gradle#BuildClasspathCommand(a:buffer)
endif
if empty(l:command)
@ -38,7 +33,8 @@ function! ale_linters#kotlin#kotlinc#RunWithImportPaths(buffer) abort
return ale#command#Run(
\ a:buffer,
\ l:command,
\ function('ale_linters#kotlin#kotlinc#GetCommand')
\ function('ale_linters#kotlin#kotlinc#GetCommand'),
\ {'cwd': l:cwd},
\)
endfunction

View File

@ -38,7 +38,7 @@ endfunction
call ale#linter#Define('less', {
\ 'name': 'lessc',
\ 'executable': {b -> ale#node#FindExecutable(b, 'less_lessc', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'less_lessc', [
\ 'node_modules/.bin/lessc',
\ ])},
\ 'command': function('ale_linters#less#lessc#GetCommand'),

View File

@ -12,7 +12,7 @@ endfunction
call ale#linter#Define('less', {
\ 'name': 'stylelint',
\ 'executable': {b -> ale#node#FindExecutable(b, 'less_stylelint', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'less_stylelint', [
\ 'node_modules/.bin/stylelint',
\ ])},
\ 'command': function('ale_linters#less#stylelint#GetCommand'),

View File

@ -39,7 +39,7 @@ endfunction
call ale#linter#Define('markdown', {
\ 'name': 'remark_lint',
\ 'aliases': ['remark-lint'],
\ 'executable': {b -> ale#node#FindExecutable(b, 'markdown_remark_lint', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'markdown_remark_lint', [
\ 'node_modules/.bin/remark',
\ ])},
\ 'command': function('ale_linters#markdown#remark_lint#GetCommand'),

View File

@ -1,9 +1,24 @@
" Author: chew-z https://github.com/chew-z
" Description: vale for Markdown files
call ale#Set('markdown_vale_executable', 'vale')
call ale#Set('markdown_vale_input_file', '%t')
call ale#Set('markdown_vale_options', '')
function! ale_linters#markdown#vale#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'markdown_vale_executable')
let l:input_file = ale#Var(a:buffer, 'markdown_vale_input_file')
" Defaults to `vale --output=JSON %t`
return ale#Escape(l:executable)
\ . ' --output=JSON '
\ . ale#Var(a:buffer, 'markdown_vale_options')
\ . ' ' . l:input_file
endfunction
call ale#linter#Define('markdown', {
\ 'name': 'vale',
\ 'executable': 'vale',
\ 'command': 'vale --output=JSON %t',
\ 'executable': {b -> ale#Var(b, 'markdown_vale_executable')},
\ 'command': function('ale_linters#markdown#vale#GetCommand'),
\ 'callback': 'ale#handlers#vale#Handle',
\})

View File

@ -5,12 +5,9 @@ call ale#Set('mercury_mmc_executable', 'mmc')
call ale#Set('mercury_mmc_options', '--make --output-compile-error-lines 100')
function! ale_linters#mercury#mmc#GetCommand(buffer) abort
let l:module_name = expand('#' . a:buffer . ':t:r')
return ale#path#BufferCdString(a:buffer)
\ . '%e --errorcheck-only '
return '%e --errorcheck-only '
\ . ale#Var(a:buffer, 'mercury_mmc_options')
\ . ' ' . l:module_name
\ . ' %s:t:r'
endfunction
function! ale_linters#mercury#mmc#Handle(buffer, lines) abort
@ -34,6 +31,7 @@ call ale#linter#Define('mercury', {
\ 'name': 'mmc',
\ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'mercury_mmc_executable')},
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#mercury#mmc#GetCommand'),
\ 'callback': 'ale_linters#mercury#mmc#Handle',
\ 'lint_file': 1,

View File

@ -1,18 +1,51 @@
" Author: Alistair Bill <@alibabzo>
" Author: Maximilian Bosch <maximilian@mbosch.me>
" Description: nix-instantiate linter for nix files
function! ale_linters#nix#nix#Command(buffer, output, meta) abort
let l:version = a:output[0][22:]
if l:version =~# '^\(2.4\|3\).*'
return 'nix-instantiate --log-format internal-json --parse -'
else
return 'nix-instantiate --parse -'
endif
endfunction
function! ale_linters#nix#nix#Handle(buffer, lines) abort
let l:pattern = '^\(.\+\): \(.\+\), at .*:\(\d\+\):\(\d\+\)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[3] + 0,
\ 'col': l:match[4] + 0,
\ 'text': l:match[1] . ': ' . l:match[2],
\ 'type': l:match[1] =~# '^error' ? 'E' : 'W',
\})
endfor
if empty(a:lines)
return l:output
endif
if a:lines[0] =~# '^@nix .*'
for l:line in a:lines
if l:line =~# '^@nix .*'
let l:result = json_decode(strpart(l:line, 4))
if has_key(l:result, 'column')
call add(l:output, {
\ 'type': 'E',
\ 'lnum': l:result.line,
\ 'col': l:result.column,
\ 'text': l:result.raw_msg
\})
endif
endif
endfor
else
let l:pattern = '^\(.\+\): \(.\+\) at .*:\(\d\+\):\(\d\+\)$'
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[3] + 0,
\ 'col': l:match[4] + 0,
\ 'text': l:match[1] . ': ' . substitute(l:match[2], ',$', '', ''),
\ 'type': l:match[1] =~# '^error' ? 'E' : 'W',
\})
endfor
endif
return l:output
endfunction
@ -21,6 +54,10 @@ call ale#linter#Define('nix', {
\ 'name': 'nix',
\ 'output_stream': 'stderr',
\ 'executable': 'nix-instantiate',
\ 'command': 'nix-instantiate --parse -',
\ 'command': {buffer -> ale#command#Run(
\ buffer,
\ 'nix-instantiate --version',
\ function('ale_linters#nix#nix#Command')
\ )},
\ 'callback': 'ale_linters#nix#nix#Handle',
\})

View File

@ -0,0 +1,16 @@
" Author: jD91mZM2 <me@krake.one>
" Description: rnix-lsp language client
function! ale_linters#nix#rnix_lsp#GetProjectRoot(buffer) abort
" rnix-lsp does not yet use the project root, so getting it right is not
" important
return fnamemodify(a:buffer, ':h')
endfunction
call ale#linter#Define('nix', {
\ 'name': 'rnix_lsp',
\ 'lsp': 'stdio',
\ 'executable': 'rnix-lsp',
\ 'command': '%e',
\ 'project_root': function('ale_linters#nix#rnix_lsp#GetProjectRoot'),
\})

View File

@ -0,0 +1,13 @@
" Author: Risto Stevcev <me@risto.codes>
" Description: The official language server for OCaml
call ale#Set('ocaml_ocamllsp_use_opam', 1)
call ale#linter#Define('ocaml', {
\ 'name': 'ocamllsp',
\ 'lsp': 'stdio',
\ 'executable': function('ale#handlers#ocamllsp#GetExecutable'),
\ 'command': function('ale#handlers#ocamllsp#GetCommand'),
\ 'language': function('ale#handlers#ocamllsp#GetLanguage'),
\ 'project_root': function('ale#handlers#ocamllsp#GetProjectRoot'),
\})

View File

@ -0,0 +1,17 @@
" Author: Andrey Popp -- @andreypopp
" Description: Report errors in OCaml code with Merlin
if !exists('g:merlin')
finish
endif
function! ale_linters#ocamlinterface#merlin#Handle(buffer, lines) abort
return merlin#ErrorLocList()
endfunction
call ale#linter#Define('ocamlinterface', {
\ 'name': 'merlin',
\ 'executable': 'ocamlmerlin',
\ 'command': 'true',
\ 'callback': 'ale_linters#ocamlinterface#merlin#Handle',
\})

View File

@ -0,0 +1,13 @@
" Author: Risto Stevcev <me@risto.codes>
" Description: The official language server for OCaml
call ale#Set('ocaml_ocamllsp_use_opam', 1)
call ale#linter#Define('ocamlinterface', {
\ 'name': 'ocamllsp',
\ 'lsp': 'stdio',
\ 'executable': function('ale#handlers#ocamllsp#GetExecutable'),
\ 'command': function('ale#handlers#ocamllsp#GetCommand'),
\ 'language': function('ale#handlers#ocamllsp#GetLanguage'),
\ 'project_root': function('ale#handlers#ocamllsp#GetProjectRoot'),
\})

View File

@ -0,0 +1,58 @@
" Author: Horacio Sanson <hsanson@gmail.com>
call ale#Set('openapi_ibm_validator_executable', 'lint-openapi')
call ale#Set('openapi_ibm_validator_options', '')
function! ale_linters#openapi#ibm_validator#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'openapi_ibm_validator_options'))
\ . ' %t'
endfunction
function! ale_linters#openapi#ibm_validator#Handle(buffer, lines) abort
let l:output = []
let l:type = 'E'
let l:message = ''
let l:nr = -1
for l:line in a:lines
let l:match = matchlist(l:line, '^errors$')
if !empty(l:match)
let l:type = 'E'
endif
let l:match = matchlist(l:line, '^warnings$')
if !empty(l:match)
let l:type = 'W'
endif
let l:match = matchlist(l:line, '^ *Message : *\(.\+\)$')
if !empty(l:match)
let l:message = l:match[1]
endif
let l:match = matchlist(l:line, '^ *Line *: *\(\d\+\)$')
if !empty(l:match)
let l:nr = l:match[1]
call add(l:output, {
\ 'lnum': l:nr + 0,
\ 'col': 0,
\ 'text': l:message,
\ 'type': l:type,
\})
endif
endfor
return l:output
endfunction
call ale#linter#Define('openapi', {
\ 'name': 'ibm_validator',
\ 'executable': {b -> ale#Var(b, 'openapi_ibm_validator_executable')},
\ 'command': function('ale_linters#openapi#ibm_validator#GetCommand'),
\ 'callback': 'ale_linters#openapi#ibm_validator#Handle',
\})

View File

@ -0,0 +1,9 @@
call ale#Set('yaml_yamllint_executable', 'yamllint')
call ale#Set('yaml_yamllint_options', '')
call ale#linter#Define('openapi', {
\ 'name': 'yamllint',
\ 'executable': {b -> ale#Var(b, 'yaml_yamllint_executable')},
\ 'command': function('ale#handlers#yamllint#GetCommand'),
\ 'callback': 'ale#handlers#yamllint#Handle',
\})

View File

@ -88,7 +88,7 @@ function! ale_linters#perl6#perl6#Handle(buffer, lines) abort
try
let l:json = json_decode(join(a:lines, ''))
catch /E474/
catch /E474\|E491/
call add(l:output, {
\ 'lnum': '1',
\ 'text': 'Received output in the default Perl6 error format. See :ALEDetail for details',

View File

@ -18,15 +18,15 @@ function! ale_linters#php#intelephense#GetProjectRoot(buffer) abort
return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : ''
endfunction
function! ale_linters#php#intelephense#GetInitializationOptions() abort
return ale#Get('php_intelephense_config')
function! ale_linters#php#intelephense#GetInitializationOptions(buffer) abort
return ale#Var(a:buffer, 'php_intelephense_config')
endfunction
call ale#linter#Define('php', {
\ 'name': 'intelephense',
\ 'lsp': 'stdio',
\ 'initialization_options': function('ale_linters#php#intelephense#GetInitializationOptions'),
\ 'executable': {b -> ale#node#FindExecutable(b, 'php_intelephense', [])},
\ 'executable': {b -> ale#path#FindExecutable(b, 'php_intelephense', [])},
\ 'command': '%e --stdio',
\ 'project_root': function('ale_linters#php#intelephense#GetProjectRoot'),
\})

View File

@ -19,7 +19,7 @@ endfunction
call ale#linter#Define('php', {
\ 'name': 'langserver',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#node#FindExecutable(b, 'php_langserver', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'php_langserver', [
\ 'vendor/bin/php-language-server.php',
\ ])},
\ 'command': 'php %e',

View File

@ -39,7 +39,7 @@ function! ale_linters#php#phan#Handle(buffer, lines) abort
let l:pattern = '^Phan error: \(\w\+\): \(.\+\) in \(.\+\) on line \(\d\+\)$'
else
" /path/to/some-filename.php:18 ERRORTYPE message
let l:pattern = '^.*:\(\d\+\)\s\(\w\+\)\s\(.\+\)$'
let l:pattern = '^\(.*\):\(\d\+\)\s\(\w\+\)\s\(.\+\)$'
endif
let l:output = []
@ -49,13 +49,15 @@ function! ale_linters#php#phan#Handle(buffer, lines) abort
let l:dict = {
\ 'lnum': l:match[4] + 0,
\ 'text': l:match[2],
\ 'filename': l:match[3],
\ 'type': 'W',
\}
else
let l:dict = {
\ 'lnum': l:match[1] + 0,
\ 'text': l:match[3],
\ 'lnum': l:match[2] + 0,
\ 'text': l:match[4],
\ 'type': 'W',
\ 'filename': l:match[1],
\}
endif

View File

@ -13,8 +13,7 @@ function! ale_linters#php#phpcs#GetCommand(buffer) abort
\ ? '--standard=' . ale#Escape(l:standard)
\ : ''
return ale#path#BufferCdString(a:buffer)
\ . '%e -s --report=emacs --stdin-path=%s'
return '%e -s --report=emacs --stdin-path=%s'
\ . ale#Pad(l:standard_option)
\ . ale#Pad(ale#Var(a:buffer, 'php_phpcs_options'))
endfunction
@ -45,10 +44,11 @@ endfunction
call ale#linter#Define('php', {
\ 'name': 'phpcs',
\ 'executable': {b -> ale#node#FindExecutable(b, 'php_phpcs', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'php_phpcs', [
\ 'vendor/bin/phpcs',
\ 'phpcs'
\ ])},
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#php#phpcs#GetCommand'),
\ 'callback': 'ale_linters#php#phpcs#Handle',
\})

View File

@ -6,6 +6,7 @@ let g:ale_php_phpstan_executable = get(g:, 'ale_php_phpstan_executable', 'phpsta
let g:ale_php_phpstan_level = get(g:, 'ale_php_phpstan_level', '')
let g:ale_php_phpstan_configuration = get(g:, 'ale_php_phpstan_configuration', '')
let g:ale_php_phpstan_autoload = get(g:, 'ale_php_phpstan_autoload', '')
call ale#Set('php_phpstan_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#php#phpstan#GetCommand(buffer, version) abort
let l:configuration = ale#Var(a:buffer, 'php_phpstan_configuration')
@ -20,8 +21,9 @@ function! ale_linters#php#phpstan#GetCommand(buffer, version) abort
let l:level = ale#Var(a:buffer, 'php_phpstan_level')
let l:config_file_exists = ale#path#FindNearestFile(a:buffer, 'phpstan.neon')
let l:dist_config_file_exists = ale#path#FindNearestFile(a:buffer, 'phpstan.neon.dist')
if empty(l:level) && empty(l:config_file_exists)
if empty(l:level) && empty(l:config_file_exists) && empty(l:dist_config_file_exists)
" if no configuration file is found, then use 4 as a default level
let l:level = '4'
endif
@ -31,8 +33,8 @@ function! ale_linters#php#phpstan#GetCommand(buffer, version) abort
\ : ''
let l:error_format = ale#semver#GTE(a:version, [0, 10, 3])
\ ? ' --error-format raw'
\ : ' --errorFormat raw'
\ ? ' --error-format json'
\ : ' --errorFormat json'
return '%e analyze --no-progress'
\ . l:error_format
@ -43,17 +45,17 @@ function! ale_linters#php#phpstan#GetCommand(buffer, version) abort
endfunction
function! ale_linters#php#phpstan#Handle(buffer, lines) abort
" Matches against lines like the following:
"
" filename.php:15:message
" C:\folder\filename.php:15:message
let l:pattern = '^\([a-zA-Z]:\)\?[^:]\+:\(\d\+\):\(.*\)$'
let l:res = ale#util#FuzzyJSONDecode(a:lines, {'files': []})
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
if type(l:res.files) is v:t_list
return l:output
endif
for l:err in l:res.files[expand('#' . a:buffer .':p')].messages
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'text': l:match[3],
\ 'lnum': l:err.line,
\ 'text': l:err.message,
\ 'type': 'E',
\})
endfor
@ -63,10 +65,16 @@ endfunction
call ale#linter#Define('php', {
\ 'name': 'phpstan',
\ 'executable': {b -> ale#Var(b, 'php_phpstan_executable')},
\ 'executable': {buffer -> ale#path#FindExecutable(buffer, 'php_phpstan', [
\ 'vendor/bin/phpstan',
\ 'phpstan'
\ ])},
\ 'command': {buffer -> ale#semver#RunWithVersionCheck(
\ buffer,
\ ale#Var(buffer, 'php_phpstan_executable'),
\ ale#path#FindExecutable(buffer, 'php_phpstan', [
\ 'vendor/bin/phpstan',
\ 'phpstan'
\ ]),
\ '%e --version',
\ function('ale_linters#php#phpstan#GetCommand'),
\ )},

View File

@ -18,7 +18,7 @@ endfunction
call ale#linter#Define('php', {
\ 'name': 'psalm',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#node#FindExecutable(b, 'php_psalm', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'php_psalm', [
\ 'vendor/bin/psalm',
\ ])},
\ 'command': function('ale_linters#php#psalm#GetCommand'),

View File

@ -20,7 +20,7 @@ function! ale_linters#php#tlint#GetProjectRoot(buffer) abort
endfunction
function! ale_linters#php#tlint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'php_tlint', [
return ale#path#FindExecutable(a:buffer, 'php_tlint', [
\ 'vendor/bin/tlint',
\ 'tlint',
\])

View File

@ -35,10 +35,11 @@ function! s:Subst(format, vars) abort
endfunction
function! ale_linters#prolog#swipl#Handle(buffer, lines) abort
let l:pattern = '\v^(ERROR|Warning)+%(:\s*[^:]+:(\d+)%(:(\d+))?)?:\s*(.*)$'
let l:output = []
let l:i = 0
let l:pattern = '\v^(ERROR|Warning)+%(:\s*[^:]+:(\d+)%(:(\d+))?)?:\s*(.*)$'
while l:i < len(a:lines)
let l:match = matchlist(a:lines[l:i], l:pattern)
@ -72,8 +73,17 @@ function! s:GetErrMsg(i, lines, text) abort
let l:i = a:i + 1
let l:text = []
while l:i < len(a:lines) && a:lines[l:i] =~# '^\s'
call add(l:text, s:Trim(a:lines[l:i]))
let l:pattern = '\v^(ERROR|Warning)?:?(.*)$'
while l:i < len(a:lines)
let l:match = matchlist(a:lines[l:i], l:pattern)
if empty(l:match) || empty(l:match[2])
let l:i += 1
break
endif
call add(l:text, s:Trim(l:match[2]))
let l:i += 1
endwhile

View File

@ -0,0 +1,24 @@
" Author: Yohei Yoshimuta <yoheimuta@gmail.com>
" Description: run the protolint for Protocol Buffer files
call ale#Set('proto_protolint_executable', 'protolint')
call ale#Set('proto_protolint_config', '')
function! ale_linters#proto#protolint#GetCommand(buffer) abort
let l:config = ale#Var(a:buffer, 'proto_protolint_config')
return '%e lint'
\ . (!empty(l:config) ? ' -config_path=' . ale#Escape(l:config) : '')
\ . ' -reporter=unix'
\ . ' %s'
endfunction
call ale#linter#Define('proto', {
\ 'name': 'protolint',
\ 'lint_file': 1,
\ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'proto_protolint_executable')},
\ 'command': function('ale_linters#proto#protolint#GetCommand'),
\ 'callback': 'ale#handlers#unix#HandleAsError',
\})

View File

@ -47,7 +47,7 @@ endfunction
call ale#linter#Define('pug', {
\ 'name': 'puglint',
\ 'executable': {b -> ale#node#FindExecutable(b, 'pug_puglint', [
\ 'executable': {b -> ale#path#FindExecutable(b, 'pug_puglint', [
\ 'node_modules/.bin/pug-lint',
\ ])},
\ 'output_stream': 'stderr',

View File

@ -6,7 +6,7 @@ call ale#Set('purescript_ls_use_global', get(g:, 'ale_use_global_executables', 0
call ale#Set('purescript_ls_config', {})
function! ale_linters#purescript#ls#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'purescript_ls', [
return ale#path#FindExecutable(a:buffer, 'purescript_ls', [
\ 'node_modules/.bin/purescript-language-server',
\])
endfunction

View File

@ -6,6 +6,7 @@ call ale#Set('python_bandit_options', '')
call ale#Set('python_bandit_use_config', 1)
call ale#Set('python_bandit_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_bandit_auto_pipenv', 0)
call ale#Set('python_bandit_auto_poetry', 0)
function! ale_linters#python#bandit#GetExecutable(buffer) abort
if (
@ -15,6 +16,13 @@ function! ale_linters#python#bandit#GetExecutable(buffer) abort
return 'pipenv'
endif
if (
\ ale#Var(a:buffer, 'python_auto_poetry')
\ || ale#Var(a:buffer, 'python_bandit_auto_poetry')
\) && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_bandit', ['bandit'])
endfunction
@ -31,7 +39,7 @@ function! ale_linters#python#bandit#GetCommand(buffer) abort
endif
endif
let l:exec_args = l:executable =~? 'pipenv$'
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run bandit'
\ : ''

View File

@ -6,6 +6,7 @@ call ale#Set('python_flake8_options', '')
call ale#Set('python_flake8_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_flake8_change_directory', 'project')
call ale#Set('python_flake8_auto_pipenv', 0)
call ale#Set('python_flake8_auto_poetry', 0)
function! s:UsingModule(buffer) abort
return ale#Var(a:buffer, 'python_flake8_options') =~# ' *-m flake8'
@ -17,6 +18,11 @@ function! ale_linters#python#flake8#GetExecutable(buffer) abort
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_flake8_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
if !s:UsingModule(a:buffer)
return ale#python#FindExecutable(a:buffer, 'python_flake8', ['flake8'])
endif
@ -38,33 +44,31 @@ function! ale_linters#python#flake8#RunWithVersionCheck(buffer) abort
\)
endfunction
function! ale_linters#python#flake8#GetCdString(buffer) abort
function! ale_linters#python#flake8#GetCwd(buffer) abort
let l:change_directory = ale#Var(a:buffer, 'python_flake8_change_directory')
let l:cd_string = ''
let l:cwd = ''
if l:change_directory is# 'project'
let l:project_root = ale#python#FindProjectRootIni(a:buffer)
if !empty(l:project_root)
let l:cd_string = ale#path#CdString(l:project_root)
let l:cwd = l:project_root
endif
endif
if (l:change_directory is# 'project' && empty(l:cd_string))
if (l:change_directory is# 'project' && empty(l:cwd))
\|| l:change_directory is# 1
\|| l:change_directory is# 'file'
let l:cd_string = ale#path#BufferCdString(a:buffer)
let l:cwd = '%s:h'
endif
return l:cd_string
return l:cwd
endfunction
function! ale_linters#python#flake8#GetCommand(buffer, version) abort
let l:cd_string = ale_linters#python#flake8#GetCdString(a:buffer)
let l:executable = ale_linters#python#flake8#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv$'
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run flake8'
\ : ''
@ -76,8 +80,7 @@ function! ale_linters#python#flake8#GetCommand(buffer, version) abort
let l:options = ale#Var(a:buffer, 'python_flake8_options')
return l:cd_string
\ . ale#Escape(l:executable) . l:exec_args
return ale#Escape(l:executable) . l:exec_args
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --format=default'
\ . l:display_name_args . ' -'
@ -161,6 +164,7 @@ endfunction
call ale#linter#Define('python', {
\ 'name': 'flake8',
\ 'executable': function('ale_linters#python#flake8#GetExecutable'),
\ 'cwd': function('ale_linters#python#flake8#GetCwd'),
\ 'command': function('ale_linters#python#flake8#RunWithVersionCheck'),
\ 'callback': 'ale_linters#python#flake8#Handle',
\})

View File

@ -7,6 +7,7 @@ call ale#Set('python_mypy_show_notes', 1)
call ale#Set('python_mypy_options', '')
call ale#Set('python_mypy_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_mypy_auto_pipenv', 0)
call ale#Set('python_mypy_auto_poetry', 0)
function! ale_linters#python#mypy#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_mypy_auto_pipenv'))
@ -14,11 +15,16 @@ function! ale_linters#python#mypy#GetExecutable(buffer) abort
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_mypy_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_mypy', ['mypy'])
endfunction
" The directory to change to before running mypy
function! s:GetDir(buffer) abort
function! ale_linters#python#mypy#GetCwd(buffer) abort
" If we find a directory with "mypy.ini" in it use that,
" else try and find the "python project" root, or failing
" that, run from the same folder as the current file
@ -36,24 +42,19 @@ function! s:GetDir(buffer) abort
endfunction
function! ale_linters#python#mypy#GetCommand(buffer) abort
let l:dir = s:GetDir(a:buffer)
let l:executable = ale_linters#python#mypy#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv$'
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run mypy'
\ : ''
" We have to always switch to an explicit directory for a command so
" we can know with certainty the base path for the 'filename' keys below.
return ale#path#CdString(l:dir)
\ . ale#Escape(l:executable) . l:exec_args
\ . ' --show-column-numbers '
\ . ale#Var(a:buffer, 'python_mypy_options')
return '%e' . l:exec_args
\ . ale#Pad(ale#Var(a:buffer, 'python_mypy_options'))
\ . ' --show-column-numbers'
\ . ' --shadow-file %s %t %s'
endfunction
function! ale_linters#python#mypy#Handle(buffer, lines) abort
let l:dir = s:GetDir(a:buffer)
let l:dir = ale_linters#python#mypy#GetCwd(a:buffer)
" Look for lines like the following:
"
" file.py:4: error: No library stub file for module 'django.db'
@ -95,6 +96,7 @@ endfunction
call ale#linter#Define('python', {
\ 'name': 'mypy',
\ 'executable': function('ale_linters#python#mypy#GetExecutable'),
\ 'cwd': function('ale_linters#python#mypy#GetCwd'),
\ 'command': function('ale_linters#python#mypy#GetCommand'),
\ 'callback': 'ale_linters#python#mypy#Handle',
\ 'output_stream': 'both'

View File

@ -2,6 +2,7 @@
" Description: prospector linter python files
call ale#Set('python_prospector_auto_pipenv', 0)
call ale#Set('python_prospector_auto_poetry', 0)
let g:ale_python_prospector_executable =
\ get(g:, 'ale_python_prospector_executable', 'prospector')
@ -17,13 +18,18 @@ function! ale_linters#python#prospector#GetExecutable(buffer) abort
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_prospector_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_prospector', ['prospector'])
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$'
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run prospector'
\ : ''

View File

@ -5,6 +5,7 @@ call ale#Set('python_pycodestyle_executable', 'pycodestyle')
call ale#Set('python_pycodestyle_options', '')
call ale#Set('python_pycodestyle_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_pycodestyle_auto_pipenv', 0)
call ale#Set('python_pycodestyle_auto_poetry', 0)
function! ale_linters#python#pycodestyle#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pycodestyle_auto_pipenv'))
@ -12,13 +13,18 @@ function! ale_linters#python#pycodestyle#GetExecutable(buffer) abort
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_pycodestyle_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_pycodestyle', ['pycodestyle'])
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$'
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run pycodestyle'
\ : ''

View File

@ -5,6 +5,7 @@ call ale#Set('python_pydocstyle_executable', 'pydocstyle')
call ale#Set('python_pydocstyle_options', '')
call ale#Set('python_pydocstyle_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_pydocstyle_auto_pipenv', 0)
call ale#Set('python_pydocstyle_auto_poetry', 0)
function! ale_linters#python#pydocstyle#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pydocstyle_auto_pipenv'))
@ -12,17 +13,21 @@ function! ale_linters#python#pydocstyle#GetExecutable(buffer) abort
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_pydocstyle_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_pydocstyle', ['pydocstyle'])
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$'
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run pydocstyle'
\ : ''
return ale#path#BufferCdString(a:buffer)
\ . ale#Escape(l:executable) . l:exec_args
return ale#Escape(l:executable) . l:exec_args
\ . ale#Pad(ale#Var(a:buffer, 'python_pydocstyle_options'))
\ . ' %s:t'
endfunction
@ -66,6 +71,7 @@ endfunction
call ale#linter#Define('python', {
\ 'name': 'pydocstyle',
\ 'executable': function('ale_linters#python#pydocstyle#GetExecutable'),
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#python#pydocstyle#GetCommand'),
\ 'callback': 'ale_linters#python#pydocstyle#Handle',
\})

View File

@ -4,6 +4,7 @@
call ale#Set('python_pyflakes_executable', 'pyflakes')
call ale#Set('python_pyflakes_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_pyflakes_auto_pipenv', 0)
call ale#Set('python_pyflakes_auto_poetry', 0)
function! ale_linters#python#pyflakes#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pyflakes_auto_pipenv'))
@ -11,13 +12,18 @@ function! ale_linters#python#pyflakes#GetExecutable(buffer) abort
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_pyflakes_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_pyflakes', ['pyflakes'])
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$'
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run pyflakes'
\ : ''

View File

@ -5,6 +5,7 @@ call ale#Set('python_pylama_executable', 'pylama')
call ale#Set('python_pylama_options', '')
call ale#Set('python_pylama_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_pylama_auto_pipenv', 0)
call ale#Set('python_pylama_auto_poetry', 0)
call ale#Set('python_pylama_change_directory', 1)
function! ale_linters#python#pylama#GetExecutable(buffer) abort
@ -13,32 +14,37 @@ function! ale_linters#python#pylama#GetExecutable(buffer) abort
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_pylama_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_pylama', ['pylama'])
endfunction
function! ale_linters#python#pylama#GetCommand(buffer) abort
let l:cd_string = ''
function! ale_linters#python#pylama#GetCwd(buffer) abort
if ale#Var(a:buffer, 'python_pylama_change_directory')
" Pylama loads its configuration from the current directory only, and
" applies file masks using paths relative to the current directory.
" Run from project root, if found, otherwise buffer dir.
let l:project_root = ale#python#FindProjectRoot(a:buffer)
let l:cd_string = l:project_root isnot# ''
\ ? ale#path#CdString(l:project_root)
\ : ale#path#BufferCdString(a:buffer)
return !empty(l:project_root) ? l:project_root : '%s:h'
endif
return ''
endfunction
function! ale_linters#python#pylama#GetCommand(buffer) abort
let l:executable = ale_linters#python#pylama#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv$'
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run pylama'
\ : ''
" Note: Using %t to lint changes would be preferable, but many pylama
" checks use surrounding paths (e.g. C0103 module name, E0402 relative
" import beyond top, etc.). Neither is ideal.
return l:cd_string
\ . ale#Escape(l:executable) . l:exec_args
return ale#Escape(l:executable) . l:exec_args
\ . ale#Pad(ale#Var(a:buffer, 'python_pylama_options'))
\ . ' %s'
endfunction
@ -86,6 +92,7 @@ endfunction
call ale#linter#Define('python', {
\ 'name': 'pylama',
\ 'executable': function('ale_linters#python#pylama#GetExecutable'),
\ 'cwd': function('ale_linters#python#pylama#GetCwd'),
\ 'command': function('ale_linters#python#pylama#GetCommand'),
\ 'callback': 'ale_linters#python#pylama#Handle',
\ 'lint_file': 1,

View File

@ -6,6 +6,7 @@ call ale#Set('python_pylint_options', '')
call ale#Set('python_pylint_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_pylint_change_directory', 1)
call ale#Set('python_pylint_auto_pipenv', 0)
call ale#Set('python_pylint_auto_poetry', 0)
call ale#Set('python_pylint_use_msg_id', 0)
function! ale_linters#python#pylint#GetExecutable(buffer) abort
@ -14,30 +15,34 @@ function! ale_linters#python#pylint#GetExecutable(buffer) abort
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_pylint_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_pylint', ['pylint'])
endfunction
function! ale_linters#python#pylint#GetCommand(buffer, version) abort
let l:cd_string = ''
function! ale_linters#python#pylint#GetCwd(buffer) abort
if ale#Var(a:buffer, 'python_pylint_change_directory')
" pylint only checks for pylintrc in the packages above its current
" directory before falling back to user and global pylintrc.
" Run from project root, if found, otherwise buffer dir.
let l:project_root = ale#python#FindProjectRoot(a:buffer)
let l:cd_string = l:project_root isnot# ''
\ ? ale#path#CdString(l:project_root)
\ : ale#path#BufferCdString(a:buffer)
return !empty(l:project_root) ? l:project_root : '%s:h'
endif
let l:executable = ale_linters#python#pylint#GetExecutable(a:buffer)
return ''
endfunction
let l:exec_args = l:executable =~? 'pipenv$'
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$'
\ ? ' run pylint'
\ : ''
return l:cd_string
\ . ale#Escape(l:executable) . l:exec_args
return ale#Escape(l:executable) . l:exec_args
\ . ale#Pad(ale#Var(a:buffer, 'python_pylint_options'))
\ . ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n'
\ . (ale#semver#GTE(a:version, [2, 4, 0]) ? ' --from-stdin' : '')
@ -104,6 +109,7 @@ call ale#linter#Define('python', {
\ '%e --version',
\ {buffer, version -> !ale#semver#GTE(version, [2, 4, 0])},
\ )},
\ 'cwd': function('ale_linters#python#pylint#GetCwd'),
\ 'command': {buffer -> ale#semver#RunWithVersionCheck(
\ buffer,
\ ale#Var(buffer, 'python_pylint_executable'),

View File

@ -1,36 +0,0 @@
" Author: aurieh <me@aurieh.me>
" Description: A language server for Python
call ale#Set('python_pyls_executable', 'pyls')
call ale#Set('python_pyls_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_pyls_auto_pipenv', 0)
call ale#Set('python_pyls_config', {})
function! ale_linters#python#pyls#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pyls_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
return ale#python#FindExecutable(a:buffer, 'python_pyls', ['pyls'])
endfunction
function! ale_linters#python#pyls#GetCommand(buffer) abort
let l:executable = ale_linters#python#pyls#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv$'
\ ? ' run pyls'
\ : ''
return ale#Escape(l:executable) . l:exec_args
endfunction
call ale#linter#Define('python', {
\ 'name': 'pyls',
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#python#pyls#GetExecutable'),
\ 'command': function('ale_linters#python#pyls#GetCommand'),
\ 'project_root': function('ale#python#FindProjectRoot'),
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
\ 'lsp_config': {b -> ale#Var(b, 'python_pyls_config')},
\})

View File

@ -0,0 +1,43 @@
" Author: aurieh <me@aurieh.me>
" Description: A language server for Python
call ale#Set('python_pylsp_executable', 'pylsp')
call ale#Set('python_pylsp_options', '')
call ale#Set('python_pylsp_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_pylsp_auto_pipenv', 0)
call ale#Set('python_pylsp_auto_poetry', 0)
call ale#Set('python_pylsp_config', {})
function! ale_linters#python#pylsp#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pylsp_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_pylsp_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_pylsp', ['pylsp'])
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$'
\ ? ' run pylsp'
\ : ''
return ale#Escape(l:executable) . l:exec_args . ale#Pad(ale#Var(a:buffer, 'python_pylsp_options'))
endfunction
call ale#linter#Define('python', {
\ 'name': 'pylsp',
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#python#pylsp#GetExecutable'),
\ 'command': function('ale_linters#python#pylsp#GetCommand'),
\ 'project_root': function('ale#python#FindProjectRoot'),
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
\ 'lsp_config': {b -> ale#Var(b, 'python_pylsp_config')},
\})

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