I'd like to change use-package's indentation style to look more distinguishable, (more or less) similar like the following indentation style:

(use-package foo
  :commands (gah)
  :init (setq f 1)
        (blubb g 2)

    (blah h 3)
    (moo i 4))

This means, keywords should be indented normal but all following options to such a keyword, should be indented a bit more and should align vertically.

I already know, that it is possible to define a function to calculate the current indentation column. Per default it is set to standard defun indentation:

(get 'use-package 'lisp-indent-function)
; → defun

The following function definition and set up of property, changes that, but I struggle with the implementation details of function my-use-package-indent-function.

(defun my-use-package-indent-function (indent-point state)
  (let* ((normal-indent (current-column))
        (indent-offset (progn (back-to-indentation)
    (goto-char indent-point)
    (if (eq ?: (char-after))
        (+ indent-offset 2)
      (+ indent-offset 5))))
(put 'use-package 'lisp-indent-function #'my-use-package-indent-function)

Above is a naive, incomplete version, but how to calculate the indentation value properly?


Since no one came up with an answer, I stepped with the debugger through the process of indenting and came up with following code.

(defun my--use-package-indent-function (indent-point state)
  "custom indentation rules for use-package s-exps.

`;;!' indents to same level as keywords
for some reason `;;;' won't be indented at all"
  (let ((indent-offset (progn (back-to-indentation)
    (goto-char indent-point)
    (cond ((eq ?: (char-after))
           (+ indent-offset 2))
          ((and (eq ?\; (char-after)) (eq ?! (char-after (+ (point) 2))))
           (+ indent-offset 2))
          ((eq ?\) (char-after))
           (+ indent-offset 2))
          ((eq ?: (progn (backward-sexp)
           (+ indent-offset (+ 2 4)))
          (t (current-column )))))

(put 'use-package 'lisp-indent-function #'my--use-package-indent-function)

It seems to work, but I'm unsure how robust this code is.

Better implementations are welcome!

Edit: following code sets up electric indent to trigger on ':', so keywords will be indented right at insertion.

(setq electric-indent-chars (append electric-indent-chars '(?:)))

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.