1

Given the file test.c:

int main()
{
    if (a)
        foo();
    else
    if (b)      // line 6
        bar();
    else
        baz();
}

Whenever a comma or paren is typed while point is on line 6 (second if), Emacs reindents the line one indent level deeper, i.e.:

int main()
{
    if (a)
        foo();
    else
        if (b)
        bar();
    else
        baz();
}

Is there any way to disable this annoying behaviour just for this situation?

  • I'm aware that I could use else if on one line instead of putting else and if on separate lines. However:
    • I don't like this style, as the if conditions are no longer aligned
    • I'm working on existing projects with an existing code style
    • The editor should not dictate the code style anyway.
  • I'm aware that I could disable electric indentation entirely, however this disables useful behaviour such as correct indentation after typing { and }.
  • The Emacs manual lists which characters trigger electric indentation:

    The electric characters are {, }, :, #, ;, ,, <, >, /, *, (, and ).

    However, there is no mention of any way to customizing them. I think leaving just { and } would be fine.

  • 1
    FWIW, your code is very unusual. The "normal" way to write it is to keep else if on the same line. Then the indentation code will do the right thing. – Stefan Feb 25 '17 at 13:44
  • Stefan, thanks for your suggestion, but as I already wrote in the question, I'm aware of that workaround, and I've already listed why I'm looking for a better solution. – Vladimir Panteleev Feb 25 '17 at 14:17
  • You should probably put your code sample at the bottom of the question, as the uncommon style is distracting and makes it less likely that people will see what you're actually asking about. – npostavs Feb 25 '17 at 14:20
  • Normally, the set of triggering chars is specified in electric-indent-chars, but IIRC cc-mode doesn't obey this yet. I suggest you report this as a bug with M-x report-emacs-bug RET. – Stefan Feb 25 '17 at 14:27
2

You could make c-mode follow your style like this:

(defun lineup-if-with-else (context)
  (pcase context
    (`(substatement . ,anchor)
     (save-excursion
       (back-to-indentation)
       (when (looking-at-p "if\\_>")
         (goto-char anchor)
         (when (looking-at-p "else\\_>")
           0))))))

(defun my-c-mode-hook ()
  "My `c-mode' hook."
  (c-set-offset 'substatement '(lineup-if-with-else +)))
(add-hook 'c-mode-hook 'my-c-mode-hook)
  • Thanks. However, this reindents lines where it does make to have the if indented. It would be preferable to just not change indentation in such ambiguous cases, and leave it to the user. – Vladimir Panteleev Feb 25 '17 at 14:23
  • Not sure which cases you're talking about, but you can certainly modify lineup-if-with-else to be more conservative. – npostavs Feb 25 '17 at 14:55
2

I guess one way is to simply unmap the undesired keys from the mode's keymap:

(eval-when-compile
  (require 'cc-mode))
(defun my-c-mode-hook ()
  "My `c-mode' hook."
  (define-key c-mode-map (kbd ",") nil)
  (define-key c-mode-map (kbd "(") nil)
  (define-key c-mode-map (kbd ")") nil))
(add-hook 'c-mode-hook 'my-c-mode-hook)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.