2013-07-05 136 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