文章目录
ALE介绍
ale是一个异步的检测插件,项目的介绍如下:
Github地址:Check syntax in Vim asynchronously and fix files, with Language Server Protocol (LSP) support
ALE安装
ale支持多种安装方式,详情参考项目github地址,这里以Vundle方式安装:
- 安装好Vundle插件
- 在
.vimrc
文件的Vundle插件列表里添加如下:
Plugin 'dense-analysis/ale'
- 打开vim然后运行命令
:PluginInstall
或者:BundleInstall
等待完成即可。 - 相应语言的
linter
,可以查看github上的支持列表,装好相应的linter
,加入环境变量即可。
Note:
- 由于Vundle插件后台还是在调用git进行代码克隆,如果失败请设置代理或者手动克隆项目到Vundle安装文件夹下,默认为
~/.vim/bundle/
。 - linux下的家目录为
~
,windows下的家目录为%HOME_PATH%
,如果在windows下可以使用\\
(whindows风格,必须是双反斜杠,取消转义)或者/
(linux风格)作为目录分割符。
ALE配置
详情参考项目github地址,在Vim中输入命令:h ale
可以查看各种相关内容,大部分配置使用默认的就可以了,这里给出一些简单显示配置(以下所有设置都在.vimrc
文件中写入,新修改的设置默认需要重启Vim才生效)。
自定义侧边提示符号
原始的ale侧边提示是这样:
--
表示警告,>>
表示错误,这样不是那么醒目,可以进行自定义设置:
" 自定义error和warning图标
let g:ale_sign_error = '✗'
let g:ale_sign_warning = '⚡'
重启打开Vim之后显示效果就变成这样了:
Note: 可以选择任何你喜欢的符号,出现乱码请检查Vim相关的编码设置以及字体是否支持该种符号。
自定义底部提示消息
默认的底部栏只显示出错消息:
可以设置添加更多的消息:
" 显示Linter名称,出错或警告等相关信息
let g:ale_echo_msg_error_str = 'E'
let g:ale_echo_msg_warning_str = 'W'
let g:ale_echo_msg_format = '[%linter%] %s [%severity%]'
增加了linter
和相关消息类型提示,显示效果如下:
高亮显示设置
默认情况检查出现警告或者错误会在代码下高亮提示,如上面所示的~
,如果不喜欢可以选择关闭。这个高亮显示是与linter
和设置有关,有些linter
设置并不支持高亮。
" 关闭高亮提示
let g:ale_set_highlights = 0
状态栏提示集成
ale提示可以集成在vim自带的状态栏或者第三方状态栏上比如airline上:
在vim自己的状态栏上显示设置如下:
"设置状态栏显示的内容,这里必须添加%{ALEGetStatusLine()到状态栏里
set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [POS=%l,%v][%p%%]\ %{strftime(\"%d/%m/%y\ -\ %H:%M\")}\ %{ALEGetStatusLine()}
"设置ale显示内容
let g:ale_statusline_format = ['✗ %d', '⚡ %d', '✔ OK']
如果安装了airline,默认在airline中是显示ale内容的,可以手动关闭:
let g:airline#extensions#tabline#enabled = 0
如果希望airline状态栏的图标改变,可以进入airline的文件夹目录(默认为:~/.vim/bundle/vim-airline/autoload/airline/extensions/
),找到ale.vim
文件修改这几行:
" 错误图标默认为E
let error_symbol = get(g:, 'airline#extensions#ale#error_symbol', 'E:')
" 警告图标默认为W
let warning_symbol = get(g:, 'airline#extensions#ale#warning_symbol', 'W:')
" 等待图标默认为...
let checking_symbol = get(g:, 'airline#extensions#ale#checking_symbol', '...')
linter相关设置
默认实时检测代码,如果希望只在保存文件时才运行,可以进行如下设置:
" 文件内容发生变化时不进行检查
let g:ale_lint_on_text_changed = 'never'
" 打开文件时不进行检查
let g:ale_lint_on_enter = 0
插件默认会使能所有支持的linter
,如果希望对某个语言单独设置相应的linter
,可以做如下设置:
" 对verilog、c++、c、python单独设置linter
let g:ale_linters = { 'verilog': ['vlog'],
\ 'c++': ['gcc'],
\ 'c': ['gcc'],
\ 'python': ['pylint'],
\}
快捷键设置
设置一些常用的快捷键:
" sp前往上一个错误或警告,sn前往下一个错误或警告
nmap sp <Plug>(ale_previous_wrap)
nmap sn <Plug>(ale_next_wrap)
" 开/关语法检查
nmap <Leader>s :ALEToggle<CR>
" 查看错误或警告的详细信息
nmap <Leader>d :ALEDetail<CR>
ALE的bug处理
Bug描述
在windows上使用某些linter
检测相应代码(特别是HDL代码)会出现问题,主要表现为:
- 插件的确调用了相应的
linter
,产生了相应的输出文件。
- 使用命令
:ALEInfo
查看运行日志,日志也提示了相应警告和错误。
- Vim界面上却没有显示任何报错信息。
Note: 这个问题在github上也有人提了issue,但是开发者目前并没有解决。
Bug分析
ale的基本工作原理是通过调用相应文件的linter
输出错误信息,然后使用正则表达式进行捕获,再将捕获的信息显示到界面上。而导致这个bug的罪魁祸首是linux和windows文件路径的区别,linux的文件路径不会出现:
这个符号,但是windows的路径会出现卷分隔符:
。ale插件的部分linter
正则表达式中并没有考虑这一情况,所以大多数linter
输出信息里含有文件名的基本都会触发这个bug,我测试的linter
中vlog
、iverilog
、ghdl
等都有这个bug,但xvlog
没有问题。
Bug解决
既然知道了Bug怎么来的了,解决方法也很简单,那就是进入ale相应的linter
文件夹(默认为:~/.vim/bundle/ale/ale_linters/
),修改相应linter
原有的正则表达式。
vlog下的修改方法
打开目录下的vlog.vim
,它的匹配函数写了两种,对应不同版本的vlog输出信息,区别就是文件名和错误码的位置不同而已,我的vlog
输出是第一种:
我们可以很清楚的看到这个文件名的捕获是[a-zA-Z0-9\-\.\_\/ ]\+
,这个意思是捕获的文件名包含至少一个大小写字母(a-zA-Z
)、数字(0-9
)、横线(-
)、下划线(_
)、点(.
)、斜杠(/
)、空格()。在windows下文件名除了
?
、"
、``/、
`、<
、>
、*
、 |
、 :
,其他字符基本都是可以的,而路径中包含有:
、\
这两种,那么最后就<
、>
、*
、?
、|
、/
、"
这七种不能包含,其他字符基本都可以,我们可以采用[^<>|?"/*]
取这七种之外的字符,也可以用个更简单的方法,直接使用.
去匹配,匹配除换行以外其他所有的字符。
将[a-zA-Z0-9\-\.\_\/ ]\+
采用两种方式替换,如下:
" 使用.匹配
let l:pattern = '^\*\*\s\(\w*\): \(.\+\)(\(\d\+\)):\s\+\(.*\)'
" 使用[^<>|?*"/]匹配
let l:pattern = '^\*\*\s\(\w*\): \([^<>"|?/*]\+\)(\(\d\+\)):\s\+\(.*\)'
功能正常,测试结果如下:
Note: 这个匹配输出的前两个*
,理论上应该使用\*
,但是源码里写的是*
。*
原意应该是前面的字符出现0至多次,这里源码这样写也能通过,但是按道理应该有点问题的,所以我修改了,不知道有没有大佬知道,给我解答一下。
iverilog下的修改方法
这里的文件名匹配直接使用[^:]
,意思是除了:
以外所有字符,显然直接把windows给忽略了,替换方法和上面一样:
" 使用[^<>|?/"*]匹配
let l:pattern = '^[^<>"|?/*]\+:\(\d\+\): \(warning\|error\|syntax error\)\(: \(.\+\)\)\?'
" 使用.匹配
let l:pattern = '^.\+:\(\d\+\): \(warning\|error\|syntax error\)\(: \(.\+\)\)\?'
功能正常,测试结果如下:
xvlog正常原因
那么问题来了,HDL的linter
很多都触发了bug,xvlog
为什么没有问题?
查看xvlog.vim
发现它的匹配为.*
,直接匹配任意任何数量的除换行符之外的其他所有字符,和.\+
如出一辙。
参考资料
- Vim插件之ale
- ALE官方Wiki
- Linter running but errors not showing #3340