tools/eval: add +overlay feature

Now, inline evaluation will display results in an overlay next to the
cursor, rather than in the minibuffer (unless it gets too big, in which
case it'll use a popup buffer).
This commit is contained in:
Henrik Lissner 2019-10-26 01:37:36 -04:00
parent c2f6aa3e9d
commit 84a063ca78
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
7 changed files with 111 additions and 33 deletions

View file

@ -76,7 +76,7 @@
;;docker ;;docker
;;editorconfig ; let someone else argue about tabs vs spaces ;;editorconfig ; let someone else argue about tabs vs spaces
;;ein ; tame Jupyter notebooks with emacs ;;ein ; tame Jupyter notebooks with emacs
eval ; run code, run (also, repls) (eval +overlay) ; run code, run (also, repls)
flycheck ; tasing you for every semicolon you forget flycheck ; tasing you for every semicolon you forget
;;flyspell ; tasing you for misspelling mispelling ;;flyspell ; tasing you for misspelling mispelling
;;gist ; interacting with github gists ;;gist ; interacting with github gists

View file

@ -84,7 +84,7 @@ Small modules that give Emacs access to external tools & services.
+ [[file:tools/direnv/README.org][direnv]]: + [[file:tools/direnv/README.org][direnv]]:
+ [[file:tools/editorconfig/README.org][editorconfig]]: + [[file:tools/editorconfig/README.org][editorconfig]]:
+ [[file:tools/ein/README.org][ein]]: + [[file:tools/ein/README.org][ein]]:
+ [[file:tools/eval/README.org][eval]]: REPL & code evaluation support for a variety of languages + [[file:tools/eval/README.org][eval]] =+overlay=: REPL & code evaluation support for a variety of languages
+ flycheck: Live error/warning highlights + flycheck: Live error/warning highlights
+ flyspell: Spell checking + flyspell: Spell checking
+ gist: + gist:

View file

@ -7,19 +7,23 @@
(defun +emacs-lisp-eval (beg end) (defun +emacs-lisp-eval (beg end)
"Evaluate a region and print it to the echo area (if one line long), otherwise "Evaluate a region and print it to the echo area (if one line long), otherwise
to a pop up buffer." to a pop up buffer."
(require 'pp) (+eval-display-results
(let ((debug-on-error t) (let* ((buffer-file-name (buffer-file-name (buffer-base-buffer))))
(buffer-file-name (buffer-file-name (buffer-base-buffer))) (string-trim-right
(doom--current-module (ignore-errors (doom-module-from-path buffer-file-name))) (condition-case-unless-debug e
(temp-buffer-show-hook (let ((result
(cons (if (fboundp '+word-wrap-mode) (let ((debug-on-error t))
'+word-wrap-mode (eval (read (buffer-substring-no-properties beg end))
'visual-line-mode) `((buffer-file-name . ,buffer-file-name)
temp-buffer-show-hook))) (doom--current-module
(pp-eval-expression . ,(ignore-errors
(read (buffer-substring-no-properties beg end))) (doom-module-from-path buffer-file-name))))))))
(when-let (win (get-buffer-window "*Pp Eval Output*")) (if (stringp result)
(fit-window-to-buffer win)))) result
(require 'pp)
(pp-to-string result)))
(error (error-message-string e)))))
(current-buffer)))
(defvar +emacs-lisp--face nil) (defvar +emacs-lisp--face nil)
;;;###autoload ;;;###autoload

View file

@ -18,11 +18,13 @@
- [[Troubleshooting][Troubleshooting]] - [[Troubleshooting][Troubleshooting]]
* Description * Description
This modules adds inline code evaluation support to Emacs, and supplies a This modules adds inline code evaluation support to Emacs and a universal
universal interface for opening and interacting with REPLs. interface for opening and interacting with REPLs.
** Module Flags ** Module Flags
This module has no flags. + =+overlay= Enables the use of overlays (near the cursor) to display the result
of inline code evaluation (rather than the minibuffer). That is, unless the
results are too big, in which case it will still fall back to popup buffers.
** Plugins ** Plugins
+ [[https://github.com/syohex/emacs-quickrun][quickrun]] + [[https://github.com/syohex/emacs-quickrun][quickrun]]

View file

@ -1,5 +1,51 @@
;;; tools/eval/autoload/eval.el -*- lexical-binding: t; -*- ;;; tools/eval/autoload/eval.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +eval-display-results-in-popup (output &optional source-buffer)
"Display OUTPUT in a popup buffer."
(let ((output-buffer (get-buffer-create "*doom eval*"))
(origin (selected-window)))
(with-current-buffer output-buffer
(setq-local scroll-margin 0)
(erase-buffer)
(insert output)
(goto-char (point-min))
(if (fboundp '+word-wrap-mode)
(+word-wrap-mode +1)
(visual-line-mode +1)))
(when-let (win (display-buffer output-buffer))
(fit-window-to-buffer win))
(select-window origin)
output-buffer))
;;;###autoload
(defun +eval-display-results-in-overlay (output &optional source-buffer)
"Display OUTPUT in a floating overlay next to the cursor."
(let ((this-command #'+eval/buffer-or-region)
eros-overlays-use-font-lock)
(with-current-buffer (or source-buffer (current-buffer))
(eros--make-result-overlay output
:where (line-end-position)
:duration eros-eval-result-duration))))
;;;###autoload
(defun +eval-display-results (output &optional source-buffer)
"Display OUTPUT in an overlay or a popup buffer."
(funcall (if (and (or current-prefix-arg
(with-temp-buffer
(insert output)
(>= (count-lines (point-min) (point-max))
+eval-overlay-max-lines)))
(require 'eros nil t))
#'+eval-display-results-in-popup
#'+eval-display-results-in-overlay)
output source-buffer)
output)
;;
;;; Commands
;;;###autoload ;;;###autoload
(defun +eval/buffer () (defun +eval/buffer ()
"Evaluate the whole buffer." "Evaluate the whole buffer."

View file

@ -1,12 +1,16 @@
;;; tools/eval/config.el -*- lexical-binding: t; -*- ;;; tools/eval/config.el -*- lexical-binding: t; -*-
(defvar +eval-overlay-max-lines 4
"The output height threshold (inclusive) before output is displayed in a popup
buffer rather than an overlay on the line at point.")
;; remove ellipsis when printing sexps in message buffer ;; remove ellipsis when printing sexps in message buffer
(setq eval-expression-print-length nil (setq eval-expression-print-length nil
eval-expression-print-level nil) eval-expression-print-level nil)
;; ;;
;; Packages ;;; Packages
(set-popup-rule! (set-popup-rule!
(lambda (bufname _) (lambda (bufname _)
@ -26,15 +30,6 @@
(set-popup-rule! "^\\*quickrun" :size 0.3 :ttl 0) (set-popup-rule! "^\\*quickrun" :size 0.3 :ttl 0)
(defadvice! +eval--quickrun-auto-close-a (&rest _)
"Allows us to silently re-run quickrun from within the quickrun buffer."
:before '(quickrun quickrun-region)
(when-let (win (get-buffer-window quickrun--buffer-name))
(let ((inhibit-message t))
(quickrun--kill-running-process)
(message ""))
(delete-window win)))
(defadvice! +eval--quickrun-fix-evil-visual-region-a () (defadvice! +eval--quickrun-fix-evil-visual-region-a ()
"Make `quickrun-replace-region' recognize evil visual selections." "Make `quickrun-replace-region' recognize evil visual selections."
:override #'quickrun--outputter-replace-region :override #'quickrun--outputter-replace-region
@ -51,17 +46,47 @@
(insert output)) (insert output))
(setq quickrun-option-outputter quickrun--original-outputter)))) (setq quickrun-option-outputter quickrun--original-outputter))))
(defadvice! +eval--quickrun-auto-close-a (&rest _)
"Silently re-create the quickrun popup when re-evaluating."
:before '(quickrun quickrun-region)
(when-let (win (get-buffer-window quickrun--buffer-name))
(let ((inhibit-message t))
(quickrun--kill-running-process)
(message ""))
(delete-window win)))
(add-hook! 'quickrun-after-run-hook (add-hook! 'quickrun-after-run-hook
(defun +eval-quickrun-shrink-window-h () (defun +eval-quickrun-shrink-window-h ()
"Shrink the quickrun output window once code evaluation is complete." "Shrink the quickrun output window once code evaluation is complete."
(when-let (win (get-buffer-window quickrun--buffer-name)) (when-let (win (get-buffer-window quickrun--buffer-name))
(with-selected-window (get-buffer-window quickrun--buffer-name) (with-selected-window (get-buffer-window quickrun--buffer-name)
(let ((ignore-window-parameters t)) (let ((ignore-window-parameters t))
(shrink-window-if-larger-than-buffer)))))) (shrink-window-if-larger-than-buffer)))))
(add-hook! 'quickrun-after-run-hook
(defun +eval-quickrun-scroll-to-bof-h () (defun +eval-quickrun-scroll-to-bof-h ()
"Ensures window is scrolled to BOF on invocation." "Ensures window is scrolled to BOF on invocation."
(when-let (win (get-buffer-window quickrun--buffer-name)) (when-let (win (get-buffer-window quickrun--buffer-name))
(with-selected-window win (with-selected-window win
(goto-char (point-min))))))) (goto-char (point-min))))))
;; Display evaluation results in an overlay next to the cursor. If the output
;; is more than 4 lines long, it is displayed in a popup.
(when (featurep! +overlay)
(defadvice! +eval--inhibit-quickrun-popup-a (buf cb)
:override #'quickrun--pop-to-buffer
(setq quickrun--original-buffer (current-buffer))
(with-current-buffer buf
(setq quickrun-option-outputter #'ignore)
(funcall cb)))
(advice-add #'quickrun--recenter :override #'ignore)
(add-hook! 'quickrun-after-run-hook
(defun +eval-display-in-popup-overlay-h ()
(+eval-display-results
(with-current-buffer quickrun--buffer-name
(string-trim (buffer-string)))
quickrun--original-buffer)))))
(use-package! eros
:when (featurep! +overlay)
:hook (emacs-lisp-mode . eros-mode))

View file

@ -2,4 +2,5 @@
;;; tools/eval/packages.el ;;; tools/eval/packages.el
(package! quickrun) (package! quickrun)
(when (featurep! +overlay)
(package! eros))