如何重新定义 "minibuffer" 模式映射中的键?

8
我正在尝试重新定义在接受正则表达式并提供C-p / C-n历史记录导航的多个命令内导航历史时使用的键。我想使用其他键,而不仅仅是C-p / C-n。例如,在使用occurreplace-regexp时,可以使用C-p和C-n来转到上一个和下一个元素。
我尝试了几种方法,但无法使其工作。我认为我在这里缺少“大局观”。
我需要修改哪个mode-map,在何时以及如何进行修改?我尝试的所有方法都失败了。
P.S:请注意,我有自己的小模式,其中包含所有建图,如此处所建议。
2个回答

7

我假设您只需要minibuffer-local-map。后续使用先前分配给该键映射的键的定义将覆盖先前的定义。要禁用先前的键分配,只需创建一个新定义并将最后一部分设置为nil而不是'function-name

(define-key minibuffer-local-map (kbd "<f6>") 'help-for-help)

这是来自Emacs Trunk .../lisp/bindings.el的一部分内容:

(let ((map minibuffer-local-map))
  (define-key map "\en"   'next-history-element)
  (define-key map [next]  'next-history-element)
  (define-key map [down]  'next-history-element)
  (define-key map [XF86Forward] 'next-history-element)
  (define-key map "\ep"   'previous-history-element)
  (define-key map [prior] 'previous-history-element)
  (define-key map [up]    'previous-history-element)
  (define-key map [XF86Back] 'previous-history-element)
  (define-key map "\es"   'next-matching-history-element)
  (define-key map "\er"   'previous-matching-history-element)
  ;; Override the global binding (which calls indent-relative via
  ;; indent-for-tab-command).  The alignment that indent-relative tries to
  ;; do doesn't make much sense here since the prompt messes it up.
  (define-key map "\t"    'self-insert-command)
  (define-key map [C-tab] 'file-cache-minibuffer-complete))

使用您的define-key,我确实可以将<f6>分配给previous-history-element,这是一个好的开始,但是...我仍然无法重新定义我在自己的小模式键中使用的键:即使我尝试首先将其设置为nil - Cedric Martin
如果需要修改自己的小型模式,那么以下是一个基于你所分配的任何名称的示例:(add-hook 'minibuffer-setup-hook (lambda () (define-key cedric-martin-mode-map (kbd "<f5>") nil) (define-key cedric-martin-mode-map (kbd "<f6>") 'help-for-help) )) (add-hook 'minibuffer-exit-hook (lambda () (define-key cedric-martin-mode-map (kbd "<f5>") 'help-for-help) (define-key cedric-martin-mode-map (kbd "<f6>") nil) )) - lawlist
你也可以修改自己的 minor mode,通过使用类似如下内容的条件语句,根据焦点是否在 minibuffer 中来指定按键绑定:(cond ((minibufferp) [插入按键定义]) (t [插入按键定义]))。如果这样做,你就不需要使用 setup 和 exit hooks 了。 - lawlist
非常感谢您的所有帮助,我正在慢慢地开始“领会”它 :) - Cedric Martin
太好了!多亏了你的评论,我终于让它工作了,但是还有一些我不理解的东西:为什么我的自定义cedric-martin-mode-map小模式会与minibuffer模式“冲突”或取代它?每次出现冲突的按键映射时都需要使用钩子似乎有点“奇怪”,不是吗?无论如何,它现在能用了,这太棒了 :) - Cedric Martin
显示剩余2条评论

6

除了 @lawlist 提到的将按键绑定到 minibuffer-local-map 中之外:

有多个 minibuffer 按键映射,具体取决于 minibuffer 中读取的内容以及读取方式。你可能想要使用其中哪些按键映射也取决于你使用的 Emacs 版本。

此外,还有用于与缓冲区 *Completions* 交互的按键映射:completion-list-mode-map

对于 minibuffer 中的完成操作,主要的按键映射是 minibuffer-local-completion-map

以下是 minibuffer 的按键映射列表。其中一些可能在你的 Emacs 版本中不可用(未被使用)。

  • minibuffer-local-map
  • minibuffer-local-ns-map
  • minibuffer-local-isearch-map
  • minibuffer-local-completion-map
  • minibuffer-local-must-match-map
  • minibuffer-local-filename-completion-map
  • minibuffer-local-filename-must-match-map
  • minibuffer-local-must-match-filename-map

此外,你可以使用 minibuffer-with-setup-hook(或直接使用 minibuffer-setup-hook)在单个 minibuffer 读取期间动态添加按键绑定。

我将添加这些信息,因为当你操作 minibuffer 按键映射时,这些信息可能非常有用:你可以使用来自库 help-fns+.el 的命令 C-h M-k(命令名称为describe-keymap)以人类可读的形式查看给定 minibuffer 按键映射的所有绑定。


给你们两个点赞。我总是尽量使用最新版本的Emacs。我几天/几周前编译了24.3.50.1版本。我会安装你建议的辅助函数,然后尝试修改这些映射。 - Cedric Martin
由于您正在使用最新的开发快照,因此通常可以忽略 *-filename-* 映射。如果您正在使用完成,则可以忽略列出的前两个映射。如果您没有使用 Isearch,则可以忽略 *-isearch-* 映射。 - Drew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接