简体   繁体   English

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

[英]More efficient movements editing python files in vim

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.我想四处走动并使用熟悉的 vim 动作编辑此文件。 For instance, using (, ), [[, ]], {, } or deleting/yanking/changing text using commands like di}.例如,使用 (, ), [[, ]], {, } 或使用 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.在其他语言(如 C++、Java、C# 等)中,花括号比比皆是,因此使用 di} 之类的动作可以轻松找到匹配的花括号并作用于该块。 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.事实上,如果我在上述文本的 'b' 字符上并在 vim 中执行 di),它会成功删除两个括号之间的文本。

The issue is in python's detection of code blocks, I think.我认为问题在于python对代码块的检测。 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.使用 (, ), [[, ]], {, or } 作为动作几乎都做同样的事情,带你到开始(在 def 行之上或之上)或结束(在函数的最后一行之后)功能。 And there is no way, as far as I know, to easily tell vim "select everything for this indentation block."据我所知,没有办法轻松地告诉 vim“选择这个缩进块的所有内容”。 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).在上面的示例中,我想在 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).我确信应该可以告诉 vim 在缩进的基础上进行这样的动作(好吧,也许不是那个特定的动作,而是一些用户定义的动作)。 Any thoughts on how to accomplish this?关于如何做到这一点的任何想法?

Square Bracket Mappings [[ , ]] , [m , ]m and similar方括号映射[[ , ]] , [m , ]m和类似的

$VIMRUNTIME/ftplugin/python.vim now (2018) remaps all builtin mappings documented under :h ]] and :h ]m for the python language. $VIMRUNTIME/ftplugin/python.vim now (2018) 重新映射记录在:h ]]:h ]m下的所有内置映射,用于 python 语言。 The mappings are:映射是:

]] 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 .如果你还没有这个文件的新版本,你可以下载它并把它放到~/.vim/ftplugin/python.vim中。 This folder takes precedence before $VIMRUNTIME/ftplugin .此文件夹优先于$VIMRUNTIME/ftplugin

Before these mappings have been added to $VIMRUNTIME , there has been the plugin python-mode which provides [[ , ]] , [M , and ]M .在将这些映射添加到$VIMRUNTIME之前,有一个插件python-mode提供[[ , ]][M]M In addition python-mode also defines the text objects aC , iC , aM , and iM :此外python-mode还定义了文本对象aCiCaMiM

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

All details and examples are given at https://github.com/jeetsukumaran/vim-pythonsense#stock-vim-vs-pythonsense-motions .所有详细信息和示例都在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).此外,该插件还定义了文本对象ic/ac (类)、 if/af (函数)、 id/ad (文档字符串)。

Neovim & nvim-treesitter-textobjects Neovim & nvim-treesitter-textobjects

For neovim, you can use treesitter and the neovim plugin nvim-treesitter-textobjects .对于neovim,您可以使用treesitter 和neovim 插件nvim-treesitter-textobjects

Textobjects if/af & ic / ac文本对象if/af & ic / ac

These are not contained in $VIMRUNTIME/ftplugin/python.vim but are provided by a few plugins这些不包含在$VIMRUNTIME/ftplugin/python.vim中,但由一些插件提供

For a discussion about textobjects for python see what's the fastest way to select a function of Python via VIM?有关 python 文本对象的讨论,请参阅通过 VIM 选择 Python 函数的最快方法是什么? . .

python.vim 蟒蛇.vim

Makes it much easier to navigate around python code blocks.使浏览 python 代码块变得更加容易。

Shortcuts:捷径:

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

python_match.vim python_match.vim

extends % :扩展%

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

All the above motions work with Normal, Visual, and Operator-pending modes, so:上述所有动作都适用于正常、视觉和操作员挂起模式,因此:

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

It's very easy to move indented blocks when you have set foldmethod=indent . set foldmethod=indent后,移动缩进块非常容易。 For example, if you're on the def main(): line in the following snippet:例如,如果您在以下代码段中的def main():行:

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

if __name__ == "__main__": main()

then dj takes the whole main function and it can be pasted elsewhere.然后dj获取整个 main 函数,它可以粘贴到其他地方。

To address your final paragraph, the following script defines a new "indent" text-object that you can perform actions on.为了解决您的最后一段,以下脚本定义了一个新的“缩进”文本对象,您可以对其执行操作。 For instance, d i i deletes everything indented at the same level as the line the cursor is on.例如, d i i删除与光标所在行同级缩进的所有内容。

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

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

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