mirror of
1
0
Fork 0

Merge branch 'amix:master' into conf2

This commit is contained in:
kimberw 2024-01-17 20:35:30 +08:00 committed by GitHub
commit 33cfddd257
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
323 changed files with 210800 additions and 2320 deletions

329
README.md
View File

@ -62,6 +62,7 @@ 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
@ -95,7 +96,7 @@ I recommend reading the docs of these plugins to understand them better. Each pl
* [pathogen.vim](https://github.com/tpope/vim-pathogen): Manage your vim runtimepath
* [snipmate.vim](https://github.com/garbas/vim-snipmate): snipmate.vim aims to be a concise vim script that implements some of TextMate's snippets features in Vim
* [ale](https://github.com/dense-analysis/ale): Syntax and lint checking for vim (ALE requires NeoVim >= 0.2.0 or Vim 8 with +timers +job +channel)
* [vim-commentary](https://github.com/tpope/vim-commentary): Comment stuff out. Use `gcc` to comment out a line (takes a count), `gc` to comment out the target of a motion. `gcu` uncomments a set of adjacent commented lines.
* [vim-commentary](https://github.com/tpope/vim-commentary): Comment stuff out. Use `gcc` to comment out a line (takes a count), `gc` to comment out the target of a motion. `gcu` uncomments a set of adjacent commented lines
* [vim-expand-region](https://github.com/terryma/vim-expand-region): Allows you to visually select increasingly larger regions of text using the same key combination
* [vim-fugitive](https://github.com/tpope/vim-fugitive): A Git wrapper so awesome, it should be illegal
* [vim-indent-object](https://github.com/michaeljsmith/vim-indent-object): Defines a new text object representing lines of code at the same indent level. Useful for python/vim scripts
@ -104,11 +105,16 @@ I recommend reading the docs of these plugins to understand them better. Each pl
* [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.
* [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
* [copilot.vim](https://github.com/github/copilot.vim) Plugin for GitHub Copilot (AI autocompletion FTW 😅)
## Included color schemes
Type `:colorscheme <Tab>` to try out color schemes on the fly,
or add the command to `~/.vim_runtime/my_configs.vim` (see [below](#how-to-include-your-own-stuff)),
for example `colorscheme pyte`.
* [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)
@ -133,9 +139,14 @@ I recommend reading the docs of these plugins to understand them better. Each pl
## How to include your own stuff?
After you have installed the setup, you can create **~/.vim_runtime/my_configs.vim** to fill in any configurations that are important for you. For instance, my **my_configs.vim** looks like this:
After you have installed the setup,
create an empty `~/.vim_runtime/my_configs.vim` file for further customization.
This file's syntax matches `vimrc` syntax,
and add `vimrc` lines like `set number` as needed.
~/.vim_runtime (master)> cat my_configs.vim
For instance, my `my_configs.vim` looks like this:
~/.vim_runtime > cat my_configs.vim
map <leader>ct :cd ~/Desktop/Todoist/todoist<cr>
map <leader>cw :cd ~/Desktop/Wedoist/wedoist<cr>
@ -146,7 +157,6 @@ You can also install your plugins, for instance, via pathogen you can install [v
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_runtime/pack/plugins/start`
* Clone the plugin that you want in that directory, for example:\
@ -162,185 +172,189 @@ The [leader](http://learnvimscriptthehardway.stevelosh.com/chapters/06.html#lead
Fast saving of a buffer (`<leader>w`):
nmap <leader>w :w!<cr>
```vim
nmap <leader>w :w!<cr>
```
Map `<Space>` to `/` (search) and `<Ctrl>+<Space>` to `?` (backwards search):
map <space> /
map <C-space> ?
```vim
map <space> /
map <C-space> ?
```
Disable highlights when you press `<leader><cr>`:
map <silent> <leader><cr> :noh<cr>
```vim
map <silent> <leader><cr> :noh<cr>
```
Smart way to move between windows (`<ctrl>j` etc.):
map <C-j> <C-W>j
map <C-k> <C-W>k
map <C-h> <C-W>h
map <C-l> <C-W>l
```vim
map <C-j> <C-W>j
map <C-k> <C-W>k
map <C-h> <C-W>h
map <C-l> <C-W>l
```
Closing of the current buffer(s) (`<leader>bd` and (`<leader>ba`)):
" Close current buffer
map <leader>bd :Bclose<cr>
" Close all buffers
map <leader>ba :1,1000 bd!<cr>
```vim
" Close current buffer
map <leader>bd :Bclose<cr>
" Close all buffers
map <leader>ba :1,1000 bd!<cr>
```
Useful mappings for managing tabs:
map <leader>tn :tabnew<cr>
map <leader>to :tabonly<cr>
map <leader>tc :tabclose<cr>
map <leader>tm :tabmove
" Opens a new tab with the current buffer's path
" Super useful when editing files in the same directory
map <leader>te :tabedit <C-r>=escape(expand("%:p:h"), " ")<cr>/
```vim
map <leader>tn :tabnew<cr>
map <leader>to :tabonly<cr>
map <leader>tc :tabclose<cr>
map <leader>tm :tabmove
" Opens a new tab with the current buffer's path
" Super useful when editing files in the same directory
map <leader>te :tabedit <C-r>=escape(expand("%:p:h"), " ")<cr>/
```
Switch [CWD](http://vim.wikia.com/wiki/Set_working_directory_to_the_current_file) to the directory of the open buffer:
map <leader>cd :cd %:p:h<cr>:pwd<cr>
```vim
map <leader>cd :cd %:p:h<cr>:pwd<cr>
```
Open `ack.vim` for fast search:
map <leader>g :Ack
```vim
map <leader>g :Ack
```
Quickly open a buffer for scripbble:
map <leader>q :e ~/buffer<cr>
```vim
map <leader>q :e ~/buffer<cr>
```
Toggle paste mode on and off:
map <leader>pp :setlocal paste!<cr>
```vim
map <leader>pp :setlocal paste!<cr>
```
### Visual mode mappings
Visual mode pressing `*` or `#` searches for the current selection:
vnoremap <silent> * :call VisualSelection('f')<CR>
vnoremap <silent> # :call VisualSelection('b')<CR>
```vim
vnoremap <silent> * :call VisualSelection('f')<CR>
vnoremap <silent> # :call VisualSelection('b')<CR>
```
When you press gv you `Ack.vim` after the selected text:
vnoremap <silent> gv :call VisualSelection('gv', '')<CR>
```vim
vnoremap <silent> gv :call VisualSelection('gv', '')<CR>
```
When you press `<leader>r` you can search and replace the selected text:
vnoremap <silent> <leader>r :call VisualSelection('replace')<CR>
```vim
vnoremap <silent> <leader>r :call VisualSelection('replace')<CR>
```
Surround the visual selection in parenthesis/brackets/etc.:
vnoremap $1 <esc>`>a)<esc>`<i(<esc>
vnoremap $2 <esc>`>a]<esc>`<i[<esc>
vnoremap $3 <esc>`>a}<esc>`<i{<esc>
vnoremap $$ <esc>`>a"<esc>`<i"<esc>
vnoremap $q <esc>`>a'<esc>`<i'<esc>
vnoremap $e <esc>`>a`<esc>`<i`<esc>
```vim
vnoremap $1 <esc>`>a)<esc>`<i(<esc>
vnoremap $2 <esc>`>a]<esc>`<i[<esc>
vnoremap $3 <esc>`>a}<esc>`<i{<esc>
vnoremap $$ <esc>`>a"<esc>`<i"<esc>
vnoremap $q <esc>`>a'<esc>`<i'<esc>
vnoremap $e <esc>`>a`<esc>`<i`<esc>
```
### Insert mode mappings
Quickly insert parenthesis/brackets/etc.:
inoremap $1 ()<esc>i
inoremap $2 []<esc>i
inoremap $3 {}<esc>i
inoremap $4 {<esc>o}<esc>O
inoremap $q ''<esc>i
inoremap $e ""<esc>i
inoremap $t <><esc>i
```vim
inoremap $1 ()<esc>i
inoremap $2 []<esc>i
inoremap $3 {}<esc>i
inoremap $4 {<esc>o}<esc>O
inoremap $q ''<esc>i
inoremap $e ""<esc>i
inoremap $t <><esc>i
```
Insert the current date and time (useful for timestamps):
iab xdate <C-r>=strftime("%d/%m/%y %H:%M:%S")<cr>
```vim
iab xdate <C-r>=strftime("%d/%m/%y %H:%M:%S")<cr>
```
### Command line mappings
$q is super useful when browsing on the command line. It deletes everything until the last slash:
cno $q <C-\>eDeleteTillSlash()<cr>
```vim
cno $q <C-\>eDeleteTillSlash()<cr>
```
Bash like keys for the command line:
```vim
cnoremap <C-A> <Home>
cnoremap <C-E> <End>
cnoremap <C-K> <C-U>
cnoremap <C-A> <Home>
cnoremap <C-E> <End>
cnoremap <C-K> <C-U>
cnoremap <C-P> <Up>
cnoremap <C-N> <Down>
cnoremap <C-P> <Up>
cnoremap <C-N> <Down>
```
Write the file as sudo (works only on Unix). Super useful when you open a file and you don't have permissions to save your changes. [Vim tip](http://vim.wikia.com/wiki/Su-write):
:W
### Plugin related mappings
Open [bufexplorer](https://github.com/vim-scripts/bufexplorer.zip) to see and manage the current buffers (`<leader>o`):
map <leader>o :BufExplorer<cr>
```vim
map <leader>o :BufExplorer<cr>
```
Open [ctrlp.vim](https://github.com/kien/ctrlp.vim) plugin to quickly find a file or a buffer (`<leader>j` or `<ctrl>f`):
```vim
" Quickly find and open a file in the CWD
let g:ctrlp_map = '<C-f>'
" Quickly find and open a file in the CWD
let g:ctrlp_map = '<C-f>'
" Quickly find and open a recently opened file
map <leader>f :MRU<CR>
" Quickly find and open a buffer
map <leader>b :CtrlPBuffer<cr>
" Quickly find and open a recently opened file
map <leader>f :MRU<CR>
" Quickly find and open a buffer
map <leader>b :CtrlPBuffer<cr>
```
[NERD Tree](https://github.com/preservim/nerdtree) mappings:
map <leader>nn :NERDTreeToggle<cr>
map <leader>nb :NERDTreeFromBookmark
map <leader>nf :NERDTreeFind<cr>
```vim
map <leader>nn :NERDTreeToggle<cr>
map <leader>nb :NERDTreeFromBookmark
map <leader>nf :NERDTreeFind<cr>
```
[goyo.vim](https://github.com/junegunn/goyo.vim) and [vim-zenroom2](https://github.com/amix/vim-zenroom2) lets you only focus on one thing at a time. It removes all the distractions and centers the content. It has a special look when editing Markdown, reStructuredText and textfiles. It only has one mapping. (`<leader>z`)
map <leader>z :Goyo<cr>
```vim
map <leader>z :Goyo<cr>
```
[vim-multiple-cursors](https://github.com/terryma/vim-multiple-cursors) mappings to manage multiple cursors at once:
let g:multi_cursor_start_word_key = '<C-s>'
let g:multi_cursor_select_all_word_key = '<A-s>'
let g:multi_cursor_start_key = 'g<C-s>'
let g:multi_cursor_select_all_key = 'g<A-s>'
let g:multi_cursor_next_key = '<C-s>'
let g:multi_cursor_prev_key = '<C-p>'
let g:multi_cursor_skip_key = '<C-x>'
let g:multi_cursor_quit_key = '<Esc>'
```vim
let g:multi_cursor_start_word_key = '<C-s>'
let g:multi_cursor_select_all_word_key = '<A-s>'
let g:multi_cursor_start_key = 'g<C-s>'
let g:multi_cursor_select_all_key = 'g<A-s>'
let g:multi_cursor_next_key = '<C-s>'
let g:multi_cursor_prev_key = '<C-p>'
let g:multi_cursor_skip_key = '<C-x>'
let g:multi_cursor_quit_key = '<Esc>'
```
[vim-yankstack](https://github.com/maxbrunsfeld/vim-yankstack) mappings to manage the kill-ring (clipboard):
nmap <C-p> <Plug>yankstack_substitute_older_paste
nmap <C-n> <Plug>yankstack_substitute_newer_paste
```vim
nmap <C-p> <Plug>yankstack_substitute_older_paste
nmap <C-n> <Plug>yankstack_substitute_newer_paste
```
[ctrl-p](https://github.com/ctrlpvim/ctrlp.vim) mappings to easily find and open a file, buffer, etc.:
let g:ctrlp_map = '<C-f>'
map <leader>j :CtrlP<cr>
map <C-b> :CtrlPBuffer<cr>
```vim
let g:ctrlp_map = '<C-f>'
map <leader>j :CtrlP<cr>
map <C-b> :CtrlPBuffer<cr>
```
[vim-snipmate](https://github.com/garbas/vim-snipmate) mappings to autocomplete via snippets:
ino <C-j> <C-r>=snipMate#TriggerSnippet()<cr>
snor <C-j> <esc>i<right><C-r>=snipMate#TriggerSnippet()<cr>
```vim
ino <C-j> <C-r>=snipMate#TriggerSnippet()<cr>
snor <C-j> <esc>i<right><C-r>=snipMate#TriggerSnippet()<cr>
```
[vim-surround](https://github.com/tpope/vim-surround) mappings to easily surround a string with `_()` gettext annotation:
vmap Si S(i_<esc>f)
au FileType mako vmap Si S"i${ _(<esc>2f"a) }<esc>
```vim
vmap Si S(i_<esc>f)
au FileType mako vmap Si S"i${ _(<esc>2f"a) }<esc>
```
[ale](https://github.com/dense-analysis/ale) to easily go to the next Ale syntax/lint error:
nmap <silent> <leader>a <Plug>(ale_next_wrap)
```vim
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:
@ -349,29 +363,26 @@ Open [ctrlp.vim](https://github.com/kien/ctrlp.vim) plugin to quickly find a fil
:IndentGuidesToggle
[vim-fugitive](https://github.com/tpope/vim-fugitive) to copy the link to the line of a Git repository to the clipboard:
nnoremap <leader>v :.GBrowse!<CR>
xnoremap <leader>v :'<'>GBrowse!<CR>
```vim
nnoremap <leader>v :.GBrowse!<CR>
xnoremap <leader>v :'<'>GBrowse!<CR>
```
### Spell checking
Pressing `<leader>ss` will toggle spell checking:
map <leader>ss :setlocal spell!<cr>
```vim
map <leader>ss :setlocal spell!<cr>
```
Shortcuts using `<leader>` instead of special characters:
map <leader>sn ]s
map <leader>sp [s
map <leader>sa zg
map <leader>s? z=
```vim
map <leader>sn ]s
map <leader>sp [s
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
```
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!
@ -386,12 +397,12 @@ To go to the previous search results do:
`<leader>p`
Cope mappings:
map <leader>cc :botright cope<cr>
map <leader>co ggVGy:tabnew<cr>:set syntax=qf<cr>pgg
map <leader>n :cn<cr>
map <leader>p :cp<cr>
```vim
map <leader>cc :botright cope<cr>
map <leader>co ggVGy:tabnew<cr>:set syntax=qf<cr>pgg
map <leader>n :cn<cr>
map <leader>p :cp<cr>
```
## How to uninstall
Just do following:

View File

@ -1,4 +1,4 @@
Copyright (c) 2016-2020, w0rp <devw0rp@gmail.com>
Copyright (c) 2016-2023, Dense Analysis
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@ -25,14 +25,24 @@ function! ale_linters#ansible#ansible_lint#Handle(buffer, version, lines) abort
if '>=6.0.0' is# l:version_group
let l:error_codes = { 'blocker': 'E', 'critical': 'E', 'major': 'W', 'minor': 'W', 'info': 'I' }
let l:linter_issues = json_decode(join(a:lines, ''))
let l:linter_issues = ale#util#FuzzyJSONDecode(a:lines, [])
for l:issue in l:linter_issues
if ale#path#IsBufferPath(a:buffer, l:issue.location.path)
if exists('l:issue.location.positions')
let l:coord_keyname = 'positions'
else
let l:coord_keyname = 'lines'
endif
let l:column_member = printf(
\ 'l:issue.location.%s.begin.column', l:coord_keyname
\)
call add(l:output, {
\ 'lnum': exists('l:issue.location.lines.begin.column') ? l:issue.location.lines.begin.line :
\ l:issue.location.lines.begin,
\ 'col': exists('l:issue.location.lines.begin.column') ? l:issue.location.lines.begin.column : 0,
\ 'lnum': exists(l:column_member) ? l:issue.location[l:coord_keyname].begin.line :
\ l:issue.location[l:coord_keyname].begin,
\ 'col': exists(l:column_member) ? l:issue.location[l:coord_keyname].begin.column : 0,
\ 'text': l:issue.check_name,
\ 'detail': l:issue.description,
\ 'code': l:issue.severity,

View File

@ -0,0 +1,47 @@
" Author: Horacio Sanson <https://github.com/hsanson>
" Description: Support ansible language server https://github.com/ansible/ansible-language-server/
call ale#Set('ansible_language_server_executable', 'ansible-language-server')
call ale#Set('ansible_language_server_config', {})
function! ale_linters#ansible#language_server#Executable(buffer) abort
return ale#Var(a:buffer, 'ansible_language_server_executable')
endfunction
function! ale_linters#ansible#language_server#GetCommand(buffer) abort
let l:executable = ale_linters#ansible#language_server#Executable(a:buffer)
return ale#Escape(l:executable) . ' --stdio'
endfunction
function! ale_linters#ansible#language_server#FindProjectRoot(buffer) abort
let l:dir = fnamemodify(
\ ale#path#FindNearestFile(a:buffer, 'ansible.cfg'),
\ ':h'
\)
if l:dir isnot# '.' && isdirectory(l:dir)
return l:dir
endif
let l:dir = fnamemodify(
\ ale#path#FindNearestDirectory(a:buffer, '.git'),
\ ':h:h'
\)
if l:dir isnot# '.' && isdirectory(l:dir)
return l:dir
endif
return ''
endfunction
call ale#linter#Define('ansible', {
\ 'name': 'language_server',
\ 'aliases': ['ansible_language_server', 'ansible-language-server'],
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#ansible#language_server#Executable'),
\ 'command': function('ale_linters#ansible#language_server#GetCommand'),
\ 'project_root': function('ale_linters#ansible#language_server#FindProjectRoot'),
\ 'lsp_config': {b -> ale#Var(b, 'ansible_language_server_config')}
\})

View File

@ -0,0 +1,37 @@
" Author: uidops <uidops@protonmail.com>
" Description: llvm-mc linter for asm files
call ale#Set('asm_llvm_mc_executable', 'llvm-mc')
call ale#Set('asm_llvm_mc_options', '')
function! ale_linters#asm#llvm_mc#GetCommand(buffer) abort
return '%e --assemble'
\ . ' --filetype=asm'
\ . ' -o ' . g:ale#util#nul_file
\ . ' ' . ale#Var(a:buffer, 'asm_llvm_mc_options')
endfunction
function! ale_linters#asm#llvm_mc#Handle(buffer, lines) abort
let l:pattern = '^.\+:\(\d\+\):\(\d\+\): \([^:]\+\): \(.\+\)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'type': l:match[3] =~? 'error' ? 'E' : 'W',
\ 'text': l:match[4],
\})
endfor
return l:output
endfunction
call ale#linter#Define('asm', {
\ 'name': 'llvm_mc',
\ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'asm_llvm_mc_executable')},
\ 'command': function('ale_linters#asm#llvm_mc#GetCommand'),
\ 'callback': 'ale_linters#asm#llvm_mc#Handle',
\})

View File

@ -0,0 +1,69 @@
" Author: Carl Smedstad <carl.smedstad at protonmail dot com>
" Description: az_bicep for bicep files
let g:ale_bicep_az_bicep_executable =
\ get(g:, 'ale_bicep_az_bicep_executable', 'az')
let g:ale_bicep_az_bicep_options =
\ get(g:, 'ale_bicep_az_bicep_options', '')
function! ale_linters#bicep#az_bicep#Executable(buffer) abort
return ale#Var(a:buffer, 'bicep_az_bicep_executable')
endfunction
function! ale_linters#bicep#az_bicep#Command(buffer) abort
let l:executable = ale_linters#bicep#az_bicep#Executable(a:buffer)
let l:options = ale#Var(a:buffer, 'bicep_az_bicep_options')
if has('win32')
let l:nullfile = 'NUL'
else
let l:nullfile = '/dev/null'
endif
return ale#Escape(l:executable)
\ . ' bicep build --outfile '
\ . l:nullfile
\ . ' --file '
\ . '%s '
\ . l:options
endfunction
function! ale_linters#bicep#az_bicep#Handle(buffer, lines) abort
let l:pattern = '\v^([A-Z]+)?(:\s)?(.*)\((\d+),(\d+)\)\s:\s([a-zA-Z]*)\s([-a-zA-Z0-9]*):\s(.*)'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
if l:match[1] is# 'ERROR'
let l:type = 'E'
elseif l:match[1] is# 'WARNING'
let l:type = 'W'
elseif l:match[6] is# 'Error'
let l:type = 'E'
elseif l:match[6] is# 'Warning'
let l:type = 'W'
else
let l:type = 'I'
endif
call add(l:output, {
\ 'filename': l:match[3],
\ 'lnum': l:match[4] + 0,
\ 'col': l:match[5] + 0,
\ 'type': l:type,
\ 'code': l:match[7],
\ 'text': l:match[8],
\})
endfor
return l:output
endfunction
call ale#linter#Define('bicep', {
\ 'name': 'az_bicep',
\ 'executable': function('ale_linters#bicep#az_bicep#Executable'),
\ 'command': function('ale_linters#bicep#az_bicep#Command'),
\ 'callback': 'ale_linters#bicep#az_bicep#Handle',
\ 'output_stream': 'stderr',
\ 'lint_file': 1,
\})

View File

@ -30,24 +30,25 @@ function! ale_linters#bicep#bicep#Command(buffer) abort
endfunction
function! ale_linters#bicep#bicep#Handle(buffer, lines) abort
let l:pattern = '\v^.*\((\d+),(\d+)\)\s:\s([a-zA-Z]*)\s([-a-zA-Z0-9]*):\s(.*)'
let l:pattern = '\v^(.*)\((\d+),(\d+)\)\s:\s([a-zA-Z]*)\s([-a-zA-Z0-9]*):\s(.*)'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
if l:match[3] is# 'Error'
if l:match[4] is# 'Error'
let l:type = 'E'
elseif l:match[3] is# 'Warning'
elseif l:match[4] is# 'Warning'
let l:type = 'W'
else
let l:type = 'I'
endif
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'filename': l:match[1],
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'type': l:type,
\ 'code': l:match[4],
\ 'text': l:match[5],
\ 'code': l:match[5],
\ 'text': l:match[6],
\})
endfor

View File

@ -0,0 +1,40 @@
" Author: Chuck Grindel <chuck.grindel@gmail.com>
" Description: Bazel Starlark lint support using buildifier.
function! ale_linters#bzl#buildifier#GetCommand(buffer) abort
let l:executable = ale#Escape(ale#fixers#buildifier#GetExecutable(a:buffer))
let l:options = ale#Var(a:buffer, 'bazel_buildifier_options')
let l:filename = ale#Escape(bufname(a:buffer))
let l:command = l:executable . ' -mode check -lint warn -path %s'
if l:options isnot# ''
let l:command .= ' ' . l:options
endif
return l:command
endfunction
function! ale_linters#bzl#buildifier#Handle(buffer, lines) abort
let l:pattern = '\v^[^:]+:(\d+):(\d+)?:?\s+(syntax error near)?(.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[3] . l:match[4],
\ 'type': l:match[3] is# 'syntax error near' ? 'E' : 'W',
\})
endfor
return l:output
endfunction
call ale#linter#Define('bzl', {
\ 'name': 'buildifier',
\ 'output_stream': 'both',
\ 'executable': function('ale#fixers#buildifier#GetExecutable'),
\ 'command': function('ale_linters#bzl#buildifier#GetCommand'),
\ 'callback': function('ale_linters#bzl#buildifier#Handle'),
\})

View File

@ -0,0 +1,38 @@
" Author: gagbo <gagbobada@gmail.com>
" : luibo <ng.akhoa98@gmail.com>
" : Jorengarenar <jorengarenar@outlook.com>
" Description: clang-check linter for C files
" modified from cpp/clangcheck.vim to match for C
call ale#Set('c_clangcheck_executable', 'clang-check')
call ale#Set('c_clangcheck_options', '')
call ale#Set('c_build_dir', '')
function! ale_linters#c#clangcheck#GetCommand(buffer) abort
let l:user_options = ale#Var(a:buffer, 'c_clangcheck_options')
" Try to find compilation database to link automatically
let l:build_dir = ale#Var(a:buffer, 'c_build_dir')
if empty(l:build_dir)
let [l:root, l:json_file] = ale#c#FindCompileCommands(a:buffer)
let l:build_dir = ale#path#Dirname(l:json_file)
endif
" The extra arguments in the command are used to prevent .plist files from
" being generated. These are only added if no build directory can be
" detected.
return '%e -analyze %s'
\ . (empty(l:build_dir) ? ' --extra-arg=-Xclang --extra-arg=-analyzer-output=text --extra-arg=-fno-color-diagnostics': '')
\ . ale#Pad(l:user_options)
\ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '')
endfunction
call ale#linter#Define('c', {
\ 'name': 'clangcheck',
\ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'c_clangcheck_executable')},
\ 'command': function('ale_linters#c#clangcheck#GetCommand'),
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'lint_file': 1,
\})

