繁体   English   中英

在 vim 中编辑 python 文件的更高效的动作

[英]More efficient movements editing python files in vim

给定一个不断重复以下内容的 python 文件:

def myFunction(a, b, c):
    if a:
        print b
    elif c:
        print 'hello'

我想四处走动并使用熟悉的 vim 动作编辑此文件。 例如,使用 (, ), [[, ]], {, } 或使用 di} 之类的命令删除/拉取/更改文本。

在其他语言(如 C++、Java、C# 等)中,花括号比比皆是,因此使用 di} 之类的动作可以轻松找到匹配的花括号并作用于该块。 事实上,如果我在上述文本的 'b' 字符上并在 vim 中执行 di),它会成功删除两个括号之间的文本。

我认为问题在于python对代码块的检测。 使用 (, ), [[, ]], {, or } 作为动作几乎都做同样的事情,带你到开始(在 def 行之上或之上)或结束(在函数的最后一行之后)功能。 据我所知,没有办法轻松地告诉 vim“选择这个缩进块的所有内容”。 在上面的示例中,我想在 if 行的“i”中打开,输入 di} 并让它删除整个 if 块(到此特定函数的末尾)。

我确信应该可以告诉 vim 在缩进的基础上进行这样的动作(好吧,也许不是那个特定的动作,而是一些用户定义的动作)。 关于如何做到这一点的任何想法?

方括号映射[[ , ]] , [m , ]m和类似的

$VIMRUNTIME/ftplugin/python.vim now (2018) 重新映射记录在:h ]]:h ]m下的所有内置映射,用于 python 语言。 映射是:

]] Jump forward to begin of next toplevel
[[ Jump backwards to begin of current toplevel (if already there, previous toplevel)
]m Jump forward to begin of next method/scope
[m Jump backwords to begin of previous method/scope

][ Jump forward to end of current toplevel
[] Jump backward to end of previous of toplevel
]M Jump forward to end of current method/scope
[M Jump backward to end of previous method/scope

以下带有注释的示例源代码说明了不同的映射

class Mapping:                              # [[[[
    def __init__(self, iterable):
        pass

    def update(self, iterable):
        pass

    __update = update                       # []

class Reverse:                              # [[ or [m[m
    def __init__(self, data):               # [m
        self.data = data
        self.index = len(data)              # [M

    def __iter__(self):                     # <--- CURSOR
        return self                         # ]M

    def __next__(self):                     # ]m
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]        # ][

class MappingSubclass(Mapping):             # ]] or ]m]m

    def update(self, keys, values):
        pass

在提交abd468ed0 (2016-09-08)、 01164a6546b4 (2017-11-02) 和7f2e9d7c9cd (2017-11-11) 中添加和改进了映射。

如果你还没有这个文件的新版本,你可以下载它并把它放到~/.vim/ftplugin/python.vim中。 此文件夹优先于$VIMRUNTIME/ftplugin

在将这些映射添加到$VIMRUNTIME之前,有一个插件python-mode提供[[ , ]][M]M 此外python-mode还定义了文本对象aCiCaMiM

插件python 模式

这个 vim 插件提供类似于内置的动作:

2.4 Vim motion ~
                                                                *pymode-motion*

Support Vim motion (See |operator|) for python objects (such as functions,
class and methods).

`C` — means class
`M` — means method or function
                                                            *pymode-motion-keys*

==========  ============================
Key         Command (modes)
==========  ============================
[[          Jump to previous class or function (normal, visual, operator)
]]          Jump to next class or function  (normal, visual, operator)
[M          Jump to previous class or method (normal, visual, operator)
]M          Jump to next class or method (normal, visual, operator)
aC          Select a class. Ex: vaC, daC, yaC, caC (normal, operator)
iC          Select inner class. Ex: viC, diC, yiC, ciC (normal, operator)
aM          Select a function or method. Ex: vaM, daM, yaM, caM (normal, operator)
iM          Select inner func. or method. Ex: viM, diM, yiM, ciM (normal, operator)
==========  ============================

插件Pythonsense

这个插件提供了类似的动作,但稍作修改:

常用的 Vim 8.0“类”运动(“]]”、“[[”等),查找从第一列开始的块,无论这些是类还是功能块,而它的方法/功能运动(“[m”、“]m”等)在任何缩进处查找所有块,无论这些块是类块还是功能块。 相比之下,“Pythonsense”类运动致力于查找所有且仅类定义,而不管其缩进级别如何,而其方法/函数运动则致力于查找所有且仅方法/函数定义,而与它们的缩进级别无关。

所有详细信息和示例都在https://github.com/jeetsukumaran/vim-pythonsense#stock-vim-vs-pythonsense-motions中给出。 此外,该插件还定义了文本对象ic/ac (类)、 if/af (函数)、 id/ad (文档字符串)。

Neovim & nvim-treesitter-textobjects

对于neovim,您可以使用treesitter 和neovim 插件nvim-treesitter-textobjects

文本对象if/af & ic / ac

这些不包含在$VIMRUNTIME/ftplugin/python.vim中,但由一些插件提供

有关 python 文本对象的讨论,请参阅通过 VIM 选择 Python 函数的最快方法是什么? .

蟒蛇.vim

使浏览 python 代码块变得更加容易。

捷径:

  • ]t -- 跳转到块的开头
  • ]e -- 跳转到块尾
  • ]v -- 选择(视觉线模式)块
  • ]< -- 向左移动方块
  • ]> -- 向右移动方块
  • ]# -- 评论选择
  • ]u -- 取消注释选择
  • ]c -- 选择当前/上一课
  • ]d -- 选择当前/上一个函数
  • ]<up> -- 跳转到具有相同/更低缩进的上一行
  • ]<down> -- 跳到具有相同/更低缩进的下一行

python_match.vim

扩展%

  • % - 循环通过 if/elif/else、try/except/catch、for/continue/break
  • g% - 与%相对移动
  • [% - 移动到当前代码块的开头
  • ]% - 移动到当前代码块的末尾

上述所有动作都适用于正常、视觉和操作员挂起模式,因此:

  • d]% - 删除直到当前块结束
  • v]%d - 应该做同样的事情,通过可视模式,以便您可以看到正在删除的内容
  • V]%d - 上面,但有行选择

set foldmethod=indent后,移动缩进块非常容易。 例如,如果您在以下代码段中的def main():行:

def main():
+-- 35 lines: gps.init()-----------------------------------------------------

if __name__ == "__main__": main()

然后dj获取整个 main 函数,它可以粘贴到其他地方。

为了解决您的最后一段,以下脚本定义了一个新的“缩进”文本对象,您可以对其执行操作。 例如, d i i删除与光标所在行同级缩进的所有内容。

有关更多信息,请参阅插件的文档:http: //www.vim.org/scripts/script.php? script_id=3037

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM