Function: neocaml-backward-up-list

neocaml-backward-up-list is an interactive and natively compiled function defined in neocaml.el.

Signature

(neocaml-backward-up-list &optional ARG)

Documentation

Move backward out of one level of OCaml list-like construct.

With ARG, do this that many times. A negative ARG means move forward but still to a less deep spot.

Unlike the built-in backward-up-list, this recognises OCaml constructs delimited by keywords (struct/end, sig/end, object/end) in addition to ordinary parens, brackets and braces. Useful for jumping out to the enclosing module, signature or object from somewhere inside its body.

On Emacs 31+, the built-in backward-up-list already understands these constructs via treesit-thing-settings, so this command simply delegates to it there.

Key Bindings

neocaml-base-mode-map C-M-u

Source Code

;; Defined in /nix/store/ahssdx4rwzyxhyhavpn0bkznk13xrggi-emacs-packages-deps/share/emacs/site-lisp/elpa/neocaml-20260907.2015/neocaml.el
(defun neocaml-backward-up-list (&optional arg)
  "Move backward out of one level of OCaml list-like construct.
With ARG, do this that many times.  A negative ARG means move
forward but still to a less deep spot.

Unlike the built-in `backward-up-list', this recognises OCaml
constructs delimited by keywords (`struct'/`end', `sig'/`end',
`object'/`end') in addition to ordinary parens, brackets and
braces.  Useful for jumping out to the enclosing module, signature
or object from somewhere inside its body.

On Emacs 31+, the built-in `backward-up-list' already understands
these constructs via `treesit-thing-settings', so this command
simply delegates to it there."
  (interactive "^p")
  (if (>= emacs-major-version 31)
      (backward-up-list arg t t)
    (let ((arg (or arg 1)))
      (dotimes (_ (abs arg))
        ;; Consider both the nearest enclosing tree-sitter list node and
        ;; the nearest syntactic delimiter, then jump to whichever is
        ;; closer to point.  This matches the Emacs 31 built-in, which
        ;; combines the two via `treesit-thing-settings'.
        (let* ((node (treesit-node-at (point)))
               (parent (treesit-parent-until
                        node
                        (lambda (n)
                          (and (string-match-p neocaml--list-node-regex
                                               (treesit-node-type n))
                               (if (< arg 0)
                                   (> (treesit-node-end n) (point))
                                 (< (treesit-node-start n) (point)))))))
               (tree-pos (and parent
                              (if (< arg 0)
                                  (treesit-node-end parent)
                                (treesit-node-start parent))))
               ;; Use `syntax-ppss' rather than `up-list': the OCaml
               ;; syntax table treats `(' as both a paren and part of the
               ;; `(*' comment delimiter, which confuses `up-list'.
               (syn-pos (let ((open (nth 1 (syntax-ppss))))
                          (cond ((null open) nil)
                                ((< arg 0) (ignore-errors (scan-sexps open 1)))
                                (t open))))
               (target (cond ((and tree-pos syn-pos)
                              (if (< arg 0)
                                  (min tree-pos syn-pos)
                                (max tree-pos syn-pos)))
                             (t (or tree-pos syn-pos)))))
          (if target
              (goto-char target)
            (user-error "At top level")))))))