Search code examples
cssemacsindentationsmie

Emacs CSS mode won't indent values across multiple lines


When a line in my CSS file appears to be too long (typically a property followed by a bunch of values), I want to split them in to several new lines like this (sorry for my low reputation):

https://i.sstatic.net/bxXvv.png

But I have to manually enter spaces before the lines to achieve that. In reality, when I hit TAB with my cursor on the url line, what I get is this:

https://i.sstatic.net/r4nxa.png

The worst thing is that, after manually inserting the spaces, when I hit TAB again on the same line, it goes back to the ugly format due to indent-region.

This is not a significant issue but it really pains me and I really hope we can have a decent solution here. Thanks in advance!

M-x version:

GNU Emacs 25.1.1 (x86_64-apple-darwin16.1.0, NS appkit-1504.60 Version 10.12.1 (Build 16B2555)) of 2016-11-27

EDIT: Also tried web-mode for css files and xah-css-mode. None of them worked out.


Solution

  • css-mode uses smie for indentation. It looks like the : in that scenario is tokenized as ":-property". One option would be changing the css-smie-rules to include another rule for indenting after that token.

    Evaluating the following redefinition seems to give the indentation you want,

    (defun css-smie-rules (kind token)
      (pcase (cons kind token)
        (`(:elem . basic) css-indent-offset)
        (`(:elem . arg) 0)
        (`(:list-intro . ,(or `";" `"")) t) ;"" stands for BOB (bug#15467).
        (`(:before . "{")
         (when (or (smie-rule-hanging-p) (smie-rule-bolp))
           (smie-backward-sexp ";")
           (smie-indent-virtual)))
        (`(:before . ,(or "{" "("))
         (if (smie-rule-hanging-p) (smie-rule-parent 0)))
        ;; *** Additional rule ***
        (`(:after . ":-property") css-indent-offset)))
    

    There is the command smie-config-show-indent that is useful to determine what indentation rules are being used at a given point.