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! Just do a git rebase!
cd ~/.vim_runtime cd ~/.vim_runtime
git reset --hard git reset --hard
git clean -d --force 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 * [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 * [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) * [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-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-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 * [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 * [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 * [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 * [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 ## 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 * [peaksea](https://github.com/vim-scripts/peaksea): The default
* [dracula](https://github.com/dracula/vim) * [dracula](https://github.com/dracula/vim)
* [vim-colors-solarized](https://github.com/altercation/vim-colors-solarized) * [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? ## 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>ct :cd ~/Desktop/Todoist/todoist<cr>
map <leader>cw :cd ~/Desktop/Wedoist/wedoist<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): You can also install plugins without any plugin manager (vim 8+ required):
* Add `packloadall` to your `.vimrc` file
* Create pack plugin directory:\ * Create pack plugin directory:\
`mkdir -p ~/.vim_runtime/pack/plugins/start` `mkdir -p ~/.vim_runtime/pack/plugins/start`
* Clone the plugin that you want in that directory, for example:\ * 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`): 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>` to `/` (search) and `<Ctrl>+<Space>` to `?` (backwards search):
```vim
map <space> / map <space> /
map <C-space> ? map <C-space> ?
```
Disable highlights when you press `<leader><cr>`: 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.): Smart way to move between windows (`<ctrl>j` etc.):
```vim
map <C-j> <C-W>j map <C-j> <C-W>j
map <C-k> <C-W>k map <C-k> <C-W>k
map <C-h> <C-W>h map <C-h> <C-W>h
map <C-l> <C-W>l map <C-l> <C-W>l
```
Closing of the current buffer(s) (`<leader>bd` and (`<leader>ba`)): Closing of the current buffer(s) (`<leader>bd` and (`<leader>ba`)):
```vim
" Close current buffer " Close current buffer
map <leader>bd :Bclose<cr> map <leader>bd :Bclose<cr>
" Close all buffers " Close all buffers
map <leader>ba :1,1000 bd!<cr> map <leader>ba :1,1000 bd!<cr>
```
Useful mappings for managing tabs: Useful mappings for managing tabs:
```vim
map <leader>tn :tabnew<cr> map <leader>tn :tabnew<cr>
map <leader>to :tabonly<cr> map <leader>to :tabonly<cr>
map <leader>tc :tabclose<cr> map <leader>tc :tabclose<cr>
map <leader>tm :tabmove map <leader>tm :tabmove
" Opens a new tab with the current buffer's path " Opens a new tab with the current buffer's path
" Super useful when editing files in the same directory " Super useful when editing files in the same directory
map <leader>te :tabedit <C-r>=escape(expand("%:p:h"), " ")<cr>/ 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: Switch [CWD](http://vim.wikia.com/wiki/Set_working_directory_to_the_current_file) to the directory of the open buffer:
```vim
map <leader>cd :cd %:p:h<cr>:pwd<cr> map <leader>cd :cd %:p:h<cr>:pwd<cr>
```
Open `ack.vim` for fast search: Open `ack.vim` for fast search:
```vim
map <leader>g :Ack map <leader>g :Ack
```
Quickly open a buffer for scripbble: Quickly open a buffer for scripbble:
```vim
map <leader>q :e ~/buffer<cr> map <leader>q :e ~/buffer<cr>
```
Toggle paste mode on and off: Toggle paste mode on and off:
```vim
map <leader>pp :setlocal paste!<cr> map <leader>pp :setlocal paste!<cr>
```
### Visual mode mappings ### Visual mode mappings
Visual mode pressing `*` or `#` searches for the current selection: Visual mode pressing `*` or `#` searches for the current selection:
```vim
vnoremap <silent> * :call VisualSelection('f')<CR> vnoremap <silent> * :call VisualSelection('f')<CR>
vnoremap <silent> # :call VisualSelection('b')<CR> vnoremap <silent> # :call VisualSelection('b')<CR>
```
When you press gv you `Ack.vim` after the selected text: When you press gv you `Ack.vim` after the selected text:
```vim
vnoremap <silent> gv :call VisualSelection('gv', '')<CR> vnoremap <silent> gv :call VisualSelection('gv', '')<CR>
```
When you press `<leader>r` you can search and replace the selected text: When you press `<leader>r` you can search and replace the selected text:
```vim
vnoremap <silent> <leader>r :call VisualSelection('replace')<CR> vnoremap <silent> <leader>r :call VisualSelection('replace')<CR>
```
Surround the visual selection in parenthesis/brackets/etc.: Surround the visual selection in parenthesis/brackets/etc.:
```vim
vnoremap $1 <esc>`>a)<esc>`<i(<esc> vnoremap $1 <esc>`>a)<esc>`<i(<esc>
vnoremap $2 <esc>`>a]<esc>`<i[<esc> vnoremap $2 <esc>`>a]<esc>`<i[<esc>
vnoremap $3 <esc>`>a}<esc>`<i{<esc> vnoremap $3 <esc>`>a}<esc>`<i{<esc>
vnoremap $$ <esc>`>a"<esc>`<i"<esc> vnoremap $$ <esc>`>a"<esc>`<i"<esc>
vnoremap $q <esc>`>a'<esc>`<i'<esc> vnoremap $q <esc>`>a'<esc>`<i'<esc>
vnoremap $e <esc>`>a`<esc>`<i`<esc> vnoremap $e <esc>`>a`<esc>`<i`<esc>
```
### Insert mode mappings ### Insert mode mappings
Quickly insert parenthesis/brackets/etc.: Quickly insert parenthesis/brackets/etc.:
```vim
inoremap $1 ()<esc>i inoremap $1 ()<esc>i
inoremap $2 []<esc>i inoremap $2 []<esc>i
inoremap $3 {}<esc>i inoremap $3 {}<esc>i
inoremap $4 {<esc>o}<esc>O inoremap $4 {<esc>o}<esc>O
inoremap $q ''<esc>i inoremap $q ''<esc>i
inoremap $e ""<esc>i inoremap $e ""<esc>i
inoremap $t <><esc>i inoremap $t <><esc>i
```
Insert the current date and time (useful for timestamps): Insert the current date and time (useful for timestamps):
```vim
iab xdate <C-r>=strftime("%d/%m/%y %H:%M:%S")<cr> iab xdate <C-r>=strftime("%d/%m/%y %H:%M:%S")<cr>
```
### Command line mappings ### Command line mappings
$q is super useful when browsing on the command line. It deletes everything until the last slash: $q is super useful when browsing on the command line. It deletes everything until the last slash:
```vim
cno $q <C-\>eDeleteTillSlash()<cr> cno $q <C-\>eDeleteTillSlash()<cr>
```
Bash like keys for the command line: 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-P> <Up>
cnoremap <C-E> <End> cnoremap <C-N> <Down>
cnoremap <C-K> <C-U> ```
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): 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 :W
### Plugin related mappings ### Plugin related mappings
Open [bufexplorer](https://github.com/vim-scripts/bufexplorer.zip) to see and manage the current buffers (`<leader>o`): Open [bufexplorer](https://github.com/vim-scripts/bufexplorer.zip) to see and manage the current buffers (`<leader>o`):
```vim
map <leader>o :BufExplorer<cr> 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`): 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 " Quickly find and open a recently opened file
let g:ctrlp_map = '<C-f>' map <leader>f :MRU<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>
" Quickly find and open a buffer
map <leader>b :CtrlPBuffer<cr>
```
[NERD Tree](https://github.com/preservim/nerdtree) mappings: [NERD Tree](https://github.com/preservim/nerdtree) mappings:
```vim
map <leader>nn :NERDTreeToggle<cr> map <leader>nn :NERDTreeToggle<cr>
map <leader>nb :NERDTreeFromBookmark map <leader>nb :NERDTreeFromBookmark
map <leader>nf :NERDTreeFind<cr> 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`) [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`)
```vim
map <leader>z :Goyo<cr> map <leader>z :Goyo<cr>
```
[vim-multiple-cursors](https://github.com/terryma/vim-multiple-cursors) mappings to manage multiple cursors at once: [vim-multiple-cursors](https://github.com/terryma/vim-multiple-cursors) mappings to manage multiple cursors at once:
```vim
let g:multi_cursor_start_word_key = '<C-s>' let g:multi_cursor_start_word_key = '<C-s>'
let g:multi_cursor_select_all_word_key = '<A-s>' let g:multi_cursor_select_all_word_key = '<A-s>'
let g:multi_cursor_start_key = 'g<C-s>' let g:multi_cursor_start_key = 'g<C-s>'
let g:multi_cursor_select_all_key = 'g<A-s>' let g:multi_cursor_select_all_key = 'g<A-s>'
let g:multi_cursor_next_key = '<C-s>' let g:multi_cursor_next_key = '<C-s>'
let g:multi_cursor_prev_key = '<C-p>' let g:multi_cursor_prev_key = '<C-p>'
let g:multi_cursor_skip_key = '<C-x>' let g:multi_cursor_skip_key = '<C-x>'
let g:multi_cursor_quit_key = '<Esc>' let g:multi_cursor_quit_key = '<Esc>'
```
[vim-yankstack](https://github.com/maxbrunsfeld/vim-yankstack) mappings to manage the kill-ring (clipboard): [vim-yankstack](https://github.com/maxbrunsfeld/vim-yankstack) mappings to manage the kill-ring (clipboard):
```vim
nmap <C-p> <Plug>yankstack_substitute_older_paste nmap <C-p> <Plug>yankstack_substitute_older_paste
nmap <C-n> <Plug>yankstack_substitute_newer_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.: [ctrl-p](https://github.com/ctrlpvim/ctrlp.vim) mappings to easily find and open a file, buffer, etc.:
```vim
let g:ctrlp_map = '<C-f>' let g:ctrlp_map = '<C-f>'
map <leader>j :CtrlP<cr> map <leader>j :CtrlP<cr>
map <C-b> :CtrlPBuffer<cr> map <C-b> :CtrlPBuffer<cr>
```
[vim-snipmate](https://github.com/garbas/vim-snipmate) mappings to autocomplete via snippets: [vim-snipmate](https://github.com/garbas/vim-snipmate) mappings to autocomplete via snippets:
```vim
ino <C-j> <C-r>=snipMate#TriggerSnippet()<cr> ino <C-j> <C-r>=snipMate#TriggerSnippet()<cr>
snor <C-j> <esc>i<right><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: [vim-surround](https://github.com/tpope/vim-surround) mappings to easily surround a string with `_()` gettext annotation:
```vim
vmap Si S(i_<esc>f) vmap Si S(i_<esc>f)
au FileType mako vmap Si S"i${ _(<esc>2f"a) }<esc> 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: [ale](https://github.com/dense-analysis/ale) to easily go to the next Ale syntax/lint error:
```vim
nmap <silent> <leader>a <Plug>(ale_next_wrap) 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`) [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: 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 :IndentGuidesToggle
[vim-fugitive](https://github.com/tpope/vim-fugitive) to copy the link to the line of a Git repository to the clipboard: [vim-fugitive](https://github.com/tpope/vim-fugitive) to copy the link to the line of a Git repository to the clipboard:
```vim
nnoremap <leader>v :.GBrowse!<CR> nnoremap <leader>v :.GBrowse!<CR>
xnoremap <leader>v :'<'>GBrowse!<CR> xnoremap <leader>v :'<'>GBrowse!<CR>
```
### Spell checking ### Spell checking
Pressing `<leader>ss` will toggle spell checking: Pressing `<leader>ss` will toggle spell checking:
```vim
map <leader>ss :setlocal spell!<cr> map <leader>ss :setlocal spell!<cr>
```
Shortcuts using `<leader>` instead of special characters: Shortcuts using `<leader>` instead of special characters:
```vim
map <leader>sn ]s map <leader>sn ]s
map <leader>sp [s map <leader>sp [s
map <leader>sa zg map <leader>sa zg
map <leader>s? z= map <leader>s? z=
```
### Running Code ### Running Code
To run code directly from vim, press `F5`. The currently open code will execute without you having to type anything. 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 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`
```
~/.vim_runtime/vimrcs/extended.vim
```
### Cope ### Cope
Query `:help cope` if you are unsure what cope is. It's super useful! 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` `<leader>p`
Cope mappings: Cope mappings:
```vim
map <leader>cc :botright cope<cr> map <leader>cc :botright cope<cr>
map <leader>co ggVGy:tabnew<cr>:set syntax=qf<cr>pgg map <leader>co ggVGy:tabnew<cr>:set syntax=qf<cr>pgg
map <leader>n :cn<cr> map <leader>n :cn<cr>
map <leader>p :cp<cr> map <leader>p :cp<cr>
```
## How to uninstall ## How to uninstall
Just do following: 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. All rights reserved.
Redistribution and use in source and binary forms, with or without 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 if '>=6.0.0' is# l:version_group
let l:error_codes = { 'blocker': 'E', 'critical': 'E', 'major': 'W', 'minor': 'W', 'info': 'I' } 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 for l:issue in l:linter_issues
if ale#path#IsBufferPath(a:buffer, l:issue.location.path) 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, { call add(l:output, {
\ 'lnum': exists('l:issue.location.lines.begin.column') ? l:issue.location.lines.begin.line : \ 'lnum': exists(l:column_member) ? l:issue.location[l:coord_keyname].begin.line :
\ l:issue.location.lines.begin, \ l:issue.location[l:coord_keyname].begin,
\ 'col': exists('l:issue.location.lines.begin.column') ? l:issue.location.lines.begin.column : 0, \ 'col': exists(l:column_member) ? l:issue.location[l:coord_keyname].begin.column : 0,
\ 'text': l:issue.check_name, \ 'text': l:issue.check_name,
\ 'detail': l:issue.description, \ 'detail': l:issue.description,
\ 'code': l:issue.severity, \ '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 endfunction
function! ale_linters#bicep#bicep#Handle(buffer, lines) abort 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 = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) 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' let l:type = 'E'
elseif l:match[3] is# 'Warning' elseif l:match[4] is# 'Warning'
let l:type = 'W' let l:type = 'W'
else else
let l:type = 'I' let l:type = 'I'
endif endif
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[1] + 0, \ 'filename': l:match[1],
\ 'col': l:match[2] + 0, \ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'type': l:type, \ 'type': l:type,
\ 'code': l:match[4], \ 'code': l:match[5],
\ 'text': l:match[5], \ 'text': l:match[6],
\}) \})
endfor 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> " 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_executable', 'starknet-compile')
call ale#Set('cairo_starknet_options', '') call ale#Set('cairo_starknet_options', '')
@ -35,3 +36,4 @@ call ale#linter#Define('cairo', {
\ 'callback': 'ale_linters#cairo#starknet#Handle', \ 'callback': 'ale_linters#cairo#starknet#Handle',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\}) \})

