Execute commands like Marty McFly
in category ui-hacksInspired by Cameron Desautels’s post and this discussion on /r/emacs I thought about ways to automate "reading the future". For some commands I would like to see the default value right away.
Commands like switch-to-buffer
already include it in their prompt, but can
we peek into the future for those which don’t? — Just kidding, of course we
can: this is Emacs!
(defvar mcfly-commands
'(query-replace-regexp
flush-lines
keep-lines))
(defvar mcfly-back-commands
'(self-insert-command
ivy-yank-char
ivy-yank-word
ivy-yank-symbol))
(defun mcfly-back-to-present ()
(remove-hook 'pre-command-hook 'mcfly-back-to-present t)
(cond ((and (memq last-command mcfly-commands)
(equal (this-command-keys-vector) (kbd "M-p")))
;; repeat one time to get straight to the first history item
(setq unread-command-events
(append unread-command-events
(listify-key-sequence (kbd "M-p")))))
((memq this-command mcfly-back-commands)
(delete-region (point)
(point-max)))))
(defun mcfly-time-travel ()
(when (memq this-command mcfly-commands)
(let* ((kbd (kbd "M-n"))
(cmd (key-binding kbd))
(future (and cmd
(with-temp-buffer
(when (ignore-errors
(call-interactively cmd) t)
(buffer-string))))))
(when future
(save-excursion
(insert (propertize future 'face 'shadow)))
(add-hook 'pre-command-hook 'mcfly-back-to-present nil t)))))
;; setup code
(add-hook 'minibuffer-setup-hook #'mcfly-time-travel)
(with-eval-after-load 'ivy
(push (cons 'swiper 'mcfly-swiper)
ivy-hooks-alist)
(defun mcfly-swiper ()
(let ((sym (with-ivy-window
(thing-at-point 'symbol))))
(when sym
(add-hook 'pre-command-hook 'mcfly-back-to-present nil t)
(save-excursion
(insert (propertize sym 'face 'shadow)))))))
For commands added to the mcfly-commands
variable the default value will be
shown in the minibuffer and you can accept it with RET. When you start
typing the preview is removed automatically. There are probably some edge
cases where the above hack fails, so feel free to submit improvements
here.
I updated the code with an example how to achieve something similar for
swiper
. A similar method could be used for any command using ivy
:
(with-eval-after-load 'ivy
(push (cons 'swiper 'mcfly-swiper)
ivy-hooks-alist)
(defun mcfly-swiper ()
(let ((sym (with-ivy-window
(thing-at-point 'symbol))))
(when sym
(add-hook 'pre-command-hook 'mcfly-back-to-present nil t)
(save-excursion
(insert (propertize sym 'face 'shadow)))))))