View File

@ -0,0 +1,31 @@
" Author: 0xhyoga <0xhyoga@gmx.com>,
" Description: scarb for cairo files
function! ale_linters#cairo#scarb#GetScarbExecutable(bufnr) abort
if ale#path#FindNearestFile(a:bufnr, 'Scarb.toml') isnot# ''
return 'scarb'
else
" if there is no Scarb.toml file, we don't use scarb even if it exists,
" so we return '', because executable('') apparently always fails
return ''
endif
endfunction
function! ale_linters#cairo#scarb#GetCommand(buffer, version) abort
return 'scarb build'
endfunction
call ale#linter#Define('cairo', {
\ 'name': 'scarb',
\ 'executable': function('ale_linters#cairo#scarb#GetScarbExecutable'),
\ 'command': {buffer -> ale#semver#RunWithVersionCheck(
\ buffer,
\ ale_linters#cairo#scarb#GetScarbExecutable(buffer),
\ '%e --version',
\ function('ale_linters#cairo#scarb#GetCommand'),
\ )},
\ 'callback': 'ale#handlers#cairo#HandleCairoErrors',
\ 'output_stream': 'both',
\ 'lint_file': 1,
\})

View File

@ -0,0 +1,54 @@
" Author: 0xHyoga <0xHyoga@gmx.com>
" Description: Report Starknet compile to sierra errors in cairo 1.0 code
call ale#Set('cairo_sierra_executable', 'starknet-compile')
call ale#Set('cairo_sierra_options', '')
function! ale_linters#cairo#sierra#Handle(buffer, lines) abort
" Matches patterns like the following:
" Error: Expected ';' but got '('
" --> /path/to/file/file.cairo:1:10:)
let l:pattern = '\v(error|warning): (.*)$'
let l:line_and_column_pattern = '\v\.cairo:(\d+):(\d+)'
let l:output = []
for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
let l:match = matchlist(l:line, l:line_and_column_pattern)
if len(l:match) > 0
let l:index = len(l:output) - 1
let l:output[l:index]['lnum'] = l:match[1] + 0
let l:output[l:index]['col'] = l:match[2] + 0
endif
else
let l:isError = l:match[1] is? 'Error'
call add(l:output, {
\ 'lnum': 0,
\ 'col': 0,
\ 'text': l:match[2],
\ 'type': l:isError ? 'E' : 'W',
\})
endif
endfor
return l:output
endfunction
function! ale_linters#cairo#sierra#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'cairo_sierra_executable')
return l:executable . ale#Pad(ale#Var(a:buffer, 'cairo_sierra_options')) . ' %s'
endfunction
call ale#linter#Define('cairo', {
\ 'name': 'sierra',
\ 'executable': {b -> ale#Var(b, 'cairo_sierra_executable')},
\ 'command': function('ale_linters#cairo#sierra#GetCommand'),
\ 'callback': 'ale_linters#cairo#sierra#Handle',
\ 'output_stream': 'stderr',
\})

View File

@ -1,5 +1,6 @@
" Author: 0xHyoga <0xHyoga@gmx.com>
" Description: Report starknet-compile errors in cairo code
" Description: Report starknet-compile errors in cairo code (pre-starknet
" 1.0). This is deprecated but kept for backwards compatability.
call ale#Set('cairo_starknet_executable', 'starknet-compile')
call ale#Set('cairo_starknet_options', '')
@ -35,3 +36,4 @@ call ale#linter#Define('cairo', {
\ 'callback': 'ale_linters#cairo#starknet#Handle',
\ 'output_stream': 'stderr',
\})

View File

@ -1,4 +1,5 @@
" Author: Taylor Blau <me@ttaylorr.com>
call ale#Set('dafny_dafny_timelimit', 10)
function! ale_linters#dafny#dafny#Handle(buffer, lines) abort
let l:pattern = '\v(.*)\((\d+),(\d+)\): (.*): (.*)'
@ -31,7 +32,6 @@ 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',

View File

@ -0,0 +1,69 @@
" Author: Shad
" Description: dockerlinter linter for dockerfile
call ale#Set('dockerfile_dockerlinter_executable', 'dockerlinter')
call ale#Set('dockerfile_dockerlinter_options', '')
function! ale_linters#dockerfile#dockerlinter#GetType(type) abort
if a:type is? 'error'
return 'E'
elseif a:type is? 'warning'
return 'W'
endif
return 'I'
endfunction
function! ale_linters#dockerfile#dockerlinter#Handle(buffer, lines) abort
try
let l:data = json_decode(join(a:lines, ''))
catch
return []
endtry
if empty(l:data)
" Should never happen, but it's better to be on the safe side
return []
endif
let l:messages = []
for l:object in l:data
let l:line = get(l:object, 'lineNumber', -1)
let l:message = l:object['message']
let l:type = l:object['level']
let l:detail = l:message
let l:code = l:object['code']
if l:code =~# '^SC'
let l:link = 'https://www.shellcheck.net/wiki/' . l:code
else
let l:link = 'https://github.com/buddy-works/dockerfile-linter/blob/master/Rules.md#' . l:code
endif
let l:detail = l:message . "\n\n" . l:link
call add(l:messages, {
\ 'lnum': l:line,
\ 'code': l:code,
\ 'text': l:message,
\ 'type': ale_linters#dockerfile#dockerlinter#GetType(l:type),
\ 'detail': l:detail,
\})
endfor
return l:messages
endfunction
function! ale_linters#dockerfile#dockerlinter#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'dockerfile_dockerlinter_options'))
\ . ' -j -f'
\ . ' %t'
endfunction
call ale#linter#Define('dockerfile', {
\ 'name': 'dockerlinter',
\ 'executable': {b -> ale#Var(b, 'dockerfile_dockerlinter_executable')},
\ 'command': function('ale_linters#dockerfile#dockerlinter#GetCommand'),
\ 'callback': 'ale_linters#dockerfile#dockerlinter#Handle',
\})

View File

@ -1,5 +1,5 @@
" Author: Jon Parise <jon@indelible.org>
" Description: ElixirLS integration (https://github.com/JakeBecker/elixir-ls)
" Description: ElixirLS integration (https://github.com/elixir-lsp/elixir-ls)
call ale#Set('elixir_elixir_ls_release', 'elixir-ls')
call ale#Set('elixir_elixir_ls_config', {})
@ -12,7 +12,8 @@ function! ale_linters#elixir#elixir_ls#GetExecutable(buffer) abort
endfunction
call ale#linter#Define('elixir', {
\ 'name': 'elixir-ls',
\ 'name': 'elixir_ls',
\ 'aliases': ['elixir-ls', 'elixirls'],
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#elixir#elixir_ls#GetExecutable'),
\ 'command': function('ale_linters#elixir#elixir_ls#GetExecutable'),

View File

@ -0,0 +1,19 @@
" Author: Axel Clark <axelclark@pm.me>
" Description: Lexical integration (https://github.com/lexical-lsp/lexical)
call ale#Set('elixir_lexical_release', 'lexical')
function! ale_linters#elixir#lexical#GetExecutable(buffer) abort
let l:dir = ale#path#Simplify(ale#Var(a:buffer, 'elixir_lexical_release'))
let l:cmd = has('win32') ? '\start_lexical.bat' : '/start_lexical.sh'
return l:dir . l:cmd
endfunction
call ale#linter#Define('elixir', {
\ 'name': 'lexical',
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#elixir#lexical#GetExecutable'),
\ 'command': function('ale_linters#elixir#lexical#GetExecutable'),
\ 'project_root': function('ale#handlers#elixir#FindMixUmbrellaRoot'),
\})