View File

@ -1,4 +1,5 @@
" Author: Taylor Blau <me@ttaylorr.com> " Author: Taylor Blau <me@ttaylorr.com>
call ale#Set('dafny_dafny_timelimit', 10)
function! ale_linters#dafny#dafny#Handle(buffer, lines) abort function! ale_linters#dafny#dafny#Handle(buffer, lines) abort
let l:pattern = '\v(.*)\((\d+),(\d+)\): (.*): (.*)' 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')) return printf('dafny %%s /compile:0 /timeLimit:%d', ale#Var(a:buffer, 'dafny_dafny_timelimit'))
endfunction endfunction
call ale#Set('dafny_dafny_timelimit', 10)
call ale#linter#Define('dafny', { call ale#linter#Define('dafny', {
\ 'name': 'dafny', \ 'name': 'dafny',
\ 'executable': '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> " 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_release', 'elixir-ls')
call ale#Set('elixir_elixir_ls_config', {}) call ale#Set('elixir_elixir_ls_config', {})
@ -12,7 +12,8 @@ function! ale_linters#elixir#elixir_ls#GetExecutable(buffer) abort
endfunction endfunction
call ale#linter#Define('elixir', { call ale#linter#Define('elixir', {
\ 'name': 'elixir-ls', \ 'name': 'elixir_ls',
\ 'aliases': ['elixir-ls', 'elixirls'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': function('ale_linters#elixir#elixir_ls#GetExecutable'), \ 'executable': function('ale_linters#elixir#elixir_ls#GetExecutable'),
\ 'command': 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_test_path', '')
call ale#Set('elm_ls_elm_analyse_trigger', 'change') 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') let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm.json')
return !empty(l:elm_json) ? fnamemodify(l:elm_json, ':p:h') : '' return !empty(l:elm_json) ? fnamemodify(l:elm_json, ':p:h') : ''
endfunction endfunction
function! elm_ls#GetOptions(buffer) abort function! ale_linters#elm#ls#GetOptions(buffer) abort
return { return {
\ 'elmPath': ale#Var(a:buffer, 'elm_ls_elm_path'), \ 'elmPath': ale#Var(a:buffer, 'elm_ls_elm_path'),
\ 'elmFormatPath': ale#Var(a:buffer, 'elm_ls_elm_format_path'), \ 'elmFormatPath': ale#Var(a:buffer, 'elm_ls_elm_format_path'),
@ -26,7 +26,8 @@ function! elm_ls#GetOptions(buffer) abort
endfunction endfunction
call ale#linter#Define('elm', { call ale#linter#Define('elm', {
\ 'name': 'elm_ls', \ 'name': 'ls',
\ 'aliases': ['elm_ls'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': {b -> ale#path#FindExecutable(b, 'elm_ls', [ \ 'executable': {b -> ale#path#FindExecutable(b, 'elm_ls', [
\ 'node_modules/.bin/elm-language-server', \ 'node_modules/.bin/elm-language-server',
@ -34,7 +35,7 @@ call ale#linter#Define('elm', {
\ 'elm-lsp' \ 'elm-lsp'
\ ])}, \ ])},
\ 'command': '%e --stdio', \ 'command': '%e --stdio',
\ 'project_root': function('elm_ls#GetRootDir'), \ 'project_root': function('ale_linters#elm#ls#GetProjectRoot'),
\ 'language': 'elm', \ 'language': 'elm',
\ 'initialization_options': function('elm_ls#GetOptions') \ '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 " 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 " ERB, so we'll have to do some substitution. This does not reduce the
" effectiveness of the linter—the translated code is still evaluated. " 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 endfunction
call ale#linter#Define('eruby', { call ale#linter#Define('eruby', {

