Highlight groups are cleared when g:ale_virtualtext_cursor = 1
Information
VIM version
NVIM v0.4.3 Build type: RelWithDebInfo
Operating System: Ubuntu 18.04.4 LTS
ALE version:
commit 36e5337e30095afb10d02ef2ae362c8d6055e70d Author: Horacio Sanson [email protected] Date: Tue Apr 21 13:36:57 2020 +0900
What went wrong
When I enabled virtualtext cursor in my init.vim configuration (let g:ale_virtualtext_cursor = 1). For some mysterious reason ALEError and ALEWarning highlight groups are cleared.
After a lot of fiddling around, I suspect some sort of race condition is happening in the order of which ale vim scripts are loaded. I couldn't pinpoint the problem though, because I lack the experience and knowledge of vim scripting.
See a patch below that happens to fix my problem so far.
Reproducing the bug
Add to init.vim: let g:ale_virtualtext_cursor = 1
open a python file
observe that :highlight ALEError prints:
ALEError xxx cleared
:ALEInfo
Current Filetype: python
Available Linters: ['bandit', 'flake8', 'mypy', 'prospector', 'pycodestyle', 'pydocstyle', 'pyflakes', 'pylama', 'pylint', 'pyls', 'pyre', 'vulture']
Enabled Linters: ['flake8', 'mypy', 'pylint']
Suggested Fixers:
'add_blank_lines_for_python_control_statements' - Add blank lines before control statements.
'autopep8' - Fix PEP8 issues with autopep8.
'black' - Fix PEP8 issues with black.
'isort' - Sort Python imports with isort.
'remove_trailing_lines' - Remove all blank lines at the end of a file.
'reorder-python-imports' - Sort Python imports with reorder-python-imports.
'trim_whitespace' - Remove all trailing whitespace characters at the end of every line.
'yapf' - Fix Python files with yapf.
Linter Variables:
let g:ale_python_auto_pipenv = 0
let g:ale_python_flake8_auto_pipenv = 0
let g:ale_python_flake8_change_directory = 1
let g:ale_python_flake8_executable = 'flake8'
let g:ale_python_flake8_options = ''
let g:ale_python_flake8_use_global = 0
let g:ale_python_mypy_auto_pipenv = 0
let g:ale_python_mypy_executable = 'mypy'
let g:ale_python_mypy_ignore_invalid_syntax = 0
let g:ale_python_mypy_options = ''
let g:ale_python_mypy_show_notes = 1
let g:ale_python_mypy_use_global = 0
let g:ale_python_pylint_auto_pipenv = 0
let g:ale_python_pylint_change_directory = 1
let g:ale_python_pylint_executable = 'pylint'
let g:ale_python_pylint_options = ''
let g:ale_python_pylint_use_global = 0
let g:ale_python_pylint_use_msg_id = 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 = 'Error'
let g:ale_echo_msg_format = '%code: %%s'
let g:ale_echo_msg_info_str = 'Info'
let g:ale_echo_msg_warning_str = 'Warning'
let g:ale_enabled = 1
let g:ale_fix_on_save = 0
let b:ale_fix_on_save = 1
let g:ale_fixers = {'rust': ['rustfmt'], 'python': ['autopep8', 'isort']}
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 = {'rust': ['rls']}
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 = '%code: %%s'
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 = 1
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 = 1
let g:ale_warn_about_trailing_blank_lines = 1
let g:ale_warn_about_trailing_whitespace = 1
Command History:
[... edited out ...]
Possible fix
I observed that the function ale#virtualtext#ShowCursorWarningWithDelay() is not loaded when the autocomand on cursormove is running. This commands seems to run early when the buffer is loaded. By checking if it exists before calling it, this magically solves the problem. I do not understand fully the root cause. This is probably some sort of race condition.
diff --git a/autoload/ale/events.vim b/autoload/ale/events.vim
index da554ef..13431b7 100644
--- a/autoload/ale/events.vim
+++ b/autoload/ale/events.vim
@@ -140,7 +140,7 @@ function! ale#events#Init() abort
endif
if g:ale_virtualtext_cursor
- autocmd CursorMoved,CursorHold * if exists('*ale#engine#Cleanup') | call ale#virtualtext#ShowCursorWarningWithDelay() | endif
+ autocmd CursorMoved,CursorHold * if exists('*ale#virtualtext#ShowCursorWarningWithDelay') | call ale#virtualtext#ShowCursorWarningWithDelay() | 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.
This bug is caused by the incorrect script loading order. NeoVIM loads virtualtext.vim first, which links ALEVirtualTextError to ALEError and automatically defines a dumy (cleared) highlight group ALEError. Then the script highlight.vim gets loaded but because the highlight group ALEError is already defined, the check just bypasses it.
I suggest wrap these 'global definition statements' into a function to ensure the order of highlight group definitions.
This bug is caused by the incorrect script loading order. NeoVIM loads
virtualtext.vimfirst, which linksALEVirtualTextErrortoALEErrorand automatically defines a dumy (cleared) highlight groupALEError. Then the scripthighlight.vimgets loaded but because the highlight groupALEErroris already defined, the check just bypasses it.
Confirmed it's the scripts loading issue described by @chengzeyi . My workaround is triggering highlight script loading in vimrc :
autocmd VimEnter * call ale#highlight#UpdateHighlights()
I've got the same behaviour in new Vim9. The workaround from @zhengpd does not solve the issue.