ambevar-dotfiles/.emacs.d/lisp/patch-smie.el

68 lines
2.8 KiB
EmacsLisp

;;; Hack around SMIE
;;; This was intended to fix some undesirable behaviour related to forced alignment in indentation with Lua.
;;; See https://github.com/immerrr/lua-mode/issues/31.
;;; 2017-10-27: Not sure this is still valid.
(require 'smie)
(defcustom smie-align nil "Whether to align function arguments.")
(defun smie-indent-exps ()
"Indentation of sequences of simple expressions without intervening keywords or operators.
E.g. 'a b c' or `g (balbla) f'. Can be a list of expressions or a
function call. If it's a function call, the first element is
special (it's the function). We distinguish function calls from
mere lists of expressions based on whether the preceding token is
listed in the `list-intro' entry of smie-indent-rules.
Overload original `smie-indent-exps': make alignment customizable
in `smie-align'."
;; TODO: to indent Lisp code, we should add a way to specify
;; particular indentation for particular args depending on the
;; function (which would require always skipping back until the
;; function).
;; TODO: to indent C code, such as "if (...) {...}" we might need
;; to add similar indentation hooks for particular positions, but
;; based on the preceding token rather than based on the first exp.
(save-excursion
(let ((positions nil)
arg)
(while (and (null (car (smie-backward-sexp)))
(push (point) positions)
(not (smie-indent--bolp))))
(save-excursion
;; Figure out if the atom we just skipped is an argument rather
;; than a function.
(setq arg
(or (null (car (smie-backward-sexp)))
(funcall smie-rules-function :list-intro
(funcall smie-backward-token-function)))))
(cond
((null positions)
;; We're the first expression of the list. In that case, the
;; indentation should be (have been) determined by its context.
nil)
(arg
;; There's a previous element, and it's not special (it's not
;; the function), so let's just align with that one.
(goto-char (car positions))
(current-column))
((cdr positions)
;; We skipped some args plus the function and bumped into something.
(if (not smie-align)
;; Indent once.
(+ (smie-indent--offset 'args) (current-column))
;; Align with the first arg.
(goto-char (cadr positions))
(current-column)))
(positions
;; We're the first arg.
(goto-char (car positions))
(+ (smie-indent--offset 'args)
;; We used to use (smie-indent-virtual), but that
;; doesn't seem right since it might then indent args less than
;; the function itself.
(current-column)))))))
(provide 'patch-smie)