View File

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

View File

@ -17,13 +17,15 @@ function! ale_linters#glsl#glslang#Handle(buffer, lines) abort
" Matches patterns like the following: " Matches patterns like the following:
" "
" ERROR: 0:5: 'foo' : undeclared identifier " 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 = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, { call add(l:output, {
\ 'lnum': str2nr(l:match[3]), \ 'lnum': str2nr(l:match[3]),
\ 'col': str2nr(l:match[2]), \ 'col' : 0,
\ 'text': l:match[4], \ 'text': l:match[4],
\ 'type': l:match[1] is# 'ERROR' ? 'E' : 'W', \ '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_go_executable', 'go')
call ale#Set('go_gobuild_options', '') 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 function! ale_linters#go#gobuild#GetMatches(lines) abort
" Matches patterns like the following: " Matches patterns like the following:
" "
@ -50,7 +40,12 @@ call ale#linter#Define('go', {
\ 'aliases': ['go build'], \ 'aliases': ['go build'],
\ 'executable': {b -> ale#Var(b, 'go_go_executable')}, \ 'executable': {b -> ale#Var(b, 'go_go_executable')},
\ 'cwd': '%s:h', \ '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', \ 'output_stream': 'stderr',
\ 'callback': 'ale_linters#go#gobuild#Handler', \ 'callback': 'ale_linters#go#gobuild#Handler',
\ 'lint_file': 1, \ 'lint_file': 1,

View File

@ -1,7 +1,7 @@
" Author: Sascha Grunert <mail@saschagrunert.de> " Author: Sascha Grunert <mail@saschagrunert.de>
" Description: Adds support of golangci-lint " 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_executable', 'golangci-lint')
call ale#Set('go_golangci_lint_package', 0) 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 " 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_go_executable', 'go')
call ale#Set('go_govet_options', '') 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', { call ale#linter#Define('go', {
\ 'name': 'govet', \ 'name': 'govet',
\ 'aliases': ['go vet'], \ 'aliases': ['go vet'],
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'go_go_executable')}, \ 'executable': {b -> ale#Var(b, 'go_go_executable')},
\ 'cwd': '%s:h', \ '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', \ 'callback': 'ale#handlers#go#Handler',
\ 'lint_file': 1, \ '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' return '%e --format=json --filename %s'
endif endif
if ale#semver#GTE(a:version, [1, 6, 0]) return '%e --json --filename %s'
" Reading from stdin was introduced in ember-template-lint@1.6.0
return '%e --json --filename %s'
endif
return '%e --json %t'
endfunction endfunction
function! ale_linters#handlebars#embertemplatelint#GetCommandWithVersionCheck(buffer) abort 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:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h'))
for l:root_file in l:serach_root_files for l:root_file in l:serach_root_files
if filereadable(l:path . l:root_file) if filereadable(l:path . '/' . l:root_file)
return l:path " Add on / so fnamemodify(..., ':h') below keeps the path.
return l:path . '/'
endif endif
endfor endfor
endfor endfor

View File

@ -48,7 +48,7 @@ endfunction
call ale#linter#Define('html', { call ale#linter#Define('html', {
\ 'name': 'angular', \ 'name': 'angular',
\ 'aliases': ['angular-language-server'], \ 'aliases': ['angular-language-server', 'angularls'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': function('ale_linters#html#angular#GetExecutable'), \ 'executable': function('ale_linters#html#angular#GetExecutable'),
\ 'command': function('ale_linters#html#angular#GetCommand'), \ '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', { call ale#linter#Define('java', {
\ 'name': 'javalsp', \ 'name': 'javalsp',
\ 'aliases': ['java_language_server'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': function('ale_linters#java#javalsp#Executable'), \ 'executable': function('ale_linters#java#javalsp#Executable'),
\ 'command': function('ale_linters#java#javalsp#Command'), \ 'command': function('ale_linters#java#javalsp#Command'),

View File

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

View File

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

View File

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

View File

@ -21,6 +21,7 @@ endfunction
call ale#linter#Define('kotlin', { call ale#linter#Define('kotlin', {
\ 'name': 'languageserver', \ 'name': 'languageserver',
\ 'aliaes': ['kotlin_language_server'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'kotlin_languageserver_executable')}, \ 'executable': {b -> ale#Var(b, 'kotlin_languageserver_executable')},
\ 'command': '%e', \ '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_executable', 'luacheck')
call ale#Set('lua_luacheck_options', '') 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 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 -' \ . ' --formatter plain --codes --filename %s -'
endfunction endfunction

View File

@ -1,10 +1,15 @@
" Author: Ty-Lucas Kelley <tylucaskelley@gmail.com> " Author: Ty-Lucas Kelley <tylucaskelley@gmail.com>
" Description: Adds support for markdownlint " Description: Adds support for markdownlint
call ale#Set('markdown_markdownlint_executable', 'markdownlint')
call ale#Set('markdown_markdownlint_options', '') 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 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') let l:options = ale#Var(a:buffer, 'markdown_markdownlint_options')
@ -14,7 +19,7 @@ endfunction
call ale#linter#Define('markdown', { call ale#linter#Define('markdown', {
\ 'name': 'markdownlint', \ 'name': 'markdownlint',
\ 'executable': 'markdownlint', \ 'executable': function('ale_linters#markdown#markdownlint#GetExecutable'),
\ 'lint_file': 1, \ 'lint_file': 1,
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'command': function('ale_linters#markdown#markdownlint#GetCommand'), \ '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 function! ale_linters#nix#nix#Command(buffer, output, meta) abort
let l:version = a:output[0][22:] let l:version = a:output[0][22:]
if l:version =~# '^\(2.[4-9]\|3\).*' if l:version =~# '^\(1\|2.[0-3]\.\).*'
return 'nix-instantiate --log-format internal-json --parse -'
else
return 'nix-instantiate --parse -' return 'nix-instantiate --parse -'
else
return 'nix-instantiate --log-format internal-json --parse -'
endif endif
endfunction endfunction

View File

@ -9,6 +9,7 @@ endfunction
call ale#linter#Define('nix', { call ale#linter#Define('nix', {
\ 'name': 'rnix_lsp', \ 'name': 'rnix_lsp',
\ 'aliases': ['rnix'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': 'rnix-lsp', \ 'executable': 'rnix-lsp',
\ 'command': '%e', \ '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', { call ale#linter#Define('ocaml', {
\ 'name': 'ols', \ 'name': 'ols',
\ 'aliases': ['ocaml-language-server'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': function('ale#handlers#ols#GetExecutable'), \ 'executable': function('ale#handlers#ols#GetExecutable'),
\ 'command': function('ale#handlers#ols#GetCommand'), \ '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') 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 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')) \ . ale#Pad(ale#Var(a:buffer, 'php_phpmd_ruleset'))
\ . ' --ignore-violations-on-exit %t' \ . ' --ignore-violations-on-exit'
endfunction endfunction
function! ale_linters#php#phpmd#Handle(buffer, lines) abort 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: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 " if no configuration file is found, then use 4 as a default level
let l:level = '4' let l:level = '4'
endif endif
@ -70,6 +68,22 @@ function! ale_linters#php#phpstan#Handle(buffer, lines) abort
return l:output return l:output
endfunction 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', { call ale#linter#Define('php', {
\ 'name': 'phpstan', \ 'name': 'phpstan',
\ 'executable': {buffer -> ale#path#FindExecutable(buffer, 'php_phpstan', [ \ 'executable': {buffer -> ale#path#FindExecutable(buffer, 'php_phpstan', [
@ -86,4 +100,5 @@ call ale#linter#Define('php', {
\ function('ale_linters#php#phpstan#GetCommand'), \ function('ale_linters#php#phpstan#GetCommand'),
\ )}, \ )},
\ 'callback': 'ale_linters#php#phpstan#Handle', \ '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', { call ale#linter#Define('puppet', {
\ 'name': 'languageserver', \ 'name': 'languageserver',
\ 'aliases': ['puppet_languageserver'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'puppet_languageserver_executable')}, \ 'executable': {b -> ale#Var(b, 'puppet_languageserver_executable')},
\ 'command': '%e --stdio', \ 'command': '%e --stdio',

View File

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

View File

@ -16,16 +16,21 @@ endfunction
function! ale_linters#python#jedils#GetCommand(buffer) abort function! ale_linters#python#jedils#GetCommand(buffer) abort
let l:executable = ale_linters#python#jedils#GetExecutable(a:buffer) let l:executable = ale_linters#python#jedils#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv$' let l:exec_args = l:executable =~? 'pipenv$'
\ ? ' run jedi-language-server' \ ? ' 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 endfunction
call ale#linter#Define('python', { call ale#linter#Define('python', {
\ 'name': 'jedils', \ 'name': 'jedils',
\ 'aliases': ['jedi_language_server'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': function('ale_linters#python#jedils#GetExecutable'), \ 'executable': function('ale_linters#python#jedils#GetExecutable'),
\ 'command': function('ale_linters#python#jedils#GetCommand'), \ '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']) return ale#python#FindExecutable(a:buffer, 'python_pylsp', ['pylsp'])
endfunction 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 function! ale_linters#python#pylsp#GetCommand(buffer) abort
let l:executable = ale_linters#python#pylsp#GetExecutable(a:buffer) let l:executable = ale_linters#python#pylsp#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry$' let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run pylsp' \ ? ' 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 endfunction
call ale#linter#Define('python', { call ale#linter#Define('python', {
\ 'name': 'pylsp', \ 'name': 'pylsp',
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': function('ale_linters#python#pylsp#GetExecutable'), \ 'executable': function('ale_linters#python#pylsp#GetExecutable'),
\ 'cwd': function('ale_linters#python#pylsp#GetCwd'),
\ 'command': function('ale_linters#python#pylsp#GetCommand'), \ 'command': function('ale_linters#python#pylsp#GetCommand'),
\ 'project_root': function('ale#python#FindProjectRoot'), \ 'project_root': function('ale#python#FindProjectRoot'),
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter', \ '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_executable', 'pyright-langserver')
call ale#Set('python_pyright_config', {}) 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 function! ale_linters#python#pyright#GetConfig(buffer) abort
let l:config = deepcopy(ale#Var(a:buffer, 'python_pyright_config')) 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 return l:config
endfunction 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', { call ale#linter#Define('python', {
\ 'name': 'pyright', \ 'name': 'pyright',
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'python_pyright_executable')}, \ 'cwd': function('ale_linters#python#pyright#GetCwd'),
\ 'command': '%e --stdio', \ 'executable': function('ale_linters#python#pyright#GetExecutable'),
\ 'command': function('ale_linters#python#pyright#GetCommand'),
\ 'project_root': function('ale#python#FindProjectRoot'), \ 'project_root': function('ale#python#FindProjectRoot'),
\ 'completion_filter': 'ale#completion#python#CompletionItemFilter', \ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
\ 'lsp_config': function('ale_linters#python#pyright#GetConfig'), \ '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 " 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')) \ . ale#Pad(ale#Var(a:buffer, 'python_ruff_options'))
\ . ' --format text' \ . (ale#semver#GTE(a:version, [0, 1, 0]) ? ' --output-format json-lines' : ' --format json-lines')
\ . (ale#semver#GTE(a:version, [0, 0, 69]) ? ' -' : ' %s') \ . (ale#semver#GTE(a:version, [0, 0, 69]) ? ' --stdin-filename %s -' : ' %s')
endfunction endfunction
function! ale_linters#python#ruff#Handle(buffer, lines) abort 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 = [] 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, { call add(l:output, {
\ 'lnum': l:match[1] + 0, \ 'lnum': l:item.location.row,
\ 'col': l:match[2] + 0, \ 'col': l:item.location.column,
\ 'text': l:match[3], \ '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 endfor

View File

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

View File

@ -15,6 +15,7 @@ endfunction
call ale#linter#Define('reason', { call ale#linter#Define('reason', {
\ 'name': 'reason-language-server', \ 'name': 'reason-language-server',
\ 'aliases': ['reason_ls'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': {buffer -> ale#Var(buffer, 'reason_ls_executable')}, \ 'executable': {buffer -> ale#Var(buffer, 'reason_ls_executable')},
\ 'command': '%e', \ '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', { call ale#linter#Define('reason', {
\ 'name': 'ols', \ 'name': 'ols',
\ 'aliases': ['ocaml-language-server'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': function('ale#handlers#ols#GetExecutable'), \ 'executable': function('ale#handlers#ols#GetExecutable'),
\ 'command': function('ale#handlers#ols#GetCommand'), \ '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', { call ale#linter#Define('rust', {
\ 'name': 'analyzer', \ 'name': 'analyzer',
\ 'aliases': ['rust_analyzer'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'initialization_options': {b -> ale#Var(b, 'rust_analyzer_config')}, \ 'initialization_options': {b -> ale#Var(b, 'rust_analyzer_config')},
\ 'executable': {b -> ale#Var(b, 'rust_analyzer_executable')}, \ 'executable': {b -> ale#Var(b, 'rust_analyzer_executable')},

View File

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

View File

@ -1,12 +1,83 @@
" Authors: Franco Victorio - https://github.com/fvictorio, Henrique Barcelos " Authors: Franco Victorio <@fvictorio>, Henrique Barcelos <@hbarcelos>
" https://github.com/hbarcelos
" Description: Report errors in Solidity code with solhint " 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', { call ale#linter#Define('solidity', {
\ 'name': 'solhint', \ 'name': 'solhint',
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'executable': function('ale#handlers#solhint#GetExecutable'), \ 'executable': function('ale_linters#solidity#solhint#GetExecutable'),
\ 'cwd': function('ale#handlers#solhint#GetCwd'), \ 'cwd': function('ale_linters#solidity#solhint#GetCwd'),
\ 'command': function('ale#handlers#solhint#GetCommand'), \ 'command': {b ->
\ 'callback': 'ale#handlers#solhint#Handle', \ 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', { call ale#linter#Define('swift', {
\ 'name': 'sourcekitlsp', \ 'name': 'sourcekitlsp',
\ 'aliases': ['sourcekit'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'sourcekit_lsp_executable')}, \ 'executable': {b -> ale#Var(b, 'sourcekit_lsp_executable')},
\ 'command': '%e', \ 'command': '%e',

View File

@ -30,6 +30,7 @@ endfunction
call ale#linter#Define('terraform', { call ale#linter#Define('terraform', {
\ 'name': 'terraform_ls', \ 'name': 'terraform_ls',
\ 'aliases': ['terraformls'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'terraform_ls_executable')}, \ 'executable': {b -> ale#Var(b, 'terraform_ls_executable')},
\ 'command': function('ale_linters#terraform#terraform_ls#GetCommand'), \ '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_executable', 'v')
call ale#Set('v_v_options', '') 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 function! ale_linters#v#v#Handler(buffer, lines) abort
let l:dir = expand('#' . a:buffer . ':p:h') let l:dir = expand('#' . a:buffer . ':p:h')
let l:output = [] let l:output = []
@ -73,9 +62,11 @@ endfunction
call ale#linter#Define('v', { call ale#linter#Define('v', {
\ 'name': 'v', \ 'name': 'v',
\ 'aliases': [],
\ 'executable': {b -> ale#Var(b, 'v_v_executable')}, \ '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', \ 'output_stream': 'stderr',
\ 'callback': 'ale_linters#v#v#Handler', \ 'callback': 'ale_linters#v#v#Handler',
\ 'lint_file': 1, \ 'lint_file': 1,

View File

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

View File

@ -3,50 +3,21 @@
" nvim-lspconfig and volar/packages/shared/src/types.ts " nvim-lspconfig and volar/packages/shared/src/types.ts
call ale#Set('vue_volar_executable', 'vue-language-server') 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', { call ale#Set('vue_volar_init_options', {
\ 'documentFeatures': { \ 'typescript': { 'tsdk': '' },
\ '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,
\ },
\}) \})
function! ale_linters#vue#volar#GetProjectRoot(buffer) abort 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 for l:project_root in l:project_roots
let l:nearest_filepath = ale#path#FindNearestFile(a:buffer, l:project_root) 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 endfunction
function! ale_linters#vue#volar#GetInitializationOptions(buffer) abort function! ale_linters#vue#volar#GetInitializationOptions(buffer) abort
let l:tsserver_path = ale#path#FindNearestExecutable(a:buffer, [ let l:tsserver_path = ale#path#FindNearestDirectory(a:buffer, 'node_modules/typescript/lib')
\ 'node_modules/typescript/lib/tsserverlibrary.js'
\ ]) 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 = 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 return l:init_options
endfunction 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_executable', 'actionlint')
call ale#Set('yaml_actionlint_options', '') 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', { call ale#linter#Define('yaml', {
\ 'name': 'actionlint', \ 'name': 'actionlint',
\ 'executable': {b -> ale#Var(b, 'yaml_actionlint_executable')}, \ 'executable': {b -> ale#Var(b, 'yaml_actionlint_executable')},
\ 'command': function('ale#handlers#actionlint#GetCommand'), \ 'command': function('ale_linters#yaml#actionlint#GetCommand'),
\ 'callback': 'ale#handlers#actionlint#Handle', \ 'callback': 'ale_linters#yaml#actionlint#Handle',
\}) \})

View File

@ -26,6 +26,7 @@ endfunction
call ale#linter#Define('yaml', { call ale#linter#Define('yaml', {
\ 'name': 'yaml-language-server', \ 'name': 'yaml-language-server',
\ 'aliases': ['yamlls'],
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': function('ale_linters#yaml#ls#GetExecutable'), \ 'executable': function('ale_linters#yaml#ls#GetExecutable'),
\ 'command': function('ale_linters#yaml#ls#GetCommand'), \ '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_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_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') 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 " LSP window/showMessage format
let g:ale_lsp_show_message_format = get(g:, 'ale_lsp_show_message_format', '%severity%:%linter%: %s') 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 " Use the filetype from the buffer
let l:filetype = getbufvar(a:buffer, '&filetype') let l:filetype = getbufvar(a:buffer, '&filetype')
let l:linters = ale#linter#Get(l: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. " Tell other sources that they can start checking the buffer now.
let g:ale_want_results_buffer = a:buffer let g:ale_want_results_buffer = a:buffer
@ -157,7 +171,7 @@ function! ale#Queue(delay, ...) abort
endif endif
endfunction 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. " A function used to check for ALE features in files outside of the project.
function! ale#Has(feature) abort function! ale#Has(feature) abort
@ -208,7 +222,7 @@ endfunction
" valid for cmd on Windows, or most shells on Unix. " valid for cmd on Windows, or most shells on Unix.
function! ale#Env(variable_name, value) abort function! ale#Env(variable_name, value) abort
if has('win32') if has('win32')
return 'set ' . a:variable_name . '=' . ale#Escape(a:value) . ' && ' return 'set ' . ale#Escape(a:variable_name . '=' . a:value) . ' && '
endif endif
return a:variable_name . '=' . ale#Escape(a:value) . ' ' 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. " \=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\%([^\%]*)code([^\%]*)\%', l:code_repl, 'g')
let l:msg = substitute(l:msg, '\V%severity%', '\=l:severity', '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') let l:msg = substitute(l:msg, '\V%linter%', '\=l:linter_name', 'g')
" Replace %s with the text. " Replace %s with the text.
let l:msg = substitute(l:msg, '\V%s', '\=a:item.text', 'g') 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\.\.\. silent! aunmenu PopUp.Refactor\.\.\.
" Only display the menu items if there's an LSP server. " Only display the menu items if there's an LSP server.
let l:has_lsp = 0 if len(ale#lsp_linter#GetEnabled(bufnr(''))) > 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 !empty(expand('<cword>')) if !empty(expand('<cword>'))
silent! anoremenu <silent> PopUp.Rename :ALERename<CR> silent! anoremenu <silent> PopUp.Rename :ALERename<CR>
endif endif

View File

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

View File

@ -824,6 +824,8 @@ endfunction
" the current buffer. 1 will be returned if there's a potential source of " 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. " completion data ALE can use, and 0 will be returned otherwise.
function! ale#completion#CanProvideCompletions() abort 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) for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp) if !empty(l:linter.lsp)
return 1 return 1
@ -890,11 +892,9 @@ function! ale#completion#GetCompletions(...) abort
let l:started = 0 let l:started = 0
for l:linter in ale#linter#Get(&filetype) for l:linter in ale#lsp_linter#GetEnabled(l:buffer)
if !empty(l:linter.lsp) if ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback)
if ale#lsp_linter#StartLSP(l:buffer, l:linter, l:Callback) let l:started = 1
let l:started = 1
endif
endif endif
endfor 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. " A wrapper for echon so we can test messages we echo in Vader tests.
function! ale#cursor#Echom(message) abort function! ale#cursor#Echom(message) abort
" no-custom-checks if mode() is# 'n'
exec "norm! :echom a:message\n" " no-custom-checks
exec "norm! :echom a:message\n"
endif
endfunction endfunction
function! ale#cursor#TruncatedEcho(original_message) abort function! ale#cursor#TruncatedEcho(original_message) abort

View File

@ -1,6 +1,8 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: This file implements debugging information for ALE " 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 = [ let s:global_variable_list = [
\ 'ale_cache_executable_check_failures', \ 'ale_cache_executable_check_failures',
\ 'ale_change_sign_column_color', \ 'ale_change_sign_column_color',
@ -18,6 +20,7 @@ let s:global_variable_list = [
\ 'ale_fix_on_save', \ 'ale_fix_on_save',
\ 'ale_fixers', \ 'ale_fixers',
\ 'ale_history_enabled', \ 'ale_history_enabled',
\ 'ale_info_default_mode',
\ 'ale_history_log_output', \ 'ale_history_log_output',
\ 'ale_keep_list_window_open', \ 'ale_keep_list_window_open',
\ 'ale_lint_delay', \ 'ale_lint_delay',
@ -53,8 +56,8 @@ let s:global_variable_list = [
\ 'ale_sign_style_warning', \ 'ale_sign_style_warning',
\ 'ale_sign_warning', \ 'ale_sign_warning',
\ 'ale_sign_highlight_linenrs', \ 'ale_sign_highlight_linenrs',
\ 'ale_statusline_format',
\ 'ale_type_map', \ 'ale_type_map',
\ 'ale_use_neovim_diagnostics_api',
\ 'ale_use_global_executables', \ 'ale_use_global_executables',
\ 'ale_virtualtext_cursor', \ 'ale_virtualtext_cursor',
\ 'ale_warn_about_trailing_blank_lines', \ 'ale_warn_about_trailing_blank_lines',
@ -198,11 +201,42 @@ function! s:EchoLSPErrorMessages(all_linter_names) abort
endfor endfor
endfunction 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:buffer = bufnr('')
let l:filetype = &filetype 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)) let l:enabled_linters = deepcopy(ale#linter#Get(l:filetype))
" But have to build the list of available linters ourselves. " 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 = uniq(sort(l:fixers[0] + l:fixers[1]))
let l:fixers_string = join(map(copy(l:fixers), '"\n " . v:val'), '') let l:fixers_string = join(map(copy(l:fixers), '"\n " . v:val'), '')
let l:non_ignored_names = map( " Get the names of ignored linters.
\ copy(ale#linter#RemoveIgnored(l:buffer, l:filetype, l:enabled_linters)), let l:ignored_names = map(
\ 'v:val[''name'']', \ s:GetIgnoredLinters(l:buffer, l:enabled_linters),
\) \ 'v:val.name'
let l:ignored_names = filter(
\ copy(l:enabled_names),
\ 'index(l:non_ignored_names, v:val) < 0'
\) \)
call s:Echo(' Current Filetype: ' . l:filetype) call s:Echo(' Current Filetype: ' . l:filetype)
@ -240,13 +271,31 @@ function! ale#debugging#Info() abort
call s:EchoLinterAliases(l:all_linters) call s:EchoLinterAliases(l:all_linters)
call s:Echo(' Enabled Linters: ' . string(l:enabled_names)) call s:Echo(' Enabled Linters: ' . string(l:enabled_names))
call s:Echo(' Ignored Linters: ' . string(l:ignored_names)) call s:Echo(' Ignored Linters: ' . string(l:ignored_names))
call s:Echo(' Suggested Fixers: ' . l:fixers_string) call s:Echo(' Suggested Fixers:' . l:fixers_string)
call s:Echo(' Linter Variables:') " We use this line with only a space to know where to end highlights.
call s:Echo('') call s:Echo(' ')
call s:EchoLinterVariables(l:variable_list)
" 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(' 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:EchoGlobalVariables()
call s:Echo(' ')
call s:EchoLSPErrorMessages(l:all_names) call s:EchoLSPErrorMessages(l:all_names)
call s:Echo(' Command History:') call s:Echo(' Command History:')
call s:Echo('') call s:Echo('')
@ -274,3 +323,41 @@ function! ale#debugging#InfoToFile(filename) abort
call writefile(split(l:output, "\n"), l:expanded_filename) call writefile(split(l:output, "\n"), l:expanded_filename)
call s:Echo('ALEInfo written to ' . l:expanded_filename) call s:Echo('ALEInfo written to ' . l:expanded_filename)
endfunction 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 endfunction
function! ale#definition#GoTo(options) abort function! ale#definition#GoTo(options) abort
for l:linter in ale#linter#Get(&filetype) for l:linter in ale#lsp_linter#GetEnabled(bufnr(''))
if !empty(l:linter.lsp) call s:GoToLSPDefinition(l:linter, a:options, 'definition')
call s:GoToLSPDefinition(l:linter, a:options, 'definition')
endif
endfor endfor
endfunction endfunction
function! ale#definition#GoToType(options) abort function! ale#definition#GoToType(options) abort
for l:linter in ale#linter#Get(&filetype) for l:linter in ale#lsp_linter#GetEnabled(bufnr(''))
if !empty(l:linter.lsp) call s:GoToLSPDefinition(l:linter, a:options, 'typeDefinition')
call s:GoToLSPDefinition(l:linter, a:options, 'typeDefinition')
endif
endfor endfor
endfunction endfunction
function! ale#definition#GoToImpl(options) abort function! ale#definition#GoToImpl(options) abort
for l:linter in ale#linter#Get(&filetype) for l:linter in ale#lsp_linter#GetEnabled(bufnr(''))
if !empty(l:linter.lsp) call s:GoToLSPDefinition(l:linter, a:options, 'implementation')
call s:GoToLSPDefinition(l:linter, a:options, 'implementation')
endif
endfor endfor
endfunction endfunction

View File

@ -184,9 +184,13 @@ endfunction
function! ale#engine#SetResults(buffer, loclist) abort function! ale#engine#SetResults(buffer, loclist) abort
let l:linting_is_done = !ale#engine#IsCheckingBuffer(a:buffer) 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. " Set signs first. This could potentially fix some line numbers.
" The List could be sorted again here by SetSigns. " 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) call ale#sign#SetSigns(a:buffer, a:loclist)
endif endif
@ -199,11 +203,12 @@ function! ale#engine#SetResults(buffer, loclist) abort
call ale#statusline#Update(a:buffer, a:loclist) call ale#statusline#Update(a:buffer, a:loclist)
endif 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) call ale#highlight#SetHighlights(a:buffer, a:loclist)
endif 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) call ale#virtualtext#SetTexts(a:buffer, a:loclist)
endif endif
@ -214,7 +219,8 @@ function! ale#engine#SetResults(buffer, loclist) abort
call ale#cursor#EchoCursorWarning() call ale#cursor#EchoCursorWarning()
endif 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. " Try and show the warning now.
" This will only do something meaningful if we're in normal mode. " This will only do something meaningful if we're in normal mode.
call ale#virtualtext#ShowCursorWarning() call ale#virtualtext#ShowCursorWarning()
@ -238,6 +244,19 @@ function! ale#engine#SetResults(buffer, loclist) abort
endif endif
endfunction 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 function! s:RemapItemTypes(type_map, loclist) abort
for l:item in a:loclist for l:item in a:loclist
let l:key = l:item.type let l:key = l:item.type

