Skip to content

Commit c07438d

Browse files
committed
Remove evil--ex-expression
As after-change-functions such as evil--ex-update are not guaranteed to run, this commit ensures evil-ex re-parses the final Ex command string instead of relying on evil--ex-expression. This makes the workaround in commit 6afd86b (Fix for evil-ex-teardown, 2025-01-03) to not overwrite a shortcut in evil--ex-expression no longer necessary. Closes #1949
1 parent 9adbebd commit c07438d

File tree

1 file changed

+26
-28
lines changed

1 file changed

+26
-28
lines changed

evil-ex.el

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -310,15 +310,15 @@ The following symbols have reserved meanings within a grammar:
310310
(defvar evil-ex-reverse-range nil
311311
"Whether the current Ex range was entered reversed.")
312312

313-
(defvar evil--ex-expression nil
314-
"The Ex evaluation tree.")
315-
316313
(defvar evil--ex-cmd nil
317314
"The current Ex command string.")
318315

319316
(defvar evil--ex-argument-handler nil
320317
"The argument handler for the current Ex command.")
321318

319+
(defvar evil--ex-shortcut-command nil
320+
"Interactive command to use instead of an Ex command.")
321+
322322
(define-error 'evil-ex-error "Ex syntax error")
323323

324324
(defun evil-ex-p ()
@@ -353,7 +353,7 @@ the initial input is the visual region '<,'> or `<,`>. The variable
353353
(let ((buffer (current-buffer))
354354
(previous-command (when evil-want-empty-ex-last-command
355355
(car evil-ex-history)))
356-
s evil--ex-expression evil--ex-cmd evil--ex-argument-handler)
356+
s evil--ex-cmd evil--ex-argument-handler evil--ex-shortcut-command)
357357
(minibuffer-with-setup-hook
358358
(lambda ()
359359
(setq-local evil-ex-original-buffer buffer)
@@ -366,17 +366,17 @@ the initial input is the visual region '<,'> or `<,`>. The variable
366366
(or initial-input
367367
(and previous-command (propertize previous-command 'face 'shadow)))
368368
evil-ex-completion-map nil 'evil-ex-history)))
369-
(if evil--ex-expression
370-
(eval evil--ex-expression t)
369+
(if evil--ex-shortcut-command
370+
(call-interactively evil--ex-shortcut-command)
371371
(when (string= s "") (setq s previous-command))
372-
(unless (= (length s) 0) (evil-ex-execute s)))))
372+
(unless (string= s "") (evil-ex-execute s)))))
373373

