Function: neocaml--setup-mode

neocaml--setup-mode is a natively compiled function defined in neocaml.el.

Signature

(neocaml--setup-mode LANGUAGE)

Documentation

Set up tree-sitter font-lock, indentation, and navigation for LANGUAGE.

Called from neocaml-mode and neocaml-interface-mode to configure the language-specific parts of the mode.

Source Code

;; Defined in /nix/store/ahssdx4rwzyxhyhavpn0bkznk13xrggi-emacs-packages-deps/share/emacs/site-lisp/elpa/neocaml-20260907.2015/neocaml.el
(defun neocaml--setup-mode (language)
  "Set up tree-sitter font-lock, indentation, and navigation for LANGUAGE.
Called from `neocaml-mode' and `neocaml-interface-mode' to configure
the language-specific parts of the mode."
  ;; Offer to install missing grammars
  (when-let* ((missing (seq-filter (lambda (r) (not (treesit-language-available-p (car r))))
                                   neocaml-grammar-recipes)))
    (when (y-or-n-p "OCaml tree-sitter grammars are not installed.  Install them now?")
      (neocaml-install-grammars)))

  ;; Warn if installed grammars are outdated
  (neocaml--check-grammar-compatibility)

  (when (treesit-ready-p language)
    ;; Emacs 31+ uses treesit-primary-parser to identify the main parser
    ;; when multiple parsers are active.
    (let ((parser (treesit-parser-create language)))
      (when (boundp 'treesit-primary-parser)
        (setq-local treesit-primary-parser parser)))

    (when neocaml--debug
      (setq-local treesit--indent-verbose t)

      (when (eq neocaml--debug 'font-lock)
        (setq-local treesit--font-lock-verbose t))

      ;; show the node at point in the minibuffer
      (treesit-inspect-mode))

    ;; font-lock settings
    (setq-local treesit-font-lock-settings
                (neocaml-mode--font-lock-settings language))

    ;; indentation
    (setq-local treesit-simple-indent-rules (neocaml--indent-rules language))

    ;; Navigation
    (when (boundp 'treesit-thing-settings)
      (setq-local treesit-thing-settings
                  (neocaml--thing-settings language)))

    (treesit-major-mode-setup)

    ;; Emacs 31's treesit-forward-comment has an off-by-one bug that
    ;; breaks uncomment-region on multi-line regions.  Override with
    ;; the corrected version.
    (when (and (>= emacs-major-version 31)
               (boundp 'forward-comment-function))
      (setq-local forward-comment-function #'neocaml--forward-comment))

    ;; treesit-major-mode-setup picks a `forward-sexp-function' for us, but
    ;; neither choice is right for OCaml:
    ;;
    ;;   - Emacs 30 uses `treesit-forward-sexp', which doesn't fall back to
    ;;     scan-sexps for delimiter characters, breaking `delete-pair'.
    ;;   - Emacs 31 sees our `list' thing and uses `treesit-forward-sexp-list',
    ;;     which moves across lists but delegates *atoms* to
    ;;     `forward-sexp-default-function', ignoring the `sexp' thing entirely.
    ;;     Keyword-led forms are then treated as bare words, so C-M-f stops
    ;;     after `fun', `function', `if', `match' or `external' instead of
    ;;     moving over the whole construct.
    ;;
    ;; Use the hybrid on every version: it walks sexps with tree-sitter and
    ;; delegates to scan-sexps only on delimiters, which keeps `delete-pair'
    ;; working without giving up sexp navigation.
    (setq-local forward-sexp-function #'neocaml--forward-sexp-hybrid)

    ;; Workaround for treesit-transpose-sexps being broken on Emacs 30
    ;; (bug#60655).  Emacs 31 rewrites the function to work correctly.
    (when (and (fboundp 'transpose-sexps-default-function)
               (< emacs-major-version 31))
      (setq-local transpose-sexps-function
                  #'transpose-sexps-default-function))))