Emacs Advent Calendar 2009ということで。
社内でマイノリティなEmacserとしては、社内啓蒙活動として参加すべきかな、と。
「Calendar -> 空前のEmacsブーム -> 社内でEmacsが浸透」を狙っています。
今日は自分が作った「空気のようなEmacs Lisp」を紹介します。
Emacsが浸透しない理由は何なのかなと思ったのですが、やはりもっとも大きな壁は「ショートカットがWindowsっぽくない」ということにつきるかと思います。
Ctrl + Aで「全体選択」かとおもいきや「行頭に移動」だったり
Ctrl + Pが「コピー」かとおもいきや「上の行に移動」だったり
人によっては「変態」という人もいますが、個人的には変態だと思います。
慣れたら非常に効率がよいと思っているのですが、多分気のせいなんだと思います。
ただ、Emacsを使っていると「もしかしたらモテる」かもしれないので、使えるようになっておくに越したことはないでしょう。
とはいえキーバインドの壁を越えなければEmacsを使いこなすのはなかなか難しいと思いますので、今回は一般的なEmacsキーバインドの習得を助けるEmacs Lispを紹介します。
このEmacs Lispは空気のようなEmacs Lispです。ついつい導入していることを忘れます。(※ただしEmacserに限る
導入は簡単です。
ロードパスに通ったところにdrill-instractor.elを設置して
.emacsにでも
(require 'drill-instructor) (setq drill-instructor-global t)
と書くだけです。簡単簡単。
さて、Emacsの再起動とかM-x load-file ~/.emacsとかしてみてください。
何も起こらないかと思います。(※ただしEmacserに限る
いままでとおり操作してもまったく問題ありません。(※ただしEmacserに限る
実はこのEmacs Lisp、カーソルキー、BackSpaceキー、Enterキー、TABキーを使用不可にします。
さらにC-hにdelete-backword-charを設定します。
まあ、一般的で健全なEmacserはカーソルキーなんて使わないでしょうから、まさに「空気のようなEmacs Lisp」です。(※ただしEmacserに限る
自分もEmacsキーバインドに慣れない時期がありまして、なんとか慣れたいなと思い鬼軍曹.elを作成して自身のEmacsに適用しました(今も適用しています)。
Emacsが動かなくなりました。
正確にはEmacsを動かす自分が動かなくなりました。
ただ、業務でEmacsを使って開発をしていたので、強制的に努力をすることになって大体3日ほどで慣れました。
慣れたら他のキーバインドも打ちやすくなって、それにともなってコーディング速度が向上しました。
その後、鬼軍曹.elは空気のようなEmacs Lispです。
皆さんも是非、鬼軍曹.elを使ってみてください。
そして、Emacs初心者な後輩のためにそっと設定を追加しておいてあげましょう。
こんなことを考えているから社内でEmacserがいないんだと思いました。
(tokyo-emacs #x02) 正式アナウンス - 日記を書く [・w・] はやみずさんということで、福岡より(tokyo-emacs #x02)に参加します。
d:id:hirose31さんから#emacs-lisp-ja@freenodeでご指名を受けたのでがんばってみた。
原因はregion関係のfaceのやりとり中にface設定がEmacs23では壊れてしまうことが問題っぽい。
なんとかface設定が壊れずに動いているみたいなので良かった。
渋ガキ - Emacsグループの機能要件だけ満たした解法。
(defun my-php-oops () "PHP == Oops" (let ((current-line (cake-get-current-line))) (unless (not (string-match " == " current-line)) (my-hoge)))) (add-hook 'post-command-hook 'my-php-oops nil t) (defun cake-get-current-line () "Get current line." (let ((line-start (progn (beginning-of-line) (point))) (line-end (progn (end-of-line) (point)))) (buffer-substring line-start line-end)))
string-match()は文字列におけるマッチ位置を返すので、それとpoint()をうまく利用すれば、あたかも「" == "を入力したタイミングのみ」Oops!を出せると思う。
ちなみに現在行の文字列を取得する関数名がcake-get-current-line()なのはcake.elからとってきたから。
ソースコードの印刷をするという何とも理解しがたい状況になったので、ディレクトリ以下のファイルを再帰的に印刷する方法を調べた。
やっぱりfindコマンドとの組み合わせになるだろうというところまでは良かったのだけれども、見つかったものはどれも一長一短。
ちなみに最終候補になったのは以下の2つ。
- e2ps -- 日本語は通るけれども、シンタックスハイライトが当たらない
- enscript -- シンタックスハイライトは当てれるけれども、日本語が通らない
「Emacsならシンタックスハイライトが当たっていて印刷もできるのに」と、思いついてしまったのでEmacs Lispを書いてみた。
(require 'cl) (defun my-print-recuresive (dir regexp) "Print recuresively." (let ((file-list (my-print-get-recuresive-path-list dir))) (loop for x in file-list do (unless (not (string-match regexp x)) (find-file x) (ps-print-buffer-with-faces) (set-buffer-modified-p nil) (kill-buffer (current-buffer)))) (message "print job setting complete."))) (defun my-print-get-recuresive-path-list (file-list) "Get file path list recuresively." (let ((path-list nil)) (unless (listp file-list) (setq file-list (list file-list))) (loop for x in file-list do (if (file-directory-p x) (setq path-list (append (my-print-get-recuresive-path-list (remove-if (lambda(y) (string-match "\\.$\\|\\.svn\\|~$\\|\\.git\\|\\.jpg$\\|\\.png$\\|\\.gif$\\|\\.swf$" y)) (directory-files x t))) path-list)) (setq path-list (push x path-list)))) path-list)) ;;; Usage ;; eval ;;(my-print-recuresive "~/.emacs.d/" "\\.el$")
my-print-recursive()は第1引数に対象ディレクトリ、第2引数に印刷対象ファイルの正規表現を書く。
「再帰的に印刷」というかなり凶悪な機能なのでコマンドにはしなかった。あとflymakeとかと相性が悪かったりするので注意が必要。
kitokitoki2009/08/20 00:08反応をありがとうございます。今、勉強させて頂いています(細かく調べています)。ところで、僕の関数名が "my-hoge" なのは...申し訳ございません。手抜きです。思わぬ恥を書いてしまいました。あと、まだOopsを表示するところまで動かせていないので、コードを読んだというレベルなのですが、cake-get-current-line は、(thing-at-point 'line) でも同等かもしれません。こちらも後日しらべてみます。突然の降臨に驚きました。ありがとうございました!
k1LoW2009/08/20 00:15(thing-at-point 'line) !!! それは知らなかったです。いいすねー。