dense-analysis / ale

Check syntax in Vim/Neovim asynchronously and fix files, with Language Server Protocol (LSP) support
BSD 2-Clause "Simplified" License
13.38k stars 1.42k forks source link

Unable to have Ale works w/ Vale to lint markdown files in VIM #3363

Closed yohannes closed 2 years ago

yohannes commented 3 years ago

Hi all,

I am not sure what I did wrong in my settings. But I can't have ale display any linting error when processing markdown file via vale in VIM. Here's outputs of some of the files.

ALEInfo (run against a README.md file that has various typos):

Current Filetype: markdown
Available Linters: ['alex', 'languagetool', 'markdownlint', 'mdl', 'proselint', 'redpen', 'remark_lint', 'textlint', 'vale', 'writegood']
   Linter Aliases:
'remark_lint' -> ['remark-lint']
'writegood' -> ['write-good']
  Enabled Linters: ['vale']
 Suggested Fixers:
  'prettier' - Apply prettier to a file.
  'remark-lint' - Fix markdown files with remark-lint
  'remove_trailing_lines' - Remove all blank lines at the end of a file.
  'textlint' - Fix text files with textlint --fix
  'trim_whitespace' - Remove all trailing whitespace characters at the end of every line.
 Linter Variables:
let g:ale_markdown_remark_lint_executable = 'remark'
let g:ale_markdown_remark_lint_options = ''
let g:ale_markdown_remark_lint_use_global = 0
 Global Variables:
let g:ale_cache_executable_check_failures = v:null
let g:ale_change_sign_column_color = 0
let g:ale_command_wrapper = ''
let g:ale_completion_delay = v:null
let g:ale_completion_enabled = 0
let g:ale_completion_max_suggestions = v:null
let g:ale_echo_cursor = 1
let g:ale_echo_msg_error_str = 'E'
let g:ale_echo_msg_format = '[%linter%] %s [%severity%]'
let g:ale_echo_msg_info_str = 'Info'
let g:ale_echo_msg_warning_str = 'W'
let g:ale_enabled = 1
let g:ale_fix_on_save = 1
let g:ale_fixers = {}
let g:ale_history_enabled = 1
let g:ale_history_log_output = 1
let g:ale_keep_list_window_open = 0
let g:ale_lint_delay = 200
let g:ale_lint_on_enter = 1
let g:ale_lint_on_filetype_changed = 1
let g:ale_lint_on_insert_leave = 1
let g:ale_lint_on_save = 1
let g:ale_lint_on_text_changed = 'normal'
let g:ale_linter_aliases = {}
let g:ale_linters = {'markdown': ['vale'], 'text': ['vale']}
let g:ale_linters_explicit = 0
let g:ale_list_vertical = 0
let g:ale_list_window_size = 10
let g:ale_loclist_msg_format = '[%linter%] %s [%severity%]'
let g:ale_lsp_root = {}
let g:ale_max_buffer_history_size = 20
let g:ale_max_signs = -1
let g:ale_maximum_file_size = v:null
let g:ale_open_list = 0
let g:ale_pattern_options = v:null
let g:ale_pattern_options_enabled = v:null
let g:ale_set_balloons = 0
let g:ale_set_highlights = 1
let g:ale_set_loclist = 1
let g:ale_set_quickfix = 0
let g:ale_set_signs = 1
let g:ale_sign_column_always = 0
let g:ale_sign_error = '>>'
let g:ale_sign_info = '--'
let g:ale_sign_offset = 1000000
let g:ale_sign_style_error = '>>'
let g:ale_sign_style_warning = '--'
let g:ale_sign_warning = '--'
let g:ale_sign_highlight_linenrs = 0
let g:ale_statusline_format = v:null
let g:ale_type_map = {}
let g:ale_use_global_executables = v:null
let g:ale_virtualtext_cursor = 0
let g:ale_warn_about_trailing_blank_lines = 1
let g:ale_warn_about_trailing_whitespace = 1
  Command History:
