helm拡張を書く例を示していきます.
題材は松屋ジェネレータを用いたものにします.
リポジトリ
イメージ
コード解説
依存パッケージの宣言
現在 helmは コア部分の helm-core, その他の helmの 2つのパッケージから構成されます. helm-coreはごくごく基本的な機能しかありません. helm関数と各種ソース構成に関する関数マクロしか呼ばない場合は helm-coreで十分です. helmのファイル機能(helm-ff-*)を使う, grep機能(helm-grep)を使うという場合は helmパッケージが必要になります.
;; Package-Requires: ((helm "1.7.7") (migemo "0"))
わからない場合は helm-coreにして, Caskでミニマルな環境を構築し, 動作検証してみるとよいでしょう. 依存パッケージの宣言が適切に行えていれば Caskは以下の内容で十分です.
(source gnu)
(source melpa)
(package-file "helm-matsuya.el")
そして cask && cask exec emacs -Q -L . -l helm-matsuya.elとし, 動かない, バイトコンパイルで警告, エラーが出る場合は helmに切り替えて試してみるとよいでしょう.
ライブラリのロード
helm.elのロードは必須です. その他は必要に応じてロードしましょう.
(require 'helm)
(require 'helm-net)
(require 'cl-lib)
groupの宣言
defcustomで定義されるカスタマイズ変数や, deffaceで定義される faceがある場合は groupを宣言しましょう. :group属性(親グループ)は helmにしておきましょう(helm拡張の拡張となる場合はその拡張で定義されるグループを親グループとすべきです).
(defgroup helm-matsuya nil
  "matsuya generator command with helm interface"
  :group 'helm)
ソースの定義
別に変数に定義しておく必要はありませんが, 変数として定義しておくとあとあと便利なこともあります. 動的に生成する必要がない場合は基本的に変数として定義するのがよいでしょう. ソースの構築は以前は association listがそのまま使われていましたが, 最近は構築のための関数を使った方がよいでしょう. ここでは用途に合わせて helm-build-sync-sourceを使っています. helm-build-でドキュメントを検索するといくつかの類似する関数が見つかりますので, 気になる方は調べてみてください(多くの場合は helm-build-sync-sourceと helm-build-in-buffer-sourceで事足りると思います)
ソースの定義関数は第一引数が名前で, 第二引数以降がキーワード引数で, キーワード, 値, ...と設定していきます. assocication listだとタイポが実行時まで気づきませんが, これだとバイトコンパイル時には気付けるのでよいのではないかと思います.
(defvar helm-matsuya--source
  (helm-build-sync-source "Menu"
    :candidates #'helm-matsuya--candidates
    :volatile t
    :migemo t
    :action (helm-make-actions
             "Open Browser" #'helm-google-suggest-action
             "Insert" #'insert)))
コマンドの定義
helm関数にはいろいろキーワード引数がありますが, :sources(使うソースのリスト), :buffer(バッファ名)をセットすればよいでしょう. 後はドキュメントを見て必要なものを足してみてください.
;;;###autoload
(defun helm-matsuya ()
  (interactive)
  (helm-migemo-mode +1)
  (helm :sources '(helm-matsuya--source) :buffer "*helm matsuya*"))
おわりに
helm拡張の作り方を大雑把に説明しました.
helmは膨大な機能があります. ドキュメントは結構書かれている方だと思いますが, そもそもどれを調べていいかわからないという状況になります. そこで私は M-x helm-descbindsを使って, それらしいキーワードで関数, 変数を絞りこみ, 調べてみるということをしています.
