wip(emacs): Abstract strategy-running
- Show docs and goto def are confirmed working
This commit is contained in:
70
users/crumb/programs/emacs/lib/syd-strategies-lookup.el
Normal file
70
users/crumb/programs/emacs/lib/syd-strategies-lookup.el
Normal file
@@ -0,0 +1,70 @@
|
||||
;; syd-strategies-lookup.el -*- lexical-binding: t; -*-
|
||||
|
||||
(require 'syd-strategies)
|
||||
(use-package better-jumper)
|
||||
(require 'better-jumper)
|
||||
|
||||
(defun syd-strat--run-lookup-strategy (strategy identifier origin)
|
||||
"Safely call a lookup STRATEGY. A lookup strategy, if it is not an
|
||||
interactive command, will be called with the lone argument IDENTIFIER.
|
||||
Interactive or not, the procedure is expected to return nil on failure. Returns
|
||||
a marker if STRATEGY returns a buffer or marker, or nil on failure.
|
||||
Modifications to the window configuration will be discarded if STRATEGY fails to
|
||||
return a buffer or marker."
|
||||
(condition-case-unless-debug e
|
||||
(let ((wconf (current-window-configuration))
|
||||
(result (condition-case-unless-debug e
|
||||
(if (commandp strategy)
|
||||
(call-interactively strategy)
|
||||
(funcall strategy identifier))
|
||||
(error
|
||||
(message "Lookup strategy %S threw an error: %s" strategy e)
|
||||
'fail))))
|
||||
(cond ((eq result 'fail)
|
||||
(set-window-configuration wconf)
|
||||
nil)
|
||||
((bufferp result)
|
||||
(with-current-buffer result
|
||||
(point-marker)))
|
||||
((or result
|
||||
(null origin)
|
||||
(/= (point-marker) origin))
|
||||
(prog1 (point-marker)
|
||||
(set-window-configuration wconf)))))
|
||||
((error user-error)
|
||||
(message "Lookup strategy %S: %s" strategy e)
|
||||
nil)))
|
||||
|
||||
(cl-defun syd-strat--lookup-and-jump-to
|
||||
(strategy-category identifier &key (display-fn #'switch-to-buffer))
|
||||
(let* ((origin (point-marker))
|
||||
(strategies (alist-get strategy-category syd-strat--strategies))
|
||||
;; TODO: If called with a prefix argument, prompt the user to select a
|
||||
;; strategy.
|
||||
(result (syd-strat-try-functions-wrapped
|
||||
#'syd-strat--run-lookup-strategy
|
||||
strategies identifier origin)))
|
||||
(unwind-protect
|
||||
(when (cond ((null result)
|
||||
(message "No lookup strategy could find %S" identifier)
|
||||
nil)
|
||||
((markerp result)
|
||||
(funcall display-fn (marker-buffer result))
|
||||
(goto-char result)
|
||||
result)
|
||||
(result))
|
||||
(with-current-buffer (marker-buffer origin)
|
||||
(better-jumper-set-jump (marker-position origin)))
|
||||
result))
|
||||
(set-marker origin nil)))
|
||||
|
||||
(defun syd-strat-lookup-documentation (identifier)
|
||||
(interactive (list (syd-thing-at-point-or-region)))
|
||||
(syd-strat--lookup-and-jump-to :documentation identifier
|
||||
:display-fn #'pop-to-buffer))
|
||||
|
||||
(defun syd-strat-lookup-definition (identifier)
|
||||
(interactive (list (syd-thing-at-point-or-region)))
|
||||
(syd-strat--lookup-and-jump-to :definition identifier))
|
||||
|
||||
(provide 'syd-strategies-lookup)
|
||||
8
users/crumb/programs/emacs/lib/syd-strategies-repl.el
Normal file
8
users/crumb/programs/emacs/lib/syd-strategies-repl.el
Normal file
@@ -0,0 +1,8 @@
|
||||
;; syd-strategies-repl.el -*- lexical-binding: t; -*-
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode syd-repl-mode
|
||||
"A minor mode for repl buffers. One use is to universally customise the
|
||||
display of all repl buffers.")
|
||||
|
||||
(provide 'syd-strategies-repl)
|
||||
37
users/crumb/programs/emacs/lib/syd-strategies.el
Normal file
37
users/crumb/programs/emacs/lib/syd-strategies.el
Normal file
@@ -0,0 +1,37 @@
|
||||
;; syd-strategies.el -*- lexical-binding: t; -*-
|
||||
|
||||
(require 'syd-text)
|
||||
|
||||
;; :documentation : Identifier -> Marker
|
||||
(defvar-local syd-strat--strategies nil)
|
||||
|
||||
(defun syd-strat-try-functions-wrapped (wrapper fns &rest args)
|
||||
"For each FN in FNS, call WRAPPER with the arguments FN followed by ARGS,
|
||||
until a FN returns non-nil."
|
||||
(cl-loop for fn in fns
|
||||
with r = nil
|
||||
do (setq r (apply wrapper fn args))
|
||||
until r
|
||||
finally return r))
|
||||
|
||||
(defun syd-strat--set-strategies (category strategies)
|
||||
(cl-loop for ref in-ref syd-strat--strategies
|
||||
until (eq category (car ref))
|
||||
finally do (pp ref)))
|
||||
|
||||
(defun syd-set-strategies (modes &rest args)
|
||||
(dolist (mode (ensure-list modes))
|
||||
(let ((hook (intern (format "%s-hook" mode)))
|
||||
(fn-name (intern (format "syd-strat--init-for-%s-h" mode))))
|
||||
(unless (cl-evenp (length args))
|
||||
(signal 'wrong-number-of-arguments args))
|
||||
;; We use this `defalias' incantation instead of a raw `fset' because the
|
||||
;; former will properly associate a source location to the definition.
|
||||
(defalias fn-name
|
||||
(function
|
||||
(lambda ()
|
||||
(cl-loop for (category strategies) on args by (lambda (x) (-drop 2 x))
|
||||
do (syd-strat--set-strategies category strategies)))))
|
||||
(add-hook hook fn-name))))
|
||||
|
||||
(provide 'syd-strategies)
|
||||
Reference in New Issue
Block a user