I want to write my emacs-lisp-mode modification which respects some of my preferences. In particular, I want to override indentation for vector literals.

Emacs treats vector literal as quoted list while applying indentation.

[if "emacs"
    "why do you"
  "indent things this way"]

[1 2
   3 4]

[(foo 1) ;; this one is OK without modifications
 (bar 2)
 "is good"]

I want this result:

[if "emacs"
 "why do you"
 "indent things this way"]

[1 2
 3 4]

[(foo 1) 
 (bar 2)
 "is good"]

How can I achieve this?


This is a slightly modified version of lisp-indent-function, which indents to the last indentation if

  • containing form is not a proper list (e.g. vector)
  • symbol to indent is a keyword
(defun ap/lisp-indent-function (indent-point state)
  "See `lisp-indent-function'."
  (let ((normal-indent (current-column)))
    (goto-char (1+ (elt state 1)))
    (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
    (if (or (not (eq ?\( (char-before)))
            (and (elt state 2)
                 (not (and (looking-at "\\sw\\|\\s_")
                           (not (eq ?: (char-after)))))))
        ;; indent as data
          (if (not (> (save-excursion (forward-line 1) (point))
              (progn (goto-char calculate-lisp-indent-last-sexp)
                     (parse-partial-sexp (point)
                                         calculate-lisp-indent-last-sexp 0 t)))
          ;; Indent under the list or under the first sexp on the same
          ;; line as calculate-lisp-indent-last-sexp.  Note that first
          ;; thing on that line has to be complete sexp since we are
          ;; inside the innermost containing sexp.
      ;; indent as function
      (let ((function (buffer-substring (point)
                                        (progn (forward-sexp 1) (point))))
        (setq method (or (function-get (intern-soft function)
                         (get (intern-soft function) 'lisp-indent-hook)))
        (cond ((or (eq method 'defun)
                   (and (null method)
                        (> (length function) 3)
                        (string-match "\\`def" function)))
               (lisp-indent-defform state indent-point))
              ((integerp method)
               (lisp-indent-specform method state
                                     indent-point normal-indent))
               (funcall method indent-point state)))))))

(setq-default lisp-indent-function 'ap/lisp-indent-function)
  • Maybe its just me, but this seems like emacs lacks some prettier API for tasks like this. Dropping down to character/regexp level for slight modification seems too low level and error-prone. Feb 18 '17 at 19:18

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.