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
;;editorconfig ; let someone else argue about tabs vs spaces
;;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
;;flyspell ; tasing you for misspelling mispelling
;;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/editorconfig/README.org][editorconfig]]:
+ [[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
+ flyspell: Spell checking
+ gist:

View file

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

View file

@ -18,11 +18,13 @@
- [[Troubleshooting][Troubleshooting]]
* Description
This modules adds inline code evaluation support to Emacs, and supplies a
universal interface for opening and interacting with REPLs.
This modules adds inline code evaluation support to Emacs and a universal
interface for opening and interacting with REPLs.
** 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
+ [[https://github.com/syohex/emacs-quickrun][quickrun]]

View file

@ -1,5 +1,51 @@
;;; 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
(defun +eval/buffer ()
"Evaluate the whole buffer."

View file

@ -1,12 +1,16 @@
;;; 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
(setq eval-expression-print-length nil
eval-expression-print-level nil)
;;
;; Packages
;;; Packages
(set-popup-rule!
(lambda (bufname _)
@ -26,15 +30,6 @@
(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 ()
"Make `quickrun-replace-region' recognize evil visual selections."
:override #'quickrun--outputter-replace-region
@ -51,17 +46,47 @@
(insert output))
(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
(defun +eval-quickrun-shrink-window-h ()
"Shrink the quickrun output window once code evaluation is complete."
(when-let (win (get-buffer-window quickrun--buffer-name))
(with-selected-window (get-buffer-window quickrun--buffer-name)
(let ((ignore-window-parameters t))
(shrink-window-if-larger-than-buffer))))))
(add-hook! 'quickrun-after-run-hook
(shrink-window-if-larger-than-buffer)))))
(defun +eval-quickrun-scroll-to-bof-h ()
"Ensures window is scrolled to BOF on invocation."
(when-let (win (get-buffer-window quickrun--buffer-name))
(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
(package! quickrun)
(when (featurep! +overlay)
(package! eros))