Function: tuareg-smie-rules
tuareg-smie-rules is a natively compiled function defined in
tuareg.el.
Signature
(tuareg-smie-rules KIND TOKEN)
Source Code
;; Defined in /nix/store/6mbh851dhnag8f92qfrlh9ckldzwf6c6-emacs-packages-deps/share/emacs/site-lisp/elpa/tuareg-20260626.936/tuareg.el
(defun tuareg-smie-rules (kind token)
;; FIXME: Handling of "= |", "with |", "function |", and "[ |" is
;; problematic.
;; FIXME: Start with (pcase (cons kind token) ...) so Edebug jumps
;; straight to the appropriate branch!
(cond
;; Special indentation for module fields.
((and (eq kind :after) (member token '("." ";"))
(smie-rule-parent-p "with")
(tuareg-smie--with-module-fields-rule)))
((and (eq kind :after) (equal token ";;"))
0)
;; Special indentation for monadic >>>, >>|, >>=, and >|= operators.
((and (eq kind :before) (tuareg-smie--monadic-rule token)))
((and (equal token "and") (smie-rule-parent-p "type"))
0)
((member token '(";" "|" "," "and" "m-and"))
(cond
((and (eq kind :before) (member token '("|" ";"))
(smie-rule-parent-p "then")
;; We have misparsed the code: TOKEN is not a child of `then' but
;; should have closed the "if E1 then E2" instead!
(tuareg-smie--if-then-hack token)))
;; FIXME: smie-rule-separator doesn't behave correctly when the separator
;; is right after the parent (on another line).
((and (smie-rule-bolp) (smie-rule-prev-p "d=" "with" "[" "function"))
(if (and (eq kind :before) (smie-rule-bolp)
(smie-rule-prev-p "[" "d=" "function"))
0 tuareg-with-indent))
((and (equal token "|") (smie-rule-bolp) (not (smie-rule-prev-p "d="))
(smie-rule-parent-p "d="))
;; FIXME: Need a comment explaining what this tries to do.
;; FIXME: Should this only apply when (eq kind :before)?
;; FIXME: Don't use smie--parent.
(when (bound-and-true-p smie--parent)
(goto-char (cadr smie--parent))
(smie-indent-forward-token)
(tuareg-skip-blank-and-comments)
`(column . ,(- (current-column) 2))))
(t (smie-rule-separator kind))))
(t
(pcase kind
(`:elem (cond
((eq token 'basic) tuareg-default-indent)
;; The default tends to indent much too deep.
((eq token 'empty-line-token) ";;")))
(`:list-intro (member token '("fun")))
(`:close-all t)
(`:before
(cond
((equal token "d=") (smie-rule-parent 2))
((member token '("fun" "match"))
(and (not (smie-rule-bolp))
(cond ((smie-rule-prev-p "d=")
(smie-rule-parent tuareg-default-indent))
((smie-rule-prev-p "begin") (smie-rule-parent)))))
((equal token "then") (smie-rule-parent))
((equal token "if") (if (and (not (smie-rule-bolp))
(smie-rule-prev-p "else"))
(smie-rule-parent)))
((and (equal token "with") (smie-rule-parent-p "{"))
(smie-rule-parent))
((and (equal token "with") (smie-rule-parent-p "d="))
(let ((td (smie-backward-sexp "with")))
(cl-assert (equal (nth 2 td) "d="))
(goto-char (nth 1 td))
(setq td (smie-backward-sexp "d="))
;; Presumably (equal (nth 1 td) "type").
(goto-char (nth 1 td))
`(column . ,(smie-indent-virtual))))
;; Align the "with" of "module type A = B \n with ..." w.r.t "module".
((and (equal token "m-with") (smie-rule-parent-p "d="))
(save-excursion
(smie-backward-sexp token)
(goto-char (nth 1 (smie-backward-sexp 'halfsexp)))
(cons 'column (+ 2 (current-column)))))
;; Treat purely syntactic block-constructs as being part of their
;; parent, when the opening statement is hanging.
((member token '("let" "(" "[" "{" "sig" "struct" "begin"))
(when (and (smie-rule-hanging-p)
(apply #'smie-rule-prev-p
tuareg-smie--exp-operator-leader))
(if (let ((openers '("{" "(" "{<" "[" "[|")))
(or (apply #'smie-rule-prev-p openers)
(not (apply #'smie-rule-parent-p openers))))
(let ((offset (if (and (member token '("(" "struct" "sig"))
(not (smie-rule-parent-p "let" "d-let")))
0
tuareg-default-indent)))
(smie-rule-parent offset))
;; In "{ a = (", "{" and "a =" are not part of the same
;; syntax rule, so "(" is part of "a =" but not of the
;; surrounding "{".
(save-excursion
(smie-backward-sexp 'halfsexp)
(cons 'column (smie-indent-virtual))))))
((and tuareg-match-patterns-aligned
(equal token "|-or") (smie-rule-parent-p "|"))
(smie-rule-parent))
;; If we're looking at the first class-field-spec
;; in a "object(type)...end", don't rely on the default behavior which
;; will treat (type) as a previous element with which to align.
((tuareg-smie--object-hanging-rule token))
;; Apparently, people like their `| pattern when test -> body' to have
;; the `when' indented deeper than the body.
((equal token "when") (smie-rule-parent tuareg-match-when-indent))))
(`:after
(cond
((equal token "d=")
(and (smie-rule-parent-p "type")
(not (smie-rule-next-p "["))
0))
((equal token "->")
(cond
((smie-rule-parent-p "with")
;; Align with "with" but only if it's the only branch (often
;; the case in try..with), since otherwise subsequent
;; branches can't be both indented well and aligned.
(if (save-excursion
(and (not (equal "|" (nth 2 (smie-forward-sexp "|"))))
;; Since we may misparse "if..then.." we need to
;; double check that smie-forward-sexp indeed got us
;; to the right place.
(equal (nth 2 (smie-backward-sexp "|")) "with")))
(smie-rule-parent 2)
;; Align with other clauses, even with no preceding "|"
tuareg-match-clause-indent))
((smie-rule-parent-p "function")
;; Similar to the previous rule but for "function"
(if (save-excursion
(and (not (equal "|" (nth 2 (smie-forward-sexp "|"))))
(equal (nth 2 (smie-backward-sexp "|")) "function")))
(smie-rule-parent tuareg-default-indent)
tuareg-match-clause-indent))
((smie-rule-parent-p "|") tuareg-match-clause-indent)
;; Special case for "CPS style" code.
;; https://github.com/ocaml/tuareg/issues/5.
((smie-rule-parent-p "fun")
(save-excursion
(smie-backward-sexp "->")
(if (eq ?\( (char-before))
(cons 'column
(+ tuareg-default-indent
(progn
(backward-char 1)
(smie-indent-virtual))))
0)))
(t 0)))
((equal token ":")
(cond
((smie-rule-parent-p "val" "external") (smie-rule-parent 2))
((smie-rule-parent-p "module") (smie-rule-parent))
(t 2)))
((equal token "in") tuareg-in-indent) ;;(if (smie-rule-hanging-p)
((equal token "with")
(cond
;; ((smie-rule-next-p "|") 2)
((smie-rule-parent-p "{") nil)
(t (+ 2 tuareg-with-indent))))
((or (member token '("." "t->" "]"))
(consp (nth 2 (assoc token tuareg-smie-grammar)))) ;; Closer.
nil)
((member token '("{" "("))
;; The virtual indent after ( can be higher than the actual one
;; because it might be "column + tuareg-default-indent", whereas
;; the token only occupies a single column. So make sure we don't
;; get caught in this trap.
(let ((vi (smie-indent-virtual)))
(forward-char 1) ;Skip paren.
(skip-chars-forward " \t")
(unless (eolp)
`(column
. ,(min (current-column)
(+ tuareg-default-indent vi))))))
(t tuareg-default-indent)))))))