emacs 上的多行 python 缩进
我是一个 emacs 新手,我希望 emacs 能够像这样缩进我的代码
egg = spam.foooooo('vivivivivivivivivi')\
.foooooo('emacs', 'emacs', 'emacs', 'emacs')
默认情况下不可能自动执行此操作(无需手动插入空格或抄送>),因为 emacs 总是缩进 4 个空格(除非我将多个参数拆分为多行)。
执行此操作的最佳方法是什么?
PS:如果这是一个坏主意(针对 PEP 8 或其他),请告诉我
Im an emacs newbie, I want emacs to be able to indent my code like this
egg = spam.foooooo('vivivivivivivivivi')\
.foooooo('emacs', 'emacs', 'emacs', 'emacs')
It's not possible to do this automatically by default (without manually inserting spaces or C-c >), since emacs always indents 4 spaces (unless Im splitting multiple arguments over multiple lines).
Whats the best approach to do this?
PS: If this is a bad idea (against PEP 8 or something) please do tell me
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我同意 Aaron 关于您风格选择的可取性的观点,但由于我也同意他的观点,即 Emacs Lisp 很有趣,所以我将描述您如何实现这一点。
Emacs
python-mode
计算函数python-calculate-indentation
以及相关部分处理连续线被深埋在函数内部,没有简单的方法来配置它。所以我们有两个选择:
python-calculate-indentation
(每当python-mode
改变时维护噩梦);或python-calculate-indentation
:也就是说,将其包装在我们自己的函数中来处理我们感兴趣的情况,否则遵循原始函数。在这种情况下,选项(2)似乎是可行的。那么让我们一起努力吧!首先要做的是阅读建议手册< /a> 这表明我们的建议应该如下所示:
这里
ad-do-it
是一个神奇的标记,defadvice
用原始函数替换。来自 Python 背景的你可能会问,“为什么不采用这种装饰器风格呢?” Emacs 建议机制的设计目的是 (1) 将建议与原始建议很好地分开; (2) 为单个功能提供多个不需要合作的建议; (3) 允许您单独控制打开和关闭哪些建议。您当然可以想象用 Python 编写类似的东西。以下是如何判断当前行是否为虚线续行:
这样做有一个问题:对
beginning-of-line
的调用实际上将指向移动到行的开头。哎呀。我们不想在仅仅计算缩进时移动点。因此,我们最好将其包装在对save- 的调用中游览
以确保该点不会漂移。我们可以通过向后跳过标记或括号表达式(Lisp 称之为“S 表达式”或“sexps”)来找到需要对齐的点,直到找到该点,或者到达该点的开头。陈述。在缓冲区的受限部分进行搜索的一个很好的 Emacs 惯用法是 缩小缓冲区以仅包含我们想要的部分:
然后继续向后跳过 sexp,直到找到点,或者直到
backward-sexp
停止前进:这里
ad -return-value
是一个神奇变量,defadvice
使用它作为建议函数的返回值。丑陋但实用。现在有两个问题。第一个是 backward-sexp 在某些情况下会发出错误信号,因此我们最好捕获该错误:
另一个问题是跳出循环并指示成功。我们可以通过声明一个命名的块然后调用 return-from 来同时执行这两项操作。 阻止和退出是 Common Lisp 功能所以我们需要
(require 'cl)
让我们把它们放在一起:
我不会说这是最好的方法,但它说明了一些相当棘手的 Emacs 和 Lisp功能:建议、游览,缩小, 移过 sexps,错误处理,阻止并退出。享受!
I agree with Aaron about the desirability of your stylistic choice, but since I also agree with him that Emacs Lisp is fun, I'll describe how you might go about implementing this.
Emacs
python-mode
computes the indentation of a line in the functionpython-calculate-indentation
and the relevant section for handling continuation lines is buried deep inside the function, with no easy way to configure it.So we have two options:
python-calculate-indentation
with our own version (a maintenance nightmare wheneverpython-mode
changes); orpython-calculate-indentation
: that is, wrap it in our own function that handles the case we're interested in, and otherwise defers to the original.Option (2) seems just about doable in this case. So let's go for it! The first thing to do is to read the manual on advice which suggests that our advice should look like this:
Here
ad-do-it
is a magic token thatdefadvice
substitutes with the original function. Coming from a Python background you might well ask, "why not do this decorator-style?" The Emacs advice mechanism is designed (1) to keep advice well separated from the original; and (2) to have multiple pieces of advice for a single function that don't need to co-operate; (3) to allow you individual control over which pieces of advice are turned on and off. You could certainly imagine writing something similar in Python.Here's how to tell if the current line is a dotted continuation line:
There's one problem with this: that call to
beginning-of-line
actually moves point to the beginning of the line. Oops. We don't want to move point around when merely calculating indention. So we better wrap this up in a call tosave-excursion
to make sure that point doesn't go a-wandering.We can find the dot that we need to line up with by skipping backwards over tokens or parenthesized expressions (what Lisp calls "S-expressions" or "sexps") until either we find the dot, or else we get to the start of the statement. A good Emacs idiom for doing a search in a restricted part of the buffer is to narrow the buffer to contain just the part we want:
and then keep skipping sexps backwards until we find the dot, or until
backward-sexp
stops making progress:Here
ad-return-value
is a magic variable thatdefadvice
uses for the return value from the advised function. Ugly but practical.Now there are two problems with this. The first is that
backward-sexp
can signal an error in certain circumstances, so we better catch that error:The other problem is that of breaking out of the loop and also indicating success. We can do both at once by declaring a named
block
and then callingreturn-from
. Blocks and exits are Common Lisp features so we'll need to(require 'cl)
Let's put it all together:
I won't claim that this is the best way to do this, but it illustrates a bunch of moderately tricky Emacs and Lisp features: advice, excursions, narrowing, moving over sexps, error handling, blocks and exits. Enjoy!
这非常难看,并且需要你编写一些 emacs lisp。我需要学习 emacs lisp,所以如果它不是那么难看的话,我可能会愿意这样做。但它是,而我不是。看起来你要学习 emacs lisp :)(如果你真的想这样做的话)。我有点嫉妒。无论如何,你说过告诉你这是一个坏主意是一个可以接受的答案,所以这里是:
这是一个糟糕的风格选择。不是
更容易阅读吗?
虽然不是专门针对 PEP 8,但提到应尽量减少行继续字符的使用。另外,这最明确、最客观地违背了 PEP 8 的精神。我只是不知道怎么办;)
That's pretty ugly and would require you to write some emacs lisp. I need to learn emacs lisp so if it wasn't so ugly, I would probably be up for doing it. But it is and I'm not. Looks like you get to learn emacs lisp :) (if you actually want to do this). I'm sort of jealous. At any rate, you said that informing you that this is a bad idea was an acceptable answer so here goes:
That's a terrible stylistic choice. Isn't
easier to read?
While not specifically against PEP 8, it is mentioned that use of the line continuation character should be kept to a minimum. Also, this most definitively and objectively goes against the spirit of PEP 8. I'm just not sure how ;)