Is there a way to make <menu> a prefix key in emacs? - emacs

I'm trying to get vimish-fold to work, and it does work. The problem is that I want to bind it to the menu key instead of the M key.
(progn
(define-prefix-command 'my-menu-key-map)
(define-key vimish-fold-mode (kdb "v f") 'vimish-fold)
(define-key vimish-fold-mode (kdb "v u") 'vimish-fold-refold)
)
(global-set-key (kdb "<menu>") my-menu-key-map)
I essentially want menu v f -> vimish-fold and menu v u -> vimish-fold-refold. The problem I'm having is it's giving me an error telling me I have the wrong type argument.
Error in private config: init.el, (wrong-type-argument keymapp nil)

You have some repeated typos:
(kdb should be (kbd
(define-key vimish-fold-mode should be (define-key my-menu-key-map

Related

How to change window-numbering default key binding

The default key binding is below:
(defvar window-numbering-keymap
(let ((map (make-sparse-keymap)))
(define-key map "\M-0" 'select-window-0)
(define-key map "\M-1" 'select-window-1)
(define-key map "\M-2" 'select-window-2)
(define-key map "\M-3" 'select-window-3)
(define-key map "\M-4" 'select-window-4)
(define-key map "\M-5" 'select-window-5)
(define-key map "\M-6" 'select-window-6)
(define-key map "\M-7" 'select-window-7)
(define-key map "\M-8" 'select-window-8)
(define-key map "\M-9" 'select-window-9)
map)
"Keymap used in by `window-numbering-mode'.")
I want to use the key "Command (s)" instead of Meta, I change the key binding like this:
(define-key map "\s-1" 'select-window-1)
but it doesn't work. In minibuffer: s-1 is undefined.
As #Drew said, changing "\s-1" to (kbd "s-1") works OK. Thank you Drew.

Elisp: call keymap from code?

Here's a minimal snippet to get things going:
(define-prefix-command 'foo)
(define-key foo "a" 'bar)
(define-key foo "b" 'baz)
(global-set-key (kbd "C-M-r") 'foo)
Now I can "call" the foo keymap when I press C-M-r.
But I wonder how I can do this from code, e.g. something like:
(funcall (lambda-from-keymap 'foo))
After this call, I expect the focus to be in the minibuffer, expecting either
a, or b or C-h to be entered.
Is something like this possible?
You can use read-key-sequence and lookup-key to implement this:
(defun call-keymap (map &optional prompt)
"Read a key sequence and call the command it's bound to in MAP."
;; Note: MAP must be a symbol so we can trick `describe-bindings' into giving
;; us a nice help text.
(let* ((overriding-local-map `(keymap (,map . ,map)))
(help-form `(describe-bindings ,(vector map)))
(key (read-key-sequence prompt))
(cmd (lookup-key map key t)))
(if (functionp cmd) (call-interactively cmd)
(user-error "%s is undefined" key))))
If you hit C-h read-key-sequence still waits for you to complete the sequence. I think you could simulate Emacs' normal behaviour by looping with read-key instead, it's a bit more involved though.
Use it like this:
(defun bar () (interactive) (message "you called bar"))
(defun baz () (interactive) (message "you called baz"))
(define-prefix-command 'foo)
(define-key foo "a" 'bar)
(define-key foo "b" 'baz)
(global-set-key (kbd "C-M-r") 'foo)
(defun call-foo ()
(interactive)
;; Note: pass the symbol form of the keymap so we can give nice help
(call-keymap 'foo "enter a foo command: "))
(global-set-key (kbd "C-c f") 'call-foo)
If the keymap is bound to a key sequence, you can invoke it by emulating the exact key sequence by setting unread-command-events:
(setq unread-command-events
(mapcar (lambda (e) `(t . ,e))
(listify-key-sequence (kbd "C-M-r"))
You need to have foo interactive. I did so using:
(global-set-key (kbd "C-M-r") (lambda () (interactive) ( foo)))
This should fix your problem.

undefine empty prefix keys recursively

There is an emacs extension that build keys to very unhandy location and I reassign key bindings in my .emacs file just after loading extension. I've peeked into the extension code, it uses no variables or defcustoms that may be passed prior its loading.
I disable existing bindings with (define-key ... nil) at first, and rebind them after that.
The issue is that all prefix bindings chain remains to live and pollutes my keyboard settings.
How can I remove all empty (with no children registered) prefix key recursively?
update with example
Assume map is an empty sparse keymap.
(define-key map (kbd "C-c M-p b") 'do-first)
(define-key map (kbd "C-c M-p b f g") 'do-second)
(define-key map (kbd "C-c M-p b r s") 'do-third)
(define-key map (kbd "C-c M-p b r s") nil)
(define-key map (kbd "C-c M-p b f g") nil)
(define-key map (kbd "C-c M-p b") nil)
After that I'd like to use some kind of function like (clean-map map) to make map empty again.
Unfortunately, there is no simple solution.
(defun eab/delete-sublist (sublst lst)
(read (replace-regexp-in-string
(prin1-to-string sublst)
""
(prin1-to-string lst))))
(defun clean-map (target-map)
(let ((map target-map))
(cl-flet ((clean-keymaps
(event def)
(if (keymapp def)
(if (keymap-emptyp def)
(progn
(setq map
(eab/delete-sublist (cons event def) map))
(map-keymap 'clean-keymaps map))
(map-keymap 'clean-keymaps def)))))
(map-keymap 'clean-keymaps map)
map)))
(defun keymap-emptyp (keymap)
(if (keymapp keymap)
(if (or (and
(eq 2 (length keymap))
(not (cdr (cadr keymap))))
(equal keymap '(keymap)))
't
nil)
nil))
(keymap-emptyp '(keymap (110))) => t
(keymap-emptyp '(keymap)) => t
(keymap-emptyp '(keymap (110) (103 . do-second))) => nil
(setq test-map (make-sparse-keymap))
(define-key test-map (kbd "C-c M-p b f k") 'do-first)
(define-key test-map (kbd "C-c M-p b f g") 'do-second)
(define-key test-map (kbd "C-c M-p b r s n") 'do-third)
(define-key test-map (kbd "C-c M-p b r s n") nil)
Before: there are two recursive prefix bindings, "r" and "r s".
C-c M-p b f Prefix Command
C-c M-p b r Prefix Command
C-c M-p b r s Prefix Command
C-c M-p b f g do-second
C-c M-p b f k do-first
(setq test-map (clean-map test-map))
After: it's cleaned.
C-c M-p b f Prefix Command
C-c M-p b f g do-second
C-c M-p b f k do-first
If #phils got you right, and using his example, you can do this:
(global-set-key (kbd "C-c b") nil)
That way the empty prefix is cleared.

One-Key Macros in Emacs

I am trying to use One-Key Macros (as was written here)
(defun toggle-kbd-macro-recording-on ()
"One-key keyboard macros: turn recording on."
(interactive)
(define-key
global-map
(events-to-keys (this-command-keys) t)
'toggle-kbd-macro-recording-off)
(start-kbd-macro nil))
(defun toggle-kbd-macro-recording-off ()
"One-key keyboard macros: turn recording off."
(interactive)
(define-key
global-map
(events-to-keys (this-command-keys) t)
'toggle-kbd-macro-recording-on)
(end-kbd-macro))
(global-set-key '[(f1)] 'call-last-kbd-macro)
(global-set-key '[(shift f1)] 'toggle-kbd-macro-recording-on)
But when I press Shift-F1 I get error:
define-key: Symbol's function
definition is void: events-to-keys
How can I fix it?
The events-to-keys function seems to be something obsolete. From what I can tell, it should work by just writing:
(defun toggle-kbd-macro-recording-on ()
"One-key keyboard macros: turn recording on."
(interactive)
(define-key
global-map
(this-command-keys)
'toggle-kbd-macro-recording-off)
(start-kbd-macro nil))
(defun toggle-kbd-macro-recording-off ()
"One-key keyboard macros: turn recording off."
(interactive)
(define-key
global-map
(this-command-keys)
'toggle-kbd-macro-recording-on)
(end-kbd-macro))
(global-set-key '[(f1)] 'call-last-kbd-macro)
(global-set-key '[(shift f1)] 'toggle-kbd-macro-recording-on)

remap emacs key

I would like to remap a key in emacs, for example { and i would it to trigger usual event.
Example, i remapped alt + ( to get { and i would like, when i use a plugin like autopair to give me the associated }.
I tried this :
(global-set-key [(alt \()] ( lambda () (interactive) (insert "{") ))
It inserts { correctly but does not trigger autopair hooks.
Is there a way to achieve it ?
Try (not tested):
(define-key key-translation-map (kbd "M-(") (kbd "{"))