emacs-pretest-bug
[Top][All Lists]
Advanced

[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)))







reply via email to

[Prev in Thread] Current Thread [Next in Thread]