4

我的大多数书签都以一个字母为前缀,第一个字母几乎总是唯一地确定书签。例如,通过这种方式,我可以使用M-x bookmark-jump RET s RET. 我把它放在快捷方式上,所以它实际上是~ s RET.

我想RET 最终摆脱,即得到M-x bookmark-quick-jump RET s ~ s 做上述工作。我还希望它恢复到默认行为:向我显示以给定字母开头的所有书签,以防万一不只有一个变体。

到目前为止,我有:

(defun bookmark-do-quick-jump (str)
  (let ((completions (all-completions str bookmark-alist)))
    (bookmark-jump
     (if (eq 1 (length completions))
         (car completions)
       (completing-read "Jump to bookmark: " bookmark-alist nil t str)))))

还有两个小插曲:

首先,我需要以某种方式跳入 minibuffer 并将这张地图贴在那里(不知道该怎么做):

(setq bookmark-quick-jump-map
      (let ((map (make-sparse-keymap)))
        (mapcar (lambda (key) 
                  (define-key map key 
                    (lambda()
                      (interactive)
                      (bookmark-do-quick-jump key))))
                (loop for c from ?a to ?z
                      collect (string c)))
        map))

其次,当我打电话时

(bookmark-do-quick-jump "o")

它带有 3 个变体(org-capture-last-stored、org-capture-last-stored-marker...)。我现在在 minibuffer 中,但我仍然需要按下 RET RET 才能看到这 3 个变体。我希望这可以自动完成。

只要我能获得我所描述的行为和可用性,我将不胜感激任何直接回答我的两个子问题或完全不同的方法的回答。

升级版:

我通过从切换completing-read到解决了第二件事ido-completing-read

(defun bookmark-do-quick-jump (str)
  (let ((completions (all-completions str bookmark-alist)))
    (bookmark-jump
     (if (eq 1 (length completions))
         (car completions)
       (ido-completing-read "Jump to bookmark: " completions nil t str)))))

顺便说一句,我忘了提到我使用bookmark+. 我不确定默认情况下是否支持跳转到 dired bookmark-jump

4

3 回答 3

2

我们可以self-insert-command在完成读取期间重新映射以触发自动完成和自动接受行为。

我最初使用(or (minibuffer-complete-and-exit) (minibuffer-completion-help))的乍一看效果很好,但正如评论中所指出的,当一个书签的名称是另一个书签的前缀时,它并不理想,因为它会立即接受较短的名称,从而使较长的名称无法访问。

然而,调用minibuffer-completeminibuffer-completion-help一起破坏了完成功能,因此我将相关部分复制minibuffer-complete-and-exit到了一个新函数中。使用它可以解决所有早期的问题。

