[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: accessible-keymaps gives wrong result for autoloaded prefix keys
From: |
Drew Adams |
Subject: |
RE: accessible-keymaps gives wrong result for autoloaded prefix keys |
Date: |
Tue, 3 Oct 2006 09:35:14 -0700 |
My fix doesn't cause accessible-keymaps to return "the right result".
E.g. if 2C-command contains a prefix key such as [f2 f1], it
would return just (([f2] . 2C-command)) even, whereas after
autoloading the map accessible-keyamps would return
(([f2] keymap ...) ([f2 f1] keymap ...))
I see. But I think that would be OK, for my code at least. I test the cdr to
see if it is `keymapp', and (keymapp '2C-command) returns t. If a user then
chooses that prefix to complete, the code accesses that keymap (for possible
completion against its keys).
> - I have code that calls `map-keymap' for each accessible
> keymap. I want it to also pick up the `f2' keymap and other
> autoloaded keymaps.
> FYI - My code lets you complete key sequences using
> minibuffer completion against the key name (description)
> plus the binding. In the case of a keymap
> binding (prefix key), you can descend into the prefix to continue
> completing. This is similar to completion of file and directory names
> (command ~ file, prefix key ~ directory) or completion of menu items
> (command ~ menu item, prefix key ~ submenu). IOW, you can
> navigate through the set of key bindings currently accessible.
> Without this fix, the effect, when you complete (i.e. choose) `f2',
> is that I can only raise an error: "No
> keys for prefix `f2'", which is misleading.
I don't understand why you need accessible-keymaps at all, then.
E.g. before C-x is entered, you don't need to know that there's another
prefix on C-x v.
Yes, it's true that I only need to know one level at a time. (That's why I
said that ([f2] . 2C-comand) would be enough for me. When the user chooses
that completion candidate, keymap `2C-command' is used, and so on.)
I don't know a function that will give me that one-level info, however;
`accessible-keymaps' seems to be the only thing of that kind, even if it's
perhaps overkill here. Suggestions welcome.
Here is the code, in case it helps suggest what I might do better. The calls
to `accessible-keymaps' are in `icicle-keys+cmds-w-prefix'.
(defun icicle-complete-keys-1 (prefix)
"Complete a key sequence for prefix key PREFIX (a vector)."
(let* ((icicle-list-join-string " = ")
(icicle-list-end-string "")
(keys+cmds (icicle-keys+cmds-w-prefix prefix)))
(unless keys+cmds (error "No keys for prefix `%s'" prefix))
(let* ((this-cmd-keys (this-command-keys-vector))
(prefix-description
(icicle-key-description
prefix icicle-key-descriptions-use-<>-flag))
(candidate
(completing-read
(concat "Complete keys"
(and (not (string= "" prefix-description))
(concat " " prefix-description))
": ")
keys+cmds nil t)))
(string-match (concat "\\(.+\\)" icicle-list-join-string
"\\(.+\\)") candidate)
(let ((key (save-match-data
(condition-case nil
(icicle-read-kbd-macro
(substring
candidate (match-beginning 1) (match-end 1))
t
(not icicle-key-descriptions-use-<>-flag))
(error nil))))
(cmd (substring
candidate (match-beginning 2) (match-end 2))))
(cond ((and (string= "..." cmd) key)
(setq last-command 'icicle-complete-keys)
(icicle-complete-keys-1 (vconcat prefix key)))
(t
(setq cmd (read cmd))
(setq this-command cmd last-command cmd)
(when (eq 'self-insert-command cmd)
(unless key (error "Cannot insert `%s'" key))
(setq last-command-char (aref key 0)))
(condition-case try-command
(call-interactively cmd nil this-cmd-keys)
(error
(error (error-message-string try-command))))))))))
(defun icicle-keys+cmds-w-prefix (prefix)
"Return alist of keys and bindings for prefix key PREFIX (a vector)."
(let* ((current-global (current-global-map))
(current-local (or overriding-terminal-local-map
overriding-local-map (current-local-map)))
(maps-from-global
(and current-global (accessible-keymaps current-global prefix)))
(maps-from-local
(and current-local (accessible-keymaps current-local prefix)))
(keys+maps
(mapcar #'car
(mapcar (lambda (map) (accessible-keymaps map prefix))
(current-minor-mode-maps))))
(keys+cmds nil))
(when maps-from-local (push (car maps-from-local) keys+maps))
(when maps-from-global (push (car maps-from-global) keys+maps))
(if (null keys+maps)
nil
(dolist (keys+map keys+maps)
(when (keymapp (cdr keys+map))
(map-keymap
(lambda (event binding)
(cond ((and (or (commandp binding) (keymapp binding))
(or (not (eq 'self-insert-command binding))
(char-valid-p event)))
(push `((,(single-key-description
event
(not icicle-key-descriptions-use-<>-flag))
,(if (keymapp binding)
"..." ; Prefix key
(format "%S" binding))))
keys+cmds))
((and (integerp event) (generic-char-p event)
(eq 'self-insert-command binding))
(ignore)))) ; Placeholder, for now.
(cdr keys+map))))
keys+cmds)))