(executable check - success) vale
(finished - exit code 0) ['/bin/zsh', '-c', 'vale --output=JSON ''/var/folders/kx/3dgbmvjx14n9nk7f6w0px7l80000gn/T/v8nPkws/2/README.md''']
<<<OUTPUT STARTS>>>
{}
<<<OUTPUT ENDS>>>

A subset of my .vimrc:

let g:ale_linters = {'markdown': ['vale'], 'text': ['vale']}
 let g:airline#extensions#ale#enabled = 1
 let g:ale_fix_on_save = 1
 let g:ale_lint_on_enter = 1

Passing the same README.md file above to Vale directly produces the right outcome. So my Vale environment has been set up correctly:

README.md
 1:3     suggestion  'vale-boilerplate' should use   Microsoft.Headings     
                     sentence-style capitalization.                         
 1:3     warning     'vale-boilerplate' should use   Google.Headings        
                     sentence-style capitalization.                         
 3:6     suggestion  Try to avoid using 'is'.        write-good.E-Prime     
 7:11    suggestion  'is optimised' looks like       Microsoft.Passive      
                     passive voice.                                         
 7:11    warning     'is optimised' may be passive   write-good.Passive     
                     voice. Use active voice if you                         
                     can.                                                   
 7:11    suggestion  In general, use active voice    Google.Passive         
                     instead of passive voice ('is                          
                     optimised').                                           
 7:11    suggestion  Try to avoid using 'is'.        write-good.E-Prime     
 7:38    warning     'however' is too wordy.         write-good.TooWordy    
 7:47    warning     Try to avoid using              Google.We              
                     first-person plural like 'we'.                         
 7:47    warning     Try to avoid using              Microsoft.We           
                     first-person plural like 'we'.                         
 12:6    suggestion  Try to avoid using 'is'.        write-good.E-Prime     
 16:17   suggestion  Try to avoid using 'is'.        write-good.E-Prime     
 16:20   warning     Consider removing 'extremely'.  Microsoft.Adverbs      
 16:20   warning     'extremely' is a weasel word!   write-good.Weasel      
 18:50   warning     Avoid using 'will'.             Google.Will            
 18:120  warning     'However' is too wordy.         write-good.TooWordy    
 18:132  warning     Try to avoid using              Google.We              
                     first-person plural like 'we'.                         
 18:132  warning     Try to avoid using              Microsoft.We           
                     first-person plural like 'we'.                         
 18:173  warning     Avoid using 'will'.             Google.Will            
 20:17   suggestion  Try to avoid using 'is'.        write-good.E-Prime     
 30:6    suggestion  Try to avoid using 'is'.        write-good.E-Prime     
 30:6    warning     'is' is repeated!               write-good.Illusions   
 34:87   suggestion  Consider using 'has' instead    Microsoft.ComplexWords 
                     of 'contains'.                                         

✖ 0 errors, 13 warnings and 10 suggestions in 1 file.

vale.vim file in /ale/ale_linters/markdown:

" Author: chew-z https://github.com/chew-z
" Description: vale for Markdown files

call ale#linter#Define('markdown', {
 \   'name': 'vale',
 \   'executable': 'vale',
 \   'command': 'vale --output=JSON %t',
 \   'callback': 'ale#handlers#vale#Handle',
 \})

Any pointer on what's causing the unexpected behavior?

codeinthehole commented 2 years ago

I have this issue too.

hsanson commented 2 years ago

ALE seems to indicate vale's output is empty:

(finished - exit code 0) ['/bin/zsh', '-c', 'vale --output=JSON ''/var/folders/kx/3dgbmvjx14n9nk7f6w0px7l80000gn/T/v8nPkws/2/README.md''']
<<<OUTPUT STARTS>>>
{}
<<<OUTPUT ENDS>>>

