commit 050dbf30aeda1b0f57fbce84a1d682ae256e1514
Author: andsy10 <andsy1016@gmail.com>
Date: Mon, 19 Oct 2026 09:19:43 +0800
Initial commit
Diffstat:
| A | README | | | 1 | + |
| A | consult-symbol.el | | | 162 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 163 insertions(+), 0 deletions(-)
diff --git a/README b/README
@@ -0,0 +1 @@
+This package was generated by LLM and has NOT been fully reviewed.
diff --git a/consult-symbol.el b/consult-symbol.el
@@ -0,0 +1,162 @@
+;;; consult-symbol.el --- Consult commands for browsing obarray symbols -*- lexical-binding: t -*-
+
+;;; Commentary:
+
+;; This package provide `consult-symbol' which completes over the
+;; symbols in `obarray' and previews their source definitions.
+;;
+;; Usage:
+;;
+;; M-x consult-symbol RET
+
+
+;;; Code:
+
+(require 'consult)
+(require 'find-func)
+(require 'help-fns)
+(require 'xref)
+
+(defvar consult-symbol--history nil)
+
+(defconst consult-symbol--narrow
+ '((?f . "Function")
+ (?v . "Variable")
+ (?a . "Face"))
+ "Narrowing configuration for `consult-symbol'.")
+
+(defun consult-symbol--type (sym)
+ "Return the narrowing type character of SYM."
+ (cond
+ ((fboundp sym) ?f)
+ ((boundp sym) ?v)
+ ((facep sym) ?a)))
+
+(defun consult-symbol--candidates ()
+ "Return symbol name candidates from `obarray'."
+ (let (cands)
+ (mapatoms
+ (lambda (sym)
+ (when-let* ((type (consult-symbol--type sym)))
+ (push (propertize (symbol-name sym)
+ 'consult--symbol sym
+ 'consult--type type)
+ cands))))
+ cands))
+
+(defun consult-symbol--file (sym type)
+ "Return the source file name of SYM's definition of TYPE.
+TYPE is either a function definition, `defvar' or `defface', as accepted
+by `find-lisp-object-file-name'. Definitions in the C sources are
+translated to a \"src/*.c\" file name."
+ (when-let* ((file (find-lisp-object-file-name sym type)))
+ (if (eq file 'C-source)
+ (help-C-file-name sym (if (eq type 'defvar) 'var 'subr))
+ file)))
+
+(defun consult-symbol--definition (sym)
+ "Return (TYPE . FILE) for the source definition of SYM, or nil.
+TYPE is nil for a function definition, `defvar' for a variable
+definition or `defface' for a face definition, as accepted by
+`find-function-search-for-symbol'."
+ (or
+ (and (fboundp sym)
+ (when-let* ((file (consult-symbol--file sym (symbol-function sym))))
+ (cons nil file)))
+ (and (boundp sym)
+ (when-let* ((file (consult-symbol--file sym 'defvar)))
+ (cons 'defvar file)))
+ (and (facep sym)
+ (when-let* ((file (consult-symbol--file sym 'defface)))
+ (cons 'defface file)))))
+
+(defun consult-symbol--find (sym open)
+ "Return a marker to the source definition of SYM, or nil.
+OPEN is a temporary file opener as returned by
+`consult--temporary-files'. Nested calls to `find-file-noselect', e.g.,
+from the OPEN function itself, are passed through to the original
+function, in order to avoid infinite recursion."
+ (pcase-let ((`(,type . ,file) (consult-symbol--definition sym)))
+ (when file
+ (condition-case nil
+ (let ((orig (symbol-function #'find-file-noselect))
+ (nested nil))
+ (pcase-let ((`(,buf . ,pos)
+ (cl-letf (((symbol-function #'find-file-noselect)
+ (lambda (name &rest args)
+ (if nested
+ (apply orig name args)
+ (setq nested t)
+ (unwind-protect
+ (funcall open name)
+ (setq nested nil))))))
+ (find-function-search-for-symbol sym type file))))
+ (when (buffer-live-p buf)
+ (with-current-buffer buf
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (or pos (point-min)))
+ (point-marker)))))))
+ (error nil)))))
+
+(defun consult-symbol--preview ()
+ "Symbol preview function, usable as :state argument of `consult--read'.
+Files are opened temporarily via `consult--temporary-files' and the
+definition is previewed via `consult--jump-preview'. Symbols whose
+source cannot be located are not previewed."
+ (let ((open (consult--temporary-files))
+ (preview (consult--jump-preview)))
+ (lambda (action sym)
+ (unless sym
+ (funcall open))
+ (funcall preview action
+ (and sym
+ (eq action 'preview)
+ (consult-symbol--find sym open))))))
+
+(defun consult-symbol--jump (sym)
+ "Jump to the source definition of SYM."
+ (pcase-let ((`(,type . ,file) (consult-symbol--definition sym)))
+ (if (not file)
+ (message "Unknown source location of `%s'" sym)
+ (xref-push-marker-stack)
+ (pcase-let ((`(,buf . ,pos)
+ (find-function-search-for-symbol sym type file)))
+ (consult--jump
+ (with-current-buffer buf
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (or pos (point-min)))
+ (point-marker))))))
+ (run-hooks 'find-function-after-hook))))
+
+;;;###autoload
+(defun consult-symbol ()
+ "Browse `obarray' symbols with preview of their source definition.
+
+The command completes over all interned symbols which are defined as
+function, variable or face. While browsing, the definition of the
+current candidate is previewed; the source file is only opened
+temporarily. After selection, jump to the definition, pushing the
+previous position to the xref marker stack. Symbols can be narrowed by
+type, see `consult-symbol--narrow'."
+ (interactive)
+ (let ((sym (symbol-at-point)))
+ (consult--read
+ (consult-symbol--candidates)
+ :prompt "Symbol: "
+ :category 'symbol
+ :require-match t
+ :history 'consult-symbol--history
+ :default (and sym (consult-symbol--type sym) (symbol-name sym))
+ :lookup (apply-partially #'consult--lookup-prop 'consult--symbol)
+ :state (consult--state-with-return
+ (consult-symbol--preview)
+ #'consult-symbol--jump)
+ :group (consult--type-group consult-symbol--narrow)
+ :narrow (consult--type-narrow consult-symbol--narrow))))
+
+(provide 'consult-symbol)
+;;; consult-symbol.el ends here