refactor(eval): rewrite module

This commit is contained in:
Henrik Lissner 2026-03-10 01:36:43 -04:00
parent f8c3decb0a
commit 04ef44d9c8
No known key found for this signature in database
GPG key ID: B60957CA074D39A3
5 changed files with 302 additions and 259 deletions

View file

@ -23,7 +23,7 @@
(cond ((and (string-prefix-p "jupyter-" lang)
(require 'jupyter nil t))
(jupyter-eval-region beg end))
((+eval-region-as-major-mode beg end (org-src-get-lang-mode lang))))))))
((+eval-with-mode-handler-fn beg end nil (org-src-get-lang-mode lang))))))))
;;;###autoload

View file

@ -1,28 +1,31 @@
;;; tools/eval/autoload/eval.el -*- lexical-binding: t; -*-
(defvar quickrun-option-cmdkey)
(defvar eros-overlays-use-font-lock)
;;
;;; Library
;;;###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)))
"Display OUTPUT in a popup buffer at the bottom of the screen."
(let ((output-buffer (get-buffer-create "*doom eval*")))
(with-current-buffer output-buffer
(setq-local scroll-margin 0)
(erase-buffer)
(insert output)
(goto-char (point-min))
(save-excursion (insert output))
(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 (/ (frame-height) 2)
nil (/ (frame-width) 2)))
(select-window origin)
(when-let* ((win (display-buffer output-buffer)))
(fit-window-to-buffer win (/ (frame-height) 2)
nil (/ (frame-width) 2)))
output-buffer))
;;;###autoload
(defun +eval-display-results-in-overlay (output &optional source-buffer)
"Display OUTPUT in a floating overlay next to the cursor."
"Display OUTPUT in a floating overlay next to or below the cursor."
(require 'eros)
(with-current-buffer (or source-buffer (current-buffer))
(let* ((this-command #'+eval/buffer-or-region)
@ -31,7 +34,6 @@
(prefixlen (length prefix))
(len (+ (apply #'max (mapcar #'length lines))
prefixlen))
(col (- (current-column) (window-hscroll)))
(next-line? (or (cdr lines)
(< (- (window-width)
(save-excursion (goto-char (line-end-position))
@ -72,108 +74,90 @@
output source-buffer)
output)
;;;###autoload
(defun +eval-region-as-major-mode (beg end &optional runner-major-mode)
"Evaluate a region between BEG and END and display the output.
Evaluate as in RUNNER-MAJOR-MODE. If RUNNER-MAJOR-MODE is nil, use major-mode
of the buffer instead."
(let ((load-file-name buffer-file-name)
(load-true-file-name
(or buffer-file-truename
(if buffer-file-name
(file-truename buffer-file-name))))
(runner-major-mode (or runner-major-mode major-mode)))
(cond ((if (fboundp '+eval--ensure-in-repl-buffer)
(ignore-errors
(get-buffer-window (or (+eval--ensure-in-repl-buffer)
t))))
(funcall (or (plist-get (cdr (alist-get runner-major-mode +eval-repls)) :send-region)
#'+eval/send-region-to-repl)
beg end))
((let (lang)
(if-let* ((runner
(or (alist-get runner-major-mode +eval-runners)
(and (require 'quickrun nil t)
(equal (setq
lang (quickrun--command-key
(buffer-file-name (buffer-base-buffer))))
"emacs")
(alist-get 'emacs-lisp-mode +eval-runners)))))
(funcall runner beg end)
(let ((quickrun-option-cmdkey lang))
(quickrun-region beg end))))))))
;;
;;; Eval handlers
;;;###autoload
(defun +eval-with-mode-handler-fn (beg end &optional _type mode)
"Evaluate the selection/buffer using a mode appropriate handler.
Uses whatever handler's been registered for MODE (or the current major-mode)
with `set-eval-handler!'."
(when-let* ((fn (alist-get (or mode major-mode) +eval-handler-alist)))
(funcall fn beg end)))
;;;###autoload
(defun +eval-with-quickrun-fn (beg end &optional type)
"Evaluate the region or buffer with `quickrun'."
(when (require 'quickrun nil t)
(pcase type
(`buffer (quickrun))
(`region (quickrun-region beg end))
(`replace (quickrun-replace-region beg end)))
t))
;;
;;; Commands
(defvar quickrun-option-cmdkey)
;;;###autoload
(defun +eval/buffer ()
"Evaluate the whole buffer."
"Evaluate the whole buffer and display the output.
See `+eval-handler-functions' for order of backends this uses. By default, falls
back to `quickrun'."
(interactive)
(let ((quickrun-option-cmdkey (bound-and-true-p quickrun-option-cmdkey)))
(if (or (assq major-mode +eval-runners)
(and (fboundp '+eval--ensure-in-repl-buffer)
(ignore-errors
(get-buffer-window (or (+eval--ensure-in-repl-buffer)
t))))
(and (require 'quickrun nil t)
(equal (setq
quickrun-option-cmdkey
(quickrun--command-key
(buffer-file-name (buffer-base-buffer))))
"emacs")
(alist-get 'emacs-lisp-mode +eval-runners)))
(if-let* ((buffer-handler (plist-get (cdr (alist-get major-mode +eval-repls)) :send-buffer)))
(funcall buffer-handler)
(+eval/region (point-min) (point-max)))
(quickrun))))
(run-hook-with-args-until-success
'+eval-handler-functions (point-min) (point-max) 'buffer))
;;;###autoload
(defun +eval/region (beg end)
"Evaluate a region between BEG and END and display the output."
"Evaluate a region between BEG and END and display the output.
If a REPL is open, code will be executed there, otherwise mode-specific handlers
will be used, falling back to `quickrun' otherwise.
See `+eval-handler-functions' for order of backends this uses. By default, falls
back to `quickrun'."
(interactive "r")
(+eval-region-as-major-mode beg end))
(run-hook-with-args-until-success
'+eval-handler-functions beg end 'region))
;;;###autoload
(defun +eval/line-or-region ()
"Evaluate the current line or selected region."
"Evaluate the current line or selected region.
If a REPL is open, code will be executed there, otherwise mode-specific handlers
will be used, falling back to `quickrun' otherwise."
(interactive)
(if (use-region-p)
(call-interactively #'+eval/region)
(+eval/region (line-beginning-position) (line-end-position))))
(+eval/region (pos-bol) (pos-eol))))
;;;###autoload
(defun +eval/buffer-or-region ()
"Evaluate the region if it's active, otherwise evaluate the whole buffer.
If a REPL is open the code will be evaluated in it, otherwise a quickrun
runner will be used."
"Execute `+eval/region' if a selection is active, otherwise `+eval/buffer'."
(interactive)
(call-interactively
(if (use-region-p)
(if (doom-region-active-p)
#'+eval/region
#'+eval/buffer)))
;;;###autoload
(defun +eval/region-and-replace (beg end)
"Evaluation a region between BEG and END, and replace it with the result."
"Evaluate a region between BEG and END, and replace it with the result.
Uses `quickrun', unless in an `emacs-lisp-mode' buffer, in which case uses the
return value of `eval'."
(interactive "r")
(let (lang)
(cond
((or (eq major-mode 'emacs-lisp-mode)
(and (require 'quickrun nil t)
(equal (setq
lang (quickrun--command-key
(buffer-file-name (buffer-base-buffer))))
"emacs")))
(kill-region beg end)
(condition-case nil
(prin1 (eval (read (current-kill 0)))
(current-buffer))
(error (message "Invalid expression")
(insert (current-kill 0)))))
((let ((quickrun-option-cmdkey lang))
(quickrun-replace-region beg end))))))
(if (not (derived-mode-p 'emacs-lisp-mode))
(quickrun-replace-region beg end)
(kill-region beg end)
(condition-case nil
(prin1 (eval (read (current-kill 0)))
(current-buffer))
(error (message "Invalid expression")
(insert (current-kill 0))))))
;;; eval.el ends here

View file

@ -1,24 +1,84 @@
;;; tools/eval/autoload/repl.el -*- lexical-binding: t; -*-
(defvar evil-move-cursor-back)
;;
;;; Variables
(defvar +eval-repl-buffers (make-hash-table :test 'equal)
"The buffer of the last open repl.")
(defvar-local +eval-repl-plist nil)
(defvar +eval-repl-plist nil)
(define-minor-mode +eval-repl-mode
"A minor mode for REPL buffers.")
(defun +eval--ensure-in-repl-buffer (&optional fn plist displayfn)
;;
;;; Library
;;;###autoload
(defun +eval-current-repl-buffer (&optional mode)
"Return the last active REPL buffer associated with this buffer's major mode.
Returns nil if none is known. If multiple are known, it returns the last
accessed buffer."
(when-let* ((project-root (doom-project-root))
(key (cons (or mode major-mode) project-root))
(buffer (gethash key +eval-repl-buffers)))
(and (bufferp buffer)
(buffer-live-p buffer)
(buffer-local-value '+eval-repl-plist buffer)
buffer)))
;;;###autoload
(defun +eval-repl-select (prompt)
"Prompt the user to select a REPL.
Prompt with PROMPT, which should be a string ending with a colon and a space.
Scans `+eval-repl-handler-alist' and all known symbols that look like
*/open-*repl and returns (NAME COMMAND), where NAME is a string label and
COMMAND is a symbol for an interactive function."
(let* ((knowns
(mapcar
(lambda (spec)
(unless (fboundp (car spec))
(error "Given string/symbol is not a major mode: %s" (car spec)))
(list (string-join
(split-string
(capitalize (string-remove-suffix "-mode" (symbol-name (car spec))))
"-")
" ")
(cadr spec)))
+eval-repl-handler-alist))
(founds
(mapcar
(lambda (spec)
(list (string-join (split-string (capitalize (cadr spec)) "-") " ")
(car spec)))
(cl-loop for sym being the symbols
for sym-name = (symbol-name sym)
if (string-match "^\\(?:\\+\\)?\\([^/]+\\)/open-\\(?:\\(.+\\)-\\)?repl$" sym-name)
collect (list sym (match-string-no-properties 1 sym-name)))))
(repls (cl-delete-duplicates (append knowns founds) :test #'equal)))
(or (assoc (or (completing-read (or prompt "Open a REPL for: ")
(mapcar #'car repls))
(user-error "aborting"))
repls)
(error "couldn't find a valid repl for %s" major-mode))))
(defun +eval--repl-open (spec &optional displayfn input)
"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."
(maphash (lambda (key buffer)
(unless (buffer-live-p buffer)
(remhash key +eval-repl-buffers)))
+eval-repl-buffers)
(let* ((project-root (doom-project-root))
(key (cons major-mode project-root))
(buffer (gethash key +eval-repl-buffers)))
(cl-check-type buffer (or buffer null))
(unless (or (eq buffer (current-buffer))
(null fn))
(pcase-let ((`(_ ,fn . ,plist) spec))
(unless (commandp fn)
(error "couldn't find a valid REPL handler for %s" major-mode))
(let* ((project-root (doom-project-root))
(key (cons major-mode project-root))
buffer)
(setq buffer
(funcall (or displayfn #'get-buffer-create)
(if (buffer-live-p buffer)
@ -28,147 +88,121 @@
(if (commandp fn)
(call-interactively fn)
(funcall fn))))
(cond ((null buffer)
(error "REPL handler %S couldn't open the REPL buffer" fn))
((not (bufferp buffer))
(error "REPL handler %S failed to return a buffer" fn)))
(unless buffer
(error "REPL handler %S couldn't open the REPL buffer" fn))
(unless (bufferp buffer)
(error "REPL handler %S failed to return a buffer" fn))
(with-current-buffer buffer
(when plist
(setq +eval-repl-plist plist))
(+eval-repl-mode +1))
(setq-local +eval-repl-plist (append (list :repl t) plist)))
(puthash key buffer +eval-repl-buffers)
buffer))))
(when (bufferp buffer)
(with-current-buffer buffer
(unless (or (derived-mode-p 'term-mode)
(eq (current-local-map) (bound-and-true-p term-raw-map)))
(goto-char (if (and (derived-mode-p 'comint-mode)
(cdr comint-last-prompt))
(cdr comint-last-prompt)
(point-max)))))
buffer)))
buffer)))
(when (bufferp buffer)
(with-current-buffer buffer
(unless (or (derived-mode-p 'term-mode)
(eq (current-local-map) (bound-and-true-p term-raw-map)))
(goto-char (if (and (derived-mode-p 'comint-mode)
(cdr comint-last-prompt))
(cdr comint-last-prompt)
(point-max))))
(when (bound-and-true-p evil-local-mode)
(call-interactively #'evil-append-line))
(when input
(insert input))
t)))))
(defun +eval-repl-known-repls ()
"Yield the available repl functions as a list of symbols."
(cl-delete-duplicates
(mapcar (lambda! ((mode fn &rest _)) (list mode fn))
+eval-repls)))
(defun +eval--repl-sender-for (mode &optional beg end)
(when-let*
((plist (cdr (alist-get mode +eval-repl-handler-alist)))
(fn (or (plist-get plist (if (and beg end) :send-region :send-buffer))
(unless (and beg end) (plist-get plist :send-region)))))
(if (and beg end)
(lambda () (funcall fn beg end))
fn)))
(defun +doom-pretty-mode-name (mode)
"Convert a mode name into a variant nicer for human eyes."
(let ((mode (if (symbolp mode) (symbol-name mode) mode)))
(if (not (string-match "^\\([a-z-]+\\)-mode$" mode))
(error "Given string/symbol is not a major mode: %s" mode)
(string-join (split-string (capitalize (match-string-no-properties 1 mode))
"-")
" "))))
(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-pretty-mode-name-from-fn (fn)
"Given a symbol name of a repl-opening function, extract a
human-readable variant of its associated major mode name."
(let ((name (symbol-name fn)))
(if (not (string-match "^\\(?:\\+\\)?\\([^/]+\\)/open-\\(?:\\(.+\\)-\\)?repl$" name))
(error "Given symbol is not a repl function: %s" name)
(string-join (split-string (capitalize (match-string-no-properties 1 name))
"-")
" "))))
(defun +eval-repl-prompt ()
"Prompt the user for the choice of a repl to open."
(let* ((knowns (mapcar (lambda! ((mode fn)) (list (+doom-pretty-mode-name mode) fn))
(+eval-repl-known-repls)))
(founds (mapcar (lambda (fn) (list (+eval-pretty-mode-name-from-fn fn) fn))
(+eval-repl-found-repls)))
(repls (cl-delete-duplicates (append knowns founds) :test #'equal))
(names (mapcar #'car repls))
(choice (or (completing-read "Open a REPL for: " names)
(user-error "Aborting"))))
(cadr (assoc choice repls))))
(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 (if (or prompt-p (not fn)) (+eval-repl-prompt) 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
;;; Eval handlers
;;;###autoload
(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.
(defun +eval-with-repl-fn (beg end &optional type)
"Evaluate the region between BEG and END (inclusive) in an open REPL.
If ARG (universal argument), prompt for a specific REPL to open."
(interactive "P")
(+eval-open-repl arg #'switch-to-buffer))
;;;###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 #'pop-to-buffer))
;;;###autoload
(defun +eval/send-region-to-repl (beg end &optional inhibit-auto-execute-p)
"Execute the selected region in the REPL.
Opens a REPL if one isn't already open. If AUTO-EXECUTE-P, then execute it
immediately after."
(interactive "rP")
(let ((buffer (+eval--ensure-in-repl-buffer)))
(unless buffer
(error "No REPL open"))
(let* ((region (buffer-substring-no-properties beg end))
(region
(with-temp-buffer
(save-excursion (insert region))
(when (> (skip-chars-forward "\n") 0)
(delete-region (point-min) (point)))
(indent-rigidly (point-min) (point-max) (- (current-indentation)))
(buffer-string))))
(with-selected-window (get-buffer-window buffer)
(with-current-buffer buffer
(goto-char (point-max))
(dolist (line (split-string region "\n"))
(insert line)
(if inhibit-auto-execute-p
(insert "\n")
;; Can't use `comint-send-input' b/c there's no guarantee the
;; current REPL uses comint. Even if it did, no telling if they
;; have their own `comint-send-input' wrapper, so to be safe, I
;; simply emulate the keypress.
If no REPL is open, do nothing. TYPE can be `buffer' or `region' to determine
what sender to use, if one's been registered with the repl for the current major
mode."
(when-let* ((buf (+eval-current-repl-buffer))
((get-buffer-window buf)))
(if-let* ((fn (if (eq type 'buffer)
(+eval--repl-sender-for major-mode)
(+eval--repl-sender-for major-mode beg end))))
(funcall fn)
;; Manually feed selection line-by-line if this repl has no
;; :send-buffer/:send-region properties for its `set-repl-handler!'
;; handler. This is a last resort and may be rife with edge cases.
(let* ((region (buffer-substring-no-properties beg end))
(region
(with-temp-buffer
(save-excursion (insert region))
(when (> (skip-chars-forward "\n") 0)
(delete-region (point-min) (point)))
(indent-rigidly (point-min) (point-max) (- (current-indentation)))
(buffer-string))))
(with-selected-window (get-buffer-window buf)
(with-current-buffer buf
(goto-char (point-max))
(dolist (line (split-string region "\n"))
(insert line)
;; HACK: Can't use `comint-send-input' b/c there's no guarantee
;; the current REPL uses comint. Even if it did, no telling if
;; they have their own `comint-send-input' wrapper, so to be
;; safe, I simply emulate the keypress.
(if (bound-and-true-p evil-local-mode)
(let (evil-move-cursor-back)
(evil-save-state
(evil-append-line 1)
(call-interactively (doom-lookup-key (kbd "RET")))))
(call-interactively (doom-lookup-key (kbd "RET")))))))))))
(call-interactively (doom-lookup-key (kbd "RET"))))))))
t)))
;;
;;; Commands
;;;###autoload
(defun +eval/open-repl-same-window (&optional spec input)
"Opens (or reopens) the REPL associated with the current major-mode and place
the cursor at the prompt.
If ARG (universal argument), prompt for a specific REPL to open."
(interactive
(list (or (unless current-prefix-arg
(assq major-mode +eval-repl-handler-alist))
(+eval-repl-select "Open REPL in this window: "))
(doom-region)))
(+eval--repl-open spec #'switch-to-buffer input))
;;;###autoload
(defun +eval/open-repl-other-window (&optional spec input)
"Does `+eval/open-repl', but in a popup window.
If ARG (universal argument), prompt for a specific REPL to open."
(interactive
(list (or (unless current-prefix-arg
(assq major-mode +eval-repl-handler-alist))
(+eval-repl-select "Open REPL in popup: "))
(doom-region)))
(+eval--repl-open spec #'pop-to-buffer input))
;;;###autoload
(defun +eval/buffer-or-region-in-repl (&optional beg end buffer?)
"Execute the selected region or whole buffer in the REPL."
(interactive "rP")
(unless (+eval-current-repl-buffer)
(call-interactively #'+eval/open-repl-other-window))
(let* ((region? (and (not buffer?) (doom-region-active-p)))
(type (if region? 'region 'buffer))
(beg (if region? beg (point-min)))
(end (if region? end (point-max))))
(+eval-with-repl-fn beg end type)))
;;; repl.el ends here

View file

@ -1,9 +1,10 @@
;;; tools/eval/autoload/settings.el -*- lexical-binding: t; -*-
;;
;; REPLs
;;; REPLs
(defvar +eval-repls nil
;;;###autoload
(defvar +eval-repl-handler-alist nil
"An alist mapping major modes to plists that describe REPLs. Used by
`+eval/open-repl-other-window' and filled with the `:repl' setting.")
@ -27,20 +28,20 @@ recognized:
A function that accepts a BEG and END, and sends the contents of the region
to the REPL. Defaults to `+eval/send-region-to-repl'.
:send-buffer FUNC
A function of no arguments that sends the contents of the buffer to the REPL.
Defaults to `+eval/region', which will run the :send-region specified function
or `+eval/send-region-to-repl'."
A function of no arguments that sends the contents of the buffer to the
REPL. Defaults to `+eval/region', which will run the :send-region specified
function or `+eval/send-region-to-repl'."
(declare (indent defun))
(dolist (mode (ensure-list modes))
(setf (alist-get mode +eval-repls)
(setf (alist-get mode +eval-repl-handler-alist)
(cons command plist))))
;;
;; Evaluation
;;; Evaluation
;;;###autoload
(defvar +eval-runners nil
(defvar +eval-handler-alist nil
"Alist mapping major modes to interactive runner functions.")
;;;###autodef
@ -57,20 +58,22 @@ MODES can be list of major mode symbols, or a single one.
3. If MODE is not a string and COMMAND is an alist, see `quickrun-add-command':
(quickrun-add-command MODE COMMAND :mode MODE).
4. If MODE is not a string and COMMANd is a symbol, add it to
`+eval-runners', which is used by `+eval/region'."
`+eval-handler-alist', which is used by `+eval/region'."
(declare (indent defun))
(dolist (mode (ensure-list modes))
(cond ((symbolp command)
(push (cons mode command) +eval-runners))
(setf (alist-get mode +eval-handler-alist nil t)
command))
((stringp command)
(after! quickrun
(push (cons mode command)
(if (stringp mode)
quickrun-file-alist
quickrun--major-mode-alist))))
(setf (alist-get mode (if (stringp mode)
quickrun-file-alist
quickrun--major-mode-alist)
nil t)
command)))
((listp command)
(after! quickrun
(quickrun-add-command
(or (cdr (assq mode quickrun--major-mode-alist))
(or (alist-get mode quickrun--major-mode-alist)
(string-remove-suffix "-mode" (symbol-name mode)))
command :mode mode))))))

View file

@ -1,16 +1,37 @@
;;; tools/eval/config.el -*- lexical-binding: t; -*-
(defvar +eval-popup-min-lines 4
"The output height threshold (inclusive) before output is displayed in a popup
buffer rather than an overlay on the line at point or the minibuffer.")
(defgroup +eval nil
"Tools and commands for evaluating code universally and managing REPLs."
:group 'doom+)
;; remove ellipsis when printing sexps in message buffer
(setq eval-expression-print-length nil
eval-expression-print-level nil)
(defcustom +eval-handler-functions
'(+eval-with-repl-fn
+eval-with-mode-handler-fn
+eval-with-quickrun-fn)
"A list of functions to execute when evaluating a region/buffer.
Stops at the first function to return non-nil. Each function takes three
arguments: a beginning position (int), an end position (int), and a symbol
(either `region' or `buffer') to hint at the scope of the evaluation.
Only affects `+eval/region', `+eval/buffer', and any other command that use
these them."
:type 'hook
:group '+eval)
(defcustom +eval-popup-min-lines 4
"The output height threshold (inclusive) before output is displayed in a popup
buffer rather than an overlay on the line at point or the minibuffer."
:type 'integer
:group '+eval)
;;
;;; Packages
;;; Config
;; Remove ellipsis when printing sexps in message buffer
(setq eval-expression-print-length nil
eval-expression-print-level nil)
;; These commands are drop-in replacements, but present an overlay/popup to
;; display the return value, and emit a backtrace if an error is encountered.
@ -19,8 +40,8 @@ buffer rather than an overlay on the line at point or the minibuffer.")
(set-popup-rule!
(lambda (bufname _)
(when (boundp '+eval-repl-mode)
(buffer-local-value '+eval-repl-mode (get-buffer bufname))))
(and (boundp '+eval-repl-plist)
(buffer-local-value '+eval-repl-plist (get-buffer bufname))))
:ttl (lambda (buf)
(unless (plist-get +eval-repl-plist :persist)
(when-let* ((process (get-buffer-process buf)))
@ -53,7 +74,8 @@ buffer rather than an overlay on the line at point or the minibuffer.")
(defadvice! +eval--quickrun-auto-close-a (&rest _)
"Silently re-create the quickrun popup when re-evaluating."
:before '(quickrun quickrun-region)
:before #'quickrun
:before #'quickrun-region
(when-let* ((win (get-buffer-window quickrun--buffer-name)))
(let ((inhibit-message t))
(quickrun--kill-running-process)
@ -64,18 +86,18 @@ buffer rather than an overlay on the line at point or the minibuffer.")
(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)
(with-selected-window win
(let ((ignore-window-parameters t))
(shrink-window-if-larger-than-buffer)))))
(defun +eval-quickrun-scroll-to-bof-h ()
"Ensures window is scrolled to BOF on invocation."
"Ensures cursor is at beginning of output window when displayed."
(when-let* ((win (get-buffer-window quickrun--buffer-name)))
(with-selected-window win
(goto-char (point-min))))))
;; Display evaluation results in an overlay at the end of the current line. If
;; the output is more than `+eval-popup-min-lines' (4) lines long, it is
;; displayed in a popup.
;; HACK: Display evaluation results in an overlay at the end of the current
;; line. If the output is more than `+eval-popup-min-lines' (4) lines long,
;; it is displayed in a popup.
(when (modulep! +overlay)
(defadvice! +eval--show-output-in-overlay-a (fn)
:filter-return #'quickrun--make-sentinel
@ -87,7 +109,7 @@ buffer rather than an overlay on the line at point or the minibuffer.")
(string-trim (buffer-string))
quickrun--original-buffer)))))
;; Suppress quickrun's popup window because we're using an overlay instead.
;; HACK: Suppress quickrun's popup because we're using an overlay instead.
(defadvice! +eval--inhibit-quickrun-popup-a (buf cb)
:override #'quickrun--pop-to-buffer
(setq quickrun--original-buffer (current-buffer))