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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/896145/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 21:04:50  来源:igfitidea点击:

More efficient movements editing python files in vim

pythonvimediting

提问by

Given a python file with the following repeated endlessly:

给定一个 python 文件,其中无休止地重复以下内容:

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

I'd like to move around and edit this file using familiar vim movements. For instance, using (, ), [[, ]], {, } or deleting/yanking/changing text using commands like di}.

我想使用熟悉的 vim 动作来回移动和编辑这个文件。例如,使用 (, ), [[, ]], {, } 或使用 di} 等命令删除/拉取/更改文本。

In other languages (like C++, Java, C#, etc) you've got curly brackets abound, so using a movement like di} can easily find a matching curly brace and act on that block. And in fact if I am on the 'b' character on the above text and do a di) in vim, it successfully deletes the text between the two parens.

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

The issue is in python's detection of code blocks, I think. Using (, ), [[, ]], {, or } as movements all pretty much do the same thing, bringing you to the start (above or on the def line) or end (after the last line of the function) of the function. And there is no way, as far as I know, to easily tell vim "select everything for this indentation block." In the above example, I'd like to be on in 'i' of the if line, type di} and have it delete the entire if block (to the end of this particular function).

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

I'm sure it should be possible to tell vim to operate on an indentation basis for such movements (well, maybe not that particular movement, but some user defined action). Any thoughts on how to accomplish this?

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

回答by Hotschke

Square Bracket Mappings [[, ]], [m, ]mand similar

括号映射[[]][m]m和类似

$VIMRUNTIME/ftplugin/python.vimnow (2018) remaps all builtin mappings documented under :h ]]and :h ]mfor the python language. The mappings are:

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

]] 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

Following example source code with comments illustrates the different mappings

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

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

The mappings have been added and improved in the commits abd468ed0(2016-09-08), 01164a6546b4(2017-11-02), and 7f2e9d7c9cd(2017-11-11).

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

If you do not have the new version of this file yet, you can download it and put it into ~/.vim/ftplugin/python.vim. This folder takes precedence before $VIMRUNTIME/ftplugin.

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

Before these mappings have been added to $VIMRUNTIME, there has been the plugin python-modewhich provides [[, ]], [M, and ]M. In addition python-modealso defines the text objects aC, iC, aM, and iM:

之前,这些映射已添加到$VIMRUNTIME,出现了该插件python-mode提供[[]][M,和]M。此外python-mode还定义了文本对象aCiCaM,和iM

Plugin python-mode

插件python模式

This vim plugin provides motions similar to built-in ones:

这个 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)
==========  ============================

Plugin Pythonsense

插件Pythonsense

This plugin provides similar motions but slightly modified:

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

The stock Vim 8.0 "class" motions ("]]", "[[", etc.), find blocks that begin at the first column, regardless of whether or not these are class or function blocks, while its method/function motions ("[m", "]m", etc.) find all blocks at any indent regardless of whether or not these are class or function blocks. In contrast, "Pythonsense" class motions work on finding all and only class definitions, regardless of their indent level, while its method/function motions work on finding all and only method/function definitions, regardless of their indent level.

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

All details and examples are given at https://github.com/jeetsukumaran/vim-pythonsense#stock-vim-vs-pythonsense-motions. In addition, this plugin defines the text objects ic/ac(class), if/af(function), id/ad(docstring).

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

For a discussion about textobjects for python see what's the fastest way to select a function of Python via VIM?.

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

回答by Rudiger Wolf

python.vim

蟒蛇.vim

Makes it much easier to navigate around python code blocks.

使在 python 代码块中导航变得更加容易。

Shortcuts:

快捷方式:

  • ]t-- Jump to beginning of block
  • ]e-- Jump to end of block
  • ]v-- Select (Visual Line Mode) block
  • ]<-- Shift block to left
  • ]>-- Shift block to right
  • ]#-- Comment selection
  • ]u-- Uncomment selection
  • ]c-- Select current/previous class
  • ]d-- Select current/previous function
  • ]<up>-- Jump to previous line with the same/lower indentation
  • ]<down>-- Jump to next line with the same/lower indentation
  • ]t-- 跳转到块的开头
  • ]e-- 跳转到块尾
  • ]v-- 选择(视线模式)块
  • ]<-- 向左移动块
  • ]>-- 向右移动方块
  • ]#-- 评论选择
  • ]u-- 取消注释选择
  • ]c-- 选择当前/以前的班级
  • ]d-- 选择当前/上一个功能
  • ]<up>-- 跳转到具有相同/较低缩进的上一行
  • ]<down>-- 跳转到具有相同/较低缩进的下一行

python_match.vim

python_match.vim

extends %:

扩展%

  • %- cycle through if/elif/else, try/except/catch, for/continue/break
  • g%- move opposite of %
  • [%- move to the beginning of the current code block
  • ]%- move to the end of the current code block
  • %- 循环 if/elif/else、try/except/catch、for/continue/break
  • g%- 移动对面 %
  • [%- 移动到当前代码块的开头
  • ]%- 移动到当前代码块的末尾

All the above motions work with Normal, Visual, and Operator-pending modes, so:

以上所有动作都适用于正常、视觉和操作员待定模式,因此:

  • d]%- delete until the end of the current block
  • v]%d- should do the same, going through Visual mode so that you can see what is being deleted
  • V]%d- above, but with line selection
  • d]%- 删除直到当前块的结尾
  • v]%d- 应该做同样的事情,通过可视化模式,以便您可以看到正在删除的内容
  • V]%d- 以上,但有行选择

回答by tzot

It's very easy to move indented blocks when you have set foldmethod=indent. For example, if you're on the def main():line in the following snippet:

当您有set foldmethod=indent. 例如,如果您def main():在以下代码段中的行:

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

if __name__ == "__main__": main()

then djtakes the whole main function and it can be pasted elsewhere.

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

回答by Randy Morris

To address your final paragraph, the following script defines a new "indent" text-object that you can perform actions on. For instance, diideletes everything indented at the same level as the line the cursor is on.

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

See the plugin's documentation for more info: http://www.vim.org/scripts/script.php?script_id=3037

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