View File

@ -10,13 +10,13 @@ call ale#Set('elm_ls_elm_format_path', '')
call ale#Set('elm_ls_elm_test_path', '')
call ale#Set('elm_ls_elm_analyse_trigger', 'change')
function! elm_ls#GetRootDir(buffer) abort
function! ale_linters#elm#ls#GetProjectRoot(buffer) abort
let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm.json')
return !empty(l:elm_json) ? fnamemodify(l:elm_json, ':p:h') : ''
endfunction
function! elm_ls#GetOptions(buffer) abort
function! ale_linters#elm#ls#GetOptions(buffer) abort
return {
\ 'elmPath': ale#Var(a:buffer, 'elm_ls_elm_path'),
\ 'elmFormatPath': ale#Var(a:buffer, 'elm_ls_elm_format_path'),
@ -26,7 +26,8 @@ function! elm_ls#GetOptions(buffer) abort
endfunction
call ale#linter#Define('elm', {
\ 'name': 'elm_ls',
\ 'name': 'ls',
\ 'aliases': ['elm_ls'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#path#FindExecutable(b, 'elm_ls', [
\ 'node_modules/.bin/elm-language-server',
@ -34,7 +35,7 @@ call ale#linter#Define('elm', {
\ 'elm-lsp'
\ ])},
\ 'command': '%e --stdio',
\ 'project_root': function('elm_ls#GetRootDir'),
\ 'project_root': function('ale_linters#elm#ls#GetProjectRoot'),
\ 'language': 'elm',
\ 'initialization_options': function('elm_ls#GetOptions')
\})

View File

@ -11,7 +11,7 @@ function! ale_linters#eruby#erb#GetCommand(buffer) abort
" Rails-flavored eRuby does not comply with the standard as understood by
" ERB, so we'll have to do some substitution. This does not reduce the
" effectiveness of the linter—the translated code is still evaluated.
return 'ruby -r erb -e ' . ale#Escape('puts ERB.new($stdin.read.gsub(%{<%=},%{<%}), nil, %{-}).src') . '< %t | ruby -c'
return 'ruby -r erb -e ' . ale#Escape('puts ERB.new($stdin.read.gsub(%{<%=},%{<%}), trim_mode: %{-}).src') . '< %t | ruby -c'
endfunction
call ale#linter#Define('eruby', {

View File

@ -12,6 +12,7 @@ endfunction
call ale#linter#Define('fortran', {
\ 'name': 'language_server',
\ 'aliases': ['fortls'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'fortran_language_server_executable')},
\ 'command': '%e',

View File

@ -17,13 +17,15 @@ function! ale_linters#glsl#glslang#Handle(buffer, lines) abort
" Matches patterns like the following:
"
" ERROR: 0:5: 'foo' : undeclared identifier
let l:pattern = '^\(.\+\): \(\d\+\):\(\d\+\): \(.\+\)'
" or when using options like -V or -G or --target-env
" ERROR: filename:5: 'foo' : undeclared identifier
let l:pattern = '^\(.\+\): \(.\+\):\(\d\+\): \(.\+\)'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': str2nr(l:match[3]),
\ 'col': str2nr(l:match[2]),
\ 'col' : 0,
\ 'text': l:match[4],
\ 'type': l:match[1] is# 'ERROR' ? 'E' : 'W',
\})

View File

@ -6,16 +6,6 @@
call ale#Set('go_go_executable', 'go')
call ale#Set('go_gobuild_options', '')
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#go#EnvString(a:buffer)
\ . ale#Var(a:buffer, 'go_go_executable') . ' test'
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' -c -o /dev/null ./'
endfunction
function! ale_linters#go#gobuild#GetMatches(lines) abort
" Matches patterns like the following:
"
@ -50,7 +40,12 @@ call ale#linter#Define('go', {
\ 'aliases': ['go build'],
\ 'executable': {b -> ale#Var(b, 'go_go_executable')},
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#go#gobuild#GetCommand'),
\ 'command': {b ->
\ ale#go#EnvString(b)
\ . ale#Escape(ale#Var(b, 'go_go_executable')) . ' test'
\ . ale#Pad(ale#Var(b, 'go_gobuild_options'))
\ . ' -c -o /dev/null ./'
\ },
\ 'output_stream': 'stderr',
\ 'callback': 'ale_linters#go#gobuild#Handler',
\ 'lint_file': 1,

View File

@ -1,7 +1,7 @@
" Author: Sascha Grunert <mail@saschagrunert.de>
" Description: Adds support of golangci-lint
call ale#Set('go_golangci_lint_options', '--enable-all')
call ale#Set('go_golangci_lint_options', '')
call ale#Set('go_golangci_lint_executable', 'golangci-lint')
call ale#Set('go_golangci_lint_package', 0)

View File

@ -1,21 +0,0 @@
" Author: neersighted <bjorn@neersighted.com>
" Description: golint for Go files
call ale#Set('go_golint_executable', 'golint')
call ale#Set('go_golint_options', '')
function! ale_linters#go#golint#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'go_golint_options')
return ale#go#EnvString(a:buffer) . '%e'
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %t'
endfunction
call ale#linter#Define('go', {
\ 'name': 'golint',
\ 'output_stream': 'both',
\ 'executable': {b -> ale#Var(b, 'go_golint_executable')},
\ 'command': function('ale_linters#go#golint#GetCommand'),
\ 'callback': 'ale#handlers#unix#HandleAsWarning',
\})

View File

@ -1,58 +0,0 @@
" Author: Ben Reedy <https://github.com/breed808>, Jeff Willette <jrwillette88@gmail.com>
" Description: Adds support for the gometalinter suite for Go files
call ale#Set('go_gometalinter_options', '')
call ale#Set('go_gometalinter_executable', 'gometalinter')
call ale#Set('go_gometalinter_lint_package', 0)
function! ale_linters#go#gometalinter#GetCommand(buffer) abort
let l:filename = expand('#' . a:buffer . ':t')
let l:options = ale#Var(a:buffer, 'go_gometalinter_options')
let l:lint_package = ale#Var(a:buffer, 'go_gometalinter_lint_package')
" 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#go#EnvString(a:buffer)
\ . '%e'
\ . (!empty(l:options) ? ' ' . l:options : '') . ' .'
endif
return ale#go#EnvString(a:buffer)
\ . '%e'
\ . ' --include=' . ale#Escape(ale#util#EscapePCRE(l:filename))
\ . (!empty(l:options) ? ' ' . l:options : '') . ' .'
endfunction
function! ale_linters#go#gometalinter#GetMatches(lines) abort
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:?:?(warning|error):?\s\*?(.+)$'
return ale#util#GetMatches(a:lines, l:pattern)
endfunction
function! ale_linters#go#gometalinter#Handler(buffer, lines) abort
let l:dir = expand('#' . a:buffer . ':p:h')
let l:output = []
for l:match in ale_linters#go#gometalinter#GetMatches(a:lines)
" l:match[1] will already be an absolute path, output from gometalinter
call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]),
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'type': tolower(l:match[4]) is# 'warning' ? 'W' : 'E',
\ 'text': l:match[5],
\})
endfor
return l:output
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

@ -1,28 +1,21 @@
" Author: neersighted <bjorn@neersighted.com>
" Author: neersighted <bjorn@neersighted.com>, John Eikenberry <jae@zhar.net>
" Description: go vet for Go files
"
" Author: John Eikenberry <jae@zhar.net>
" Description: updated to work with go1.10
call ale#Set('go_go_executable', 'go')
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#go#EnvString(a:buffer)
\ . ale#Var(a:buffer, 'go_go_executable') . ' vet '
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' .'
endfunction
call ale#linter#Define('go', {
\ 'name': 'govet',
\ 'aliases': ['go vet'],
\ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'go_go_executable')},
\ 'cwd': '%s:h',
\ 'command': function('ale_linters#go#govet#GetCommand'),
\ 'command': {b ->
\ ale#go#EnvString(b)
\ . '%e vet'
\ . ale#Pad(ale#Var(b, 'go_govet_options'))
\ . ' .'
\ },
\ 'callback': 'ale#handlers#go#Handler',
\ 'lint_file': 1,
\})

View File

@ -0,0 +1,46 @@
" Author: lucas-str <lucas.sturelle@ik.me>
" Description: Integration of npm-groovy-lint for Groovy files.
call ale#Set('groovy_npmgroovylint_executable', 'npm-groovy-lint')
call ale#Set('groovy_npmgroovylint_options', '--loglevel warning')
function! ale_linters#groovy#npmgroovylint#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'groovy_npmgroovylint_options')
return '%e --failon none --output json'
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %t'
endfunction
function! ale_linters#groovy#npmgroovylint#Handle(buffer, lines) abort
let l:output = []
let l:json = ale#util#FuzzyJSONDecode(a:lines, {})
for [l:filename, l:file] in items(get(l:json, 'files', {}))
for l:error in get(l:file, 'errors', [])
let l:output_line = {
\ 'filename': l:filename,
\ 'lnum': l:error.line,
\ 'text': l:error.msg,
\ 'type': toupper(l:error.severity[0]),
\}
if has_key(l:error, 'range')
let l:output_line.col = l:error.range.start.character
let l:output_line.end_col = l:error.range.end.character
let l:output_line.end_lnum = l:error.range.end.line
endif
call add(l:output, l:output_line)
endfor
endfor
return l:output
endfunction
call ale#linter#Define('groovy', {
\ 'name': 'npm-groovy-lint',
\ 'executable': {b -> ale#Var(b, 'groovy_npmgroovylint_executable')},
\ 'command': function('ale_linters#groovy#npmgroovylint#GetCommand'),
\ 'callback': 'ale_linters#groovy#npmgroovylint#Handle',
\})

View File

@ -16,12 +16,7 @@ function! ale_linters#handlebars#embertemplatelint#GetCommand(buffer, version) a
return '%e --format=json --filename %s'
endif
if ale#semver#GTE(a:version, [1, 6, 0])
" Reading from stdin was introduced in ember-template-lint@1.6.0
return '%e --json --filename %s'
endif
return '%e --json %t'
return '%e --json --filename %s'
endfunction
function! ale_linters#handlebars#embertemplatelint#GetCommandWithVersionCheck(buffer) abort

View File

@ -16,8 +16,9 @@ function! ale_linters#haskell#hls#FindRootFile(buffer) abort
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
if filereadable(l:path . '/' . l:root_file)
" Add on / so fnamemodify(..., ':h') below keeps the path.
return l:path . '/'
endif
endfor
endfor

View File

@ -48,7 +48,7 @@ endfunction
call ale#linter#Define('html', {
\ 'name': 'angular',
\ 'aliases': ['angular-language-server'],
\ 'aliases': ['angular-language-server', 'angularls'],
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#html#angular#GetExecutable'),
\ 'command': function('ale_linters#html#angular#GetCommand'),

View File

@ -0,0 +1,12 @@
" Author: Victor Ananyev <vindex10@gmail.com>
" Description: eslint for js snippets in HTML files
call ale#linter#Define('html', {
\ '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

@ -46,6 +46,7 @@ endfunction
call ale#linter#Define('java', {
\ 'name': 'javalsp',
\ 'aliases': ['java_language_server'],
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#java#javalsp#Executable'),
\ 'command': function('ale_linters#java#javalsp#Command'),

View File

@ -17,7 +17,8 @@ function! ale_linters#javascript#flow_ls#FindProjectRoot(buffer) abort
endfunction
call ale#linter#Define('javascript', {
\ 'name': 'flow-language-server',
\ 'name': 'flow_ls',
\ 'aliaes': ['flow-language-server'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#path#FindExecutable(b, 'javascript_flow_ls', [
\ 'node_modules/.bin/flow',

View File

@ -1,6 +1,22 @@
" Author: Dalius Dobravolskas <dalius.dobravolskas@gmail.com>
" Description: VSCode json language server
call ale#Set('json_vscodejson_executable', '<auto>')
function! ale_linters#json#vscodejson#GetExecutable(buffer) abort
let l:executable = ale#Var(a:buffer, 'json_vscodejson_executable')
if l:executable is# '<auto>'
if ale#engine#IsExecutable(a:buffer, 'vscode-json-languageserver')
let l:executable = 'vscode-json-languageserver'
else
let l:executable = 'vscode-json-language-server'
endif
endif
return l:executable
endfunction
function! ale_linters#json#vscodejson#GetProjectRoot(buffer) abort
let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
@ -10,7 +26,7 @@ endfunction
call ale#linter#Define('json', {
\ 'name': 'vscodejson',
\ 'lsp': 'stdio',
\ 'executable': 'vscode-json-language-server',
\ 'executable': function('ale_linters#json#vscodejson#GetExecutable'),
\ 'command': '%e --stdio',
\ 'project_root': function('ale_linters#json#vscodejson#GetProjectRoot'),
\})

View File

@ -13,6 +13,7 @@ endfunction
call ale#linter#Define('julia', {
\ 'name': 'languageserver',
\ 'aliases': ['julials'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'julia_executable')},
\ 'command': function('ale_linters#julia#languageserver#GetCommand'),

View File

@ -21,6 +21,7 @@ endfunction
call ale#linter#Define('kotlin', {
\ 'name': 'languageserver',
\ 'aliaes': ['kotlin_language_server'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'kotlin_languageserver_executable')},
\ 'command': '%e',

View File

@ -0,0 +1,15 @@
" Author: w0rp <dev@w0rp.com>
" Description: lua-language-server integration (https://github.com/LuaLS/lua-language-server)
call ale#Set('lua_language_server_executable', 'lua-language-server')
call ale#Set('lua_language_server_config', {})
call ale#linter#Define('lua', {
\ 'name': 'lua_language_server',
\ 'aliases': ['lua-language-server', 'lua_ls'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'lua_language_server_executable')},
\ 'command': '%e',
\ 'project_root': function('ale#lua#FindProjectRoot'),
\ 'lsp_config': {b -> ale#Var(b, 'lua_language_server_config')},
\})

View File

@ -4,8 +4,43 @@
call ale#Set('lua_luacheck_executable', 'luacheck')
call ale#Set('lua_luacheck_options', '')
function! s:IsInRuntimepath(buffer) abort
let l:runtimepath_dirs = split(&runtimepath, ',')
for l:dir in ale#path#Upwards(expand('#' . a:buffer . ':p:h'))
for l:runtime_dir in l:runtimepath_dirs
if l:dir is# l:runtime_dir
return 1
endif
endfor
endfor
return 0
endfunction
function! ale_linters#lua#luacheck#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'lua_luacheck_options'))
let l:options = ale#Var(a:buffer, 'lua_luacheck_options')
" Add `--globals vim` by default if the file is in runtimepath.
if l:options !~# '--globals'
let l:in_runtime = getbufvar(a:buffer, 'ale_in_runtimepath', v:null)
if l:in_runtime is v:null
let l:in_runtime = s:IsInRuntimepath(a:buffer)
" Save the result of check this buffer so we only check once.
call setbufvar(a:buffer, 'ale_in_runtimepath', l:in_runtime)
endif
if l:in_runtime
if !empty(l:options)
let l:options .= ' '
endif
let l:options .= '--globals vim'
endif
endif
return '%e' . ale#Pad(l:options)
\ . ' --formatter plain --codes --filename %s -'
endfunction

View File

@ -1,10 +1,15 @@
" Author: Ty-Lucas Kelley <tylucaskelley@gmail.com>
" Description: Adds support for markdownlint
call ale#Set('markdown_markdownlint_executable', 'markdownlint')
call ale#Set('markdown_markdownlint_options', '')
function! ale_linters#markdown#markdownlint#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'markdown_markdownlint_executable')
endfunction
function! ale_linters#markdown#markdownlint#GetCommand(buffer) abort
let l:executable = 'markdownlint'
let l:executable = ale_linters#markdown#markdownlint#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'markdown_markdownlint_options')
@ -14,7 +19,7 @@ endfunction
call ale#linter#Define('markdown', {
\ 'name': 'markdownlint',
\ 'executable': 'markdownlint',
\ 'executable': function('ale_linters#markdown#markdownlint#GetExecutable'),
\ 'lint_file': 1,
\ 'output_stream': 'both',
\ 'command': function('ale_linters#markdown#markdownlint#GetCommand'),

View File

