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

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.
  • 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 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

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.