Standardize REPL commands & improve SPC o r

- SPC o r now prompts for a REPL to open when none was found for the
  current buffer.
- REPL handlers must now follow the naming convention "*/open*-repl".
  e.g. +python/open-ipython-repl, +emacs-lisp/open-repl, etc.
- +eval/open-repl has been split in two:
  - +eval/open-repl-other-window
  - +eval/open-repl-same-window
This commit is contained in:
Henrik Lissner 2019-02-18 01:56:38 -05:00
parent 4437d80133
commit 94b16cba6c
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
19 changed files with 83 additions and 52 deletions

View file

@ -52,7 +52,8 @@ Invoked via:
+ =SPC o r= or ~:repl~ will open a REPL in a popup window. =C-u SPC o r= or
~:repl!~ will open a REPL in the current window. If a REPL is already open and
a selection is active, it will be sent to the REPL.
+ ~M-x +eval/open-repl~
+ ~M-x +eval/open-repl-other-window~
+ ~M-x +eval/open-repl-same-window~
+ ~M-x +eval/send-region-to-repl~ while a selection (and REPL) is active
* Configuration
@ -60,8 +61,9 @@ Invoked via:
REPLs are defined for most languages Doom supports. Check that language module's
README.org to see if it does (and if it requires additional setup).
To use them, you may use ~M-x +eval/open-repl~, ~:repl~ (for evil users) or the
default binding: =SPC o r=. These will open a REPL in a popup window.
To use them, you may use ~M-x +eval/open-repl-other-window~, ~M-x
+eval/open-repl-same-window~, ~:repl~ (for evil users) or the default binding:
=SPC o r=. These will open a REPL in a popup window.
#+begin_quote
You can simply call that mode's REPL command manually. e.g. ~M-x ielm~, but
@ -75,12 +77,12 @@ FUNCTION should return a repl buffer. Any window changes in this function are
ignored, then the REPL is opened in a popup window.
#+BEGIN_SRC emacs-lisp
(defun +lua/repl ()
(defun +lua/open-repl ()
(interactive)
(lua-start-process "lua" "lua")
(pop-to-buffer lua-process-buffer))
(set-repl-handler! 'lua-mode #'+lua/repl)
(set-repl-handler! 'lua-mode #'+lua/open-repl)
#+END_SRC
** Change how code is evaluated in a major mode

View file

@ -19,5 +19,5 @@
:move-point nil
(interactive "<r><!>")
(if (evil-normal-state-p)
(+eval/open-repl bang)
(+eval/open-repl-other-window bang)
(+eval/send-region-to-repl beg end bang)))

View file

@ -6,7 +6,7 @@
(define-minor-mode +eval-repl-mode
"A minor mode for REPL buffers.")
(defun +eval--ensure-in-repl-buffer (&optional command same-window-p)
(defun +eval--ensure-in-repl-buffer (&optional command other-window-p)
(maphash (lambda (key buffer)
(unless (buffer-live-p buffer)
(remhash key +eval-repl-buffers)))
@ -16,7 +16,7 @@
(buffer (gethash key +eval-repl-buffers)))
(cl-check-type buffer (or buffer null))
(unless (eq buffer (current-buffer))
(funcall (if same-window-p #'switch-to-buffer #'pop-to-buffer)
(funcall (if other-window-p #'pop-to-buffer #'switch-to-buffer)
(if (buffer-live-p buffer)
buffer
(setq buffer
@ -36,19 +36,51 @@
(point-max)))
buffer)))
(defun +eval-open-repl (prompt-p other-window-p)
(let ((command (cdr (assq major-mode +eval-repls))))
(when (or (not command) 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 command
(intern-soft
(format "+%s/open-%srepl" module
(if (string= repl "default")
""
repl))))))
(unless (commandp command)
(error "Couldn't find a valid REPL for %s" major-mode))
(when (+eval--ensure-in-repl-buffer command other-window-p)
(when (bound-and-true-p evil-mode)
(call-interactively #'evil-append-line))
t)))
;;;###autoload
(defun +eval/open-repl (&optional same-window-p)
(defun +eval/open-repl-same-window (&optional arg)
"Opens (or reopens) the REPL associated with the current major-mode and place
the cursor at the prompt.
If SAME-WINDOW-P is non-nil, open REPL in current window."
If ARG (universal argument), prompt for a specific REPL to open."
(interactive "P")
(if-let* ((command (cdr (assq major-mode +eval-repls))))
(when (+eval--ensure-in-repl-buffer command same-window-p)
(when (bound-and-true-p evil-mode)
(call-interactively #'evil-append-line))
t)
(user-error "No REPL is defined for %s" major-mode)))
(+eval-open-repl arg))
;;;###autoload
(defun +eval/open-repl-other-window (&optional arg)
"Does `+eval/open-repl', but in a popup window.
If ARG (universal argument), prompt for a specific REPL to open."
(interactive "P")
(+eval-open-repl arg t))
;;;###autoload
(defun +eval/send-region-to-repl (beg end &optional auto-execute-p)

View file

@ -6,7 +6,7 @@
;;;###autoload
(defvar +eval-repls nil
"An alist mapping major modes to plists that describe REPLs. Used by
`+eval/open-repl' and filled with the `:repl' setting.")
`+eval/open-repl-other-window' and filled with the `:repl' setting.")
;;;###autodef
(defun set-repl-handler! (modes command)