我目前有一个解析日志文件的语法文件,非常类似于以下[这适用于syslog]:
syn match syslogText /.*$/
syn match syslogFacility /.\{-1,}:/ nextgroup=syslogText skipwhite
syn match syslogHost /\S\+/ nextgroup=syslogFacility,syslogText skipwhite
syn match syslogDate /^.\{-}\d\d:\d\d:\d\d/ nextgroup=syslogHost skipwhite
我想使用地图切换是否隐藏给定组(例如,syslogHost)。有没有办法做类似下面的伪代码:
map <leader>ch :syn match syslogHost conceal!
从而切换syslogHost的定义:
syn match syslogHost /\S\+/ nextgroup=syslogFacility,syslogText skipwhite
和
syn match syslogHost /\S\+/ nextgroup=syslogFacility,syslogText skipwhite conceal
感谢。
答案 0 :(得分:4)
我认为这样做的唯一方法是使用函数:
map <leader>ch :call ToggleGroupConceal('sysLogHost')<CR>
function! ToggleGroupConceal(group)
" Get the existing syntax definition
redir => syntax_def
exe 'silent syn list' a:group
redir END
" Split into multiple lines
let lines = split(syntax_def, "\n")
" Clear the existing syntax definitions
exe 'syn clear' a:group
for line in lines
" Only parse the lines that mention the desired group
" (so don't try to parse the "--- Syntax items ---" line)
if line =~ a:group
" Get the required bits (the syntax type and the full definition)
let matcher = a:group . '\s\+xxx\s\+\(\k\+\)\s\+\(.*\)'
let type = substitute(line, matcher, '\1', '')
let definition = substitute(line, matcher, '\2', '')
" Either add or remove 'conceal' from the definition
if definition =~ 'conceal'
let definition = substitute(definition, ' conceal\>', '', '')
exe 'syn' type a:group definition
else
exe 'syn' type a:group definition 'conceal'
endif
endif
endfor
endfunction
答案 1 :(得分:1)
这是对@ DrAl原始版本的修改,适用于匹配和区域类型的语法组。
" function to toggle conceal attribute for a syntax group
function! ToggleGroupConceal(group)
" Get the existing syntax definition for specified group
redir => syntax_def
exe 'silent syn list' a:group
redir END
" Split into multiple lines
let lines = split(syntax_def, "\n")
" Clear the existing syntax definitions
exe 'syn clear' a:group
for line in lines
" Only parse lines that contain the desired group's definition
" (skip "--- Syntax items ---" line and 'links to' lines)
if line =~ a:group
"echo 'line = ' . line
" need to handle match and region types separately since type
" isn't specified for regions in the syn list output like it is
" for matches.
let type = substitute(line, '\v' . a:group . '\s+xxx\s+(\k+)\s+(.*)', '\1', '')
if type == 'match'
" get args as everything after 'xxx match'
let args = substitute(line, '\v' . a:group . '\s+xxx\s+(\k+)\s+(.*)', '\2', '')
else
" get args as everything after 'xxx'
let args = substitute(line, '\v' . a:group . '\s+xxx\s+(.*)', '\1', '')
if args =~ 'start' && args =~ 'end'
let type = 'region'
endif
endif
"echo ' type = ' . type
"echo ' args = ' . args
" Either add or remove 'conceal' from the definition
if args =~ 'conceal'
exe 'syn' type a:group substitute(args, ' conceal', '', '')
else
exe 'syn' type a:group args 'conceal'
endif
endif
endfor
endfunction
答案 2 :(得分:0)
您还可以更改文件的语法。我对json
文件有一些隐藏规则,我没有为javascript
文件隐藏(例如,我隐藏引号和尾随逗号以使文件更易于阅读。)所以当我想要的时候要查看整个文件,我只使用set syntax=javascript
。您可以更进一步,只需为文件类型定义两组规则(例如,syslog.vim和syslog2.vim),其中1从2继承,然后应用隐藏规则,然后您可以绑定一个键以在它们之间切换。