[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Call CMD w/ keybinding VS execute-extended-command: redisplay behaviour
From: |
Tino Calancha |
Subject: |
Call CMD w/ keybinding VS execute-extended-command: redisplay behaviour |
Date: |
Sun, 25 Mar 2018 18:32:38 +0900 |
Dear Emacs,
I have defined a command (see below snippet code) which updates
the header line in a buffer inheriting from tabulated-list.
The effect on the header line is visible inmediately, i.e.,
the screen is automatically redisplayed, but...
* If I bind this command to 'r', then there is no automatic
redisplay anymore; I need to push some keys until a
window redisplay is fired.
* If I call the command and rigth after run `repeat', i.e. `C-x z'
then the header line is not automatically updated either.
Is there a reason why it is preferable this distintion between
calling a command with a keybinding VS calling
it via `execute-extended-command'?
I wish the keybinding 'r' update the screen as well.
How can I do that?
Note: I don't want to revert the buffer, just redisplay the header line.
To reproduce, create a file foo.el with following content:
--8<-----------------------------cut here---------------start------------->8---
(defvar foo-format
[("Category" 12 t)
("Knight (best friend: hadoken)" 30 t)
("Energy" 50 t)]
"Table format.")
(defvar foo-mode nil "Save status of the `foo-mode'.")
(defun foo-tabulated-list-entries ()
(setq tabulated-list-entries
'((1 ["bronze" "Seiya" "98"]) (2 ["bronze" "Shiryu" "95"])))
(tabulated-list-init-header))
(defun foo ()
(interactive)
(let ((foo-buffer (generate-new-buffer "*foo*")))
(switch-to-buffer foo-buffer)
(or foo-mode (foo-mode))
(setq tabulated-list-use-header-line t)
(foo-tabulated-list-entries)
(tabulated-list-print)))
(defun foo--new-knight()
(let ((knights '("Ikki" "Shun" "Hyoga")))
(nth (random (length knights)) knights)))
(defun foo-update-friend()
"Update header line with new friend."
(interactive)
(let ((regexp "Knight (best friend: \\([^)]+\\))")
(knight-new (foo--new-knight)))
(when (string-match regexp header-line-format)
(let ((knight (match-string 1 header-line-format)))
(while (string= knight knight-new) (setq knight-new (foo--new-knight)))
(setq header-line-format
(replace-match
knight-new nil nil header-line-format 1))
(message "Updated knight to: '%s'" knight-new)
;; Don't regenerate all rows because it might be expensive;
;; just redisplay the header line.
(redisplay)))))
;;; Foo Mode map
(defvar foo-mode-map
(let ((map (make-keymap)))
(define-key map (kbd "r") 'foo-update-friend)
map))
;;; Define mode
(define-derived-mode foo-mode tabulated-list-mode "Foo"
(setq tabulated-list-format foo-format))
--8<-----------------------------cut here---------------end--------------->8---
emacs -Q -l foo.el:
M-x foo RET
;; Note the difference between the following:
M-x foo-update-friend RET
;; Updates the knight's friend in the header line, i.e., the name
;; showed in the minibuffer matches the friend name in the header line.
r
;; It doesn't update the knight's friend; you can see that name in the
;; minibuffer doesn't match the one in the header line. If you input
;; something for example if you use the down arrow, then the header
;; line is updated.