Add settings for the Alex linter

The executable for the Alex linter is currently hard-coded as 'alex',
which is an issue given the fact that it conflicts with the Haskell
lexer generator, whose executable is also called 'alex', has been around
a dozen years before the linter, and is packaged in the official
repositories of the major Linux distributions.

This commit adds options to use a local executable for the alex linter
(which is a node package), and an option to set a custom executable.

As side changes:
* The pattern in the alex handler is made more readable by turnig it
  into a very-magic regex.
* Alex handles plain text, markdown, and HTML. Specific flags for HTML
  and markdown are provided when instantiating the linters for the
  respective filetypes, while before those formats were treated as plain
  text.
This commit is contained in:
Martino Pilia 2019-02-02 15:45:32 +01:00
parent 4d426bf287
commit 771581a945
No known key found for this signature in database
GPG Key ID: CDEE463095565E17
18 changed files with 105 additions and 108 deletions

View File

@ -1,11 +1,4 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: alex for asciidoc files
call ale#linter#Define('help', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
call ale#handlers#alex#DefineLinter('asciidoc', '--text')

View File

@ -1,11 +1,4 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: alex for help files
call ale#linter#Define('help', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
call ale#handlers#alex#DefineLinter('help', '--text')

View File

@ -1,11 +1,4 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: alex for HTML files
call ale#linter#Define('html', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
call ale#handlers#alex#DefineLinter('html', '--html')

View File

@ -1,11 +1,4 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: alex for HTML files
" Description: alex for mail files
call ale#linter#Define('mail', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
call ale#handlers#alex#DefineLinter('mail', '--text')

View File

@ -1,11 +1,4 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: alex for markdown files
call ale#linter#Define('markdown', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
call ale#handlers#alex#DefineLinter('markdown', '')

View File

@ -1,11 +1,4 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: alex for nroff files
call ale#linter#Define('nroff', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
call ale#handlers#alex#DefineLinter('nroff', '--text')

View File

@ -1,11 +1,4 @@
" Author: Cian Butler https://github.com/butlerx
" Description: alex for PO files
call ale#linter#Define('po', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
call ale#handlers#alex#DefineLinter('po', '--text')

View File

@ -1,11 +1,4 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: alex for pod files
call ale#linter#Define('pod', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
call ale#handlers#alex#DefineLinter('pod', '--text')

View File

@ -1,11 +1,4 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: alex for rst files
call ale#linter#Define('rst', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
call ale#handlers#alex#DefineLinter('rst', '--text')

View File

@ -1,11 +1,4 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: alex for TeX files
call ale#linter#Define('tex', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
call ale#handlers#alex#DefineLinter('tex', '--text')

View File

@ -1,11 +1,4 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: alex for texinfo files
call ale#linter#Define('texinfo', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
call ale#handlers#alex#DefineLinter('texinfo', '--text')

View File

@ -1,11 +1,4 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: alex for text files
call ale#linter#Define('text', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
call ale#handlers#alex#DefineLinter('text', '--text')

View File

@ -1,11 +1,4 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: alex for XHTML files
call ale#linter#Define('xhtml', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
call ale#handlers#alex#DefineLinter('xhtml', '--text')

View File

