こないだ諸事情あって(というか、趣味ですが) emacs lisp でマイナーモードを書いてました。
メジャーモードは比較的需要があるのか、詳しいページが多いのですが、マイナーモードに関しては詳しいページが無かったりします。
おそらく調べた限りだと
おもてなしの空間
が最有力だと思われます。
ここだと、easy-mmode という emacs についてくるマクロを利用した作成方法とスクラッチで頑張る方法と二種類について説明されます。
ただ、(主観的判断ですが)easy-mmode を推しているようで、スクラッチの記述があんまりありません。
そうなると、マイナーモードを作るための勉強方法としてはリファレンスをゴリゴリ読むか、人様が書いてくれたマイナーモードのソースコードをハックする、という選択肢になってきます。
僕は結局 easy-mmode を使いたくなかったので、人様のソースコードをひたすら読み続けたのですが、あんまり効率的じゃありません。
そこで前置きは長くなりましたが、マイナーモードをスクラッチで書くための方法を紹介したいと思います。
サンプルとして、hoge.el を考えるとします。
まず、hoge.el を hoge-mode というマイナーモードとして作成したい場合、以下のひな形に従います。
;; hoge-mode キーバインド。モード起動はグローバルにしておく。 ;; 拡張子自動起動設定は別途調べてください。 (global-set-key "\C-c\C-c\C-c" 'hoge-mode) ;; ;; mode 変数。これで状態判定 ;; ないと動かないらしい(未確認) (defvar hoge-mode nil) ;; ;; mode 行の設定。なくてもOK。 (if (not (assq 'hoge-mode minor-mode-alist)) (setq minor-mode-alist (cons '(hoge-mode "モード行に出したい文字列") minor-mode-alist))) ;; ;; mode 関数。こいつでモード起動の内容を書く。 ;; いわゆる main 関数。最初の引数処理はお約束なのでそのまま書く。 ;; 引数はoptional 限定 (defun hoge-mode (&optional arg) "hoge minor-mode" (interactive) ;; mode variable settings (cond ((< (prefix-numeric-value arg) 0) ; 引数が1未満の数値なら起動しない (setq hoge-mode nil)) (arg ; 何かしらの引数をもつならば起動 (setq hoge-mode t)) (t ; symbol t を引数にもつならばモードを逆転。 (setq hoge-mode (not hoge-mode)))) ;; content (if hoge-mode ; モードが起動されているならば実行 ;; 具体的処理を書く (progn ) など nil) ) ;; ;; 他の関数など ;; ;; mode provider関数 (provide 'hoge)
基本的にこれさえ守れば、マイナーモードとして動作してくれます。
なお、マイナーモードに限らないことですが、グローバル変数のスコープに注意しましょう。
(defun hoge-func () (setq hoge-var 1))
とかやると、hoge-var が外部参照できちゃったりします。なので、意識的に
(defun hoge-func () (let ( (hoge-var 1) ) ;; 中身 ))
というように明示的なローカルスコープを利用しましょう。また、外部から参照をうけざるを得ない名前(関数名、共有変数)などは、hoge-FUNCTION-NAME といったようにモード名を頭に付加することで衝突回避を行いましょう。
その他 hook など、モード作成で便利な事は沢山あるのですが、それはおいおい。。。
この記事を見る人が少しでも楽にマイナーモードを書けることを祈って
コメント
作ったモノは公開しないんですか?
諸事情あって公開はできなくなってます。
一部の希望者に限り、ってところですかね。