2013-07-05 53 views
4

我的大部分书签都以前缀 的字母作为前缀,几乎总是唯一确定书签。 这样我可以,例如, 跳转到我的源文件夹(书签为“s:源”)与M-X书签跳转RET的RET。我有一个快捷方式,所以它实际上是〜s RETEmacs更快捷的书签跳转?

我想最终摆脱RET的, 即得到M-X的书签,快速跳RET小号或 做上述工作。 我还想回到默认行为:向我展示所有以给定字母开头的书签 ,以防不仅有一个变体。

到目前为止,我有:

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

有仍然是两个打嗝:

首先,我要跳进小缓冲区不知何故,坚持在那里此地图(不知道如何做到这一点):

(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个变体。我想这是自动完成的。

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

UPD:

我切换从completing-readido-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+。我不确定跳转到 是否由默认的bookmark-jump支持。

+0

这可能是更容易实现与调用键盘宏功能。唯一的复杂情况是键盘宏的其中一个键必须是该函数的参数。 – Malabarba

+0

@ abo-abo您可否提供用于为书签创建唯一名称的方法,并设置问题第一行中提到的快捷方式?另外,您是否在最终解决方案中使用了auto-completion-read.el?谢谢。 – Anusha

+0

我通过用唯一字符加前缀来制作书签名称。我只有50左右,所以小写字母和大写字母就足够了。请参阅http://oremacs.com/2015/01/06/rushing-headlong/。 –

回答

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。有点不幸的是,你没有得到下一个'重要角色',突出了你在正常的微型缓冲器完成时的方式(因为这是下一个输入内容的一个很好的指示),但是这在其他方面似乎很好。

(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 
+0

感谢您的一个伟大的答案,@ phils。 虽然有几件事: 1.我必须用RET确认以 (1 2 d)开头的唯一书签,例如0和8以及其他字母。这可能是一个关键地图问题吗? 2.带有“o”的'bookmark-do-quick-jump'匹配 '(org-capture-last-stored org-capture-last-stored-marker org-refile-last-stored)。 当我输入“c”时,它立即选择第一个元素,尽管第二个元素仍然可以匹配。 –

+0

啊。是的,如果一个书签名称是另一个书签的前缀,那么它本身也是一个有效的完成,所以'minibuffer-complete-and-exit'一旦完成就立即退出。 – phils

+0

我不确定您的键盘映射问题,除了注意到单字符书签名称在将我带到书签之前似乎延迟告诉我“[唯一完成]”,而我没有更长时间观察它名。 – phils

0

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

  • 用户选项icicle-incremental-completionnil和非t方式显示所有只要你键入输入相匹配。

  • 选项icicle-top-level-when-sole-completion-flagnil表示接受孤独的比赛,而不需要你打一个键(例如RET)。

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

+0

我曾经尝试过冰柱,我不喜欢它。 它太臃肿了。而不是一个好的组织模式, ,但在一个'gnus'王的方式。 –

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)) 
+0

我喜欢第一个。非常简洁。 –

+0

有一个'后自我插入钩子'?我甚至没有想到要看。 *那*简化了事情。 – phils

+0

@phils:它是Emacs-24中的新功能。但在这种情况下,您可以使用'after-change-functions'来获得相似的结果。 – Stefan