3

I'm trying to implement qmake-mode using SMIE(https://www.gnu.org/software/emacs/manual/html_node/elisp/SMIE.html), but I have no idea how to control indent width in line-continuation. Block indentation works(yes, I stole block indentation from sh-script.sh(sh-mode))

For example, I expect this

SOURCES += a.cpp \
    b.cpp

rather than

SOURCES += a.cpp \
        b.cpp

Here is brief code:

(defconst qmake-smie-grammar  
  (smie-prec2->grammar
   (smie-bnf->prec2
    '((var)
      (value)
      (exp (var "+=" value)
           (var "=" value)
           (var "-=" value))
      (inst (exp "||" exp)
            (exp "&&" exp))
      (insts (inst ";" insts)))
    '((assoc "+=" "=" "-="))
    '((assoc "||" "&&"))
    '((assoc ";"))
    )))

(defun qmake-smie-backward-token ()
  (let ((bol (line-beginning-position))
        pos tok)
    (forward-comment (- (point)))
    (cond
     ((< (point) bol)
      (cond
       ((qmake-smie--looking-back-at-continuation-p)
        (forward-char -1)
        (funcall smie-backward-token-function))
       ((qmake-smie--newline-semi-p) ";")
       (t (funcall smie-backward-token-function))))
     (t tok))))

(defun qmake-smie-rules (kind token)
  (pcase (cons kind token)
    (`(:elem . basic) qmake-indentation)
    ((and `(:before . ,_)
          (guard (when qmake-indent-after-continuation
                   (save-excursion
                     (ignore-errors
                       (skip-chars-backward " \t")
                       (qmake-smie--looking-back-at-continuation-p))))))
     ;; After a line-continuation, make sure the rest is indented.
     (let* ((qmake-indent-after-continuation nil)
            (indent (smie-indent-calculate))
            (initial (qmake-smie--continuation-start-indent)))
       (when (and (numberp indent) (numberp initial)
                  (<= indent initial))
         `(column . ,(+ initial qmake-indentation)))))
    (`(:before . ,(or `"(" `"{" `"["))
     (if (smie-rule-hanging-p) (smie-rule-parent)))))

Here is full code: https://gist.github.com/inlinechan/2ff5194d06cfcfb34016

Drew
  • 75,699
  • 9
  • 109
  • 225
Chan
  • 33
  • 3

1 Answers1

2

Check the code that uses sh-indent-after-continuation since that's the config variable that decides how continued lines should be indented. You'll probably want to look at the following change I installed recently:

commit d6b49570f6fe1cfb5314c1b61b81ede0497a06b2
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Date:   Tue Sep 29 21:43:07 2015 -0400

    * lisp/progmodes/sh-script.el: Old "dumb" continued line indent

    (sh-indent-after-continuation): Add new value `always' (bug#17620)
    (sh-smie-sh-rules): Remove old handling of continued lines.
    (sh-smie--indent-continuation): New function.
    (sh-set-shell): Use it.
Stefan
  • 26,154
  • 3
  • 46
  • 84
  • Thanks you for your answer. But, I should have asked "how to implement indentation both in line-continuation and block". After I post my question and look into this problem few days, I found that it's impossible to get indentation just work out of box by using SMIE with little effort. After all, I implemented custom indent function without SMIE. I like to share my implementation https://github.com/inlinechan/qmake-mode – Chan Nov 11 '15 at 12:18
  • I don't know what means "indentation both in line-continuation and block". Of course SMIE is no silver bullet. In my experience, the main benefit of SMIE is that it helps *structure* the indentation code (which otherwise tends to quickly become an unmanageable mess). – Stefan Nov 15 '15 at 23:36