@ -0,0 +1,35 @@
" Author: Peter Benjamin <petermbenjamin@gmail.com>
" Description: Write Markdown with code assist and intelligence in the comfort of your favourite editor.
call ale#Set('markdown_marksman_executable', 'marksman')
function! ale_linters#markdown#marksman#GetCommand(buffer) abort
return '%e server'
endfunction
function! ale_linters#markdown#marksman#GetProjectRoot(buffer) abort
" Find nearest .marksman.toml
let l:marksman_toml = ale#path#FindNearestFile(a:buffer, '.marksman.toml')
if !empty(l:marksman_toml)
return fnamemodify(l:marksman_toml, ':h')
endif
" Find nearest .git/ directory
let l:project_root = finddir('.git/..', expand('#' . a:buffer . '...').';')
if !empty(l:project_root)
return l:project_root
endif
return ''
endfunction
call ale#linter#Define('markdown', {
\ 'name': 'marksman',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'markdown_marksman_executable')},
\ 'command': function('ale_linters#markdown#marksman#GetCommand'),
\ 'project_root': function('ale_linters#markdown#marksman#GetProjectRoot'),
\ 'initialization_options': {},
\})

View File

@ -0,0 +1,13 @@
call ale#Set('nix_deadnix_executable', 'deadnix')
call ale#Set('nix_deadnix_options', '')
function! ale_linters#nix#deadnix#GetCommand(buffer) abort
return '%e -o json' . ale#Pad(ale#Var(a:buffer, 'nix_deadnix_options')) . ' -- %t'
endfunction
call ale#linter#Define('nix', {
\ 'name': 'deadnix',
\ 'executable': {b -> ale#Var(b, 'nix_deadnix_executable')},
\ 'command': function('ale_linters#nix#deadnix#GetCommand'),
\ 'callback': 'ale#handlers#deadnix#Handle',
\})

View File

@ -5,10 +5,10 @@
function! ale_linters#nix#nix#Command(buffer, output, meta) abort
let l:version = a:output[0][22:]
if l:version =~# '^\(2.[4-9]\|3\).*'
return 'nix-instantiate --log-format internal-json --parse -'
else
if l:version =~# '^\(1\|2.[0-3]\.\).*'
return 'nix-instantiate --parse -'
else
return 'nix-instantiate --log-format internal-json --parse -'
endif
endfunction

View File

@ -9,6 +9,7 @@ endfunction
call ale#linter#Define('nix', {
\ 'name': 'rnix_lsp',
\ 'aliases': ['rnix'],
\ 'lsp': 'stdio',
\ 'executable': 'rnix-lsp',
\ 'command': '%e',

View File

@ -6,6 +6,7 @@ call ale#Set('ocaml_ols_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#linter#Define('ocaml', {
\ 'name': 'ols',
\ 'aliases': ['ocaml-language-server'],
\ 'lsp': 'stdio',
\ 'executable': function('ale#handlers#ols#GetExecutable'),
\ 'command': function('ale#handlers#ols#GetCommand'),

View File

@ -7,9 +7,9 @@ let g:ale_php_phpmd_executable = get(g:, 'ale_php_phpmd_executable', 'phpmd')
let g:ale_php_phpmd_ruleset = get(g:, 'ale_php_phpmd_ruleset', 'cleancode,codesize,controversial,design,naming,unusedcode')
function! ale_linters#php#phpmd#GetCommand(buffer) abort
return '%e %s text'
return '%e %t text'
\ . ale#Pad(ale#Var(a:buffer, 'php_phpmd_ruleset'))
\ . ' --ignore-violations-on-exit %t'
\ . ' --ignore-violations-on-exit'
endfunction
function! ale_linters#php#phpmd#Handle(buffer, lines) abort

View File

@ -26,10 +26,8 @@ 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) && empty(l:dist_config_file_exists)
if empty(l:level) && empty(ale_linters#php#phpstan#FindConfigFile(a:buffer))
" if no configuration file is found, then use 4 as a default level
let l:level = '4'
endif
@ -70,6 +68,22 @@ function! ale_linters#php#phpstan#Handle(buffer, lines) abort
return l:output
endfunction
function! ale_linters#php#phpstan#GetCwd(buffer) abort
let l:result = ale#path#Dirname(ale_linters#php#phpstan#FindConfigFile(a:buffer))
return empty(l:result) ? v:null : l:result
endfunction
function! ale_linters#php#phpstan#FindConfigFile(buffer) abort
let l:result = ale#path#FindNearestFile(a:buffer, 'phpstan.neon')
if empty(l:result)
let l:result = ale#path#FindNearestFile(a:buffer, 'phpstan.neon.dist')
endif
return l:result
endfunction
call ale#linter#Define('php', {
\ 'name': 'phpstan',
\ 'executable': {buffer -> ale#path#FindExecutable(buffer, 'php_phpstan', [
@ -86,4 +100,5 @@ call ale#linter#Define('php', {
\ function('ale_linters#php#phpstan#GetCommand'),
\ )},
\ 'callback': 'ale_linters#php#phpstan#Handle',
\ 'cwd': function('ale_linters#php#phpstan#GetCwd'),
\})

View File

@ -29,6 +29,7 @@ endfunction
call ale#linter#Define('puppet', {
\ 'name': 'languageserver',
\ 'aliases': ['puppet_languageserver'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'puppet_languageserver_executable')},
\ 'command': '%e --stdio',

View File

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

View File

@ -16,16 +16,21 @@ endfunction
function! ale_linters#python#jedils#GetCommand(buffer) abort
let l:executable = ale_linters#python#jedils#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv$'
\ ? ' run jedi-language-server'
\ : ''
let l:env_string = ''
return ale#Escape(l:executable) . l:exec_args
if ale#Var(a:buffer, 'python_auto_virtualenv')
let l:env_string = ale#python#AutoVirtualenvEnvString(a:buffer)
endif
return l:env_string . ale#Escape(l:executable) . l:exec_args
endfunction
call ale#linter#Define('python', {
\ 'name': 'jedils',
\ 'aliases': ['jedi_language_server'],
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#python#jedils#GetExecutable'),
\ 'command': function('ale_linters#python#jedils#GetCommand'),

View File

@ -0,0 +1,86 @@
" Author: Yining <zhang.yining@gmail.com>
" Description: pycln as linter for python files
call ale#Set('python_pycln_executable', 'pycln')
call ale#Set('python_pycln_options', '')
call ale#Set('python_pycln_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_pycln_change_directory', 1)
call ale#Set('python_pycln_auto_pipenv', 0)
call ale#Set('python_pycln_auto_poetry', 0)
call ale#Set('python_pycln_config_file', '')
function! ale_linters#python#pycln#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pycln_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_pycln_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_pycln', ['pycln'])
endfunction
function! ale_linters#python#pycln#GetCwd(buffer) abort
if ale#Var(a:buffer, 'python_pycln_change_directory')
" Run from project root if found, else from buffer dir.
let l:project_root = ale#python#FindProjectRoot(a:buffer)
return !empty(l:project_root) ? l:project_root : '%s:h'
endif
return ''
endfunction
function! ale_linters#python#pycln#GetCommand(buffer, version) abort
let l:executable = ale_linters#python#pycln#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run pycln'
\ : ''
let l:options = ale#Var(a:buffer, 'python_pycln_options')
let l:config_file = ale#Var(a:buffer, 'python_pycln_config_file')
let l:config_file = l:options !~# '\v(^| )--config ' && !empty(l:config_file)
\ ? ale#Escape(ale#path#Simplify(l:config_file))
\ : ''
" NOTE: pycln version `1.3.0` supports liniting input from stdin
return ale#Escape(l:executable) . l:exec_args
\ . ale#Pad(ale#Var(a:buffer, 'python_pycln_options'))
\ . (empty(l:config_file) ? '' : ' --config ' . l:config_file)
\ . ' --check'
\ . (ale#semver#GTE(a:version, [1, 3, 0]) ? ' -' : ' %s')
endfunction
function! ale_linters#python#pycln#Handle(buffer, lines) abort
" Example: tmp/test.py:3:0 'import os' would be removed!
let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):(\d+):? (.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[3],
\})
endfor
return l:output
endfunction
call ale#linter#Define('python', {
\ 'name': 'pycln',
\ 'executable': function('ale_linters#python#pycln#GetExecutable'),
\ 'cwd': function('ale_linters#python#pycln#GetCwd'),
\ 'command': {buffer -> ale#semver#RunWithVersionCheck(
\ buffer,
\ ale_linters#python#pycln#GetExecutable(buffer),
\ '%e --version',
\ function('ale_linters#python#pycln#GetCommand'),
\ )},
\ 'callback': 'ale_linters#python#pycln#Handle',
\ 'output_stream': 'both',
\ 'read_buffer': 1,
\})

View File

@ -22,20 +22,38 @@ function! ale_linters#python#pylsp#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_pylsp', ['pylsp'])
endfunction
" Force the cwd of the server to be the same as the project root to
" fix issues with treating local files matching first or third party library
" names being imported incorrectly.
function! ale_linters#python#pylsp#GetCwd(buffer) abort
let l:fake_linter = {
\ 'name': 'pylsp',
\ 'project_root': function('ale#python#FindProjectRoot'),
\}
let l:root = ale#lsp_linter#FindProjectRoot(a:buffer, l:fake_linter)
return !empty(l:root) ? l:root : v:null
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'
\ : ''
let l:env_string = ''
return ale#Escape(l:executable) . l:exec_args . ale#Pad(ale#Var(a:buffer, 'python_pylsp_options'))
if ale#Var(a:buffer, 'python_auto_virtualenv')
let l:env_string = ale#python#AutoVirtualenvEnvString(a:buffer)
endif
return l:env_string . 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'),
\ 'cwd': function('ale_linters#python#pylsp#GetCwd'),
\ 'command': function('ale_linters#python#pylsp#GetCommand'),
\ 'project_root': function('ale#python#FindProjectRoot'),
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',

View File

@ -1,5 +1,21 @@
call ale#Set('python_pyright_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_pyright_executable', 'pyright-langserver')
call ale#Set('python_pyright_config', {})
call ale#Set('python_pyright_auto_pipenv', 0)
call ale#Set('python_pyright_auto_poetry', 0)
" Force the cwd of the server to be the same as the project root to
" fix issues with treating local files matching first or third party library
" names being imported incorrectly.
function! ale_linters#python#pyright#GetCwd(buffer) abort
let l:fake_linter = {
\ 'name': 'pyright',
\ 'project_root': function('ale#python#FindProjectRoot'),
\}
let l:root = ale#lsp_linter#FindProjectRoot(a:buffer, l:fake_linter)
return !empty(l:root) ? l:root : v:null
endfunction
function! ale_linters#python#pyright#GetConfig(buffer) abort
let l:config = deepcopy(ale#Var(a:buffer, 'python_pyright_config'))
@ -32,11 +48,40 @@ function! ale_linters#python#pyright#GetConfig(buffer) abort
return l:config
endfunction
function! ale_linters#python#pyright#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pyright_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_pyright_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_pyright', ['pyright-langserver'])
endfunction
function! ale_linters#python#pyright#GetCommand(buffer) abort
let l:executable = ale_linters#python#pyright#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run pyright-langserver'
\ : ''
let l:env_string = ''
if ale#Var(a:buffer, 'python_auto_virtualenv')
let l:env_string = ale#python#AutoVirtualenvEnvString(a:buffer)
endif
return l:env_string . ale#Escape(l:executable) . l:exec_args . ' --stdio'
endfunction
call ale#linter#Define('python', {
\ 'name': 'pyright',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'python_pyright_executable')},
\ 'command': '%e --stdio',
\ 'cwd': function('ale_linters#python#pyright#GetCwd'),
\ 'executable': function('ale_linters#python#pyright#GetExecutable'),
\ 'command': function('ale_linters#python#pyright#GetCommand'),
\ 'project_root': function('ale#python#FindProjectRoot'),
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
\ 'lsp_config': function('ale_linters#python#pyright#GetConfig'),

View File

@ -0,0 +1,73 @@
" Author: Yining <zhang.yining@gmail.com>
" Description: refurb as linter for python files
call ale#Set('python_refurb_executable', 'refurb')
call ale#Set('python_refurb_options', '')
call ale#Set('python_refurb_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_refurb_change_directory', 1)
call ale#Set('python_refurb_auto_pipenv', 0)
call ale#Set('python_refurb_auto_poetry', 0)
function! ale_linters#python#refurb#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_refurb_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_refurb_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_refurb', ['refurb'])
endfunction
function! ale_linters#python#refurb#GetCwd(buffer) abort
if ale#Var(a:buffer, 'python_refurb_change_directory')
" Run from project root if found, else from buffer dir.
let l:project_root = ale#python#FindProjectRoot(a:buffer)
return !empty(l:project_root) ? l:project_root : '%s:h'
endif
return ''
endfunction
function! ale_linters#python#refurb#GetCommand(buffer) abort
let l:executable = ale_linters#python#refurb#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run refurb'
\ : ''
return ale#Escape(l:executable) . l:exec_args
\ . ale#Pad(ale#Var(a:buffer, 'python_refurb_options'))
\ . ' %s'
endfunction
function! ale_linters#python#refurb#Handle(buffer, lines) abort
"Example: path/to/file.py:3:17 [FURB109]: Replace `in [x, y, z]` with `in (x, y, z)`
let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):(\d+)?:?\s*\[FURB(\d+)\]:\s*(.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'code': l:match[3] + 0,
\ 'text': l:match[4],
\ 'type': 'W',
\})
endfor
return l:output
endfunction
call ale#linter#Define('python', {
\ 'name': 'refurb',
\ 'executable': function('ale_linters#python#refurb#GetExecutable'),
\ 'cwd': function('ale_linters#python#refurb#GetCwd'),
\ 'command': function('ale_linters#python#refurb#GetCommand'),
\ 'callback': 'ale_linters#python#refurb#Handle',
\ 'output_stream': 'both',
\ 'read_buffer': 0,
\})

View File

