Emacs Helm: 使用關鍵字搜索、獲取、執行任何東西


Helm 是一個emacs的軟件包,定義了一個通用框架,交互式地、動態縮減式地使用關鍵字選擇、獲取、執行任何東西。比如:

  • 執行emacs 命令
  • 打開文件
  • 查看man文檔
  • 執行grep操作
  • 執行apt命令
  • 相看imenu函數定義
  • 切換buffer

Helm軟件包本身包含兩部分,框架本身及應用。以上列表均為應用。基於框架,可以輕松創建新的應用。

基本原理

Helm的三個重要概念:candidate, narrowing, action.

Candidate

Candidate即候選值,是一個列表,保存所有可供選擇的條目。對於打開文件的命令,candidate是所有的文件名稱的列表。

Narrowing

Helm命令啟動后,用戶未輸入任何關鍵字前,會將candidate中的所有條目顯示出來,每行顯示一個項,可通過'C-n', 'C-p'上下移動光標選擇當前條目。

如果candidate的數目較少,此時沒必要輸入關鍵字,通過上下移動光標選擇就行了;但如果candidate數目較多,目標條目沒有被顯示在第一頁,可輸入關鍵字,對candidate的條目進行篩選,只有匹配到關鍵字的條目才會被顯示出來。這就是narrowing。

值得一提的是,這個過程是動態的,即每輸入一個字符,candidate的條目都會被重新篩選。有時只輸入了一個字符,目標條目已經顯示在第一頁,則可停止輸入,通過移動光標選擇當前條目;有時輸入了一個關鍵字,目標條目仍然沒有出現,則可按空格,繼續輸入另一個關鍵字,進行更精確的篩選,直到目標條目出現為止。

輸入的關鍵字越多,candidate的數目會越少,目標條目出現在第一頁第一個條目位置的機率就越大,進而選擇也就越方便。

Action

當一個candidate被選中后,按下Enter后,就會有一個action被執行。對於打開文件,其action對應到emacs命令就是'find-file'。可以為一個條目定義多個action,如對於文件條目action可以為打開文件、重命令文件、刪除文件等。 通過TAB鍵從多個action中選擇,如果直接按Enter會執行第一個action.

定義一個新的helm應用

基本例子

要定義一個新的helm命令,只需定義一個變量指定candidate及對應的action,然后將其作為參數傳給helm就可以了,以下為一個例子。

(setq some-helm-source
      '((name . "HELM at the Emacs")
        (candidates . (1 2 3 4))
        (action . (lambda (candidate)
                    (message-box "%s" candidate)))))

(helm :sources '(some-helm-source))

其中定義candidate、action的變量叫做source, 是一個assoc list。candidates是一個list, action是一個函數,action函數被調用時,當前選擇的candidate會被作為參數傳入。

定義多個action

上面的例子中action的值為一個匿名函數,如果要定義多個action,則需要將action的值設置為一個list,list的元素是一個cons:(說明 . 函數)。如下所示,定義了兩個action。

(setq some-helm-source
      '((name . "HELM at the Emacs")
        (candidates . (1 2 3 4))
        (action .
                (("Display" .  (lambda (candidate)
                                 (message-box "%s" candidate)))
                 ("None" . identify)
                 ))
        ))
(helm :sources '(some-helm-source))

將candidate的選擇值與真實值分離

有時候需要通過不同的值選擇candidate,此時可將candidates設置為cons (KEY . VALUE)的list。其中KEY將用於選擇,VALUE將作為action函數的輸入參數值。

(setq some-helm-source
      '((name . "HELM at the Emacs")
        (candidates . (("one" . 1) 2 ("three" . 3) 4))
        (action .
                (("Display" .  (lambda (candidate)
                                 (message-box "%s" candidate)))
                 ("None" . identify)
                 ))
        ))
(helm :sources '(some-helm-source))

動態candidate

有時candidates需要動態計算,或者靜態計算量會很大,此時可將candidates設置為一個函數,這個函數將被用於計算所有candidates的值。

(defun random-candidates ()
  "Return a list of 4 random numbers from 0 to 10"
  (loop for i below 4 collect (random 10)))

(setq some-helm-source
      '((name . "HELM at the Emacs")
        (candidates . random-candidates)
        (action . (lambda (candidate)
                    (message "%s" candidate)))))

(helm :sources '(some-helm-source))

添加一個persistent action

Persistent action是指執行action后,不退出helm,類似於預覽功能,默認綁定在\C-z。通過'persistent-action'來指定,如果未指定,則與第一個action一樣。

(setq some-helm-source
      '((name . "HELM at the Emacs")
        (candidates . (1 2 3 4))
        (persistent-action . (lambda (candidate) (message "%s" candidate)))
        (action . (lambda (candidate)
                    (message-box "%s" candidate)))))

(helm :sources '(some-helm-source))

helm-org-headlines的定義

這個命令由helm默認提供,其定義如下,可為實現新的命令提供參考。

(setq helm-source-org-headline
      `((name . "Org Headline")
        (headline
         ,@(mapcar
            (lambda (num)
              (format "^\\*\\{%d\\} \\(.+?\\)\\([ \t]*:[a-zA-Z0-9_@:]+:\\)?[ \t]*$"
                      num))
            (number-sequence 1 8)))
        (condition . (eq major-mode 'org-mode))
        (migemo)
        (subexp . 1)
        (persistent-action . (lambda (elm)
                               (helm-action-line-goto elm)
                               (org-cycle)))
        (action-transformer
         . (lambda (actions candidate)
             '(("Go to line" . helm-action-line-goto)
               ("Refile to this headline" . helm-org-headline-refile)
               ("Insert link to this headline"
                . helm-org-headline-insert-link-to-headline))))))

(defun helm-org-headlines ()
  "Preconfigured helm to show org headlines."
  (interactive)
  (helm-other-buffer 'helm-source-org-headline "*org headlines*"))


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM