6

I would like to define a function which behaves differently depending on the last keystroke. More specifically I would like that it behaves differently if the last keystroke (before the execution of that function) has been <home>. Like below

(defun foo ()
  (interactive)
  (if (the-last-keystroke-is-home)
     (message "yes")
    (message "no")))
  • 3
    Why not re-bind <home> and do your thing there? – stsquad Jun 3 '15 at 8:58
  • 2
    Is it the key that really matters, or the command? If it's the command, last-command is probably what you want. If it's the key, look at key-chord.el. – Gilles 'SO- stop being evil' Jun 3 '15 at 18:13
  • @Gilles for my case, the key matters, thanks for mentioning key-chord. I will look at. – Name Jun 3 '15 at 18:22
5

You could take advantage of the recent-keys function. It returns a vector of the last 300 events.

Using

(defun get-last-key ()
  (interactive)
  (let ((vect (recent-keys)))
    (aref vect (1- (length vect)))))

And then doing C-x C-e on

(get-last-key)

You will get

5 (#o5, #x5, ?\C-e)

You will "just" have to compare this to the keystroke you want.

Note that as suggested by @stsquad, when you will call this function, your last keystroke probably won't be <home> (more likely <return>). So depending on what you want to achieve, re-binding <home> might be the way to go.


If you want a "readable" key, use the single-key-description function. To be thorough, you should also use prin1-to-string:

(defun get-last-key ()
  (interactive)
  (let* ((vect (recent-keys))
        (key (aref vect (1- (length vect)))))
        (if (or (integerp key) (symbolp key) (listp key))
            (single-key-description key)
            (prin1-to-string key nil)))
        )

(get-last-key); C-xC-e will give the string "C-e"
  • Regardless of the previous keystrokes,doing C-x C-e on (get-last-key) gives only 5. Also the value of (if (equal (get-last-key) "home") is always nil. I think I misunderstand something here. – Name Jun 3 '15 at 10:15
  • Use single-key-description then. You will have to compare to "<home>" – fredtantini Jun 3 '15 at 10:35
  • 1
    last-command-event might be useful. A few other related functions and variables are : this-command-keys, this-single-command-keys, this-command-keys-vector, this-single-command-raw-keys and possibly current-prefix-arg. – YoungFrog Jun 3 '15 at 11:37
  • Thanks now if I in my original function I put (defun foo () (interactive) (if (equal get-last-key "<home>") (message "yes") (message "no"))), then if I make <home> then running foo, I expect that the message "yes" to be printed, but it prints "no". I think it is because of the line (aref vect (1- (length vect)) in your code. I seems that it get the last entry of the recent-keys vector, but it should take the entry before the last entry. – Name Jun 3 '15 at 12:25
  • Depending on the keystroke changing (aref vect (1- (length vect))) to (aref vect (- (length vect) n)) where n is a convenient number can do the job. – Name Jun 3 '15 at 15:57
3
(defun foo (keys)
  (interactive "kUse a key sequence: ")
  (let ((ks  (this-single-command-keys)))
    (setq ks  (aref ks (1- (length ks))))
    (if (eq 'home ks) (message "yes") (message "no"))))

Get rid of the argument and the interactive spec, if you intend to use this in a context where a key sequence has already been read and you want to test it.

Wrt other attempts shown here so far: Don't test key descriptions (strings). Test the actual key/event values.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.