View File

@ -1,6 +1,26 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: Code for ignoring linters. Only loaded and if configured. " 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 " Given a filetype and a configuration for ignoring linters, return a List of
" Strings for linter names to ignore. " Strings for linter names to ignore.
function! ale#engine#ignore#GetList(filetype, config) abort function! ale#engine#ignore#GetList(filetype, config) abort
@ -21,24 +41,51 @@ function! ale#engine#ignore#GetList(filetype, config) abort
return [] return []
endfunction 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. " Given a List of linter descriptions, exclude the linters to be ignored.
function! ale#engine#ignore#Exclude(filetype, all_linters, config, disable_lsp) abort 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) 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 = [] let l:filtered_linters = []
for l:linter in a:all_linters for l:linter in a:all_linters
let l:name_list = [l:linter.name] + l:linter.aliases let l:should_include = index(l:names_to_remove, l:linter.name) == -1
let l:should_include = 1 let l:i = 0
for l:name in l:name_list while l:should_include && l:i < len(l:linter.aliases)
if index(l:names_to_remove, l:name) >= 0 let l:name = l:linter.aliases[l:i]
let l:should_include = 0 let l:should_include = index(l:names_to_remove, l:name) == -1
break let l:i += 1
endif endwhile
endfor
if a:disable_lsp && has_key(l:linter, 'lsp') && l:linter.lsp isnot# '' if l:should_include && l:ignore_all_lsps
let l:should_include = 0 let l:should_include = empty(get(l:linter, 'lsp'))
endif endif
if l:should_include if l:should_include