374374
(defun evil-ex-execute (string)
375375
"Execute STRING as an Ex command."
376376
(eval (or (evil-ex-parse string) (signal 'evil-ex-error string)) t))
377377

378-
(defun evil-ex-parse (string &optional syntax entrypoint)
379-
"Parse STRING as an Ex expression and return an evaluation tree.
378+
(defun evil-ex-parse (&optional string syntax entrypoint)
379+
"Parse STRING as an Ex expression and return its evaluation tree.
380380
If STRING is nil, parse the text after point instead. If SYNTAX is
381381
non-nil, return a syntax tree instead. ENTRYPOINT is the start
382382
symbol, which defaults to `expression'."
@@ -416,7 +416,7 @@ actions during Ex state."
416416
"Return non-nil if the string COMMAND has a \"!\" suffix."
417417
(and (> (length command) 1) (eq (aref command (1- (length command))) ?!)))
418418

419-
(defun evil--ex-update (&optional beg _end _len string)
419+
(defun evil--ex-update (&optional beg _end _old-len)
420420
"Update Ex variables when the minibuffer changes.
421421
This function is usually called from `after-change-functions'
422422
hook. If BEG is non-nil (which is the case when called from
@@ -425,22 +425,22 @@ in case of incomplete or unknown commands."
425425
(when (and beg (eq this-command #'self-insert-command))
426426
(let ((cmd (lookup-key evil-ex-shortcut-map (minibuffer-contents-no-properties))))
427427
(when (commandp cmd)
428-
(setq evil--ex-expression `(call-interactively #',cmd))
428+
(setq evil--ex-shortcut-command cmd)
429429
(exit-minibuffer))))
430430

431-
(setq evil--ex-expression (save-excursion (goto-char (minibuffer-prompt-end))
432-
(evil-ex-parse string))
433-
evil--ex-cmd nil)
434-
(when (eq (car evil--ex-expression) #'evil-ex-call-command)
435-
(let (current-prefix-arg func handler evil-ex-range evil-ex-bang evil-ex-argument)
431+
(setq evil--ex-cmd nil)
432+
(let ((expr (save-excursion (goto-char (minibuffer-prompt-end))
433+
(evil-ex-parse)))
434+
func handler current-prefix-arg evil-ex-range evil-ex-bang evil-ex-argument)
435+
(when (eq (car expr) #'evil-ex-call-command)
436436
(with-current-buffer evil-ex-original-buffer
437-
(let* ((range (eval (nth 1 evil--ex-expression) t))
437+
(let* ((range (eval (nth 1 expr) t))
438438
(count (when (integerp range) range)))
439439
(setq current-prefix-arg count
440440
evil-ex-range (if count (evil-ex-range count count) range)
441-
evil--ex-cmd (eval (nth 2 evil--ex-expression) t)
441+
evil--ex-cmd (eval (nth 2 expr) t)
442442
evil-ex-bang (evil--ex-bang-p evil--ex-cmd)
443-
evil-ex-argument (eval (nth 3 evil--ex-expression) t))))
443+
evil-ex-argument (eval (nth 3 expr) t))))
444444
(cond
445445
((not beg))
446446
;; Test the current command when called from `after-change-functions'
@@ -451,8 +451,7 @@ in case of incomplete or unknown commands."
451451
(if (eq handler evil--ex-argument-handler)
452452
(let ((runner (evil-ex-argument-handler-runner handler)))
453453
(when runner (funcall runner 'update evil-ex-argument)))
454-
(let ((runner (evil-ex-argument-handler-runner
455-
evil--ex-argument-handler)))
454+
(let ((runner (evil-ex-argument-handler-runner evil--ex-argument-handler)))
456455
(when runner (funcall runner 'stop)))
457456
(setq evil--ex-argument-handler handler)
458457
(let ((runner (evil-ex-argument-handler-runner handler)))
@@ -465,9 +464,6 @@ in case of incomplete or unknown commands."
465464
(defun evil-ex-teardown ()
466465
"Deinitialize Ex minibuffer.
467466
Clean up everything set up by `evil-ex-setup'."
468-
(when (eq this-command #'exit-minibuffer)
469-
;; Call ex--update one last time, in case after-change-functions are combined
470-
(evil--ex-update))
471467
(let ((runner (evil-ex-argument-handler-runner evil--ex-argument-handler)))
472468
(when runner (funcall runner 'stop))))
473469

@@ -747,6 +743,8 @@ This function interprets special file names like # and %."
747743
(unless (zerop (length evil-ex-argument))
748744
(evil-ex-replace-special-filenames evil-ex-argument)))
749745

746+
(define-error 'evil-ex-no-previous-cmd "No previous command line")
747+
750748
(defun evil-ex-repeat (&optional count)
751749
"Repeat the last Ex command."
752750
(interactive "P")
@@ -756,10 +754,10 @@ This function interprets special file names like # and %."
756754
(cl-loop
757755
with evil-ex-original-buffer = (current-buffer)
758756
for last-cmd in evil-ex-history do
759-
(evil--ex-update nil nil nil last-cmd)
760-
(let ((expr (or evil--ex-expression (signal 'evil-ex-error last-cmd))))
761-
(unless (eq (evil-ex-binding evil--ex-cmd) #'evil-ex-repeat)
762-
(cl-return (eval expr t))))))
757+
(condition-case nil
758+
(cl-return (let (evil-ex-history) (evil-ex-execute last-cmd)))
759+
(evil-ex-no-previous-cmd))
760+
finally (signal 'evil-ex-no-previous-cmd nil)))
763761

764762
(defun evil-ex-call-command (range command argument)
765763
"Execute the given command COMMAND."

0 commit comments

Comments
 (0)