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

@ -590,7 +590,7 @@
:desc "Jump to definition" "d" #'+lookup/definition :desc "Jump to definition" "d" #'+lookup/definition
:desc "Evaluate buffer/region" "e" #'+eval/buffer-or-region :desc "Evaluate buffer/region" "e" #'+eval/buffer-or-region
:desc "Format buffer/region" "f" #'+format/region-or-buffer :desc "Format buffer/region" "f" #'+format/region-or-buffer
:desc "Open REPL" "r" #'+eval/open-repl :desc "Open REPL" "r" #'+eval/open-repl-other-window
:desc "Delete trailing whitespace" "w" #'delete-trailing-whitespace :desc "Delete trailing whitespace" "w" #'delete-trailing-whitespace
:desc "List errors" "x" #'flycheck-list-errors) :desc "List errors" "x" #'flycheck-list-errors)
@ -703,7 +703,8 @@
:desc "Org agenda" "a" #'org-agenda :desc "Org agenda" "a" #'org-agenda
:desc "Default browser" "b" #'browse-url-of-file :desc "Default browser" "b" #'browse-url-of-file
:desc "Debugger" "d" #'+debug/open :desc "Debugger" "d" #'+debug/open
:desc "REPL" "r" #'+eval/open-repl :desc "REPL" "r" #'+eval/open-repl-other-window
:desc "REPL (same window)" "R" #'+eval/open-repl-same-window
:desc "Dired" "-" #'dired-jump :desc "Dired" "-" #'dired-jump
(:when (featurep! :ui neotree) (:when (featurep! :ui neotree)
:desc "Project sidebar" "p" #'+neotree/open :desc "Project sidebar" "p" #'+neotree/open

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 + =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 ~: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. 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 + ~M-x +eval/send-region-to-repl~ while a selection (and REPL) is active
* Configuration * Configuration
@ -60,8 +61,9 @@ Invoked via:
REPLs are defined for most languages Doom supports. Check that language module's 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). 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 To use them, you may use ~M-x +eval/open-repl-other-window~, ~M-x
default binding: =SPC o r=. These will open a REPL in a popup window. +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 #+begin_quote
You can simply call that mode's REPL command manually. e.g. ~M-x ielm~, but 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. ignored, then the REPL is opened in a popup window.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(defun +lua/repl () (defun +lua/open-repl ()
(interactive) (interactive)
(lua-start-process "lua" "lua") (lua-start-process "lua" "lua")
(pop-to-buffer lua-process-buffer)) (pop-to-buffer lua-process-buffer))
(set-repl-handler! 'lua-mode #'+lua/repl) (set-repl-handler! 'lua-mode #'+lua/open-repl)
#+END_SRC #+END_SRC
** Change how code is evaluated in a major mode ** Change how code is evaluated in a major mode

View file

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

View file

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

View file

