Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

linter/markdown: adds support for languatool #2155

Merged
merged 14 commits into from
Mar 9, 2019
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ale_linters/mail/languagetool.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
" Author: Vincent (wahrwolf [ät] wolfpit.net)
" Description: languagetool for mails


call ale#handlers#languagetool#DefineLinter('mail')
5 changes: 5 additions & 0 deletions ale_linters/markdown/languagetool.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
" Author: Vincent (wahrwolf [ät] wolfpit.net)
" Description: languagetool for markdown files


call ale#handlers#languagetool#DefineLinter('markdown')
4 changes: 4 additions & 0 deletions ale_linters/text/languagetool.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
" Author: Vincent (wahrwolf [ät] wolfpit.net)
" Description: languagetool for text files

call ale#handlers#languagetool#DefineLinter('text')
62 changes: 62 additions & 0 deletions autoload/ale/handlers/languagetool.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
" Author: Vincent (wahrwolf [ät] wolfpit.net)
" Description: languagetool for markdown files

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)) &&
wahrwolf marked this conversation as resolved.
Show resolved Hide resolved
\ (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': 'languagetool',
\ 'command': 'languagetool --autoDetect %s ',
\ 'output_stream': 'stdout',
\ 'callback': 'ale#handlers#languagetool#HandleOutput',
\ 'lint_file': 1,
\})
endfunction
62 changes: 62 additions & 0 deletions test/handler/test_languagetool_handler.vader
Original file line number Diff line number Diff line change
@@ -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)'
\ ])