@ -46,22 +46,26 @@ function! ale_linters#python#ruff#GetCommand(buffer, version) abort
\ : ''
" NOTE: ruff version `0.0.69` supports liniting input from stdin
return ale#Escape(l:executable) . l:exec_args
" NOTE: ruff version `0.1.0` deprecates `--format text`
return ale#Escape(l:executable) . l:exec_args . ' -q'
\ . ale#Pad(ale#Var(a:buffer, 'python_ruff_options'))
\ . ' --format text'
\ . (ale#semver#GTE(a:version, [0, 0, 69]) ? ' -' : ' %s')
\ . (ale#semver#GTE(a:version, [0, 1, 0]) ? ' --output-format json-lines' : ' --format json-lines')
\ . (ale#semver#GTE(a:version, [0, 0, 69]) ? ' --stdin-filename %s -' : ' %s')
endfunction
function! ale_linters#python#ruff#Handle(buffer, lines) abort
"Example: path/to/file.py:10:5: E999 SyntaxError: unexpected indent
let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):(\d+)?:? (.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
for l:line in a:lines
let l:item = json_decode(l:line)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[3],
\ 'lnum': l:item.location.row,
\ 'col': l:item.location.column,
\ 'end_lnum': l:item.end_location.row,
\ 'end_col': l:item.end_location.column - 1,
\ 'code': l:item.code,
\ 'text': l:item.message,
\ 'type': l:item.code =~? '\vE\d+' ? 'E' : 'W',
\})
endfor

View File

@ -19,6 +19,7 @@ endfunction
call ale#linter#Define('r', {
\ 'name': 'languageserver',
\ 'aliases': ['r_language_server'],
\ 'lsp': 'stdio',
\ 'lsp_config': {b -> ale#Var(b, 'r_languageserver_config')},
\ 'executable': 'Rscript',

View File

@ -15,6 +15,7 @@ endfunction
call ale#linter#Define('reason', {
\ 'name': 'reason-language-server',
\ 'aliases': ['reason_ls'],
\ 'lsp': 'stdio',
\ 'executable': {buffer -> ale#Var(buffer, 'reason_ls_executable')},
\ 'command': '%e',

View File

@ -6,6 +6,7 @@ call ale#Set('reason_ols_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#linter#Define('reason', {
\ 'name': 'ols',
\ 'aliases': ['ocaml-language-server'],
\ 'lsp': 'stdio',
\ 'executable': function('ale#handlers#ols#GetExecutable'),
\ 'command': function('ale#handlers#ols#GetCommand'),

View File

@ -0,0 +1,55 @@
" Author: ymap - https://github.com/ymap
" Description: Packwerk, a static analyzer used to enforce boundaries and modularize Rails applications.
call ale#Set('ruby_packwerk_executable', 'packwerk')
call ale#Set('ruby_packwerk_options', '')
function! ale_linters#ruby#packwerk#Handle(buffer, lines) abort
let l:pattern = '\v^[^:]+:(\d+):(\d+)$'
let l:index = 0
let l:output = []
while l:index < len(a:lines) - 1
let l:cleaned_line = substitute(a:lines[l:index], '\v\e\[[0-9;]*m', '', 'g')
let l:match = matchlist(l:cleaned_line, l:pattern)
if len(l:match) > 0
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': a:lines[l:index + 1],
\})
endif
let l:index += 1
endwhile
return l:output
endfunction
function! ale_linters#ruby#packwerk#GetCommand(buffer) abort
let l:rails_root = ale#ruby#FindRailsRoot(a:buffer)
if l:rails_root is? ''
return ''
endif
let l:executable = ale#Var(a:buffer, 'ruby_packwerk_executable')
let l:sep = has('win32') ? '\' : '/'
let l:abs_path = expand('#' . a:buffer . ':p')
let l:rel_path = substitute(l:abs_path, escape(l:rails_root . l:sep, '\'), '', '')
return ale#ruby#EscapeExecutable(l:executable, 'packwerk')
\ . ' check'
\ . ale#Pad(ale#Var(a:buffer, 'ruby_packwerk_options'))
\ . ' '
\ . ale#Escape(rel_path)
endfunction
call ale#linter#Define('ruby', {
\ 'name': 'packwerk',
\ 'executable': {b -> ale#Var(b, 'ruby_packwerk_executable')},
\ 'command': function('ale_linters#ruby#packwerk#GetCommand'),
\ 'callback': 'ale_linters#ruby#packwerk#Handle',
\ 'lint_file': 1,
\})

View File

@ -28,6 +28,7 @@ endfunction
call ale#linter#Define('rust', {
\ 'name': 'analyzer',
\ 'aliases': ['rust_analyzer'],
\ 'lsp': 'stdio',
\ 'initialization_options': {b -> ale#Var(b, 'rust_analyzer_config')},
\ 'executable': {b -> ale#Var(b, 'rust_analyzer_executable')},

View File

@ -1,11 +1,6 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Lints shell files by invoking the shell with -n
" Backwards compatibility
if exists('g:ale_linters_sh_shell_default_shell')
let g:ale_sh_shell_default_shell = g:ale_linters_sh_shell_default_shell
endif
" This option can be changed to change the default shell when the shell
" cannot be taken from the hashbang line.
if !exists('g:ale_sh_shell_default_shell')

View File

@ -1,12 +1,83 @@
" Authors: Franco Victorio - https://github.com/fvictorio, Henrique Barcelos
" https://github.com/hbarcelos
" Authors: Franco Victorio <@fvictorio>, Henrique Barcelos <@hbarcelos>
" Description: Report errors in Solidity code with solhint
call ale#Set('solidity_solhint_options', '')
call ale#Set('solidity_solhint_executable', 'solhint')
call ale#Set('solidity_solhint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#solidity#solhint#Handle(buffer, lines) abort
let l:output = []
" Matches lines like the following:
" contracts/Bounty.sol:14:3: Expected indentation of 4 spaces but found 2 [Error/indent]
let l:lint_pattern = '\v^[^:]+:(\d+):(\d+): %(Parse error: )@<!\ze(.*)\s+\[(Error|Warning)\/([^\]]+)\]$'
for l:match in ale#util#GetMatches(a:lines, l:lint_pattern)
let l:is_error = l:match[4] is? 'error'
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[3],
\ 'code': l:match[5],
\ 'type': l:is_error ? 'E' : 'W',
\})
endfor
" Matches lines like the following:
" contracts/Bounty.sol:203:4: Parse error: no viable alternative at input '_loserStakeMultiplier}' [Error]
let l:syntax_pattern = '\v^[^:]+:(\d+):(\d+): Parse error: (.*)\s+\[Error\]$'
for l:match in ale#util#GetMatches(a:lines, l:syntax_pattern)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[3],
\ 'code': 'Parse error',
\ 'type': 'E',
\})
endfor
return l:output
endfunction
let s:executables = [
\ 'node_modules/.bin/solhint',
\ 'node_modules/solhint/solhint.js',
\ 'solhint',
\]
let s:sep = has('win32') ? '\' : '/'
" Given a buffer, return an appropriate working directory for solhint.
function! ale_linters#solidity#solhint#GetCwd(buffer) abort
" If solhint is installed in a directory which contains the buffer, assume
" it is the solhint project root. Otherwise, use nearest node_modules.
" Note: If node_modules not present yet, can't load local deps anyway.
let l:executable = ale#path#FindNearestExecutable(a:buffer, s:executables)
if !empty(l:executable)
let l:nmi = strridx(l:executable, 'node_modules')
let l:project_dir = l:executable[0:l:nmi - 2]
else
let l:modules_dir = ale#path#FindNearestDirectory(a:buffer, 'node_modules')
let l:project_dir = !empty(l:modules_dir) ? fnamemodify(l:modules_dir, ':h:h') : ''
endif
return !empty(l:project_dir) ? l:project_dir : ''
endfunction
function! ale_linters#solidity#solhint#GetExecutable(buffer) abort
return ale#path#FindExecutable(a:buffer, 'solidity_solhint', s:executables)
endfunction
call ale#linter#Define('solidity', {
\ 'name': 'solhint',
\ 'output_stream': 'both',
\ 'executable': function('ale#handlers#solhint#GetExecutable'),
\ 'cwd': function('ale#handlers#solhint#GetCwd'),
\ 'command': function('ale#handlers#solhint#GetCommand'),
\ 'callback': 'ale#handlers#solhint#Handle',
\ 'executable': function('ale_linters#solidity#solhint#GetExecutable'),
\ 'cwd': function('ale_linters#solidity#solhint#GetCwd'),
\ 'command': {b ->
\ ale#node#Executable(b, ale_linters#solidity#solhint#GetExecutable(b))
\ . ale#Pad(ale#Var(b, 'solidity_solhint_options'))
\ . ' --formatter unix %s'
\ },
\ 'callback': 'ale_linters#solidity#solhint#Handle',
\})

View File

@ -0,0 +1,72 @@
" Author: Carl Smedstad <carl.smedstad at protonmail dot com>
" Description: sqlfluff for SQL files
let g:ale_sql_sqlfluff_executable =
\ get(g:, 'ale_sql_sqlfluff_executable', 'sqlfluff')
let g:ale_sql_sqlfluff_options =
\ get(g:, 'ale_sql_sqlfluff_options', '')
function! ale_linters#sql#sqlfluff#Executable(buffer) abort
return ale#Var(a:buffer, 'sql_sqlfluff_executable')
endfunction
function! ale_linters#sql#sqlfluff#Command(buffer) abort
let l:executable = ale_linters#sql#sqlfluff#Executable(a:buffer)
let l:options = ale#Var(a:buffer, 'sql_sqlfluff_options')
let l:cmd =
\ ale#Escape(l:executable)
\ . ' lint'
let l:config_file = ale#path#FindNearestFile(a:buffer, '.sqlfluff')
if !empty(l:config_file)
let l:cmd .= ' --config ' . ale#Escape(l:config_file)
else
let l:cmd .= ' --dialect ansi'
endif
let l:cmd .=
\ ' --format json '
\ . l:options
\ . ' %t'
return l:cmd
endfunction
function! ale_linters#sql#sqlfluff#Handle(buffer, lines) abort
let l:output = []
let l:json_lines = ale#util#FuzzyJSONDecode(a:lines, [])
if empty(l:json_lines)
return l:output
endif
let l:json = l:json_lines[0]
" if there's no warning, 'result' is `null`.
if empty(get(l:json, 'violations'))
return l:output
endif
for l:violation in get(l:json, 'violations', [])
call add(l:output, {
\ 'filename': l:json.filepath,
\ 'lnum': l:violation.line_no,
\ 'col': l:violation.line_pos,
\ 'text': l:violation.description,
\ 'code': l:violation.code,
\ 'type': 'W',
\})
endfor
return l:output
endfunction
call ale#linter#Define('sql', {
\ 'name': 'sqlfluff',
\ 'executable': function('ale_linters#sql#sqlfluff#Executable'),
\ 'command': function('ale_linters#sql#sqlfluff#Command'),
\ 'callback': 'ale_linters#sql#sqlfluff#Handle',
\})

View File

@ -5,6 +5,7 @@ call ale#Set('sourcekit_lsp_executable', 'sourcekit-lsp')
call ale#linter#Define('swift', {
\ 'name': 'sourcekitlsp',
\ 'aliases': ['sourcekit'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'sourcekit_lsp_executable')},
\ 'command': '%e',

View File

@ -30,6 +30,7 @@ endfunction
call ale#linter#Define('terraform', {
\ 'name': 'terraform_ls',
\ 'aliases': ['terraformls'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'terraform_ls_executable')},
\ 'command': function('ale_linters#terraform#terraform_ls#GetCommand'),

View File

@ -4,17 +4,6 @@
call ale#Set('v_v_executable', 'v')
call ale#Set('v_v_options', '')
function! ale_linters#v#v#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'v_v_options')
" Run v in local directory with relative path
let l:command = ale#Var(a:buffer, 'v_v_executable')
\ . ale#Pad(l:options)
\ . ' .' . ' -o /tmp/vim-ale-v'
return l:command
endfunction
function! ale_linters#v#v#Handler(buffer, lines) abort
let l:dir = expand('#' . a:buffer . ':p:h')
let l:output = []
@ -73,9 +62,11 @@ endfunction
call ale#linter#Define('v', {
\ 'name': 'v',
\ 'aliases': [],
\ 'executable': {b -> ale#Var(b, 'v_v_executable')},
\ 'command': function('ale_linters#v#v#GetCommand'),
\ 'command': {b ->
\ '%e' . ale#Pad(ale#Var(b, 'v_v_options'))
\ . ' . -o /tmp/vim-ale-v'
\ },
\ 'output_stream': 'stderr',
\ 'callback': 'ale_linters#v#v#Handler',
\ 'lint_file': 1,

View File

@ -12,6 +12,7 @@ endfunction
call ale#linter#Define('vue', {
\ 'name': 'vls',
\ 'aliases': ['vuels'],
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#path#FindExecutable(b, 'vue_vls', [
\ 'node_modules/.bin/vls',

View File

@ -3,50 +3,21 @@
" nvim-lspconfig and volar/packages/shared/src/types.ts
call ale#Set('vue_volar_executable', 'vue-language-server')
call ale#Set('vue_volar_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('vue_volar_use_global', 1)
call ale#Set('vue_volar_init_options', {
\ 'documentFeatures': {
\ 'documentColor': v:false,
\ 'documentFormatting': {
\ 'defaultPrintWidth': 100,
\ },
\ 'documentSymbol': v:true,
\ 'foldingRange': v:true,
\ 'linkedEditingRange': v:true,
\ 'selectionRange': v:true,
\ },
\ 'languageFeatures': {
\ 'callHierarchy': v:true,
\ 'codeAction': v:true,
\ 'codeLens': v:true,
\ 'completion': {
\ 'defaultAttrNameCase': 'kebabCase',
\ 'defaultTagNameCase': 'both',
\ 'getDocumentNameCaseRequest': v:false,
\ 'getDocumentSelectionRequest': v:false,
\ },
\ 'definition': v:true,
\ 'diagnostics': v:true,
\ 'documentHighlight': v:true,
\ 'documentLink': v:true,
\ 'hover': v:true,
\ 'references': v:true,
\ 'rename': v:true,
\ 'renameFileRefactoring': v:true,
\ 'schemaRequestService': v:true,
\ 'semanticTokens': v:false,
\ 'signatureHelp': v:true,
\ 'typeDefinition': v:true,
\ 'workspaceSymbol': v:false,
\ },
\ 'typescript': {
\ 'serverPath': '',
\ 'localizedPath': v:null,
\ },
\ 'typescript': { 'tsdk': '' },
\})
function! ale_linters#vue#volar#GetProjectRoot(buffer) abort
let l:project_roots = ['package.json', 'vite.config.js', '.git', bufname(a:buffer)]
let l:project_roots = [
\ 'package.json',
\ 'vite.config.js',
\ 'vite.config.mjs',
\ 'vite.config.cjs',
\ 'vite.config.ts',
\ '.git',
\ bufname(a:buffer)
\]
for l:project_root in l:project_roots
let l:nearest_filepath = ale#path#FindNearestFile(a:buffer, l:project_root)
@ -60,11 +31,19 @@ function! ale_linters#vue#volar#GetProjectRoot(buffer) abort
endfunction
function! ale_linters#vue#volar#GetInitializationOptions(buffer) abort
let l:tsserver_path = ale#path#FindNearestExecutable(a:buffer, [
\ 'node_modules/typescript/lib/tsserverlibrary.js'
\ ])
let l:tsserver_path = ale#path#FindNearestDirectory(a:buffer, 'node_modules/typescript/lib')
if l:tsserver_path is# ''
" no-custom-checks
echohl WarningMsg
" no-custom-checks
echom '[volar] Must have typescript installed in project, please install via `npm install -D typescript`.'
" no-custom-checks
echohl None
endif
let l:init_options = ale#Var(a:buffer, 'vue_volar_init_options')
let l:init_options.typescript.serverPath = l:tsserver_path
let l:init_options.typescript.tsdk = l:tsserver_path
return l:init_options
endfunction

View File

@ -1,11 +1,47 @@
" Author: bretello <bretello@distruzione.org>
" Author: Peter Benjamin <petermbenjamin@gmail.com>
" Description: Linter for GitHub Workflows
call ale#Set('yaml_actionlint_executable', 'actionlint')
call ale#Set('yaml_actionlint_options', '')
function! ale_linters#yaml#actionlint#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'yaml_actionlint_options')
if l:options !~# '-no-color'
let l:options .= ale#Pad('-no-color')
endif
if l:options !~# '-oneline'
let l:options .= ale#Pad('-oneline')
endif
return '%e' . ale#Pad(l:options)
endfunction
function! ale_linters#yaml#actionlint#Handle(buffer, lines) abort
" Matches patterns line the following:
".github/workflows/main.yml:19:0: could not parse as YAML: yaml: line 19: mapping values are not allowed in this context [yaml-syntax]
let l:pattern = '\v^.*:(\d+):(\d+): (.+) \[(.+)\]$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:item = {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[3],
\ 'code': l:match[4],
\ 'type': 'E',
\}
call add(l:output, l:item)
endfor
return l:output
endfunction
call ale#linter#Define('yaml', {
\ 'name': 'actionlint',
\ 'executable': {b -> ale#Var(b, 'yaml_actionlint_executable')},
\ 'command': function('ale#handlers#actionlint#GetCommand'),
\ 'callback': 'ale#handlers#actionlint#Handle',
\ 'command': function('ale_linters#yaml#actionlint#GetCommand'),
\ 'callback': 'ale_linters#yaml#actionlint#Handle',
\})

View File

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

View File

@ -7,9 +7,6 @@ let g:ale_echo_msg_error_str = get(g:, 'ale_echo_msg_error_str', 'Error')
let g:ale_echo_msg_info_str = get(g:, 'ale_echo_msg_info_str', 'Info')
let g:ale_echo_msg_log_str = get(g:, 'ale_echo_msg_log_str', 'Log')
let g:ale_echo_msg_warning_str = get(g:, 'ale_echo_msg_warning_str', 'Warning')
" Ignoring linters, for disabling some, or ignoring LSP diagnostics.
let g:ale_linters_ignore = get(g:, 'ale_linters_ignore', {})
let g:ale_disable_lsp = get(g:, 'ale_disable_lsp', 0)
" LSP window/showMessage format
let g:ale_lsp_show_message_format = get(g:, 'ale_lsp_show_message_format', '%severity%:%linter%: %s')
@ -100,7 +97,24 @@ function! s:Lint(buffer, should_lint_file, timer_id) abort
" Use the filetype from the buffer
let l:filetype = getbufvar(a:buffer, '&filetype')
let l:linters = ale#linter#Get(l:filetype)
let l:linters = ale#linter#RemoveIgnored(a:buffer, l:filetype, l:linters)
let l:ignore_config = ale#Var(a:buffer, 'linters_ignore')
let l:disable_lsp = ale#Var(a:buffer, 'disable_lsp')
" Load code to ignore linters only if we need to.
if (
\ !empty(l:ignore_config)
\ || l:disable_lsp is 1
\ || l:disable_lsp is v:true
\ || (l:disable_lsp is# 'auto' && get(g:, 'lspconfig', 0))
\)
let l:linters = ale#engine#ignore#Exclude(
\ l:filetype,
\ l:linters,
\ l:ignore_config,
\ l:disable_lsp,
\)
endif
" Tell other sources that they can start checking the buffer now.
let g:ale_want_results_buffer = a:buffer
@ -157,7 +171,7 @@ function! ale#Queue(delay, ...) abort
endif
endfunction
let s:current_ale_version = [3, 2, 0]
let s:current_ale_version = [3, 3, 0]
" A function used to check for ALE features in files outside of the project.
function! ale#Has(feature) abort
@ -208,7 +222,7 @@ endfunction
" valid for cmd on Windows, or most shells on Unix.
function! ale#Env(variable_name, value) abort
if has('win32')
return 'set ' . a:variable_name . '=' . ale#Escape(a:value) . ' && '
return 'set ' . ale#Escape(a:variable_name . '=' . a:value) . ' && '
endif
return a:variable_name . '=' . ale#Escape(a:value) . ' '
@ -254,6 +268,7 @@ function! ale#GetLocItemMessage(item, format_string) abort
" \=l:variable is used to avoid escaping issues.
let l:msg = substitute(l:msg, '\v\%([^\%]*)code([^\%]*)\%', l:code_repl, 'g')
let l:msg = substitute(l:msg, '\V%severity%', '\=l:severity', 'g')
let l:msg = substitute(l:msg, '\V%type%', '\=l:type', 'g')
let l:msg = substitute(l:msg, '\V%linter%', '\=l:linter_name', 'g')
" Replace %s with the text.
let l:msg = substitute(l:msg, '\V%s', '\=a:item.text', 'g')

