feat(emacs): handle

This commit is contained in:
2025-09-22 11:20:33 -06:00
parent e3decb9bb1
commit a24b3d7ec7
2 changed files with 88 additions and 11 deletions

View File

@@ -33,7 +33,7 @@
(bury-buffer b)
b)))))
(defun syd-elisp-lookup-documentation (identifier)
(defun syd-elisp-handle-docs (identifier)
"Lookup IDENTIFIER with `describe-symbol'"
;; HACK: Much to my frustration, `describe-symbol' has no defined return
;; value. To test if the call was successful or not, we check if any window
@@ -45,9 +45,8 @@
(and (get-buffer-window-list buffer)
buffer)))
;; (handle '(emacs-lisp-mode lisp-interaction-mode
;; inferior-emacs-lisp-mode)
;; :repl #'syd-elisp-open-repl)
(syd-handle '(emacs-lisp-mode lisp-interaction-mode)
:docs #'syd-elisp-handle-docs)

View File

@@ -3,14 +3,92 @@
(require 'cl-lib)
(require 'syd/straight)
(require 'syd/use-package)
(require 'syd/dash)
(eval-when-compile (require 'cl-lib))
(use-package handle
:preface
(require 'cl-lib)
:init
(setq handle-keywords
'(:repl
:docs)))
;;; Core machinery
(defun syd-parent-mode-list (mode)
"Return a list of MODE, then MODE's parent, then MODE's grandparent..."
(cl-loop for m = mode then (get m 'derived-mode-parent)
while m
collect m))
(defun syd-handler-alist-name (type)
(intern (concat "syd-handle-"
(symbol-name type)
"-alist")))
(defun syd-handler-function-name (type)
(intern (concat "syd-handle-" (symbol-name type))))
(defmacro syd-define-handler-type
(handler-type arglist &optional docstring)
(declare (indent defun))
(let ((hook-name (syd-handler-alist-name handler-type))
(fn-name (syd-handler-function-name handler-type)))
`(progn
(defvar ,hook-name nil)
(defun ,fn-name (&rest args)
,@(ensure-list docstring)
(let (r)
(cl-loop
for (mode . handle) in ,hook-name
;; Test mode's variable to determine if it's active. Some modes
;; lack an associated variable, which is very annoying! The
;; `major-mode' and sledgehammer `minor-mode-list' tests should
;; catch these guys.
;;
;; TODO: Use `syd-parent-mode-list' to support hierarchies of modes.
when (or (eq mode major-mode)
(and (boundp mode)
(symbol-value mode))
(memq mode minor-mode-list))
do (setq r (apply handle args))
when r return r))))))
(defun syd-handle (modes &rest args)
(declare (indent defun))
(cl-loop
for m in (ensure-list modes)
do (cl-loop for (type handler) on args by (lambda (xs)
(cdr (cdr xs)))
do (let ((s (->> (symbol-name type)
(string-remove-prefix ":")
intern
syd-handler-alist-name)))
(set s (cons (cons m handler)
(symbol-value s)))))))
;;; Docs handler
(syd-define-handler-type docs (identifier)
"Return a buffer visiting documentation for IDENTIFIER.")
(defun syd-handle-docs* (identifier)
(interactive (list (symbol-at-point)))
(if-let* ((b (save-excursion
(save-window-excursion
(syd-handle-docs identifier)))))
(display-buffer b)
(message "Couldn't find documentation on %S"
(substring-no-properties identifier))))
;;; REPL handler
(syd-define-handler-type repl ()
"Return a buffer.")
(defun syd-handle-repl* ()
(if-let* ((b (save-window-excursion
(syd-handle-repl))))
(display-buffer b)
(message "Couldn't open a REPL for %S"
(substring-no-properties identifier))))
(provide 'syd/handle)