View File

@ -92,6 +92,62 @@ function! ale#events#FileChangedEvent(buffer) abort
endif endif
endfunction 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 function! ale#events#Init() abort
" This value used to be a Boolean as a Number, and is now a String. " 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 let l:text_changed = '' . g:ale_lint_on_text_changed
@ -127,33 +183,40 @@ function! ale#events#Init() abort
\) \)
endif endif
if g:ale_lint_on_insert_leave " Add an InsertEnter event if we need to close the preview window
autocmd InsertLeave * if ale#Var(str2nr(expand('<abuf>')), 'lint_on_insert_leave') | call ale#Queue(0) | endif " 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 endif
let l:add_insert_leave_event = g:ale_lint_on_insert_leave
if g:ale_echo_cursor || g:ale_cursor_detail 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 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 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 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. endif
" The script's position variable used when moving the cursor will
" not be changed here. if l:add_insert_leave_event
autocmd InsertLeave * if exists('*ale#engine#Cleanup') | call ale#virtualtext#ShowCursorWarning() | endif autocmd InsertLeave * call ale#events#InsertLeaveEvent(str2nr(expand('<abuf>')))
endif endif
if g:ale_hover_cursor if g:ale_hover_cursor
autocmd CursorHold * if exists('*ale#lsp#Send') | call ale#hover#ShowTruncatedMessageAtCursor() | endif autocmd CursorHold * if exists('*ale#lsp#Send') | call ale#hover#ShowTruncatedMessageAtCursor() | endif
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 endif
augroup END augroup END

