Function: tuareg-backward-beginning-of-defun

tuareg-backward-beginning-of-defun is a natively compiled function defined in tuareg.el.

Signature

(tuareg-backward-beginning-of-defun &optional STAY-IN-CURRENT)

Documentation

Move the point backward to the beginning of a definition.

Return the token starting the phrase (nil if it is an expression). If STAY-IN-CURRENT is non-nil, don't go to the previous defun if already at the start of one.

Aliases

tuareg--beginning-of-phrase (obsolete since Apr 10, 2019)

Source Code

;; Defined in /nix/store/6mbh851dhnag8f92qfrlh9ckldzwf6c6-emacs-packages-deps/share/emacs/site-lisp/elpa/tuareg-20260626.936/tuareg.el
(defun tuareg-backward-beginning-of-defun (&optional stay-in-current)
  "Move the point backward to the beginning of a definition.
Return the token starting the phrase (`nil' if it is an expression).
If STAY-IN-CURRENT is non-nil, don't go to the previous defun if already
at the start of one."
  (let ((state (syntax-ppss)))
    (cond
     ;; In a string: move to its end (via the beginning).
     ((nth 3 state)
      (goto-char (nth 8 state))
      (smie-forward-sexp))
     ;; In a comment: move to its beginning.
     ((nth 4 state)
      (goto-char (nth 8 state)))
     ;; At start of a word and we may move to previous defun: stay put.
     ((and (not stay-in-current)
           (looking-at (rx symbol-start))))
     ;; If in or at the beginning of a word, move to the end.
     ((/= (skip-syntax-forward "w_") 0))
     ;; Otherwise, skip possibly trailing ";;".
     (t (tuareg--skip-backward-comments-semicolon))))

  ;; We treat each "and" clause belonging to "d-let" or "type" as defuns
  ;; in the own right since that is how programmers think about it.
  (let* ((opoint (point))
         (and-pos nil)
         (ret-tok nil)
         (tick (buffer-chars-modified-tick))
         (cache-valid (eql tuareg-smie--and-cache-tick tick)))
    (while
        (and (not (bobp))
             ;; Memoised call to (smie-backward-sexp "and")
             (let* ((cached
                     (and cache-valid
                          (assq (point) tuareg-smie--backward-and-cache)))
                    (td (if cached
                            (progn
                              (goto-char (nth 1 cached))
                              (nth 2 cached))
                          (unless cache-valid
                            (setq tuareg-smie--forward-and-cache nil)
                            (setq tuareg-smie--backward-and-cache nil)
                            (setq tuareg-smie--and-cache-tick tick)
                            (setq cache-valid t))
                          (let* ((pt (point))
                                 (r (smie-backward-sexp "and")))
                            (push (list pt (point) r)
                                  tuareg-smie--backward-and-cache)
                            r))))
               (and (nth 0 td)
                    (let ((tpos (nth 1 td))
                          (tok (nth 2 td)))
                      (cond
                       ;; Arrived at a token that always starts a defun.
                       ((member tok '("type" "d-let" "exception" "module"
                                      "class" "val" "external" "open"))
                        (if (and and-pos (member tok '("d-let" "type")))
                            ;; Previously found "and" is the start of the
                            ;; defun: return it.
                            (progn
                              (goto-char and-pos)
                              (setq ret-tok "and"))
                          ;; This is the start of the defun.
                          (goto-char tpos)
                          (setq ret-tok tok))
                        nil)
                       ;; Arrived at "and": keep going backwards to find
                       ;; out whether it was the start of a defun.
                       ((equal tok "and")
                        (unless and-pos
                          (setq and-pos tpos))
                        (goto-char tpos)
                        t)
                       ;; Arrived at "let": keep going backwards.
                       ((equal tok "let")
                        ;; Any previous "and" was not the start of a defun.
                        (setq and-pos nil)
                        (goto-char tpos)
                        t)
                       ((equal tok ";;")
                        (if (and (= (point) opoint) (not stay-in-current))
                            ;; Assume this ";;" to be the last part of
                            ;; the defun to go past: skip and continue.
                            (progn
                              (goto-char tpos)
                              t)
                          ;; This marks the beginning of the defun.
                          (setq ret-tok t)  ; Any non-nil value should do.
                          nil))
                       ((member tok '("do" "downto" "to"))
                        (goto-char tpos)
                        t)
                       ;; Left bracket or similar: keep going.
                       ((not (numberp (nth 0 td)))
                        (goto-char tpos)
                        t)
                       ;; Something else: stop.
                       (t nil)))))))
    ret-tok))