【问题标题】:Emacs: Altering python.el indentation in derived modeEmacs:在派生模式下更改 python.el 缩进
【发布时间】:2014-02-15 17:08:03
【问题描述】:

我正在尝试从 python.el(当前的官方 gnu one)为 Boo 派生一个新的 emacs 模式,但我在更改缩进时遇到了麻烦。有人对如何最好地处理这个问题有任何建议吗?我不需要彻底改变任何东西,只需添加一些新的块形式和东西。

例如,由于这是针对 Boo,try/except 语法使用“ensure”而不是“finally”。我可以通过更改 python-rx-constituents 的 block-start def 在 python.el 中轻松更改这一点。但是,我似乎无法在派生模式下覆盖它,因为 python-rx-constituents 正在被宏 python-rx 使用,我猜一旦在 python.el 加载时定义了这两个东西(因为它必须,因为我是从它派生的),我不能再在加载后或在钩子中覆盖它?因为我肯定在 python.el 加载后的内存和钩子中以及在加载后的语句中更改了它,但它们都不起作用。虽然直接改变 python.el 工作正常。

这是来自 python.el 的代码:

(eval-when-compile
  (defconst python-rx-constituents
    `((block-start          . ,(rx symbol-start
                                   (or "def" "class" "if" "elif" "else" "try"
                                       "except" "finally" "for" "while" "with"
                                       )
                                   symbol-end))
      (decorator            . ,(rx line-start (* space) ?@ (any letter ?_)
                                   (* (any word ?_))))
      (defun                . ,(rx symbol-start (or "def" "class") symbol-end))
      (if-name-main         . ,(rx line-start "if" (+ space) "__name__"
                                   (+ space) "==" (+ space)
                                   (any ?' ?\") "__main__" (any ?' ?\")
                                   (* space) ?:))
      (symbol-name          . ,(rx (any letter ?_) (* (any word ?_))))
      (open-paren           . ,(rx (or "{" "[" "(")))
      (close-paren          . ,(rx (or "}" "]" ")")))
      (simple-operator      . ,(rx (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%)))
      ;; FIXME: rx should support (not simple-operator).
      (not-simple-operator  . ,(rx
                                (not
                                 (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%))))
      ;; FIXME: Use regexp-opt.
      (operator             . ,(rx (or "+" "-" "/" "&" "^" "~" "|" "*" "<" ">"
                                       "=" "%" "**" "//" "<<" ">>" "<=" "!="
                                       "==" ">=" "is" "not")))
      ;; FIXME: Use regexp-opt.
      (assignment-operator  . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**="
                                       ">>=" "<<=" "&=" "^=" "|=")))
      (string-delimiter . ,(rx (and
                                ;; Match even number of backslashes.
                                (or (not (any ?\\ ?\' ?\")) point
                                    ;; Quotes might be preceded by a escaped quote.
                                    (and (or (not (any ?\\)) point) ?\\
                                         (* ?\\ ?\\) (any ?\' ?\")))
                                (* ?\\ ?\\)
                                ;; Match single or triple quotes of any kind.
                                (group (or  "\"" "\"\"\"" "'" "'''"))))))
    "Additional Python specific sexps for `python-rx'")

  (defmacro python-rx (&rest regexps)
    "Python mode specialized rx macro.
This variant of `rx' supports common python named REGEXPS."
    (let ((rx-constituents (append python-rx-constituents rx-constituents)))
      (cond ((null regexps)
             (error "No regexp"))
            ((cdr regexps)
             (rx-to-string `(and ,@regexps) t))
            (t
             (rx-to-string (car regexps) t))))))

我想更改 python-rx-constituents 以便 block-start 包含“ensure”而不是 finally。

【问题讨论】:

  • 派生模式似乎不适合这里。为什么不直接复制文件,存储为 boo.el,将前缀替换为“boo-”,重新加载并编辑需要更改的内容?
  • 这实际上正是我在第一次尝试时所做的,Andreas,它运行良好。但是,我想“清理它”以便我可以发布它的源代码,并且我认为从现有模式派生将是版权和归属等更好的方式。现在我只是很困惑为什么当我覆盖变量和宏时似乎什么都没有发生。值已更改,但没有明显效果。
  • 实际的问题是在编译python.el的过程中,正则表达式是由python-rx-macro生成的,然后直接作为字符串合并到源代码中。实际缩进在python-indent-calculate-indentation 中计算。在python-indent-context 中检测到状态after-beginning-of-block,您可以在函数定义中直接调用(python-rx block-start)python-rx-constituents的变量定义也封装在eval-when-compile中。
  • 托拜厄斯,谢谢!如果我不编译代码而是使用它解释怎么办?我认为eval-when-compile 将转换为progn,然后可以稍后覆盖宏,这样当调用python-indent-context 时,它将使用新的python-rx 宏。我想我对何时评估宏感到困惑。
  • 你是对的。 progn 解释。也适用于load-library

标签: python emacs elisp boo python.el


【解决方案1】:

正如已经评论的那样,在这里使用派生模式不适合:您不能反向更改宏。也不建议重新定义它:加载/评估的顺序将决定哪个有效 - 在更大的范围内,这意味着会陷入混乱。

复制文件,存储为 boo.el,将前缀替换为“boo-”,重新加载并编辑需要更改的内容。

您对 IMO 表达的担忧是没有道理的,因为允许复制、更改和重新发布更改后的代码是 GPL 的核心。

【讨论】:

    【解决方案2】:

    复制文件确实是个坏主意,因为跟踪 python.el 的演变会很痛苦。 推导也不是一个好主意,因为 Boo 并不是 Python 的真正扩展或变体,因此您可能希望重用它的一些缩进机制和它的一些代码来理解显着缩进,但仅此而已比那个。

    您可能想联系 python.el 的作者(抄送至 emacs-devel),看看是否可以调整 python.el 以使您的生活更轻松。例如也许将公共代码提取到可以在两者之间共享的辅助文件中。理想情况下,此文件可能可用于 cofferscript-mode 和 Haskell-mode。

    【讨论】:

      猜你喜欢
      • 2014-04-07
      • 2011-05-09
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多