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


November 2018


209 time


In most emacs modes, when typing a closing brace at the end of a block, the brace is automatically pulled back to the indentation level of its respective opening line. For instance, after typing the following:

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

the closing brace is pulled back to the left:

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

When using web-mode, however, this is not the case, at least with the default setup. The closing brace is not pulled back to the correct indentation until there is certain additional input, e.g. pressing tab or enter while the cursor is on the line of the closing brace. This doesn't work well with a style of coding where one adds the closing brace before adding any block content, which does work well when coding in C in emacs (specifically, I mean typing "{ enter enter } C-p"). In this sequence, there is nothing to trigger the closing braces to pull back one indent level, so my code looks like this:

class Header extends React.Component {
    render() {
        return (

unless I add a tab press to that sequence ("{ enter enter } tab C-p").

I know it's just one key, and I could just change my habits, but is there a way to change emacs' behavior instead? I don't see any relevant variables to change in web-mode's documentation, but am I missing something?

Edit: After learning a lot more about emacs than I ever thought I would, I realize that what I'm looking for is actually a specific feature of cc-mode. In cc-mode, } is bound to c-electric-brace. From the source:

(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

\(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."

So it seems that to get this feature in web-mode, I need to learn some lisp and submit a PR. That's what I'll be doing, and will submit an answer here if/when I finish. In the meantime, I'd still love input from anyone who knows more about this.

2 answers


Так что я в конечном итоге подав PR с помощью этой функции, но сопровождающий , по- видимому имел ту же самую идею и объединить его в себе. Это живой , как из v14.0.36 (совершить 3e74b74 ).

Как я уже говорил в правкой мой вопрос, с-электрическая распорка является одним из ключевых связывания, так что эффект немедленно. Это более трудно реализовать в ситуации , когда он может быть легко включить / отключить, поэтому в веб-режиме, он будет добавлен в качестве пост-команды крючке. В результате, это происходит после мигания согласования скобки / скобки / кронштейна , если шоу-скобка-режим включен. Таким образом , существует небольшая задержка.

Этот эффект включен , когда 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]+[]})]"))
  ;;(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))

используя defunот web-mode.elпопытки:

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