Just a guess but I believe this is because we are missing some configuration? What exact command needs to be executed for vale to properly output errors?? I have never been able to get vale output any errors/warning on my markdown files.

codeinthehole commented 2 years ago

I know what this is now. It's to do with the filepath of the temprary file not matching the globs in the Vale config fle and so no styles are checked and you get an empty object {} as output.

In my case, my .vale.ini was configured to look in a posts folder:

[posts/*.md]
BasedOnStyles = Vale, write-good

but Ale effectively executes this:

vale --output=JSON /var/folders/p8/qs2_s2zn4976_hdmjwb7r4zh0000gn/T/v9iGdUc/2/some-file.md

which doesn't match on posts/*.md and so no rules are applied.

The fix for me was to relax the glob to *.md in .vale.ini.

hsanson commented 2 years ago

Thanks for the investigation. Seems vale can work using STDIN as input so wonder if the glob patterns affect in this case too. If not then it would be good idea to modify ALE to use STDIN instead of temporary files.

If time allows would you mind testing if STDIN works even if the glob pattern is [posts/*.md]? or in general how these patters affect if STDIN is used?

vale --output=JSON --ext "md" < /absolute/path/to/file.md
codeinthehole commented 2 years ago

Glob patterns that include a folder name (like posts/*.md) don't work with STDIN even if the --ext=.md option is used:

$ vale --ext=.md < posts/file-with-errors.md
{}

You have to use a glob of *.md for the STDIN approach to work.

So ultimately it's simpler to stick with temporary files as you don't require the additional --ext=.md option.

hsanson commented 2 years ago

Thanks for the investigative work. Is unfortunate that vale behaves such way. The only solution is to use *.md glob in any case.

I created a separate issue to get this detail documented in ALE's non-existend vale documentation #4092 and close this one.

jdkato commented 1 year ago

Is unfortunate that vale behaves such way.

This topic was recently brought to my attention with the implication being, as is the case here, that this is a "flaw" of Vale.

@hsanson, could you elaborate on how this is "unfortunate" behavior? What should Vale do here?

If the user explicitly provides a glob pattern, then there are only two options:

  1. Respect the pattern and ignore files that do not match.
  2. Ignore the pattern, which would render the feature useless.

(1) is obviously the correct behavior here. It seems to me that the "unfortunate" behavior, if any, is the use of temporary file paths.

hsanson commented 1 year ago

I believe, after re-reading the thread since this was more than a year ago, that what I referred as unfortunate is this behavior:

Glob patterns that include a folder name (like posts/*.md) don't work with STDIN even if the --ext=.md option is used

The best approach to integrate a tool with ALE is if it supports STDIN input that allows ALE to lint the buffer in quasi-realtime (as you type) instead of reading files from disk. Unfortunately when using STDIN input the filename and/or extension are not available so tools need additional parameters that allow ALE to pass that info (e.g. --ext) but seems that this does not work as expected in vale.

jdkato commented 1 year ago

I believe, after re-reading the thread since this was more than a year ago, that what I referred as unfortunate is this behavior:

Glob patterns that include a folder name (like posts/*.md) don't work with STDIN even if the --ext=.md option is used

The best approach to integrate a tool with ALE is if it supports STDIN input that allows ALE to lint the buffer in quasi-realtime (as you type) instead of reading files from disk. Unfortunately when using STDIN input the filename and/or extension are not available so tools need additional parameters that allow ALE to pass that info (e.g. --ext) but seems that this does not work as expected in vale.

No, it works exactly as it should. The problem is that Vale can't know if a glob like posts/*.md should match unless it has the file path, not just the extension.

At best, you could say that it'd be nice if Vale had something along the lines of a --filepath flag so that using a general pattern (like *.md) isn't necessary. But all of this discussion is due to the (questionable) particulars of ALE's implementation. There's absolutely no argument for Vale working "unexpectedly" here.