linter/markdown: adds support for languatool (#2155)

This commit is contained in:
Vincent Dahmen 2019-03-09 14:55:54 +01:00 committed by w0rp
parent fd31987f23
commit 7eae06d3f3
6 changed files with 165 additions and 0 deletions

View File

@ -0,0 +1,5 @@
" Author: Vincent (wahrwolf [ät] wolfpit.net)
" Description: languagetool for mails
call ale#handlers#languagetool#DefineLinter('mail')

View File

@ -0,0 +1,5 @@
" Author: Vincent (wahrwolf [ät] wolfpit.net)
" Description: languagetool for markdown files
call ale#handlers#languagetool#DefineLinter('markdown')

View File

@ -0,0 +1,4 @@
" Author: Vincent (wahrwolf [ät] wolfpit.net)
" Description: languagetool for text files
call ale#handlers#languagetool#DefineLinter('text')

View File

@ -0,0 +1,74 @@
" Author: Vincent (wahrwolf [ät] wolfpit.net)
" Description: languagetool for markdown files
"
call ale#Set('languagetool_executable', 'languagetool')
function! ale#handlers#languagetool#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'languagetool_executable')
endfunction
function! ale#handlers#languagetool#GetCommand(buffer) abort
let l:executable = ale#handlers#languagetool#GetExecutable(a:buffer)
return ale#Escape(l:executable) . ' --autoDetect '
endfunction
function! ale#handlers#languagetool#HandleOutput(buffer, lines) abort
" Match lines like:
" 1.) Line 5, column 1, Rule ID:
let l:head_pattern = '^\v.+.\) Line (\d+), column (\d+), Rule ID. (.+)$'
let l:head_matches = ale#util#GetMatches(a:lines, l:head_pattern)
" Match lines like:
" Message: Did you forget a comma after a conjunctive/linking adverb?
let l:message_pattern = '^\vMessage. (.+)$'
let l:message_matches = ale#util#GetMatches(a:lines, l:message_pattern)
" Match lines like:
" ^^^^^ "
let l:markers_pattern = '^\v *(\^+) *$'
let l:markers_matches = ale#util#GetMatches(a:lines, l:markers_pattern)
let l:output = []
" Okay tbh I was to lazy to figure out a smarter solution here
" We just check that the arrays are same sized and merge everything
" together
let l:i = 0
while l:i < len(l:head_matches)
\ && (
\ (len(l:head_matches) == len(l:markers_matches))
\ && (len(l:head_matches) == len(l:message_matches))
\ )
let l:item = {
\ 'lnum' : str2nr(l:head_matches[l:i][1]),
\ 'col' : str2nr(l:head_matches[l:i][2]),
\ 'end_col' : str2nr(l:head_matches[l:i][2]) + len(l:markers_matches[l:i][1])-1,
\ 'type' : 'W',
\ 'code' : l:head_matches[l:i][3],
\ 'text' : l:message_matches[l:i][1]
\}
call add(l:output, l:item)
let l:i+=1
endwhile
return l:output
endfunction
" Define the languagetool linter for a given filetype.
" TODO:
" - Add language detection settings based on user env (for mothertongue)
" - Add fixer
" - Add config options for rules
function! ale#handlers#languagetool#DefineLinter(filetype) abort
call ale#linter#Define(a:filetype, {
\ 'name': 'languagetool',
\ 'executable_callback': 'ale#handlers#languagetool#GetExecutable',
\ 'command_callback': 'ale#handlers#languagetool#GetCommand',
\ 'output_stream': 'stdout',
\ 'callback': 'ale#handlers#languagetool#HandleOutput',
\ 'lint_file': 1,
\})
endfunction

View File

@ -0,0 +1,15 @@
Before:
call ale#assert#SetUpLinterTest('text', 'languagetool')
After:
call ale#assert#TearDownLinterTest()
Execute(The default command should be correct):
AssertLinter 'languagetool', ale#Escape('languagetool')
\ . ' --autoDetect '
Execute(Should be able to set a custom executable):
let g:ale_languagetool_executable = 'foobar'
AssertLinter 'foobar' , ale#Escape('foobar')
\ . ' --autoDetect '

View File

@ -0,0 +1,62 @@
Before:
runtime! ale_linters/text/languagetool.vim
After:
call ale#linter#Reset()
Execute(languagetool handler should report 3 errors):
AssertEqual
\ [
\ {
\ 'lnum': 3,
\ 'col': 19,
\ 'end_col': 20,
\ 'text': 'This sentence does not start with an uppercase letter',
\ 'type': 'W',
\ 'code': 'UPPERCASE_SENTENCE_START',
\ },
\ {
\ 'lnum': 3,
\ 'col': 36,
\ 'end_col': 42,
\ 'text': "Did you mean 'to see'?",
\ 'type': 'W',
\ 'code': 'TOO_TO[1]',
\ },
\ {
\ 'lnum': 3,
\ 'col': 44,
\ 'end_col': 45,
\ 'text': "Use 'a' instead of 'an' if the following word doesn't start with a vowel sound, e.g. 'a sentence', 'a university'",
\ 'type': 'W',
\ 'code': 'EN_A_VS_AN',
\ }
\ ],
\ ale#handlers#languagetool#HandleOutput(bufnr(''), [
\ '1.) Line 3, column 19, Rule ID: UPPERCASE_SENTENCE_START',
\ 'Message: This sentence does not start with an uppercase letter',
\ 'Suggestion: Or',
\ '...red phrases for details on potential errors. or use this text too see an few of of the probl...',
\ ' ^^ ',
\ '',
\ '2.) Line 3, column 36, Rule ID: TOO_TO[1]',
\ "Message: Did you mean 'to see'?",
\ 'Suggestion: to see',
\ '...etails on potential errors. or use this text too see an few of of the problems that LanguageTool ...',
\ ' ^^^^^^^ ',
\ '',
\ '3.) Line 3, column 44, Rule ID: EN_A_VS_AN',
\ "Message: Use 'a' instead of 'an' if the following word doesn't start with a vowel sound, e.g. 'a sentence', 'a university'",
\ 'Suggestion: a',
\ '...n potential errors. or use this text too see an few of of the problems that LanguageTool can...',
\ ' ^^ ',
\ 'Time: 2629ms for 8 sentences (3.0 sentences/sec)'
\ ])
Execute(languagetool handler should report no errors on empty input):
AssertEqual
\ [],
\ ale#handlers#languagetool#HandleOutput(bufnr(''), [
\ '',
\ 'Time: 2629ms for 8 sentences (3.0 sentences/sec)'
\ ])