emacs + snippet.el の定型文補完(スニペット)で楽々HTML編集

emacsでHTMLを編集する際の、定型HTML文の入力を、snippet.elを利用してカスタマイズしてみる。HTMLを書いて慣れてくると、おなじようなタグ構造を、よく使うようになります。例えば、こんなタグの組み合わせは、かなりの頻度で使う。

EmacsScreenSnapz003.png

いちいち、すべてのタグを個別に入力するのが面倒なので、これを簡単なキーストロークで入力できるようにするという試み。

HTMLの編集には、psgmlモードをXHTMLのDTDで利用しています。psgmlについては、このあたりを参考に。

snippet.el のインストール

次に、定型文を入力補完するために、snippet.elをセットアップ。emacsでRuby on Railsする時に便利な、rails.el で使われているライブラリですね。rails.el をインストールすれば、rails 系の自動補完はすぐに利用可能。インストールは以下を参考に。もちろん、snippet.el単体だけでの利用も可能です。

今回は、Railsのソースではなく、HTMLをpsgmlで編集する際にも、このsnippet.elを活用するのが目的。snippet.el については、検索してもあまり解説記事などが見つからず。snippet.el ファイル内に書かれているドキュメントが一番充実していました。

Abbrevとは

snippet.elは、emacsの基本機能である略称展開 Abbrevを使っているよう。なにぶん、emacs初級者なので、まずはabbrev から調べる。

略称展開という単語は難しいですが、modeごとに定型文を指定する、emacsの基本機能のようです。 一通り、abbrev の機能を使ってみると、感覚的に分かってきた。

  • M-x abbrev-mode
    • abbrev-mode を開始・終了する
  • M-x list-abbrevs
    • すべての略称定義を表示
  • M-x edit-abbrevs
    • 略称定義を編集.付加,変更,消去が可能.
  • M-x unexpand-abbrev
    • 最後の略称展開を取り消す

自分で独自に登録した略称は、以下のファイルに保存される。

‾/.abbrev_defs

.emacs.elでカスタマイズ

snippet.elを使った、定型文のカスタマイズは、 .emacs.el に記述します。いくつかの書き方ができるようですが、複数の定型文を登録するには、以下のフォーマットが便利なようです。

(require 'snippet)
(snippet-with-abbrev-table 'local-abbrev-table ;; モード指定
  ("略称の文字列1" .  "展開する文字列1")
  ("略称の文字列2" .  "展開する文字列2") ;; 続けて複数指定できる
)

例えば、<a>タグを入力するスニペットは、こんな感じにテンプレートを記述。

(snippet-with-abbrev-table 'local-abbrev-table ;; モード指定
  ("hthref" .  "<a href=¥"¥"></a>") 
)

この指定で、編集中にhthref と入力して、スペースやリターンなどを押すと、<a>タグが自動的に展開されて入力されます。

しかし、これだけではただタグが入力されるだけ。snippet.el では、各要素をタブキーで移動しながら入力するための指定が可能です。

(snippet-with-abbrev-table 'local-abbrev-table ;; モード指定
  ("hthref" .  "<a href=¥"$${url}¥">$${title}</a>") ;; 要素指定あり
)
EmacsScreenSnapz002.png

上記のように記述すると、テンプレート内で$${}を記述した場所がハイライトされて、定型文が挿入されます。タブキーを押すと、それぞれのハイライト要素にカーソルが移動して、テキストを手早く入力できます。$${url}のなかでurlと書いてあるキーワードは、別に何でもOK。ただ、キーワードはその定型文入力の間、共有されるので、同じ単語を複数入力する際には、同じキーワードを設定しておくと便利です。他にも、以下のような特殊記号が利用可能。

$${}  ;;  タブキーで移動可能な入力エリア
$.    ;;  タブ入力を終了した後の、カーソルの位置
$> ;;  その行をインデントする       

インデントは、改行と組み合わせて使いますが、記号を置く場所にちょっと工夫がいります。こんな感じに書くと、きれいにインデントされた定型文が入力されます。

("htdiv3" . "<div class=¥"section¥">¥n$>$><h3>$${title}</h3>¥n$><p>$${body}</p>¥n$.</div>$>")  
EmacsScreenSnapz003.png

あとは、このsnippetの指定を、.emacs.elの中で、psgmlモードにフックします。.emacs.elに以下を記述して保存。

;;------------------------------------------------
;; PSGML 用のsnippetを記述
;;------------------------------------------------
(require 'snippet)

;; snippet.el で、addrev に定型文を追加する
(add-hook 'sgml-mode-hook
           '(lambda ()
			  (setq-default abbrev-mode t) ;; abbrev-mode をon
			  (snippet-with-abbrev-table 'local-abbrev-table 
	  ("htdiv3" . "<div class=¥"section¥">¥n$>$><h3>$${title}</h3>¥n$><p>$${body}</p>¥n$.</div>$>")
	  ("htdiv4" . "<div class=¥"section¥">¥n$>$><h4>$${title}</h4>¥n$><p>$${body}</p>¥n$.</div>$>")
	  ("htdivr" . "<div class=¥"section refer¥">¥n$><ul class=¥"source¥">¥n$>$><li><cite><a href=¥"$${cite}¥">$${title}</a></cite> より</li>¥n</ul>$>¥n$><blockquote cite=¥"$${cite}¥" title=¥"$${title}¥">¥n$><p>$${body}</p>¥n</blockquote>$>¥n</div>$>")
    ("hthref" .  "<a href=¥"$${url}¥">$${title}</a>") ;; 続けて複数指定できる
	  )
))

これで、次回のemacs起動時から、htmlファイルの編集などでpsgmlモードが呼ばれると、上記のスニペット定型文の自動補完が始まります。もちろん、psgmlモードでのhtml編集以外にも、text-modeやruby-modeなどでも独自のスニペットの指定が同じ方法で可能。これは一度使い始めると、激しく便利!