View File

@ -339,17 +339,7 @@ function! ale#code_action#GetCodeActions(options) abort
silent! aunmenu PopUp.Refactor\.\.\.
" Only display the menu items if there's an LSP server.
let l:has_lsp = 0
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
let l:has_lsp = 1
break
endif
endfor
if l:has_lsp
if len(ale#lsp_linter#GetEnabled(bufnr(''))) > 0
if !empty(expand('<cword>'))
silent! anoremenu <silent> PopUp.Rename :ALERename<CR>
endif

View File

@ -473,15 +473,9 @@ function! ale#codefix#Execute(range, ...) abort
endif
let l:MenuCallback = get(a:000, 0, v:null)
let l:lsp_linters = []
let l:linters = ale#lsp_linter#GetEnabled(bufnr(''))
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
call add(l:lsp_linters, l:linter)
endif
endfor
if empty(l:lsp_linters)
if empty(l:linters)
if l:MenuCallback is v:null
call s:message('No active LSPs')
else
@ -491,7 +485,7 @@ function! ale#codefix#Execute(range, ...) abort
return
endif
for l:lsp_linter in l:lsp_linters
call s:ExecuteGetCodeFix(l:lsp_linter, a:range, l:MenuCallback)
for l:linter in l:linters
call s:ExecuteGetCodeFix(l:linter, a:range, l:MenuCallback)
endfor
endfunction

View File

@ -824,6 +824,8 @@ endfunction
" the current buffer. 1 will be returned if there's a potential source of
" completion data ALE can use, and 0 will be returned otherwise.
function! ale#completion#CanProvideCompletions() abort
" NOTE: We can report that ALE can provide completions to Deoplete from
" here, and we might ignore linters still below.
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
return 1
@ -890,11 +892,9 @@ function! ale#completion#GetCompletions(...) abort
let l:started = 0
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
if ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
let l:started = 1
endif
for l:linter in ale#lsp_linter#GetEnabled(l:buffer)
if ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
let l:started = 1
endif
endfor

View File

@ -12,8 +12,10 @@ let s:cursor_timer = -1
" A wrapper for echon so we can test messages we echo in Vader tests.
function! ale#cursor#Echom(message) abort
" no-custom-checks
exec "norm! :echom a:message\n"
if mode() is# 'n'
" no-custom-checks
exec "norm! :echom a:message\n"
endif
endfunction
function! ale#cursor#TruncatedEcho(original_message) abort

View File

@ -1,6 +1,8 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: This file implements debugging information for ALE
let g:ale_info_default_mode = get(g:, 'ale_info_default_mode', 'preview')
let s:global_variable_list = [
\ 'ale_cache_executable_check_failures',
\ 'ale_change_sign_column_color',
@ -18,6 +20,7 @@ let s:global_variable_list = [
\ 'ale_fix_on_save',
\ 'ale_fixers',
\ 'ale_history_enabled',
\ 'ale_info_default_mode',
\ 'ale_history_log_output',
\ 'ale_keep_list_window_open',
\ 'ale_lint_delay',
@ -53,8 +56,8 @@ let s:global_variable_list = [
\ 'ale_sign_style_warning',
\ 'ale_sign_warning',
\ 'ale_sign_highlight_linenrs',
\ 'ale_statusline_format',
\ 'ale_type_map',
\ 'ale_use_neovim_diagnostics_api',
\ 'ale_use_global_executables',
\ 'ale_virtualtext_cursor',
\ 'ale_warn_about_trailing_blank_lines',
@ -198,11 +201,42 @@ function! s:EchoLSPErrorMessages(all_linter_names) abort
endfor
endfunction
function! ale#debugging#Info() abort
function! s:GetIgnoredLinters(buffer, enabled_linters) abort
let l:filetype = &filetype
let l:ignore_config = ale#Var(a:buffer, 'linters_ignore')
let l:disable_lsp = ale#Var(a:buffer, 'disable_lsp')
if (
\ !empty(l:ignore_config)
\ || l:disable_lsp is 1
\ || l:disable_lsp is v:true
\ || (l:disable_lsp is# 'auto' && get(g:, 'lspconfig', 0))
\)
let l:non_ignored = ale#engine#ignore#Exclude(
\ l:filetype,
\ a:enabled_linters,
\ l:ignore_config,
\ l:disable_lsp,
\)
else
let l:non_ignored = copy(a:enabled_linters)
endif
call map(l:non_ignored, 'v:val.name')
return filter(
\ copy(a:enabled_linters),
\ 'index(l:non_ignored, v:val.name) < 0'
\)
endfunction
function! ale#debugging#Info(...) abort
let l:options = (a:0 > 0) ? a:1 : {}
let l:show_preview_info = get(l:options, 'preview')
let l:buffer = bufnr('')
let l:filetype = &filetype
" We get the list of enabled linters for free by the above function.
let l:enabled_linters = deepcopy(ale#linter#Get(l:filetype))
" But have to build the list of available linters ourselves.
@ -226,13 +260,10 @@ function! ale#debugging#Info() abort
let l:fixers = uniq(sort(l:fixers[0] + l:fixers[1]))
let l:fixers_string = join(map(copy(l:fixers), '"\n " . v:val'), '')
let l:non_ignored_names = map(
\ copy(ale#linter#RemoveIgnored(l:buffer, l:filetype, l:enabled_linters)),
\ 'v:val[''name'']',
\)
let l:ignored_names = filter(
\ copy(l:enabled_names),
\ 'index(l:non_ignored_names, v:val) < 0'
" Get the names of ignored linters.
let l:ignored_names = map(
\ s:GetIgnoredLinters(l:buffer, l:enabled_linters),
\ 'v:val.name'
\)
call s:Echo(' Current Filetype: ' . l:filetype)
@ -240,13 +271,31 @@ function! ale#debugging#Info() abort
call s:EchoLinterAliases(l:all_linters)
call s:Echo(' Enabled Linters: ' . string(l:enabled_names))
call s:Echo(' Ignored Linters: ' . string(l:ignored_names))
call s:Echo(' Suggested Fixers: ' . l:fixers_string)
call s:Echo(' Linter Variables:')
call s:Echo('')
call s:EchoLinterVariables(l:variable_list)
call s:Echo(' Suggested Fixers:' . l:fixers_string)
" We use this line with only a space to know where to end highlights.
call s:Echo(' ')
" Only show Linter Variables directive if there are any.
if !empty(l:variable_list)
call s:Echo(' Linter Variables:')
if l:show_preview_info
call s:Echo('" Press Space to read :help for a setting')
endif
call s:EchoLinterVariables(l:variable_list)
" We use this line with only a space to know where to end highlights.
call s:Echo(' ')
endif
call s:Echo(' Global Variables:')
call s:Echo('')
if l:show_preview_info
call s:Echo('" Press Space to read :help for a setting')
endif
call s:EchoGlobalVariables()
call s:Echo(' ')
call s:EchoLSPErrorMessages(l:all_names)
call s:Echo(' Command History:')
call s:Echo('')
@ -274,3 +323,41 @@ function! ale#debugging#InfoToFile(filename) abort
call writefile(split(l:output, "\n"), l:expanded_filename)
call s:Echo('ALEInfo written to ' . l:expanded_filename)
endfunction
function! ale#debugging#InfoToPreview() abort
let l:output = execute('call ale#debugging#Info({''preview'': 1})')
call ale#preview#Show(split(l:output, "\n"), {
\ 'filetype': 'ale-info',
\})
endfunction
function! ale#debugging#InfoCommand(...) abort
if len(a:000) > 1
" no-custom-checks
echom 'Invalid ALEInfo arguments!'
return
endif
" Get 'echo' from '-echo', if there's an argument.
let l:mode = get(a:000, '')[1:]
if empty(l:mode)
let l:mode = ale#Var(bufnr(''), 'info_default_mode')
endif
if l:mode is# 'echo'
call ale#debugging#Info()
elseif l:mode is# 'clip' || l:mode is# 'clipboard'
call ale#debugging#InfoToClipboard()
else
call ale#debugging#InfoToPreview()
endif
endfunction
function! ale#debugging#InfoToClipboardDeprecatedCommand() abort
" no-custom-checks
echom 'ALEInfoToClipboard is deprecated. Use ALEInfo -clipboard instead.'
call ale#debugging#InfoToClipboard()
endfunction

View File

@ -168,26 +168,20 @@ function! s:GoToLSPDefinition(linter, options, capability) abort
endfunction
function! ale#definition#GoTo(options) abort
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
call s:GoToLSPDefinition(l:linter, a:options, 'definition')
endif
for l:linter in ale#lsp_linter#GetEnabled(bufnr(''))
call s:GoToLSPDefinition(l:linter, a:options, 'definition')
endfor
endfunction
function! ale#definition#GoToType(options) abort
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
call s:GoToLSPDefinition(l:linter, a:options, 'typeDefinition')
endif
for l:linter in ale#lsp_linter#GetEnabled(bufnr(''))
call s:GoToLSPDefinition(l:linter, a:options, 'typeDefinition')
endfor
endfunction
function! ale#definition#GoToImpl(options) abort
for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp)
call s:GoToLSPDefinition(l:linter, a:options, 'implementation')
endif
for l:linter in ale#lsp_linter#GetEnabled(bufnr(''))
call s:GoToLSPDefinition(l:linter, a:options, 'implementation')
endfor
endfunction

View File

@ -184,9 +184,13 @@ endfunction
function! ale#engine#SetResults(buffer, loclist) abort
let l:linting_is_done = !ale#engine#IsCheckingBuffer(a:buffer)
if g:ale_use_neovim_diagnostics_api
call ale#engine#SendResultsToNeovimDiagnostics(a:buffer, a:loclist)
endif
" Set signs first. This could potentially fix some line numbers.
" The List could be sorted again here by SetSigns.
if g:ale_set_signs
if !g:ale_use_neovim_diagnostics_api && g:ale_set_signs
call ale#sign#SetSigns(a:buffer, a:loclist)
endif
@ -199,11 +203,12 @@ function! ale#engine#SetResults(buffer, loclist) abort
call ale#statusline#Update(a:buffer, a:loclist)
endif
if g:ale_set_highlights
if !g:ale_use_neovim_diagnostics_api && g:ale_set_highlights
call ale#highlight#SetHighlights(a:buffer, a:loclist)
endif
if g:ale_virtualtext_cursor == 2
if !g:ale_use_neovim_diagnostics_api
\&& (g:ale_virtualtext_cursor is# 'all' || g:ale_virtualtext_cursor == 2)
call ale#virtualtext#SetTexts(a:buffer, a:loclist)
endif
@ -214,7 +219,8 @@ function! ale#engine#SetResults(buffer, loclist) abort
call ale#cursor#EchoCursorWarning()
endif
if g:ale_virtualtext_cursor == 1
if !g:ale_use_neovim_diagnostics_api
\&& (g:ale_virtualtext_cursor is# 'current' || g:ale_virtualtext_cursor == 1)
" Try and show the warning now.
" This will only do something meaningful if we're in normal mode.
call ale#virtualtext#ShowCursorWarning()
@ -238,6 +244,19 @@ function! ale#engine#SetResults(buffer, loclist) abort
endif
endfunction
function! ale#engine#SendResultsToNeovimDiagnostics(buffer, loclist) abort
if !has('nvim-0.6')
" We will warn the user on startup as well if they try to set
" g:ale_use_neovim_diagnostics_api outside of a Neovim context.
return
endif
" Keep the Lua surface area really small in the VimL part of ALE,
" and just require the diagnostics.lua module on demand.
let l:SendDiagnostics = luaeval('require("ale.diagnostics").sendAleResultsToDiagnostics')
call l:SendDiagnostics(a:buffer, a:loclist)
endfunction
function! s:RemapItemTypes(type_map, loclist) abort
for l:item in a:loclist
let l:key = l:item.type

View File

@ -1,6 +1,26 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Code for ignoring linters. Only loaded and if configured.
" A map for remapping lspconfig server names to linter names or aliases in
" ALE. We should change the names where they will conflict with names in ALE.
"
" Notes on names from nvim-lspconfig not included here.
"
" * 'rubocop' is run in a language server mode
" * 'eslint' is run via 'vscode-eslint-language-server'
let s:lspconfig_map = {
\ 'als': 'adals',
\ 'ansiblels': 'ansible-language-server',
\ 'bicep': 'bicep_language_server',
\ 'cmake': 'cmake_language_server',
\ 'denols': 'deno',
\ 'erlangls': 'erlang_ls',
\ 'html': 'vscodehtml',
\ 'ocamlls': 'ocaml-language-server',
\ 'ols': 'odin-lsp',
\ 'puppet': 'puppet_languageserver',
\}
" Given a filetype and a configuration for ignoring linters, return a List of
" Strings for linter names to ignore.
function! ale#engine#ignore#GetList(filetype, config) abort
@ -21,24 +41,51 @@ function! ale#engine#ignore#GetList(filetype, config) abort
return []
endfunction
" This function can be mocked in tests.
function! ale#engine#ignore#GetLSPConfigNames() abort
return luaeval('require ''ale.util''.configured_lspconfig_servers()')
endfunction
function! s:GetMappedLSPConfigNames() abort
" Check the lspconfig flag before calling luaeval.
if !get(g:, 'lspconfig', 0)
return []
endif
let l:lspconfig_servers = ale#engine#ignore#GetLSPConfigNames()
return map(
\ !empty(l:lspconfig_servers) ? l:lspconfig_servers : [],
\ {_, val -> get(s:lspconfig_map, val, val) }
\)
endfunction
" Given a List of linter descriptions, exclude the linters to be ignored.
function! ale#engine#ignore#Exclude(filetype, all_linters, config, disable_lsp) abort
let l:names_to_remove = ale#engine#ignore#GetList(a:filetype, a:config)
" If configured to automatically ignore otherwise configured LSP linter
" names, add them to the names to remove. This could ignore linters
" with matching names that are not marked as LSP linters.
if a:disable_lsp is# 'auto'
call extend(l:names_to_remove, s:GetMappedLSPConfigNames())
endif
let l:ignore_all_lsps = a:disable_lsp is 1 || a:disable_lsp is v:true
let l:filtered_linters = []
for l:linter in a:all_linters
let l:name_list = [l:linter.name] + l:linter.aliases
let l:should_include = 1
let l:should_include = index(l:names_to_remove, l:linter.name) == -1
let l:i = 0
for l:name in l:name_list
if index(l:names_to_remove, l:name) >= 0
let l:should_include = 0
break
endif
endfor
while l:should_include && l:i < len(l:linter.aliases)
let l:name = l:linter.aliases[l:i]
let l:should_include = index(l:names_to_remove, l:name) == -1
let l:i += 1
endwhile
if a:disable_lsp && has_key(l:linter, 'lsp') && l:linter.lsp isnot# ''
let l:should_include = 0
if l:should_include && l:ignore_all_lsps
let l:should_include = empty(get(l:linter, 'lsp'))
endif
if l:should_include

View File

@ -92,6 +92,62 @@ function! ale#events#FileChangedEvent(buffer) abort
endif
endfunction
" A timer for emulating InsertLeave.
"
" We only need a single timer, and we'll lint the last buffer we entered
" insert mode on.
if !exists('s:insert_leave_timer')
let s:insert_leave_timer = -1
endif
function! ale#events#EmulateInsertLeave(buffer) abort
if mode() is# 'n'
call timer_stop(s:insert_leave_timer)
call ale#Queue(0, '', a:buffer)
endif
endfunction
function! ale#events#InsertEnterEvent(buffer) abort
if g:ale_close_preview_on_insert && exists('*ale#preview#CloseIfTypeMatches')
call ale#preview#CloseIfTypeMatches('ale-preview')
endif
" Start a repeating timer if the use might not trigger InsertLeave, so we
" can emulate its behavior.
if ale#Var(a:buffer, 'lint_on_insert_leave')
\&& maparg("\<C-c>", 'i') isnot# '<Esc>'
call timer_stop(s:insert_leave_timer)
let s:insert_leave_timer = timer_start(
\ 100,
\ {-> ale#events#EmulateInsertLeave(a:buffer) },
\ {'repeat': -1}
\)
endif
endfunction
function! ale#events#InsertLeaveEvent(buffer) abort
if ale#Var(a:buffer, 'lint_on_insert_leave')
" Kill the InsertLeave emulation if the event fired.
call timer_stop(s:insert_leave_timer)
call ale#Queue(0)
endif
" Look for a warning to echo as soon as we leave Insert mode.
" The script's position variable used when moving the cursor will
" not be changed here.
"
" We don't echo this message in emulated insert leave mode, as the user
" may want less work to happen on pressing <C-c> versus <Esc>
if exists('*ale#engine#Cleanup')
call ale#cursor#EchoCursorWarning()
if g:ale_virtualtext_cursor is# 'current' || g:ale_virtualtext_cursor is# 1 || g:ale_virtualtext_cursor is# '1'
" Show a virtualtext message if enabled.
call ale#virtualtext#ShowCursorWarning()
endif
endif
endfunction
function! ale#events#Init() abort
" This value used to be a Boolean as a Number, and is now a String.
let l:text_changed = '' . g:ale_lint_on_text_changed
@ -127,33 +183,40 @@ function! ale#events#Init() abort
\)
endif
if g:ale_lint_on_insert_leave
autocmd InsertLeave * if ale#Var(str2nr(expand('<abuf>')), 'lint_on_insert_leave') | call ale#Queue(0) | endif
" Add an InsertEnter event if we need to close the preview window
" on entering insert mode, or if we want to run ALE on leaving
" insert mode and <C-c> is not the same as <Esc>.
"
" We will emulate leaving insert mode for users that might not
" trigger InsertLeave.
if g:ale_close_preview_on_insert
\|| (g:ale_lint_on_insert_leave && maparg("\<C-c>", 'i') isnot# '<Esc>')
autocmd InsertEnter * call ale#events#InsertEnterEvent(str2nr(expand('<abuf>')))
endif
let l:add_insert_leave_event = g:ale_lint_on_insert_leave
if g:ale_echo_cursor || g:ale_cursor_detail
" We need to make the message display on InsertLeave
let l:add_insert_leave_event = 1
autocmd CursorMoved,CursorHold * if exists('*ale#engine#Cleanup') | call ale#cursor#EchoCursorWarningWithDelay() | endif
" Look for a warning to echo as soon as we leave Insert mode.
" The script's position variable used when moving the cursor will
" not be changed here.
autocmd InsertLeave * if exists('*ale#engine#Cleanup') | call ale#cursor#EchoCursorWarning() | endif
endif
if g:ale_virtualtext_cursor == 1
if g:ale_virtualtext_cursor is# 'current' || g:ale_virtualtext_cursor is# 1 || g:ale_virtualtext_cursor is# '1'
" We need to make the message display on InsertLeave
let l:add_insert_leave_event = 1
autocmd CursorMoved,CursorHold * if exists('*ale#engine#Cleanup') | call ale#virtualtext#ShowCursorWarningWithDelay() | endif
" Look for a warning to echo as soon as we leave Insert mode.
" The script's position variable used when moving the cursor will
" not be changed here.
autocmd InsertLeave * if exists('*ale#engine#Cleanup') | call ale#virtualtext#ShowCursorWarning() | endif
endif
if l:add_insert_leave_event
autocmd InsertLeave * call ale#events#InsertLeaveEvent(str2nr(expand('<abuf>')))
endif
if g:ale_hover_cursor
autocmd CursorHold * if exists('*ale#lsp#Send') | call ale#hover#ShowTruncatedMessageAtCursor() | endif
endif
if g:ale_close_preview_on_insert
autocmd InsertEnter * if exists('*ale#preview#CloseIfTypeMatches') | call ale#preview#CloseIfTypeMatches('ale-preview') | endif
endif
endif
augroup END

View File

@ -94,9 +94,10 @@ function! s:ExecuteFileRename(linter, options) abort
endfunction
function! ale#filerename#Execute() abort
let l:buffer = bufnr('')
let l:lsp_linters = []
for l:linter in ale#linter#Get(&filetype)
for l:linter in ale#lsp_linter#GetEnabled(l:buffer)
if l:linter.lsp is# 'tsserver'
call add(l:lsp_linters, l:linter)
endif
@ -108,7 +109,6 @@ function! ale#filerename#Execute() abort
return
endif
let l:buffer = bufnr('')
let l:old_name = expand('#' . l:buffer . ':p')
let l:new_name = ale#util#Input('New file name: ', l:old_name, 'file')

View File

@ -32,7 +32,7 @@ function! ale#fix#ApplyQueuedFixes(buffer) abort
endif
endif
endif
catch /E21/
catch /E21\|E5555/
" If we cannot modify the buffer now, try again later.
let g:ale_fix_buffer_data[a:buffer] = l:data

View File

@ -7,6 +7,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['python'],
\ 'description': 'Add blank lines before control statements.',
\ },
\ 'alejandra': {
\ 'function': 'ale#fixers#alejandra#Fix',
\ 'suggested_filetypes': ['nix'],
\ 'description': 'The Uncompromising Nix Code Formatter',
\ },
\ 'align_help_tags': {
\ 'function': 'ale#fixers#help#AlignTags',
\ 'suggested_filetypes': ['help'],
@ -174,7 +179,12 @@ let s:default_registry = {
\ 'yamlfix': {
\ 'function': 'ale#fixers#yamlfix#Fix',
\ 'suggested_filetypes': ['yaml'],
\ 'description': 'Fix yaml files with yamlfix.',
\ 'description': 'Fix YAML files with yamlfix.',
\ },
\ 'yamlfmt': {
\ 'function': 'ale#fixers#yamlfmt#Fix',
\ 'suggested_filetypes': ['yaml'],
\ 'description': 'Format YAML files with yamlfmt.',
\ },
\ 'yapf': {
\ 'function': 'ale#fixers#yapf#Fix',
@ -263,8 +273,8 @@ let s:default_registry = {
\ },
\ 'clang-format': {
\ 'function': 'ale#fixers#clangformat#Fix',
\ 'suggested_filetypes': ['c', 'cpp', 'cuda'],
\ 'description': 'Fix C/C++ and cuda files with clang-format.',
\ 'suggested_filetypes': ['c', 'cpp', 'cs', 'cuda', 'java', 'javascript', 'json', 'objc', 'proto'],
\ 'description': 'Fix C, C++, C#, CUDA, Java, JavaScript, JSON, ObjectiveC and Protobuf files with clang-format.',
\ },
\ 'cmakeformat': {
\ 'function': 'ale#fixers#cmakeformat#Fix',
@ -276,6 +286,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['fish'],
\ 'description': 'Format fish scripts using fish_indent.',
\ },
\ 'forge': {
\ 'function': 'ale#fixers#forge#Fix',
\ 'suggested_filetypes': ['solidity'],
\ 'description': 'Fix Solidity files with forge fmt.',
\ },
\ 'gofmt': {
\ 'function': 'ale#fixers#gofmt#Fix',
\ 'suggested_filetypes': ['go'],
@ -301,6 +316,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['gomod'],
\ 'description': 'Fix Go module files with go mod edit -fmt.',
\ },
\ 'gopls': {
\ 'function': 'ale#fixers#gopls#Fix',
\ 'suggested_filetypes': ['go'],
\ 'description': 'Fix Go files with gopls.',
\ },
\ 'tslint': {
\ 'function': 'ale#fixers#tslint#Fix',
\ 'suggested_filetypes': ['typescript'],
@ -386,6 +406,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['sh'],
\ 'description': 'Fix sh files with shfmt.',
\ },
\ 'sqlfluff': {
\ 'function': 'ale#fixers#sqlfluff#Fix',
\ 'suggested_filetypes': ['sql'],
\ 'description': 'Fix SQL files with sqlfluff.',
\ },
\ 'sqlfmt': {
\ 'function': 'ale#fixers#sqlfmt#Fix',
\ 'suggested_filetypes': ['sql'],
@ -546,6 +571,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['haskell'],
\ 'description': 'A formatter for Haskell source code.',
\ },
\ 'fourmolu': {
\ 'function': 'ale#fixers#fourmolu#Fix',
\ 'suggested_filetypes': ['haskell'],
\ 'description': 'A formatter for Haskell source code.',
\ },
\ 'jsonnetfmt': {
\ 'function': 'ale#fixers#jsonnetfmt#Fix',
\ 'suggested_filetypes': ['jsonnet'],
@ -575,7 +605,42 @@ let s:default_registry = {
\ 'function': 'ale#fixers#raco_fmt#Fix',
\ 'suggested_filetypes': ['racket'],
\ 'description': 'Fix Racket files with raco fmt.',
\ }
\ },
\ 'ruff': {
\ 'function': 'ale#fixers#ruff#Fix',
\ 'suggested_filetypes': ['python'],
\ 'description': 'Fix python files with ruff.',
\ },
\ 'ruff_format': {
\ 'function': 'ale#fixers#ruff_format#Fix',
\ 'suggested_filetypes': ['python'],
\ 'description': 'Fix python files with the ruff formatter.',
\ },
\ 'pycln': {
\ 'function': 'ale#fixers#pycln#Fix',
\ 'suggested_filetypes': ['python'],
\ 'description': 'remove unused python import statements',
\ },
\ 'rustywind': {
\ 'function': 'ale#fixers#rustywind#Fix',
\ 'suggested_filetypes': ['html'],
\ 'description': 'Sort Tailwind CSS classes',
\ },
\ 'npm-groovy-lint': {
\ 'function': 'ale#fixers#npmgroovylint#Fix',
\ 'suggested_filetypes': ['groovy'],
\ 'description': 'Fix Groovy files with npm-groovy-fix.',
\ },
\ 'erb-formatter': {
\ 'function': 'ale#fixers#erbformatter#Fix',
\ 'suggested_filetypes': ['eruby'],
\ 'description': 'Apply erb-formatter -w to eruby/erb files.',
\ },
\ 'nickel_format': {
\ 'function': 'ale#fixers#nickel_format#Fix',
\ 'suggested_filetypes': ['nickel'],
\ 'description': 'Fix nickel files with nickel format',
\ },
\}
" Reset the function registry to the default entries.

View File

@ -0,0 +1,13 @@
call ale#Set('nix_alejandra_executable', 'alejandra')
call ale#Set('nix_alejandra_options', '')
function! ale#fixers#alejandra#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'nix_alejandra_executable')
let l:options = ale#Var(a:buffer, 'nix_alejandra_options')
return {
\ 'command': ale#Escape(l:executable)
\ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' -- -'
\}
endfunction

View File

@ -0,0 +1,13 @@
" Author: Arash Mousavi <arash-m>
" Description: Support for ERB::Formetter https://github.com/nebulab/erb-formatter
call ale#Set('eruby_erbformatter_executable', 'erb-formatter')
function! ale#fixers#erbformatter#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'eruby_erbformatter_executable')
return {
\ 'command': ale#Escape(l:executable) . ' -w %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -0,0 +1,11 @@
call ale#Set('solidity_forge_executable', 'forge')
function! ale#fixers#forge#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'solidity_forge_executable')
return {
\ 'command': ale#Escape(l:executable)
\ . ' fmt %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -0,0 +1,20 @@
call ale#Set('haskell_fourmolu_executable', 'fourmolu')
call ale#Set('haskell_fourmolu_options', '')
function! ale#fixers#fourmolu#GetExecutable(buffer) abort
let l:executable = ale#Var(a:buffer, 'haskell_fourmolu_executable')
return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'fourmolu')
endfunction
function! ale#fixers#fourmolu#Fix(buffer) abort
let l:executable = ale#fixers#fourmolu#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'haskell_fourmolu_options')
return {
\ 'command': l:executable
\ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' --stdin-input-file '
\ . ale#Escape(@%),
\}
endfunction

View File

@ -0,0 +1,23 @@
" Author: Sean Enck <enckse@voidedtech.com>
" Description: Integration of gopls format with ALE.
call ale#Set('go_gopls_fix_executable', 'gopls')
call ale#Set('go_gopls_fix_options', '')
function! ale#fixers#gopls#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'go_gopls_fix_executable')
let l:options = ale#Var(a:buffer, 'go_gopls_fix_options')
let l:env = ale#go#EnvString(a:buffer)
if !executable(l:executable)
return 0
endif
return {
\ 'command': l:env . ale#Escape(l:executable)
\ . ' format'
\ . ale#Pad(l:options)
\ . ' -l -w %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -0,0 +1,16 @@
" Author: Yining <zhang.yining@gmail.com>
" Description: nickel format as ALE fixer for Nickel files
call ale#Set('nickel_nickel_format_executable', 'nickel')
call ale#Set('nickel_nickel_format_options', '')
function! ale#fixers#nickel_format#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'nickel_nickel_format_executable')
let l:options = ale#Var(a:buffer, 'nickel_nickel_format_options')
return {
\ 'command': ale#Escape(l:executable) . ' format'
\ . (empty(l:options) ? '' : ' ' . l:options)
\}
endfunction

View File

@ -0,0 +1,16 @@
" Author: lucas-str <lucas.sturelle@ik.me>
" Description: Integration of npm-groovy-lint for Groovy files.
call ale#Set('groovy_npmgroovylint_fix_options', '--fix')
function! ale#fixers#npmgroovylint#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'groovy_npmgroovylint_executable')
let l:options = ale#Var(a:buffer, 'groovy_npmgroovylint_fix_options')
return {
\ 'command': ale#Escape(l:executable)
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %t',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -0,0 +1,90 @@
" Author: Yining <zhang.yining@gmail.com>
" Description: pycln as ALE fixer for python files
call ale#Set('python_pycln_executable', 'pycln')
call ale#Set('python_pycln_options', '')
call ale#Set('python_pycln_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_pycln_change_directory', 1)
call ale#Set('python_pycln_auto_pipenv', 0)
call ale#Set('python_pycln_auto_poetry', 0)
call ale#Set('python_pycln_config_file', '')
function! ale#fixers#pycln#GetCwd(buffer) abort
if ale#Var(a:buffer, 'python_pycln_change_directory')
" Run from project root if found, else from buffer dir.
let l:project_root = ale#python#FindProjectRoot(a:buffer)
return !empty(l:project_root) ? l:project_root : '%s:h'
endif
return '%s:h'
endfunction
function! ale#fixers#pycln#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pycln_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_pycln_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_pycln', ['pycln'])
endfunction
function! ale#fixers#pycln#GetCommand(buffer) abort
let l:executable = ale#fixers#pycln#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run pycln'
\ : ''
return ale#Escape(l:executable) . l:exec_args
endfunction
function! ale#fixers#pycln#FixForVersion(buffer, version) abort
let l:executable = ale#fixers#pycln#GetExecutable(a:buffer)
let l:cmd = [ale#Escape(l:executable)]
if l:executable =~? 'pipenv\|poetry$'
call extend(l:cmd, ['run', 'pycln'])
endif
let l:options = ale#Var(a:buffer, 'python_pycln_options')
if !empty(l:options)
call add(l:cmd, l:options)
endif
let l:config_file = ale#Var(a:buffer, 'python_pycln_config_file')
let l:config_file = l:options !~# '\v(^| )--config ' && !empty(l:config_file)
\ ? ale#Escape(ale#path#Simplify(l:config_file))
\ : ''
if !empty(l:config_file)
call add(l:cmd, '--config ' . l:config_file)
endif
call add(l:cmd, '--silence')
" NOTE: pycln version `1.3.0` support reading from stdin
call add(l:cmd, ale#semver#GTE(a:version, [1, 3, 0]) ? '-' : '%s')
return {
\ 'cwd': ale#fixers#pycln#GetCwd(a:buffer),
\ 'command': join(l:cmd, ' '),
\}
endfunction
function! ale#fixers#pycln#Fix(buffer) abort
let l:executable = ale#fixers#pycln#GetExecutable(a:buffer)
let l:command = ale#fixers#pycln#GetCommand(a:buffer) . ale#Pad('--version')
return ale#semver#RunWithVersionCheck(
\ a:buffer,
\ l:executable,
\ l:command,
\ function('ale#fixers#pycln#FixForVersion'),
\)
endfunction

View File

@ -1,6 +1,13 @@
" Author: Yining <zhang.yining@gmail.com>
" Description: ruff as ALE fixer for python files
call ale#Set('python_ruff_executable', 'ruff')
call ale#Set('python_ruff_options', '')
call ale#Set('python_ruff_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_ruff_change_directory', 1)
call ale#Set('python_ruff_auto_pipenv', 0)
call ale#Set('python_ruff_auto_poetry', 0)
function! ale#fixers#ruff#GetCwd(buffer) abort
if ale#Var(a:buffer, 'python_ruff_change_directory')
" Run from project root if found, else from buffer dir.
@ -9,7 +16,7 @@ function! ale#fixers#ruff#GetCwd(buffer) abort
return !empty(l:project_root) ? l:project_root : '%s:h'
endif
return ''
return '%s:h'
endfunction
function! ale#fixers#ruff#GetExecutable(buffer) abort
@ -26,29 +33,57 @@ function! ale#fixers#ruff#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'python_ruff', ['ruff'])
endfunction
function! ale#fixers#ruff#GetCommand(buffer, version) abort
let l:executable = ale_linters#python#ruff#GetExecutable(a:buffer)
function! ale#fixers#ruff#GetCommand(buffer) abort
let l:executable = ale#fixers#ruff#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run ruff'
\ : ''
" NOTE: ruff version `0.0.72` implement `--fix` with stdin
return ale#Escape(l:executable) . l:exec_args
\ . ale#Pad(ale#Var(a:buffer, 'python_ruff_options'))
\ . ' --fix'
\ . (ale#semver#GTE(a:version, [0, 0, 72]) ? ' -' : ' %s')
endfunction
function! ale#fixers#ruff#FixForVersion(buffer, version) abort
let l:executable = ale#fixers#ruff#GetExecutable(a:buffer)
let l:cmd = [ale#Escape(l:executable)]
if l:executable =~? 'pipenv\|poetry$'
call extend(l:cmd, ['run', 'ruff'])
endif
let l:options = ale#Var(a:buffer, 'python_ruff_options')
if !empty(l:options)
call add(l:cmd, l:options)
endif
" when --stdin-filename present, ruff will use it for proj root resolution
" https://github.com/charliermarsh/ruff/pull/1281
let l:fname = expand('#' . a:buffer . '...')
call add(l:cmd, '--stdin-filename '.ale#Escape(ale#path#Simplify(l:fname)))
call add(l:cmd, '--fix')
" NOTE: ruff version `0.0.72` implements `--fix` with stdin
if ale#semver#GTE(a:version, [0, 0, 72])
call add(l:cmd, '-')
else
call add(l:cmd, '%s')
endif
return {
\ 'cwd': ale#fixers#ruff#GetCwd(a:buffer),
\ 'command': join(l:cmd, ' '),
\}
endfunction
function! ale#fixers#ruff#Fix(buffer) abort
let l:fix_cmd = {buffer -> ale#semver#RunWithVersionCheck(
\ buffer,
\ ale#fixers#ruff#GetExecutable(buffer),
\ '%e --version',
\ function('ale#fixers#ruff#GetCommand'),
\ )}(a:buffer)
let l:executable = ale#fixers#ruff#GetExecutable(a:buffer)
let l:command = ale#fixers#ruff#GetCommand(a:buffer) . ale#Pad('--version')
return {
\ 'cwd': ale#fixers#ruff#GetCwd(a:buffer),
\ 'command': l:fix_cmd,
\}
return ale#semver#RunWithVersionCheck(
\ a:buffer,
\ l:executable,
\ l:command,
\ function('ale#fixers#ruff#FixForVersion'),
\)
endfunction

View File

@ -0,0 +1,72 @@
" Author: Yining <zhang.yining@gmail.com>, Joseph Henrich <crimsonknave@gmail.com>
" Description: ruff formatter as ALE fixer for python files
call ale#Set('python_ruff_format_executable', 'ruff')
call ale#Set('python_ruff_format_options', '')
call ale#Set('python_ruff_format_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_ruff_format_change_directory', 1)
call ale#Set('python_ruff_format_auto_pipenv', 0)
call ale#Set('python_ruff_format_auto_poetry', 0)
function! ale#fixers#ruff_format#GetCwd(buffer) abort
if ale#Var(a:buffer, 'python_ruff_format_change_directory')
" Run from project root if found, else from buffer dir.
let l:project_root = ale#python#FindProjectRoot(a:buffer)
return !empty(l:project_root) ? l:project_root : '%s:h'
endif
return '%s:h'
endfunction
function! ale#fixers#ruff_format#GetExecutable(buffer) abort
if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_ruff_format_auto_pipenv'))
\ && ale#python#PipenvPresent(a:buffer)
return 'pipenv'
endif
if (ale#Var(a:buffer, 'python_auto_poetry') || ale#Var(a:buffer, 'python_ruff_format_auto_poetry'))
\ && ale#python#PoetryPresent(a:buffer)
return 'poetry'
endif
return ale#python#FindExecutable(a:buffer, 'python_ruff_format', ['ruff'])
endfunction
function! ale#fixers#ruff_format#GetCommand(buffer) abort
let l:executable = ale#fixers#ruff_format#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run ruff'
\ : ''
return ale#Escape(l:executable) . l:exec_args
endfunction
function! ale#fixers#ruff_format#Fix(buffer) abort
let l:executable = ale#fixers#ruff_format#GetExecutable(a:buffer)
let l:cmd = [ale#Escape(l:executable)]
if l:executable =~? 'pipenv\|poetry$'
call extend(l:cmd, ['run', 'ruff'])
endif
let l:options = ale#Var(a:buffer, 'python_ruff_format_options')
" when --stdin-filename present, ruff will use it for proj root resolution
" https://github.com/charliermarsh/ruff/pull/1281
let l:fname = expand('#' . a:buffer . '...')
call add(l:cmd, 'format')
if !empty(l:options)
call add(l:cmd, l:options)
endif
call add(l:cmd, '--stdin-filename '.ale#Escape(ale#path#Simplify(l:fname)))
call add(l:cmd, '-')
return {
\ 'cwd': ale#fixers#ruff_format#GetCwd(a:buffer),
\ 'command': join(l:cmd, ' '),
\}
endfunction

View File

@ -0,0 +1,17 @@
scriptencoding utf-8
" Author: Guillermo Roig <groig@protonmail.com>
" Description: Sort TailwindCSS classes with rustywind
call ale#Set('html_rustywind_executable', 'rustywind')
call ale#Set('html_rustywind_options', '')
function! ale#fixers#rustywind#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'html_rustywind_executable')
let l:options = ale#Var(a:buffer, 'html_rustywind_options')
return {
\ 'command': ale#Escape(l:executable)
\ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' --stdin'
\}
endfunction

View File

@ -0,0 +1,25 @@
" Author: Carl Smedstad <carl.smedstad at protonmail dot com>
" Description: Fixing SQL files with sqlfluff
call ale#Set('sql_sqlfluff_executable', 'sqlfluff')
function! ale#fixers#sqlfluff#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'sql_sqlfluff_executable')
let l:cmd =
\ ale#Escape(l:executable)
\ . ' fix --force'
let l:config_file = ale#path#FindNearestFile(a:buffer, '.sqlfluff')
if !empty(l:config_file)
let l:cmd .= ' --config ' . ale#Escape(l:config_file)
else
let l:cmd .= ' --dialect ansi'
endif
return {
\ 'command': l:cmd . ' %t > /dev/null',
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -1,4 +1,4 @@
" Author: Cyril Roelandt <tipecaml@gmail.com>
" Author: Cyril Roelandt <tipecaml@gmail.com>, jiz4oh <me@jiz4oh.com>
" Description: Integration of xmllint with ALE.
call ale#Set('xml_xmllint_executable', 'xmllint')
@ -7,7 +7,14 @@ call ale#Set('xml_xmllint_indentsize', 2)
function! ale#fixers#xmllint#Fix(buffer) abort
let l:executable = ale#Escape(ale#Var(a:buffer, 'xml_xmllint_executable'))
let l:filename = ale#Escape(bufname(a:buffer))
let l:filename = bufname(a:buffer)
if empty(l:filename)
let l:filename = '%t'
else
let l:filename = ale#Escape(l:filename)
endif
let l:command = l:executable . ' --format ' . l:filename
let l:indent = ale#Var(a:buffer, 'xml_xmllint_indentsize')

View File

@ -0,0 +1,20 @@
" Author: https://github.com/Spixmaster
" Description: Format YAML files with yamlfmt.
call ale#Set('yaml_yamlfmt_executable', 'yamlfmt')
call ale#Set('yaml_yamlfmt_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('yaml_yamlfmt_options', '')
function! ale#fixers#yamlfmt#Fix(buffer) abort
let l:executable = ale#python#FindExecutable(
\ a:buffer,
\ 'yaml_yamlfmt',
\ ['yamlfmt']
\)
let l:options = ale#Var(a:buffer, 'yaml_yamlfmt_options')
return {
\ 'command': ale#Escape(l:executable) . ' ' . l:options . ' -in',
\}
endfunction

View File

@ -37,24 +37,30 @@ function! s:NvimShow(lines, options) abort
endif
" Execute commands in window context
let l:parent_window = nvim_get_current_win()
if exists('*win_execute')
for l:command in get(a:options, 'commands', [])
call win_execute(w:preview['id'], l:command)
endfor
else
let l:parent_window = nvim_get_current_win()
call nvim_set_current_win(w:preview['id'])
call nvim_set_current_win(w:preview['id'])
for l:command in get(a:options, 'commands', [])
call execute(l:command)
endfor
for l:command in get(a:options, 'commands', [])
call execute(l:command)
endfor
call nvim_set_current_win(l:parent_window)
call nvim_set_current_win(l:parent_window)
endif
" Return to parent context on move
augroup ale_floating_preview_window
autocmd!
if g:ale_close_preview_on_insert
autocmd CursorMoved,TabLeave,WinLeave,InsertEnter <buffer> ++once call s:NvimClose()
autocmd CursorMoved,TabLeave,WinLeave,BufWinLeave,WinScrolled,InsertEnter <buffer> ++once call s:NvimClose()
else
autocmd CursorMoved,TabLeave,WinLeave <buffer> ++once call s:NvimClose()
autocmd CursorMoved,TabLeave,WinLeave,BufWinLeave,WinScrolled <buffer> ++once call s:NvimClose()
endif
augroup END
@ -99,48 +105,30 @@ function! s:NvimPrepareWindowContent(lines) abort
let l:width = max(map(copy(a:lines), 'strdisplaywidth(v:val)'))
let l:height = min([len(a:lines), l:max_height])
if empty(g:ale_floating_window_border)
return [a:lines, l:width, l:height]
endif
" Add the size of borders
let l:width += 2
let l:height += 2
let l:left = get(g:ale_floating_window_border, 0, '|')
let l:top = get(g:ale_floating_window_border, 1, '-')
let l:top_left = get(g:ale_floating_window_border, 2, '+')
let l:top_right = get(g:ale_floating_window_border, 3, '+')
let l:bottom_right = get(g:ale_floating_window_border, 4, '+')
let l:bottom_left = get(g:ale_floating_window_border, 5, '+')
let l:right = get(g:ale_floating_window_border, 6, l:left)
let l:bottom = get(g:ale_floating_window_border, 7, l:top)
let l:lines = [l:top_left . repeat(l:top, l:width - 2) . l:top_right]
for l:line in a:lines
let l:line_width = strchars(l:line)
let l:lines = add(l:lines, l:left . l:line . repeat(' ', l:width - l:line_width - 2). l:right)
endfor
" Truncate the lines
if len(l:lines) > l:max_height + 1
let l:lines = l:lines[0:l:max_height]
endif
let l:lines = add(l:lines, l:bottom_left . repeat(l:bottom, l:width - 2) . l:bottom_right)
return [l:lines, l:width, l:height]
return [a:lines[0:l:height-1], l:width, l:height]
endfunction
function! s:NvimCreate(options) abort
let l:left = get(g:ale_floating_window_border, 0, '|')
let l:top = get(g:ale_floating_window_border, 1, '-')
let l:popup_opts = extend({
\ 'relative': 'cursor',
\ 'row': 1,
\ 'col': 0,
\ 'width': 42,
\ 'height': 4,
\ 'style': 'minimal'
\ 'style': 'minimal',
\ 'border': empty(g:ale_floating_window_border) ? 'none' : [
\ get(g:ale_floating_window_border, 2, '+'),
\ l:top,
\ get(g:ale_floating_window_border, 3, '+'),
\ get(g:ale_floating_window_border, 6, l:left),
\ get(g:ale_floating_window_border, 4, '+'),
\ get(g:ale_floating_window_border, 7, l:top),
\ get(g:ale_floating_window_border, 5, '+'),
\ l:left,
\ ],
\ }, s:GetPopupOpts())
let l:buffer = nvim_create_buf(v:false, v:false)

View File

@ -1,36 +0,0 @@
function! ale#handlers#actionlint#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'yaml_actionlint_options')
" automatically add --no-color option if not defined
if l:options !~# '--no-color'
let l:options .= ' --no-color'
endif
" automatically add --oneline option if not defined
if l:options !~# '--oneline'
let l:options .= ' --oneline'
endif
return '%e ' . l:options . ' %t'
endfunction
function! ale#handlers#actionlint#Handle(buffer, lines) abort
" Matches patterns line the following:
".github/workflows/main.yml:19:0: could not parse as YAML: yaml: line 19: mapping values are not allowed in this context [yaml-syntax]
let l:pattern = '\v^.*:(\d+):(\d+): (.+) \[(.+)\]$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:item = {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[3],
\ 'code': l:match[4],
\ 'type': 'E',
\}
call add(l:output, l:item)
endfor
return l:output
endfunction

View File

@ -0,0 +1,41 @@
" Author: 0xhyoga <0xhyoga@gmx.com>,
" Description: This file implements handlers specific to Cairo
"
function! ale#handlers#cairo#HandleCairoErrors(buffer, lines) abort
" Matches patterns like the following:
" Error: Expected ';' but got '('
" --> /path/to/file/file.cairo:1:10:)
let l:pattern = '\v(error|warning): (.*)$'
let l:line_and_column_pattern = '\v\.cairo:(\d+):(\d+)'
let l:exclude_pattern = '\vcould not compile.*'
let l:output = []
for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0
let l:match = matchlist(l:line, l:line_and_column_pattern)
if len(l:match) > 0
let l:index = len(l:output) - 1
let l:output[l:index]['lnum'] = l:match[1] + 0
let l:output[l:index]['col'] = l:match[2] + 0
endif
else
let l:text = l:match[2]
if l:text !~# l:exclude_pattern
let l:isError = l:match[1] is? 'Error'
call add(l:output, {
\ 'lnum': 0,
\ 'col': 0,
\ 'text': l:text,
\ 'type': l:isError ? 'E' : 'W',
\})
endif
endif
endfor
return l:output
endfunction

View File

@ -24,14 +24,19 @@ endfunction
function! ale#handlers#cspell#Handle(buffer, lines) abort
" Look for lines like the following:
"
" /home/user/repos/ale/README.md:723:48 - Unknown word (stylelint)
let l:pattern = '\v^.*:(\d+):(\d+) - (.*)$'
" /home/user/repos/ale/README.md:3:128 - Unknown word (Neovim)
" match1: 3
" match2: 128
" match3: Unknown word (Neovim)
" match4: Neovim
let l:pattern = '\v^.*:(\d+):(\d+) - ([^\(]+\(([^\)]+)\).*)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'end_col': l:match[2] + len(l:match[4]) - 1,
\ 'text': l:match[3],
\ 'type': 'W',
\})

View File

@ -0,0 +1,33 @@
function! ale#handlers#deadnix#Handle(buffer, lines) abort
let l:output = []
for l:line in a:lines
try
let l:file = ale#util#FuzzyJSONDecode(l:line, v:null)
catch
continue
endtry
if type(l:file) isnot v:t_dict
continue
endif
for l:error in l:file['results']
try
let l:ale_error = {
\ 'lnum': l:error['line'],
\ 'col': l:error['column'],
\ 'end_col': l:error['endColumn'],
\ 'text': l:error['message'],
\ 'type': 'W',
\}
catch
continue
endtry
call add(l:output, l:ale_error)
endfor
endfor
return l:output
endfunction

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