Skip to content

Latest commit

 

History

History

zfold

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

基于正则的手动/自动折叠统一扩展

基于 manual 的折叠模式,使用脚本简化手动折叠的操作,支持正则表达式。

激活使用

安装请参考本仓库的首页文档。可用如下命令之一激活:

:PI zfold
:call zfold#plugin#load()

默认定义空格映射与 :Z 命令如下:

nnoremap <Space> :call zfold#cmd#nFold()<CR>
vnoremap <Space> :call zfold#cmd#vFold()<CR>
command! -range -nargs=* -bang Z <line1>,<line2>call zfold#cmd#Fold(<bang>0, <f-args>)

空格用于切换折叠,如果没有折叠则尝试 matchit 插件,类似 zf% 折叠,如果也未能实 现 % 折叠,则使用 zj 跳转到下一个折叠区。

选择模式下空格,类似 zf 创建折叠。

:Z 命令可接收一系列参数,对当前文件或指定范围进行扫描,按要求进行折叠。同时将 折叠方式置为手动档。部分参数也可修改其他折叠相关设置。

定制与个人配置

如果不喜这些默认映射或命令名,可将 plugin.vim 复制到 ~/.vim 个人目录相应位 置处修改,例如修改为 F 键与 :Fold 命令:

" file: ~/.vim/autoload/zfold/plugin.vim
nnoremap F :call zfold#cmd#nFold()<CR>
vnoremap F :call zfold#cmd#vFold()<CR>
command! {命令参数不改} Fold {命令定义不改}

配置文件采用 json 格式,如有必要增减修改,也可以将 set.json 一并复制到个人目 录:

$ cp plugin.vim ~/.vim/autoload/zfold/plugin.vim
$ cp set.json ~/.vim/autoload/zfold/set.json

折叠命令参数

:1,$ Z! /start-regexp/ /end-regexp/

用空格分隔两个命令行参数,每个参数首尾的 // 可省略。省略 // 时,自动在参数 前加 ^\s*, 除非参数本身以 ^ 开头或以 $ 结尾。使用 // 的好处主要是可以 末尾附加选项,也可单独使用 // 表示空串正则参数。

可指定范围行,默认全文件行。在该范围内搜索起始与终止正则表达式创建折叠。一般在 选择模式按 : 会自动添加行范围。此外在原有的折叠行,普通模式下按 : 也会隐含 传入当前折叠区的行范围。

如果命令有 ! 修饰,在创建折叠前调用 zE 删除原来所有折叠,否则新折叠与旧折 叠共存。

:Z /start-regexp/< /end-regexp/>
:Z /start-regexp/+ /end-regexp/-

正则参数选项 < 表示起始参数,> 表示终止参数,一般情况下可以省略,用位置即 可表示起始或终止参数。

选项 + 表示从匹配参数的下一行开始折叠,- 表示从匹配参数的上一行开始折叠。 目前认为只有必要支持偏移一行,即等效于 +1-1 ,可省略数字且不支持其他数字。

:Z /match-regexp/
:Z /match-regexp/~
:Z /match-regexp/!

只提供一个起始参数时,或在正则参数末尾加入 ~ 选项,将连续匹配该正则参数的行折叠。 如果末尾是 ! 选项,则将匹配反转,折叠连续不匹配的行。

:Z /toggle-regexp/=

如果正则参数附加选项 = ,表示起始与终止参数都相同。在第 1 个与第 2 个匹配之 间的行折叠,第 3 与第 4 匹配之间的行折叠,但第 2 与第 3 匹配之间的行不折叠。

在之前一般情况下,起始与终止正则参数不同时,有可能实现嵌套折叠。但起止参数相同 时,只能实现同一层次的间隔性折叠。

:Z /sib1-regexp/== /sib2-regexp/== [... /$/==]

= 选项的间隔性折叠不同,== 选项表示连续性折叠,且这些正则参数是平级折叠 。例如 case:default: 的情况,每两个 case:default: 之间的行都进 行折叠。但为了避免折叠区重叠,相当于在终止参数后加了 - 选项,即实际折叠从匹 配前一个 case: 到后一个 case: 前一行的范围。

连续折叠选项的参数个数不限,顺序不限,如果最后指定一个特殊的 /$/== 参数,表 示匹配(执行 :Z 命令的范围的)最后一行,会将最后一个匹配的行到最后一行也折叠 起来,否则留下最后一个匹配悬空不折叠。

:Z /kid1-regexp/=> /kid2-regexp/=> [... /$/=>]

级联选项 => 与连续性折叠类似,但是有顺序层次关系。典型示例运用如 markdown 的层级 标题::Z /^#\s.\+/=> /^##\s.\+/=> /^###\s.\+/=> /^####\s.\+/=> /$/=> (当然 这里简化假设规范 # 之后至少有个空格,否则要注意匹配 ## 的也必然匹配 #) 。另一种示例如 vim 的标记折叠方式 {{{1 {{{2 ...

封尾参数 /$/=> 的意义类似。是否需要封尾也视个人需求场合而定。

特殊折叠参数

:Z {}
:Z ()
:Z []

如果参数是一对括号且不包含在 // 中,则按括号折叠。不过左括号必须在行尾,右括号必 须在行首,忽略行尾或行首的空白。相当自动展成 {\s*$ ^\s*} 两个参数。

如果在括号中插入空格如 { } ,则当作正常的两个正则参数,不会自动限制行尾或行 首。

