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:
parent
78895d89ee
commit
0123dd1648
1 changed files with 44 additions and 35 deletions
|
@ -48,42 +48,51 @@
|
|||
(point-max)))))
|
||||
buffer)))
|
||||
|
||||
(defun +eval-open-repl (prompt-p &optional displayfn)
|
||||
(cl-destructuring-bind (_mode fn . plist)
|
||||
(or (assq major-mode +eval-repls)
|
||||
(list nil nil))
|
||||
(when (or (not fn) prompt-p)
|
||||
(let* ((choices (or (cl-loop for sym being the symbols
|
||||
for sym-name = (symbol-name sym)
|
||||
if (string-match "^\\(?:\\+\\)?\\([^/]+\\)/open-\\(?:\\(.+\\)-\\)?repl$" sym-name)
|
||||
collect
|
||||
(format "%s (%s)"
|
||||
(match-string-no-properties 1 sym-name)
|
||||
(or (match-string-no-properties 2 sym-name) "default")))
|
||||
(user-error "There are no known available REPLs")))
|
||||
(choice (or (completing-read "Open a REPL for: " choices)
|
||||
(user-error "Aborting")))
|
||||
(choice-split (split-string choice " " t))
|
||||
(module (car choice-split))
|
||||
(repl (substring (cadr choice-split) 1 -1)))
|
||||
(setq fn
|
||||
(intern-soft
|
||||
(format "+%s/open-%srepl" module
|
||||
(if (string= repl "default")
|
||||
""
|
||||
(concat repl "-")))))))
|
||||
(let ((region (if (use-region-p)
|
||||
(buffer-substring-no-properties (region-beginning)
|
||||
(region-end)))))
|
||||
(unless (commandp fn)
|
||||
(error "Couldn't find a valid REPL for %s" major-mode))
|
||||
(with-current-buffer (+eval--ensure-in-repl-buffer fn plist displayfn)
|
||||
(when (bound-and-true-p evil-mode)
|
||||
(call-interactively #'evil-append-line))
|
||||
(when region
|
||||
(insert region))
|
||||
t))))
|
||||
(defun +eval-repl-known-repls ()
|
||||
"Yield the available repl functions as a list of symbols."
|
||||
(seq-uniq (mapcar #'cl-second +eval-repls)))
|
||||
|
||||
(defun +eval-repl-found-repls ()
|
||||
"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)
|
||||
if (string-match "^\\(?:\\+\\)?\\([^/]+\\)/open-\\(?:\\(.+\\)-\\)?repl$" sym-name)
|
||||
collect
|
||||
sym))
|
||||
|
||||
(defun +eval-repl-prompt ()
|
||||
"Prompt the user for the choice of a repl to open."
|
||||
(let* ((repls (seq-uniq (append (+eval-repl-known-repls)
|
||||
(+eval-repl-found-repls))))
|
||||
(choice (or (completing-read "Open a REPL for: " repls)
|
||||
(user-error "Aborting"))))
|
||||
(intern-soft choice)))
|
||||
|
||||
(defun +eval-repl-from-major-mode ()
|
||||
"Fetch the repl associated with the current major mode, if there
|
||||
is one."
|
||||
(pcase-let ((`(_ ,fn . ,plist) (assq major-mode +eval-repls)))
|
||||
(list fn plist)))
|
||||
|
||||
(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)
|
||||
(region-end)))))
|
||||
(unless (commandp fn)
|
||||
(error "Couldn't find a valid REPL for %s" major-mode))
|
||||
(with-current-buffer (+eval--ensure-in-repl-buffer fn plist displayfn)
|
||||
(when (bound-and-true-p evil-mode)
|
||||
(call-interactively #'evil-append-line))
|
||||
(when region
|
||||
(insert region))
|
||||
t)))
|
||||
|
||||
;;
|
||||
;;; Commands
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue