feat(emacs): handle
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user