@ -1,10 +1,23 @@
" Author: Johannes Wienke <languitar@semipol.de>
" Description: Error handling for errors in alex output format
function! ale#handlers#alex#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'alex', [
\ 'node_modules/.bin/alex',
\ 'node_modules/alex/cli.js',
\])
endfunction
function! ale#handlers#alex#CreateCommandCallback(flags) abort
return {b -> ale#node#Executable(b, ale#handlers#alex#GetExecutable(b))
\ . ' %s '
\ . a:flags}
endfunction
function! ale#handlers#alex#Handle(buffer, lines) abort
" Example output:
" 6:256-6:262 warning Be careful with “killed”, its profane in some cases killed retext-profanities
let l:pattern = '^ *\(\d\+\):\(\d\+\)-\(\d\+\):\(\d\+\) \+warning \+\(.\{-\}\) \+\(.\{-\}\) \+\(.\{-\}\)$'
let l:pattern = '\v^ *(\d+):(\d+)-(\d+):(\d+) +warning +(.{-}) +(.{-}) +(.{-})$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
@ -20,3 +33,21 @@ function! ale#handlers#alex#Handle(buffer, lines) abort
return l:output
endfunction
" Define a linter for a specific filetype. Accept flags to adapt to the filetype.
" no flags treat input as markdown
" --html treat input as HTML
" --text treat input as plaintext
function! ale#handlers#alex#DefineLinter(filetype, flags) abort
call ale#Set('alex_executable', 'alex')
call ale#Set('alex_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#linter#Define(a:filetype, {
\ 'name': 'alex',
\ 'executable_callback': 'ale#handlers#alex#GetExecutable',
\ 'command_callback': ale#handlers#alex#CreateCommandCallback(a:flags),
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})
endfunction

View File

@ -20,7 +20,8 @@ CONTENTS *ale-contents*
5.6 Symbol Search.....................|ale-symbol-search|
6. Global Options.......................|ale-options|
6.1 Highlights........................|ale-highlights|
6.2 Options for write-good Linter.....|ale-write-good-options|
6.2 Options for alex Linter...........|ale-alex-options|
6.3 Options for write-good Linter.....|ale-write-good-options|
7. Integration Documentation............|ale-integrations|
ada...................................|ale-ada-options|
gcc.................................|ale-ada-gcc|
@ -2219,7 +2220,29 @@ ALEWarningSign *ALEWarningSign*
-------------------------------------------------------------------------------
6.2. Options for write-good *ale-write-good-options*
6.2. Options for alex *ale-alex-options*
The options for the alex linter are global because it does not make sense to
have them specified on a per-language basis.
g:ale_alex_executable *g:ale_alex_executable*
*b:ale_alex_executable*
Type: |String|
Default: `'alex'`
See |ale-integrations-local-executables|
g:ale_alex_use_global *g:ale_alex_use_global*
*b:ale_alex_use_global*
Type: |Number|
Default: `get(g:, 'ale_use_global_executables', 0)`
See |ale-integrations-local-executables|
-------------------------------------------------------------------------------
6.3. Options for write-good *ale-write-good-options*
The options for the write-good linter are global because it does not make
sense to have them specified on a per-language basis.

View File

View File

View File

@ -0,0 +1,34 @@
Before:
call ale#assert#SetUpLinterTest('tex', 'alex')
call ale#test#SetFilename('test_file.tex')
After:
call ale#assert#TearDownLinterTest()
Execute(The global executable should be used when the local one cannot be found):
AssertLinter 'alex',
\ ale#Escape('alex') . ' %s --text',
Execute(Should use the node_modules/.bin executable, if available):
call ale#test#SetFilename('alex-node-modules/test_file.tex')
AssertLinter ale#path#Simplify(g:dir . '/alex-node-modules/node_modules/.bin/alex'),
\ ale#Escape(ale#path#Simplify(g:dir . '/alex-node-modules/node_modules/.bin/alex'))
\ . ' %s --text',
Execute(Should use the node_modules/alex executable, if available):
call ale#test#SetFilename('alex-node-modules-2/test_file.tex')
AssertLinter ale#path#Simplify(g:dir . '/alex-node-modules-2/node_modules/alex/cli.js'),
\ (has('win32') ? 'node.exe ' : '')
\ . ale#Escape(ale#path#Simplify(g:dir . '/alex-node-modules-2/node_modules/alex/cli.js'))
\ . ' %s --text',
Execute(Should let users configure a global executable and override local paths):
call ale#test#SetFilename('write-good-node-modules-2/test_file.tex')
let g:ale_alex_executable = '/path/to/custom/alex'
let g:ale_alex_use_global = 1
AssertLinter '/path/to/custom/alex',
\ ale#Escape('/path/to/custom/alex') . ' %s --text'