@ -6,7 +6,7 @@
;;;###autoload ;;;###autoload
(defvar +eval-repls nil (defvar +eval-repls nil
"An alist mapping major modes to plists that describe REPLs. Used by "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 ;;;###autodef
(defun set-repl-handler! (modes command) (defun set-repl-handler! (modes command)

View file

@ -79,7 +79,7 @@ library/userland functions"
;; Commands ;; Commands
;;;###autoload ;;;###autoload
(defun +emacs-lisp/repl () (defun +emacs-lisp/open-repl ()
"Open the Emacs Lisp REPL (`ielm')." "Open the Emacs Lisp REPL (`ielm')."
(interactive) (interactive)
(pop-to-buffer (pop-to-buffer

View file

@ -14,7 +14,7 @@
(add-to-list 'auto-mode-alist '("\\.Cask\\'" . emacs-lisp-mode)) (add-to-list 'auto-mode-alist '("\\.Cask\\'" . emacs-lisp-mode))
(after! elisp-mode (after! elisp-mode
(set-repl-handler! 'emacs-lisp-mode #'+emacs-lisp/repl) (set-repl-handler! 'emacs-lisp-mode #'+emacs-lisp/open-repl)
(set-eval-handler! 'emacs-lisp-mode #'+emacs-lisp-eval) (set-eval-handler! 'emacs-lisp-mode #'+emacs-lisp-eval)
(set-lookup-handlers! 'emacs-lisp-mode (set-lookup-handlers! 'emacs-lisp-mode
:definition #'elisp-def :definition #'elisp-def

View file

@ -1,14 +1,10 @@
;;; lang/haskell/autoload.el -*- lexical-binding: t; -*- ;;; lang/haskell/autoload.el -*- lexical-binding: t; -*-
;;;###autoload ;;;###autoload
(defun +haskell-repl-buffer (&optional arg) (defun +haskell/open-repl (&optional arg)
"Returns the appropriate Haskell REPL buffer."
(if (featurep! +intero)
(intero-repl-buffer arg)
(haskell-session-interactive-buffer (haskell-session))))
;;;###autoload
(defun +haskell/repl (&optional arg)
"Opens a Haskell REPL." "Opens a Haskell REPL."
(interactive "P") (interactive "P")
(display-buffer (+haskell-repl-buffer arg))) (display-buffer
(if (featurep! +intero)
(intero-repl-buffer arg)
(haskell-session-interactive-buffer (haskell-session)))))

View file

@ -16,7 +16,7 @@
interactive-haskell-mode)) interactive-haskell-mode))
(set-lookup-handlers! 'haskell-mode :definition #'haskell-mode-jump-to-def-or-tag) (set-lookup-handlers! 'haskell-mode :definition #'haskell-mode-jump-to-def-or-tag)
(set-file-template! 'haskell-mode :trigger #'haskell-auto-insert-module-template :project t) (set-file-template! 'haskell-mode :trigger #'haskell-auto-insert-module-template :project t)
(set-repl-handler! '(haskell-mode haskell-cabal-mode literate-haskell-mode) #'+haskell-repl-buffer) (set-repl-handler! '(haskell-mode haskell-cabal-mode literate-haskell-mode) #'+haskell/open-repl)
(add-to-list 'completion-ignored-extensions ".hi") (add-to-list 'completion-ignored-extensions ".hi")

View file

@ -34,5 +34,5 @@ sudo pacman --needed --noconfirm -S nodejs npm
** Commands ** Commands
| command | key / ex command | description | | command | key / ex command | description |
|----------------------------------+------------------+------------------------------------------------------------| |----------------------------------+------------------+------------------------------------------------------------|
| ~+javascript/repl~ | =:repl= | Open the NodeJS REPL (or send the current selection to it) | | ~+javascript/open-repl~ | =:repl= | Open the NodeJS REPL (or send the current selection to it) |
| ~+javascript/skewer-this-buffer~ | =SPC m S= | Attaches a browser to the current buffer | | ~+javascript/skewer-this-buffer~ | =SPC m S= | Attaches a browser to the current buffer |

View file

@ -36,7 +36,7 @@ ignore the cache."
;; Commands ;; Commands
;;;###autoload ;;;###autoload
(defun +javascript/repl () (defun +javascript/open-repl ()
"Open a Javascript REPL. Meaning either `skewer-repl', if any of the "Open a Javascript REPL. Meaning either `skewer-repl', if any of the
skewer-*-mode's are enabled, or `nodejs-repl' otherwise." skewer-*-mode's are enabled, or `nodejs-repl' otherwise."
(interactive) (interactive)

View file

@ -52,7 +52,7 @@
mode-name "JS2") mode-name "JS2")
(set-electric! 'js2-mode :chars '(?\} ?\) ?. ?:)) (set-electric! 'js2-mode :chars '(?\} ?\) ?. ?:))
(set-repl-handler! 'js2-mode #'+javascript/repl) (set-repl-handler! 'js2-mode #'+javascript/open-repl)
(map! :map js2-mode-map (map! :map js2-mode-map
:localleader :localleader

View file

@ -1,7 +1,7 @@
;;; lang/lua/autoload.el -*- lexical-binding: t; -*- ;;; lang/lua/autoload.el -*- lexical-binding: t; -*-
;;;###autoload ;;;###autoload
(defun +lua/repl () (defun +lua/open-repl ()
"Open Lua REPL." "Open Lua REPL."
(interactive) (interactive)
(lua-start-process "lua" "lua") (lua-start-process "lua" "lua")

View file

@ -15,7 +15,7 @@
:config :config
(set-lookup-handlers! 'lua-mode :documentation 'lua-search-documentation) (set-lookup-handlers! 'lua-mode :documentation 'lua-search-documentation)
(set-electric! 'lua-mode :words '("else" "end")) (set-electric! 'lua-mode :words '("else" "end"))
(set-repl-handler! 'lua-mode #'+lua/repl) (set-repl-handler! 'lua-mode #'+lua/open-repl)
(set-company-backend! 'lua-mode '(company-lua company-yasnippet))) (set-company-backend! 'lua-mode '(company-lua company-yasnippet)))

View file

@ -4,7 +4,7 @@
"TODO") "TODO")
;;;###autoload ;;;###autoload
(defun +python/repl () (defun +python/open-repl ()
"Open the Python REPL." "Open the Python REPL."
(interactive) (interactive)
(unless python-shell-interpreter (unless python-shell-interpreter
@ -28,7 +28,7 @@
(interactive) (interactive)
(let ((python-shell-interpreter "ipython") (let ((python-shell-interpreter "ipython")
(python-shell-interpreter-args +python-jupyter-repl-args)) (python-shell-interpreter-args +python-jupyter-repl-args))
(+python/repl))) (+python/open-repl)))
;;;###autoload ;;;###autoload
(defun +python/open-jupyter-repl () (defun +python/open-jupyter-repl ()
@ -37,7 +37,7 @@
(add-to-list 'python-shell-completion-native-disabled-interpreters "jupyter") (add-to-list 'python-shell-completion-native-disabled-interpreters "jupyter")
(let ((python-shell-interpreter "jupyter") (let ((python-shell-interpreter "jupyter")
(python-shell-interpreter-args (format "console %s" +python-jupyter-repl-args))) (python-shell-interpreter-args (format "console %s" +python-jupyter-repl-args)))
(+python/repl))) (+python/open-repl)))
(defun +python--extract-version (prefix str) (defun +python--extract-version (prefix str)
(when str (when str

View file

@ -26,7 +26,7 @@ called.")
:config :config
(set-env! "PYTHONPATH" "PYENV_ROOT" "ANACONDA_HOME") (set-env! "PYTHONPATH" "PYENV_ROOT" "ANACONDA_HOME")
(set-electric! 'python-mode :chars '(?:)) (set-electric! 'python-mode :chars '(?:))
(set-repl-handler! 'python-mode #'+python/repl) (set-repl-handler! 'python-mode #'+python/open-repl)
(set-pretty-symbols! 'python-mode (set-pretty-symbols! 'python-mode
;; Functional ;; Functional

View file

@ -8,9 +8,9 @@ This module adds support for shell scripting languages.
+ REPL support + REPL support
* Table of Contents :TOC: * Table of Contents :TOC:
- [[#install][Install]] - [[Install][Install]]
- [[#appendix][Appendix]] - [[Appendix][Appendix]]
- [[#commands][Commands]] - [[Commands][Commands]]
* Install * Install
This module has no dependencies. This module has no dependencies.
@ -18,5 +18,5 @@ This module has no dependencies.
* Appendix * Appendix
** Commands ** Commands
| command | key / ex command | description | | command | key / ex command | description |
|------------+------------------+-------------------------------------------------------| |-----------------+------------------+-------------------------------------------------------|
| ~+sh/repl~ | =:repl= | Open a terminal (or send the current selection to it) | | ~+sh/open-repl~ | =:repl= | Open a terminal (or send the current selection to it) |

View file

@ -27,7 +27,7 @@
(defvar sh-shell-file) (defvar sh-shell-file)
;;;###autoload ;;;###autoload
(defun +sh/repl () (defun +sh/open-repl ()
"Open a shell REPL." "Open a shell REPL."
(let* ((dest-sh (symbol-name sh-shell)) (let* ((dest-sh (symbol-name sh-shell))
(sh-shell-file dest-sh)) (sh-shell-file dest-sh))

View file

@ -15,7 +15,7 @@
:mode ("/bspwmrc\\'" . sh-mode) :mode ("/bspwmrc\\'" . sh-mode)
:config :config
(set-electric! 'sh-mode :words '("else" "elif" "fi" "done" "then" "do" "esac" ";;")) (set-electric! 'sh-mode :words '("else" "elif" "fi" "done" "then" "do" "esac" ";;"))
(set-repl-handler! 'sh-mode #'+sh/repl) (set-repl-handler! 'sh-mode #'+sh/open-repl)
(setq sh-indent-after-continuation 'always) (setq sh-indent-after-continuation 'always)