如何在Python代码中推荐使用Vim的折叠功能?

128
我对在Vim中为Python代码启用代码折叠很感兴趣。我注意到有多种方法可以实现。
有人有偏好的方法来在Vim中进行Python代码折叠吗?例如,
- 你有使用和喜欢的特定Vim插件吗? - 你使用手动折叠还是在注释中放置标记? - 有其他推荐的在Vim中进行Python代码折叠的方法吗?
12个回答

149

就我个人而言,我无法说服自己在代码中添加标记。我已经习惯了使用缩进折叠,并且非常高效。再加上我的空格键映射(见下文)用于打开/关闭折叠以及zR和zM命令,我感到非常舒适。对于Python来说非常完美!

set foldmethod=indent
nnoremap <space> za
vnoremap <space> zf

这将空格键映射为在正常模式下打开/关闭当前缩进折叠。它还将空格键映射为在可视模式下创建手动折叠。但是,如果foldmethod设置为indent,则此功能无法使用,其目的成为一个谜。


83
设置折叠方法为缩进方式(foldmethod=indent first)。我在谷歌上搜索这个问题,偶然看到了你的答案,非常好! :) - tmadsen
54
我朋友也喜欢使用set foldnestmax=2,这样可以折叠类的方法,但是不会折叠内部语句。 - Denilson Sá Maia
11
我不确定为什么第二个映射出现在zf的答案中。如果正在使用缩进折叠,它将不会被使用。但是,如果您正在进行手动折叠,则此映射是完全合理的。然而,za似乎是快速打开/关闭折叠的最佳方式。我还建议使用折叠导航(zk、zj)。 - Derek Litz
1
vnoremap 对于手动映射非常好用。在你的 ftplugin 中,为 Python 添加 set foldmethod=indent。然后,在你的 .vimrc 中,设置 foldmethod=manual。现在,你可以使用空格键映射在 Python 和非 Python 中折叠了。 - Lionel

25

我使用this语法文件来编写Python。它将折叠方法设置为语法,并折叠所有类和函数,但不包括其他内容。


如何在展开后折叠?我找不到快捷方式!谢谢 - Moj
尝试了这个语法文件,高亮显示效果还不错。但是对于冷折叠却完全没有作用,当我使用'zM'时什么都没有发生,当我在类中使用'za'时则提示E490(未找到折叠)。出了什么问题? - Dani Gehtdichnixan
一开始尝试时,Python代码(class,method)折叠对我来说非常有效。采用Walter's(https://dev59.com/HnRC5IYBdhLWcg3wROtQ#360634)的答案将空格键映射为折叠命令,但这个解决方案对我来说不太好用。感谢@Tomas的参考。 - Johnny Utahh
@DaniGehtdichnixan,也许你需要使用:AnsiEsc--研究一下,我认为你会找到解决方案。 - serup

11

又一个用于折叠Python代码的插件。它相当简单,可以处理文档字符串,并且在GitHub上可用:

SimpylFold

享受吧!


这是最好的方法。自从它从未引起任何头疼以来,我已经完全停止考虑代码折叠。 - iankit
1
@iankit,我有时候希望它也能折叠ifforwhile块,你不觉得吗? - iago-lito
嗯,我认为这可能并不是非常有帮助。如果他折叠这些块,那么在折叠状态下内容就不是很清晰了。但是对于方法和其他命名的块,名称就能说明一切。通过查看其名称,我可以猜测折叠块正在做什么。 - iankit
@iankit 我不知道...我想试试。为什么不尝试呢?^ ^ - iago-lito

7

Python非常适合根据缩进进行折叠,但是对于编写自己的代码,我使用标记,因为它们可以将文档压缩到您想要的方式,并且可以作为目录的一种形式。在查看别人的代码时,我在我的vimrc中切换这两种方式。

#Toggle fold methods \fo
let g:FoldMethod = 0
map <leader>fo :call ToggleFold()<cr>
fun! ToggleFold()
    if g:FoldMethod == 0
        exe 'set foldmethod=indent'
        let g:FoldMethod = 1
    else
        exe 'set foldmethod=marker'
        let g:FoldMethod = 0
    endif
endfun
#Add markers (trigger on class Foo line)
nnoremap ,f2 ^wywO#<c-r>0 {{{2<esc>
nnoremap ,f3 ^wywO#<c-r>0 {{{3<esc> 
nnoremap ,f4 ^wywO#<c-r>0 {{{4<esc>
nnoremap ,f1 ^wywO#<c-r>0 {{{1<esc>

5

5

1
不幸的是,这个插件使用的处理器时间比我想要的多(即使使用了a版本),因为我喜欢保持我的vim速度快。还有其他建议吗? - Paul D. Eden
12
这个答案确实需要说明。 - sixtyfootersdude


4
在你的.vimrc文件中:
set foldmethod=indent
set shiftwidth=4

然后使用zM来隐藏所有内容,使用zR来展开所有内容。我还添加了:

nnoremap <space> za
vnoremap <space> zf
map z1  :set foldlevel=0<CR><Esc>
map z2  :set foldlevel=1<CR><Esc>
map z3  :set foldlevel=2<CR><Esc>
map z4  :set foldlevel=3<CR><Esc>
map z5  :set foldlevel=4<CR><Esc>
map z6  :set foldlevel=5<CR><Esc>
map z7  :set foldlevel=6<CR><Esc>
map z8  :set foldlevel=7<CR><Esc>
map z9  :set foldlevel=8<CR><Esc>

所以您可以使用z1z2逐渐取消缩进。


3
对我来说,理想的折叠方式是仅折叠classdef块,缩进折叠对我来说太多了。我认为一种优雅的解决方案是使用像Tomas提到的这个这个语法系统。然而,这个语法系统是用来替代原始语法文件的,它可能比原始语法文件还要老(例如,该脚本没有提到Python 3语法)。
我的解决方案是将一个名为python.vim的文件放在~/.vim/syntax文件夹中,其中只包含重要的行(从上面的脚本中获取)。
syn match   pythonDefStatement  /^\s*\%(def\|class\)/
       \ nextgroup=pythonFunction skipwhite
syn region  pythonFunctionFold  start="^\z(\s*\)\%(def\|class\)\>"
       \ end="\ze\%(\s*\n\)\+\%(\z1\s\)\@!." fold transparent

hi link pythonDefStatement Statement

那么,您只需要使用:set foldmethod=syntax 来激活折叠即可。

2
我喜欢这个解决方案。但是它不能匹配以换行开头的'n'折叠classdef。由于我几乎无法阅读表达式,因此我很难调整它以匹配^def^class。这很奇怪,因为\s*应该可以很好地处理这个问题。 - iago-lito

2

3
这个语法文件并不包含折叠信息,因此您不能将此语法文件与语法折叠一起使用。 - KFL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接