View File

@ -94,9 +94,10 @@ function! s:ExecuteFileRename(linter, options) abort
endfunction endfunction
function! ale#filerename#Execute() abort function! ale#filerename#Execute() abort
let l:buffer = bufnr('')
let l:lsp_linters = [] 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' if l:linter.lsp is# 'tsserver'
call add(l:lsp_linters, l:linter) call add(l:lsp_linters, l:linter)
endif endif
@ -108,7 +109,6 @@ function! ale#filerename#Execute() abort
return return
endif endif
let l:buffer = bufnr('')
let l:old_name = expand('#' . l:buffer . ':p') let l:old_name = expand('#' . l:buffer . ':p')
let l:new_name = ale#util#Input('New file name: ', l:old_name, 'file') 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 endif
endif endif
catch /E21/ catch /E21\|E5555/
" If we cannot modify the buffer now, try again later. " If we cannot modify the buffer now, try again later.
let g:ale_fix_buffer_data[a:buffer] = l:data let g:ale_fix_buffer_data[a:buffer] = l:data

View File

@ -7,6 +7,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['python'], \ 'suggested_filetypes': ['python'],
\ 'description': 'Add blank lines before control statements.', \ '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': { \ 'align_help_tags': {
\ 'function': 'ale#fixers#help#AlignTags', \ 'function': 'ale#fixers#help#AlignTags',
\ 'suggested_filetypes': ['help'], \ 'suggested_filetypes': ['help'],
@ -174,7 +179,12 @@ let s:default_registry = {
\ 'yamlfix': { \ 'yamlfix': {
\ 'function': 'ale#fixers#yamlfix#Fix', \ 'function': 'ale#fixers#yamlfix#Fix',
\ 'suggested_filetypes': ['yaml'], \ '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': { \ 'yapf': {
\ 'function': 'ale#fixers#yapf#Fix', \ 'function': 'ale#fixers#yapf#Fix',
@ -263,8 +273,8 @@ let s:default_registry = {
\ }, \ },
\ 'clang-format': { \ 'clang-format': {
\ 'function': 'ale#fixers#clangformat#Fix', \ 'function': 'ale#fixers#clangformat#Fix',
\ 'suggested_filetypes': ['c', 'cpp', 'cuda'], \ 'suggested_filetypes': ['c', 'cpp', 'cs', 'cuda', 'java', 'javascript', 'json', 'objc', 'proto'],
\ 'description': 'Fix C/C++ and cuda files with clang-format.', \ 'description': 'Fix C, C++, C#, CUDA, Java, JavaScript, JSON, ObjectiveC and Protobuf files with clang-format.',
\ }, \ },
\ 'cmakeformat': { \ 'cmakeformat': {
\ 'function': 'ale#fixers#cmakeformat#Fix', \ 'function': 'ale#fixers#cmakeformat#Fix',
@ -276,6 +286,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['fish'], \ 'suggested_filetypes': ['fish'],
\ 'description': 'Format fish scripts using fish_indent.', \ 'description': 'Format fish scripts using fish_indent.',
\ }, \ },
\ 'forge': {
\ 'function': 'ale#fixers#forge#Fix',
\ 'suggested_filetypes': ['solidity'],
\ 'description': 'Fix Solidity files with forge fmt.',
\ },
\ 'gofmt': { \ 'gofmt': {
\ 'function': 'ale#fixers#gofmt#Fix', \ 'function': 'ale#fixers#gofmt#Fix',
\ 'suggested_filetypes': ['go'], \ 'suggested_filetypes': ['go'],
@ -301,6 +316,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['gomod'], \ 'suggested_filetypes': ['gomod'],
\ 'description': 'Fix Go module files with go mod edit -fmt.', \ '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': { \ 'tslint': {
\ 'function': 'ale#fixers#tslint#Fix', \ 'function': 'ale#fixers#tslint#Fix',
\ 'suggested_filetypes': ['typescript'], \ 'suggested_filetypes': ['typescript'],
@ -386,6 +406,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['sh'], \ 'suggested_filetypes': ['sh'],
\ 'description': 'Fix sh files with shfmt.', \ 'description': 'Fix sh files with shfmt.',
\ }, \ },
\ 'sqlfluff': {
\ 'function': 'ale#fixers#sqlfluff#Fix',
\ 'suggested_filetypes': ['sql'],
\ 'description': 'Fix SQL files with sqlfluff.',
\ },
\ 'sqlfmt': { \ 'sqlfmt': {
\ 'function': 'ale#fixers#sqlfmt#Fix', \ 'function': 'ale#fixers#sqlfmt#Fix',
\ 'suggested_filetypes': ['sql'], \ 'suggested_filetypes': ['sql'],
@ -546,6 +571,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['haskell'], \ 'suggested_filetypes': ['haskell'],
\ 'description': 'A formatter for Haskell source code.', \ 'description': 'A formatter for Haskell source code.',
\ }, \ },
\ 'fourmolu': {
\ 'function': 'ale#fixers#fourmolu#Fix',
\ 'suggested_filetypes': ['haskell'],
\ 'description': 'A formatter for Haskell source code.',
\ },
\ 'jsonnetfmt': { \ 'jsonnetfmt': {
\ 'function': 'ale#fixers#jsonnetfmt#Fix', \ 'function': 'ale#fixers#jsonnetfmt#Fix',
\ 'suggested_filetypes': ['jsonnet'], \ 'suggested_filetypes': ['jsonnet'],
@ -575,7 +605,42 @@ let s:default_registry = {
\ 'function': 'ale#fixers#raco_fmt#Fix', \ 'function': 'ale#fixers#raco_fmt#Fix',
\ 'suggested_filetypes': ['racket'], \ 'suggested_filetypes': ['racket'],
\ 'description': 'Fix Racket files with raco fmt.', \ '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. " 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> " Author: Yining <zhang.yining@gmail.com>
" Description: ruff as ALE fixer for python files " 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 function! ale#fixers#ruff#GetCwd(buffer) abort
if ale#Var(a:buffer, 'python_ruff_change_directory') if ale#Var(a:buffer, 'python_ruff_change_directory')
" Run from project root if found, else from buffer dir. " 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' return !empty(l:project_root) ? l:project_root : '%s:h'
endif endif
return '' return '%s:h'
endfunction endfunction
function! ale#fixers#ruff#GetExecutable(buffer) abort 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']) return ale#python#FindExecutable(a:buffer, 'python_ruff', ['ruff'])
endfunction endfunction
function! ale#fixers#ruff#GetCommand(buffer, version) abort function! ale#fixers#ruff#GetCommand(buffer) abort
let l:executable = ale_linters#python#ruff#GetExecutable(a:buffer) let l:executable = ale#fixers#ruff#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv\|poetry$' let l:exec_args = l:executable =~? 'pipenv\|poetry$'
\ ? ' run ruff' \ ? ' run ruff'
\ : '' \ : ''
" NOTE: ruff version `0.0.72` implement `--fix` with stdin
return ale#Escape(l:executable) . l:exec_args return ale#Escape(l:executable) . l:exec_args
\ . ale#Pad(ale#Var(a:buffer, 'python_ruff_options')) endfunction
\ . ' --fix'
\ . (ale#semver#GTE(a:version, [0, 0, 72]) ? ' -' : ' %s') 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 endfunction
function! ale#fixers#ruff#Fix(buffer) abort function! ale#fixers#ruff#Fix(buffer) abort
let l:fix_cmd = {buffer -> ale#semver#RunWithVersionCheck( let l:executable = ale#fixers#ruff#GetExecutable(a:buffer)
\ buffer, let l:command = ale#fixers#ruff#GetCommand(a:buffer) . ale#Pad('--version')
\ ale#fixers#ruff#GetExecutable(buffer),
\ '%e --version',
\ function('ale#fixers#ruff#GetCommand'),
\ )}(a:buffer)
return { return ale#semver#RunWithVersionCheck(
\ 'cwd': ale#fixers#ruff#GetCwd(a:buffer), \ a:buffer,
\ 'command': l:fix_cmd, \ l:executable,
\} \ l:command,
\ function('ale#fixers#ruff#FixForVersion'),
\)
endfunction 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. " Description: Integration of xmllint with ALE.
call ale#Set('xml_xmllint_executable', 'xmllint') 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 function! ale#fixers#xmllint#Fix(buffer) abort
let l:executable = ale#Escape(ale#Var(a:buffer, 'xml_xmllint_executable')) 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:command = l:executable . ' --format ' . l:filename
let l:indent = ale#Var(a:buffer, 'xml_xmllint_indentsize') 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 endif
" Execute commands in window context " 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', []) for l:command in get(a:options, 'commands', [])
call execute(l:command) call execute(l:command)
endfor endfor
call nvim_set_current_win(l:parent_window) call nvim_set_current_win(l:parent_window)
endif
" Return to parent context on move " Return to parent context on move
augroup ale_floating_preview_window augroup ale_floating_preview_window
autocmd! autocmd!
if g:ale_close_preview_on_insert 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 else
autocmd CursorMoved,TabLeave,WinLeave <buffer> ++once call s:NvimClose() autocmd CursorMoved,TabLeave,WinLeave,BufWinLeave,WinScrolled <buffer> ++once call s:NvimClose()
endif endif
augroup END augroup END
@ -99,48 +105,30 @@ function! s:NvimPrepareWindowContent(lines) abort
let l:width = max(map(copy(a:lines), 'strdisplaywidth(v:val)')) let l:width = max(map(copy(a:lines), 'strdisplaywidth(v:val)'))
let l:height = min([len(a:lines), l:max_height]) let l:height = min([len(a:lines), l:max_height])
if empty(g:ale_floating_window_border) return [a:lines[0:l:height-1], l:width, l:height]
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]
endfunction endfunction
function! s:NvimCreate(options) abort 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({ let l:popup_opts = extend({
\ 'relative': 'cursor', \ 'relative': 'cursor',
\ 'row': 1, \ 'row': 1,
\ 'col': 0, \ 'col': 0,
\ 'width': 42, \ 'width': 42,
\ 'height': 4, \ '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()) \ }, s:GetPopupOpts())
let l:buffer = nvim_create_buf(v:false, v:false) 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 function! ale#handlers#cspell#Handle(buffer, lines) abort
" Look for lines like the following: " Look for lines like the following:
" "
" /home/user/repos/ale/README.md:723:48 - Unknown word (stylelint) " /home/user/repos/ale/README.md:3:128 - Unknown word (Neovim)
let l:pattern = '\v^.*:(\d+):(\d+) - (.*)$' " match1: 3
" match2: 128
" match3: Unknown word (Neovim)
" match4: Neovim
let l:pattern = '\v^.*:(\d+):(\d+) - ([^\(]+\(([^\)]+)\).*)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0, \ 'col': l:match[2] + 0,
\ 'end_col': l:match[2] + len(l:match[4]) - 1,
\ 'text': l:match[3], \ 'text': l:match[3],
\ 'type': 'W', \ '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