<commit_before>;;; tools/lookup/autoload/lookup.el -*- lexical-binding: t; -*-

(defvar +lookup--handler-alist nil)

;;;###autodef
(cl-defun set-lookup-handlers!
    (modes &rest plist &key definition references documentation file xref-backend async)
  "Define jump handlers for major or minor MODES.

This overwrites previously defined handlers for MODES. If used on minor modes,
they are stacked onto handlers defined for other minor modes or the major mode
it's activated in.

This can be passed nil as its second argument to unset handlers for MODES. e.g.

  (set-lookup-handlers! 'python-mode nil)

Otherwise, these properties are available to be set:

:definition FN
  Run when jumping to a symbol's definition.
  Used by `+lookup/definition'.
:references FN
  Run when looking for usage references of a symbol in the current project.
  Used by `+lookup/references'.
:documentation FN
  Run when looking up documentation for a symbol.
  Used by `+lookup/documentation'.
:file FN
  Run when looking up the file for a symbol/string. Typically a file path.
  Used by `+lookup/file'.
:xref-backend FN
  Defines an xref backend for a major-mode. If you define :definition and
  :references along with :xref-backend, those will have higher precedence.
:async BOOL
  Indicates that *all* supplied FNs are asynchronous. Note: async handlers do
  not fall back to the default handlers, due to their nature. To get around
  this, you must write specialized wrappers to wait for the async response.

  If you only want to specify one FN is async, use a PLIST instead:

    (set-lookup-handlers! 'rust-mode
      :definition '(racer-find-definition :async t))

Handlers can either be interactive or non-interactive. Non-interactive handlers
must take one argument: the identifier being looked up. This function must
change the current buffer or window or return non-nil when it succeeds.

If it doesn't change the current buffer, or it returns nil, the lookup module
will fall back to the next handler in `+lookup-definition-functions',
`+lookup-references-functions', `+lookup-file-functions' or
`+lookup-documentation-functions'."
  (declare (indent defun))
  (dolist (mode (doom-enlist modes))
    (let ((hook (intern (format "%s-hook" mode)))
          (fn   (intern (format "+lookup|init-%s" mode))))
      (cond ((null (car plist))
             (remove-hook hook fn)
             (delq! mode +lookup--handler-alist 'assq)
             (unintern fn nil))
            ((fset fn
                   (lambda ()
                     (when (or (eq major-mode mode)
                               (and (boundp mode)
                                    (symbol-value mode)))
                       (cl-mapc #'+lookup--set-handler
                                (list definition
                                      references
                                      documentation
                                      file
                                      xref-backend)
                                (list '+lookup-definition-functions
                                      '+lookup-references-functions
                                      '+lookup-documentation-functions
                                      '+lookup-file-functions
                                      'xref-backend-functions)
                                async))))
             (add-hook hook fn))))))


;;
;;; Helpers

(defun +lookup--set-handler (spec functions-var &optional async)
  (when spec
    (cl-destructuring-bind (fn . plist)
        (doom-enlist spec)
      (put fn '+lookup-plist (plist-put plist :async async))
      (add-hook functions-var fn nil t))))

(defun +lookup--symbol-or-region (&optional initial)
  (cond ((stringp initial)
         initial)
        ((use-region-p)
         (buffer-substring-no-properties (region-beginning)
                                         (region-end)))
        ((require 'xref nil t)
         (xref-backend-identifier-at-point (xref-find-backend)))))

(defun +lookup--run-handler (handler identifier)
  (if (commandp handler)
      (call-interactively handler)
    (funcall handler identifier)))

(defun +lookup--run-handlers (handler identifier origin &optional other-window)
  (doom-log "Looking up '%s' with '%s'" identifier handler)<commit_msg>Fix lookup handlers not being used #1378<commit_after>;;; tools/lookup/autoload/lookup.el -*- lexical-binding: t; -*-

(defvar +lookup--handler-alist nil)

;;;###autodef
(cl-defun set-lookup-handlers!
    (modes &rest plist &key definition references documentation file xref-backend async)
  "Define jump handlers for major or minor MODES.

This overwrites previously defined handlers for MODES. If used on minor modes,
they are stacked onto handlers defined for other minor modes or the major mode
it's activated in.

This can be passed nil as its second argument to unset handlers for MODES. e.g.

  (set-lookup-handlers! 'python-mode nil)

Otherwise, these properties are available to be set:

:definition FN
  Run when jumping to a symbol's definition.
  Used by `+lookup/definition'.
:references FN
  Run when looking for usage references of a symbol in the current project.
  Used by `+lookup/references'.
:documentation FN
  Run when looking up documentation for a symbol.
  Used by `+lookup/documentation'.
:file FN
  Run when looking up the file for a symbol/string. Typically a file path.
  Used by `+lookup/file'.
:xref-backend FN
  Defines an xref backend for a major-mode. If you define :definition and
  :references along with :xref-backend, those will have higher precedence.
:async BOOL
  Indicates that *all* supplied FNs are asynchronous. Note: async handlers do
  not fall back to the default handlers, due to their nature. To get around
  this, you must write specialized wrappers to wait for the async response.

  If you only want to specify one FN is async, use a PLIST instead:

    (set-lookup-handlers! 'rust-mode
      :definition '(racer-find-definition :async t))

Handlers can either be interactive or non-interactive. Non-interactive handlers
must take one argument: the identifier being looked up. This function must
change the current buffer or window or return non-nil when it succeeds.

If it doesn't change the current buffer, or it returns nil, the lookup module
will fall back to the next handler in `+lookup-definition-functions',
`+lookup-references-functions', `+lookup-file-functions' or
`+lookup-documentation-functions'."
  (declare (indent defun))
  (dolist (mode (doom-enlist modes))
    (let ((hook (intern (format "%s-hook" mode)))
          (fn   (intern (format "+lookup|init-%s" mode))))
      (cond ((null (car plist))
             (remove-hook hook fn)
             (delq! mode +lookup--handler-alist 'assq)
             (unintern fn nil))
            ((fset fn
                   (lambda ()
                     (when (or (eq major-mode mode)
                               (and (boundp mode)
                                    (symbol-value mode)))
                       (cl-mapc #'+lookup--set-handler
                                (list definition
                                      references
                                      documentation
                                      file
                                      xref-backend)
                                (list '+lookup-definition-functions
                                      '+lookup-references-functions
                                      '+lookup-documentation-functions
                                      '+lookup-file-functions
                                      'xref-backend-functions)
                                (make-list 5 async)))))
             (add-hook hook fn))))))


;;
;;; Helpers

(defun +lookup--set-handler (spec functions-var &optional async)
  (when spec
    (cl-destructuring-bind (fn . plist)
        (doom-enlist spec)
      (put fn '+lookup-plist (plist-put plist :async async))
      (add-hook functions-var fn nil t))))

(defun +lookup--symbol-or-region (&optional initial)
  (cond ((stringp initial)
         initial)
        ((use-region-p)
         (buffer-substring-no-properties (region-beginning)
                                         (region-end)))
        ((require 'xref nil t)
         (xref-backend-identifier-at-point (xref-find-backend)))))

(defun +lookup--run-handler (handler identifier)
  (if (commandp handler)
      (call-interactively handler)
    (funcall handler identifier)))

(defun +lookup--run-handlers (handler identifier origin &optional other-window)
  (doom-log "Looking up '%s' with '%s'" identifier handler)
{'fraction_non_alphanumeric': 0.09375363498894963, 'fraction_numerical': 0.0005815982319413749, 'mean_word_length': 2.1402483564645727, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4318597', 'n_tokens_mistral': 2329, 'n_tokens_neox': 2199, 'n_words': 847}