(require 'bookmark)

(defvar bookmark-do-quick-jump-map (copy-keymap minibuffer-local-must-match-map)
  "Keymap for `bookmark-do-quick-jump'.

`minibuffer-local-must-match-map' is used by `completing-read' when its
REQUIRE-MATCH argument is t.

In `bookmark-do-quick-jump' we bind this modified copy to use in its place.")

(define-key bookmark-do-quick-jump-map
  [remap self-insert-command] 'my-self-insert-complete-and-exit)

(defun bookmark-do-quick-jump ()
  "Jump to specified bookmark with auto-completion and auto-acceptance."
  (interactive)
  (bookmark-maybe-load-default-file)
  (let ((minibuffer-local-must-match-map bookmark-do-quick-jump-map))
    (bookmark-jump
     (completing-read "Jump to bookmark: " bookmark-alist nil t))))

(defun my-self-insert-complete-and-exit (n)
  "Insert the character, then attempt to complete the current string,
automatically exiting when only one option remains, and displaying the
completion options otherwise."
  (interactive "p")
  (self-insert-command n)
  (my-minibuffer-complete)
  (let ((my-completions (completion-all-sorted-completions)))
    (if (and my-completions (eq 0 (cdr my-completions)))
        (exit-minibuffer)
      (minibuffer-completion-help))))

(defun my-minibuffer-complete ()
  "Copied from `minibuffer-complete-and-exit'."
  (interactive)
  (condition-case nil
      (completion--do-completion nil 'expect-exact)
    (error 1)))

编辑:

我使用 ido 对此进行了另一次尝试。有点不幸的是,您没有像使用常规 minibuffer 完成一样突出显示下一个“重要字符”(因为这是下一步键入内容的一个很好的指标),但这似乎在其他方面工作得很好.

(require 'bookmark)
(require 'ido)

(defvar bookmark-ido-quick-jump-map (copy-keymap minibuffer-local-map)
  "Keymap for `bookmark-ido-quick-jump'.

Every time `ido-completing-read' is called it re-initializes
`ido-common-completion-map' and sets its parent to be `minibuffer-local-map'.

In `bookmark-ido-quick-jump' we provide this modified copy as a replacement
parent.")

(define-key bookmark-ido-quick-jump-map
  [remap self-insert-command] 'my-self-insert-and-ido-complete)

(defun bookmark-ido-quick-jump ()
  "Jump to selected bookmark, using auto-completion and auto-acceptance."
  (interactive)
  (bookmark-maybe-load-default-file)
  (let ((minibuffer-local-map bookmark-ido-quick-jump-map)
        (ido-enable-prefix t))
    (bookmark-jump
     (ido-completing-read "Jump to bookmark: " 
                          (loop for b in bookmark-alist collect (car b))))))

(defun my-self-insert-and-ido-complete (n)
  "Insert the character, then attempt to complete the current string,
automatically exiting when only one option remains."
  (interactive "p")
  (self-insert-command n)
  ;; ido uses buffer-local pre- and post-command hooks, so we need to
  ;; co-operate with those. We append our post-command function so that
  ;; it executes after ido has finished processing our self-insert.
  (add-hook 'post-command-hook
            'my-self-insert-and-ido-complete-post-command t t))

(defun my-self-insert-and-ido-complete-post-command ()
  (remove-hook 'post-command-hook
               'my-self-insert-and-ido-complete-post-command t)
  ;; Now that ido has finished its normal processing for the current
  ;; command, we simulate a subsequent `ido-complete' command.
  (ido-tidy) ;; pre-command-hook
  (ido-complete)
  (ido-exhibit)) ;; post-command-hook
于 2013-07-06T06:33:17.517 回答
2

这是另一种看法:

(defun bookmark-do-quick-jump (str)
  (let ((completions (all-completions str bookmark-alist)))
    (if (null (cdr completions))
        (bookmark-jump (car completions))
      (minibuffer-with-setup-hook
          (lambda () (insert str)
                     (minibuffer-completion-help))
        (call-interactively 'bookmark-jump)))))

或者另一个(甚至更保证未经测试):

(defadvice bookmark-jump (around quick-bookmarks activate)
  (minibuffer-with-setup-hook
      (lambda ()
        (add-hook 'post-self-insert-hook
                  (lambda ()
                    (let ((completions
                           (all-completions (minibuffer-contents)
                                            bookmark-alist)))
                      (if (cdr completions)
                          (minibuffer-completion-help)
                        (minibuffer-complete-and-exit))))
                  nil t))
    ad-do-it))
于 2013-07-22T14:16:42.717 回答
0

听起来你正在做很多额外的工作。只需使用冰柱

  • 用户选项icicle-incremental-completionnon-nil和 non-t表示在您输入输入后立即显示所有匹配项。

  • 选项icicle-top-level-when-sole-completion-flagnon-nil意味着接受一个单独的匹配项,而无需按键(例如RET)。

您可以将它们绑定到您自己的命令中的值,而不是自定义选项以获得这些值。

于 2013-07-12T06:59:05.017 回答