emacs上的多行python缩进

emacs上的多行python缩进,python,emacs,elisp,indentation,Python,Emacs,Elisp,Indentation,我是一个emacs新手,我希望emacs能够像这样缩进我的代码 egg = spam.foooooo('vivivivivivivivivi')\ .foooooo('emacs', 'emacs', 'emacs', 'emacs') 默认情况下无法自动执行此操作(无需手动插入空格或C-C>),因为emacs总是缩进4个空格(除非Im在多行上拆分多个参数) 最好的方法是什么 PS:如果这是一个坏主意(反对PEP 8或其他东西),请告诉我这很难看,需要您编写一些emacs

我是一个emacs新手,我希望emacs能够像这样缩进我的代码

egg = spam.foooooo('vivivivivivivivivi')\
          .foooooo('emacs', 'emacs', 'emacs', 'emacs')
默认情况下无法自动执行此操作(无需手动插入空格或C-C>),因为emacs总是缩进4个空格(除非Im在多行上拆分多个参数)

最好的方法是什么


PS:如果这是一个坏主意(反对PEP 8或其他东西),请告诉我这很难看,需要您编写一些emacs lisp。我需要学习emacs lisp,所以如果它不是那么难看的话,我可能会去做。但它是,我不是。看起来您可以学习emacs lisp:)(如果您真的想这样做的话)。我有点嫉妒。无论如何,你说告诉你这是一个坏主意是一个可以接受的答案,因此:

这是一个糟糕的文体选择。不是吗

egg = spam.foo('viviviv')
egg = egg.foo('emacs', 'emacs', 'emacs')
更容易阅读


虽然不是专门针对PEP 8,但提到行连续字符的使用应保持在最低限度。而且,这最明确、最客观地违背了政治公众人物8号的精神。我只是不知道怎么做;)

我同意Aaron关于您的风格选择的可取性的观点,但我也同意他关于Emacs Lisp很有趣的观点,因此我将描述您可能如何实现这一点

Emacs
python模式
计算函数中一行的缩进,用于处理连续行的相关部分被深埋在函数中,没有简单的配置方法

因此,我们有两种选择:

  • 将整个
    python计算缩进
    替换为我们自己的版本(每当
    python模式
    发生变化时,这将是一场维护噩梦);或
  • “”函数
    python calculate indentation
    :也就是说,将其封装在我们自己的函数中,该函数处理我们感兴趣的情况,否则将遵从原始的情况
  • 在这种情况下,选项(2)似乎是可行的。所以,让我们努力吧!首先要做的是阅读建议,建议我们的建议如下:

    (defadvice python-calculate-indentation (around continuation-with-dot)
      "Handle continuation lines that start with a dot and try to
    line them up with a dot in the line they continue from."
      (unless 
          (this-line-is-a-dotted-continuation-line) ; (TODO)
        ad-do-it))
    
    这里的
    ad do it
    是一个神奇的标记,
    defadvice
    用原始函数替代。来自Python背景的您可能会问,“为什么不使用这种装饰风格?”Emacs建议机制的设计(1)是为了使建议与原始建议保持良好的分离;(2)针对单个功能提供多条不需要合作的建议;(3) 允许您单独控制打开和关闭哪些建议。您当然可以想象用Python编写类似的东西

    下面是如何判断当前行是否是虚线延续线:

    (beginning-of-line)
    (when (and (python-continuation-line-p)
               (looking-at "\\s-*\\."))
        ;; Yup, it's a dotted continuation line. (TODO)
        ...)
    
    这有一个问题:调用
    行的开头实际上将点移动到行的开头。哎呀。我们不想在仅仅计算缩进时移动点。所以我们最好在电话中总结一下,以确保这一点不会偏离正轨

    我们可以通过向后跳过标记或括号表达式(Lisp称之为“S表达式”或“sexps”)找到需要对齐的点,直到找到点,或者到达语句的开头。在缓冲区的受限部分中执行搜索的一个好的Emacs习惯用法是,将缓冲区设置为只包含我们想要的部分:

    (narrow-to-region (point)
                      (save-excursion
                        (end-of-line -1)
                        (python-beginning-of-statement)
                        (point)))
    
    然后继续向后跳过sexps,直到找到点,或者直到
    向后sexp
    停止前进:

    (let ((p -1))
      (while (/= p (point))
        (setq p (point))
        (when (looking-back "\\.")
          ;; Found the dot to line up with.
          (setq ad-return-value (1- (current-column)))
          ;; Stop searching backward and report success (TODO)
          ...)
        (backward-sexp)))
    
    这里,
    ad返回值
    是一个神奇的变量,
    defadvice
    用于建议函数的返回值。丑陋但实用

    现在有两个问题。首先,在某些情况下,
    backward sexp
    可能会发出错误信号,因此我们最好捕获该错误:

    (ignore-errors (backward-sexp))
    
    另一个问题是打破循环,也表明成功。通过声明一个命名的
    ,然后从
    调用
    返回,我们可以同时执行这两项操作。是常见的Lisp功能,因此我们需要
    (要求'cl)

    让我们把它们放在一起:

    (require 'cl)
    
    (defadvice python-calculate-indentation (around continuation-with-dot)
      "Handle continuation lines that start with a dot and try to
    line them up with a dot in the line they continue from."
      (unless 
          (block 'found-dot
            (save-excursion
              (beginning-of-line)
              (when (and (python-continuation-line-p)
                         (looking-at "\\s-*\\."))
                (save-restriction
                  ;; Handle dotted continuation line.
                  (narrow-to-region (point)
                                    (save-excursion
                                      (end-of-line -1)
                                      (python-beginning-of-statement)
                                      (point)))
                  ;; Move backwards until we find a dot or can't move backwards
                  ;; any more (e.g. because we hit a containing bracket)
                  (let ((p -1))
                    (while (/= p (point))
                      (setq p (point))
                      (when (looking-back "\\.")
                        (setq ad-return-value (1- (current-column)))
                        (return-from 'found-dot t))
                      (ignore-errors (backward-sexp))))))))
        ;; Use original indentation.
        ad-do-it))
    
    (ad-activate 'python-calculate-indentation)
    

    我不会说这是实现这一点的最佳方法,但它展示了一系列中等难度的Emacs和Lisp特性:。享受吧

    我同意这是非常有风格的:)。我也想到了你的建议。看来我必须更新我的问题,以询问更多关于样式的意见。算了吧。实质重于风格。如果我想学习PEP 8,我会遵循你的答案。我解释了如何在Emacs中实现所需的缩进。任何人都不应该实际使用它。最好将您的
    spam.foooo(…)
    放在括号内:
    egg=(spam.fooo…
    )。这样,您就不需要继续标记(还有其他优点)。这是一种糟糕的样式。第二个Fooooo方法通常与垃圾邮件无关,正如对齐所建议的那样,而是与第一个Fooooo返回的内容有关。在
    之后打断(
    或在
    中的一个之后打断更为惯用(在任何一种情况下,您都不必使用``因为自动括号继续).1.+10如果可以的话,因为这绝对值得一个“好答案”徽章。谢谢。我担心Emacs有点少数派的味道。现在如果是Eclipse…这里有大量的答案。写得很好的教程,有很好的链接。我不认为我会很快尝试这个,但thx很多。应该投票更多。对不起,aaronasterling,我更改了它,所以这就是答案。不过我确实投票支持你