在网络模式下 - 如何将右大括号和括号拉到开头行的缩进级别

In web-mode - how to pull closing braces and parenthesis to indentation level of opening line

在大多数 emacs 模式中,当在块的末尾键入右大括号时,大括号会自动拉回其相应开始行的缩进级别。例如,输入以下内容后:

int main(int argc, char* argv[]) {
    // stuff
    }

右大括号向左拉回:

int main(int argc, char* argv[]) {
    // stuff
}   // <---- pulled back with no additional input

然而,当使用网络模式时,情况并非如此,至少在默认设置下是这样。直到有某些额外的输入,例如当光标位于右大括号所在的行时按 Tab 或 Enter。这不适用于在添加任何块内容之前添加右括号的编码风格,这在 emacs 中用 C 编码时效果很好(具体来说,我的意思是键入“{enter enter} C-p”)。在这个序列中,没有什么可以触发右大括号向后拉一个缩进级别,所以我的代码如下所示:

class Header extends React.Component {
    render() {
        return (
            <div></div>
            );
        }
    }

除非我在该序列中添加一个 Tab 键(“{ enter enter } tab C-p”)。

我知道这只是一个键,我可以改变我的习惯,但是有没有办法改变 emacs 的行为呢?我在网络模式 documentation 中没有看到任何相关变量需要更改,但我是否遗漏了什么?

编辑: 在对 emacs 的了解比我想象的要多得多之后,我意识到我正在寻找的实际上是 cc-mode 的一个特定功能。在 cc-mode 中,} 绑定到 c-electric-brace。来自消息来源:

(defun c-electric-brace (arg)
  "Insert a brace.

If `c-electric-flag' is non-nil, the brace is not inside a literal and a
numeric ARG hasn't been supplied, the command performs several electric
actions:

\(a) If the auto-newline feature is turned on (indicated by \"/la\" on
the mode line) newlines are inserted before and after the brace as
directed by the settings in `c-hanging-braces-alist'.

\(b) Any auto-newlines are indented.  The original line is also
reindented unless `c-syntactic-indentation' is nil.

\(c) If auto-newline is turned on, various newline cleanups based on the
settings of `c-cleanup-list' are done."

所以看来要在网络模式下获得此功能,我需要学习一些 lisp 并提交 PR。这就是我要做的,并将在此处提交答案 if/when 我完成了。与此同时,我仍然喜欢任何对此有更多了解的人的意见。

使用 web-mode.el 中的 defun 尝试:

(local-set-key (kbd "RET") 'newline-and-indent)

所以我最终确实提交了一个带有这个特性的 PR,但是维护者显然有同样的想法并把它合并到自己身上。它从 v14.0.36 开始运行(提交 3e74b74)。

正如我在对问题的编辑中所述,c-electric-brace 是一个键绑定,所以效果是立竿见影的。这在可能很容易 enabled/disabled 的情况下更难实现,因此在 web-mode 中,它被添加为 post-command 钩子。因此,如果启用 show-paren-mode,它会在 after 闪烁匹配的 parenthesis/brace/bracket 后发生。因此有一个短暂的延迟。

默认情况下,当 web-mode-enable-auto-indentation 设置为 t 时启用此效果。这是相关代码(合并添加,不是我的):

(when (and web-mode-enable-auto-indentation
           (member this-command '(self-insert-command))
           (member (get-text-property (point) 'part-side) '(javascript jsx))
           (looking-back "^[ \t]+[]})]"))
  (indent-according-to-mode)
  ;;(message "%S" (point))
  (when (and web-mode-change-end (> web-mode-change-end (point-max)))
    (message "post-command: enlarge web-mode-change-end")
    (setq web-mode-change-end (point-max))
  )
)