fix(tools): improve detection of available REPLs

Previously, when setting up a prompt for choosing from the available
REPLs, not all known options were detected via the regex pattern. This
commit modularizes the logic and provides a backup for detecting REPLs
that we definitely know about from the `+eval-repls` list.
This commit is contained in:
Colin Woodbury 2023-02-23 23:35:26 +09:00 committed by Henrik Lissner
parent 78895d89ee
commit 0123dd1648

View file

@ -48,31 +48,41 @@
(point-max))))) (point-max)))))
buffer))) buffer)))
(defun +eval-open-repl (prompt-p &optional displayfn) (defun +eval-repl-known-repls ()
(cl-destructuring-bind (_mode fn . plist) "Yield the available repl functions as a list of symbols."
(or (assq major-mode +eval-repls) (seq-uniq (mapcar #'cl-second +eval-repls)))
(list nil nil))
(when (or (not fn) prompt-p) (defun +eval-repl-found-repls ()
(let* ((choices (or (cl-loop for sym being the symbols "Search the interned symbol list for functions that looks like
repl openers."
(cl-loop for sym being the symbols
for sym-name = (symbol-name sym) for sym-name = (symbol-name sym)
if (string-match "^\\(?:\\+\\)?\\([^/]+\\)/open-\\(?:\\(.+\\)-\\)?repl$" sym-name) if (string-match "^\\(?:\\+\\)?\\([^/]+\\)/open-\\(?:\\(.+\\)-\\)?repl$" sym-name)
collect collect
(format "%s (%s)" sym))
(match-string-no-properties 1 sym-name)
(or (match-string-no-properties 2 sym-name) "default"))) (defun +eval-repl-prompt ()
(user-error "There are no known available REPLs"))) "Prompt the user for the choice of a repl to open."
(choice (or (completing-read "Open a REPL for: " choices) (let* ((repls (seq-uniq (append (+eval-repl-known-repls)
(user-error "Aborting"))) (+eval-repl-found-repls))))
(choice-split (split-string choice " " t)) (choice (or (completing-read "Open a REPL for: " repls)
(module (car choice-split)) (user-error "Aborting"))))
(repl (substring (cadr choice-split) 1 -1))) (intern-soft choice)))
(setq fn
(intern-soft (defun +eval-repl-from-major-mode ()
(format "+%s/open-%srepl" module "Fetch the repl associated with the current major mode, if there
(if (string= repl "default") is one."
"" (pcase-let ((`(_ ,fn . ,plist) (assq major-mode +eval-repls)))
(concat repl "-"))))))) (list fn plist)))
(let ((region (if (use-region-p)
(defun +eval-open-repl (prompt-p &optional displayfn)
"Open a repl via the given DISPLAYFN. If PROMPT-P, the user will be
prompted for a repl choice, even if the major mode they're in
already has a known one."
(pcase-let* ((`(,fn ,plist) (+eval-repl-from-major-mode))
(fn (cond ((or prompt-p (not fn)) (+eval-repl-prompt))
(t fn)))
(region (when (use-region-p)
(buffer-substring-no-properties (region-beginning) (buffer-substring-no-properties (region-beginning)
(region-end))))) (region-end)))))
(unless (commandp fn) (unless (commandp fn)
@ -82,8 +92,7 @@
(call-interactively #'evil-append-line)) (call-interactively #'evil-append-line))
(when region (when region
(insert region)) (insert region))
t)))) t)))
;; ;;
;;; Commands ;;; Commands