patch-smie.el 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. ;;; Hack around SMIE
  2. ;;; This was intended to fix some undesirable behaviour related to forced alignment in indentation with Lua.
  3. ;;; See https://github.com/immerrr/lua-mode/issues/31.
  4. ;;; 2017-10-27: Not sure this is still valid.
  5. (require 'smie)
  6. (defcustom smie-align nil "Whether to align function arguments.")
  7. (defun smie-indent-exps ()
  8. "Indentation of sequences of simple expressions without intervening keywords or operators.
  9. E.g. 'a b c' or `g (balbla) f'. Can be a list of expressions or a
  10. function call. If it's a function call, the first element is
  11. special (it's the function). We distinguish function calls from
  12. mere lists of expressions based on whether the preceding token is
  13. listed in the `list-intro' entry of smie-indent-rules.
  14. Overload original `smie-indent-exps': make alignment customizable
  15. in `smie-align'."
  16. ;; TODO: to indent Lisp code, we should add a way to specify
  17. ;; particular indentation for particular args depending on the
  18. ;; function (which would require always skipping back until the
  19. ;; function).
  20. ;; TODO: to indent C code, such as "if (...) {...}" we might need
  21. ;; to add similar indentation hooks for particular positions, but
  22. ;; based on the preceding token rather than based on the first exp.
  23. (save-excursion
  24. (let ((positions nil)
  25. arg)
  26. (while (and (null (car (smie-backward-sexp)))
  27. (push (point) positions)
  28. (not (smie-indent--bolp))))
  29. (save-excursion
  30. ;; Figure out if the atom we just skipped is an argument rather
  31. ;; than a function.
  32. (setq arg
  33. (or (null (car (smie-backward-sexp)))
  34. (funcall smie-rules-function :list-intro
  35. (funcall smie-backward-token-function)))))
  36. (cond
  37. ((null positions)
  38. ;; We're the first expression of the list. In that case, the
  39. ;; indentation should be (have been) determined by its context.
  40. nil)
  41. (arg
  42. ;; There's a previous element, and it's not special (it's not
  43. ;; the function), so let's just align with that one.
  44. (goto-char (car positions))
  45. (current-column))
  46. ((cdr positions)
  47. ;; We skipped some args plus the function and bumped into something.
  48. (if (not smie-align)
  49. ;; Indent once.
  50. (+ (smie-indent--offset 'args) (current-column))
  51. ;; Align with the first arg.
  52. (goto-char (cadr positions))
  53. (current-column)))
  54. (positions
  55. ;; We're the first arg.
  56. (goto-char (car positions))
  57. (+ (smie-indent--offset 'args)
  58. ;; We used to use (smie-indent-virtual), but that
  59. ;; doesn't seem right since it might then indent args less than
  60. ;; the function itself.
  61. (current-column)))))))
  62. (provide 'patch-smie)