:Z $
:Z $2
:Z $-2
:Z $config_name
:Z $ENVIRONMENT_VARIABLE

正常的正则参数不可能以 $ 开头,故用 $ 表示特殊用途。可通过配置将常用折叠正 则表达式参数(组)作易记方便的命名,然后在命令行中快捷引用。如果恰好存在相应的 环境变量,则展开环境变量作为命令行参数。支持从配置或环境变量中获取命令参数补全 。

单个 $ 参数表示取与当前文件类型 &filetype 的配置。

如果是数字,表示设置 &foldlevel 折叠开关层次选项,而非扫描创建折叠。如果是负数, 则设置 &foldcolunm 折叠栏列宽选项。

:Z $indent
:Z $syntax
:Z $marker
:Z $expr
:Z $xml

这些是保留配置名,用于将其他的折叠方式,转为自动创建折叠,可与自动管理折叠并存。 而 xml/html 的标签关系,恐怕难以用简单正则表示,需要单独实现。

目前只实现了按缩进折叠 $indent$xml 简易版标签折叠。要求开标签 <tag> 与闭标签 </tag> 分别单独占一行的规范才能正确折叠;另外也能折叠 <!-- 多行注释 -->

一般情况下,不需单独使用以上 $syntax $expr 这类命令,可以直接切换折叠方法 的选项,如:

:set foldmethod=syntax |" 或 expr indent marker
:set foldmethod=manual |" 或无参数命令 :Z

因为切换至 manual 手动折叠时,会保留之前的折叠,这样就可以在之前的折叠设置基 础上,再手动微调 zf 创建折叠或 zd 删除折叠等。不过 &foldmethod 切换影响 的是全文档,而用这里的 :Z $indent 系列命令可指定范围。再如 markdonw 文件中若 存在大段 html ,可选择范围使用 :'<,'>Z $xml 局部折叠。

命名参数配置

采用 json 格式,解析为一个 dict 对象。键名不包含前导 $ ,值是可用于 :Z 命 令的参数字符串,多个参数用空格分隔,每个正则表达式参数不应该包含空格。

该 json 对象的第一层键作为全局名字。其中保留一个键名 ft ,是个嵌套对象,用于 保存每种需要配置的文件类型,以文件类型为键提供一个局部命名空间。例如: json.ft.vim.if = 'if endif' 。并且约定文件类型的一个特殊键 '0' 表示该文件 类型的默认参数,当命令行使用单字符 $ 时调用 json.ft[&ft]['0']

建议配置键名用小写,以区别于环境变量。环境变量可用 :let 命令在 vimrc 等初 始化脚本中定义。并不鼓励用环境变量配置参数,如果一定要用,建议用统一直观的前缀 如::let ZFOLD_IF = 'if endif'

配置示例文件见 set.json 。顶层的 json.indentjson.xml 等空 值键只为给 :Z 提供补全提示。然后有如下关系:

json.ft.xml.0 == '$xml'
json.ft.hmtl.0 == '$xml'
json.ft.python.0 == '$indent'

可以表示 xml/html 文件默认使用 $xml 参数折叠,pyhton 文件默认使用 $indent 折叠。

注意:json 双引号字符串对反斜杠 \ 的转义,如正则 \s\+ 要写成 "\s\+" 。

混合参数使用

可以将以上参数类型放在一个 :Z 命令中,等效于分批次执行命令。例如:

:Z start end /start/+ /end/- /match/~ /nomatch/! /toggle/= $2

相当于依次执行:

:Z ^\s*start ^\s*end
:Z /start/+ /end/
:Z /match/
:Z /nomatch/!
:Z /toggle/ /toggle/
:Z $2

除最后设置 foldlevel 等级的显示外,每次命令都独立重新扫描指定的范围。

注意:若将 /match/~ 混在参数中间,必须加 ~ 选项,否则可能当作一个起始正则 参数。

级联参数组 => 与连续参数组 == 也可以一起混入参数。

本插件扩展主要特点

手动折叠足够灵活,且不像 marker 插入标记会修改源文件。可以充分利用 z 系快捷键 创建、开头、浏览折叠。通过正则参数单次命令创建折叠也便捷,且可以叠加,分步创建 完全不同类型的折叠。

语法折叠 syntax 或表达式折叠 expr ,虽然更自动化,但如果遇到需要微调折叠时很不 方便。且对于大文件,复杂的 syntax 与 expr 折叠可能很慢。用本插件,也可以为每个 文件类型配置相对简单的默认参数只折叠一层以提供文档大纲视图,然后根据需要执行更 复杂的折叠。

已知问题与限制

手动折叠没法保存,始终需要手动执行命令折叠。但是可以在 ftplugin/ 目录中对感兴 趣的文件类型,自动配置调用一系列 :Z 命令进行折叠。或者先配置为 syntax 等基本 满意的折叠方法,有必要时再 :Z 切换到手动折叠。

:Z {} 折叠不能达到 C 系列语言语法折叠的效果,没法排除在注释区的 {} 。

基于单行的正则匹配,在源文件格式良好规范时运用更佳。如果在单行同时匹配起始参数 /start/ 与终止参数 /end/ ,会忽略,认为没必要折叠单行。也不在意是否在单行 匹配多次。

致谢

zfold 插件名及 :Z 命令名,主要是考虑与内置 z 系统的折叠命令相统一。

按正则手动折叠的思想源于 https://github.com/ZSaberLv0/ZFVimFoldBloc 的启发。