gnome3, emacs23 and elisp chunks (2011/12/26)


gnome3

かなりせっぱつまってから書き始めた原稿が完成しないうちに うっかり apt-get dist-upgrade したら、 インタフェースが gnome3 に入れ替わってしまい、 一時はどうなることかと思ったが案外問題なく使え、 その後普通に便利に使っています。

画面上端のなんとかバーというやつが邪魔だったので(そういう意見は多いようだ) 隠すための extension というものをインストールしてみた( rpm を alien して dpkg -i した)ら、 中身はなんてことない javascript で書かれていてちょっと驚いた。 こういうものを一から全部書くというのは私には無理ですが、 ちょっと修正するくらいなら簡単で良いですね。

以下 tips

設定データは xml で拡張も js といろんなものが普通のテキストファイルであり おかげでコマンド操作にも案外親和性があるようなきがする。 たとえば gsettings で、音に関係ありそうな設定項目とその値はこんな感じで探せる

yuji@dedepo:~%for s in `gsettings list-schemas | grep sound`
do
gsettings list-recursively $s
done
  

などと言ってるうちに gnome3.2 にアップグレードされました. gnome-shell の extension に関するいろいろが変更されており, 自動で上のバーを隠す extension とかも動かなくなって難儀しました.

どうやら gsettings で enable な extension を明示的に指定しないと動かないようです. こんな感じで指定します.

gsettings set org.gnome.shell enabled-extensions "['systemMonitor@gnome-shell-extensions.gnome.org', 'autohidetopbar2@werewolves.us']"

複数指定する場合は上のように "," で区切って並べます. これって JavaScript の配列のリテラルか何かかね. extension の記述の流儀も 3.0 とはまったく違っており, 全然違う版を使わないとまったく動きません. 難儀です. でも cpu メータがおまけでついてるので, それはよかったです.

clojure

jvm などで動く関数プログラミングなアレ。 次のシミュレーションはこれで書く予定。

clojure が いいと思うところ

どうかな、と思うところはいまのところ無い。 関数定義の時の引数リストは [] ではさまないといけないわけですが、 これはあまり慣れないですね

migrate from XEmacs21 to GNU-Emacs23.3.1

XEmacs で clojure mode が動かなかったので GNU の版に引っ越すことにした。

ずっとgnuの版もしくはそれを元に拡張した版を使っていましたが、あるとき、komatsuhに勧められて ヘルプが使いやすくて elisp が書きやすい XEmacs に移行したのでした。多分10年ぐらいまえのことだと思います。そのときも移行はそれなりに大変でしたが、当時はコンピュータを使うという事自体に非常な情熱を持っていたので、作業は楽しかったような気がします。

引越しが順調にいったので調子にのってついでに日本語入力を変更して若干はまりました。 いまは ibus.el で anthy を使っています。 他にも自作関数等(笑)で若干おかしいところはありますが、 だいたい動いているのでまあいいか。でも正直もうしあげてもう emacs lisp みたいなのをいじくりまわすのは遠慮したいです。特にこの変数スコープが(以下自主規制

というわけで、今後はできるだけ設定をいじらず、いじらねばならないばあいも .emacs などに自作の腐れコードを、うだーっと書くのではなく custom-set-variables に勝手に書き出される備え付けのインタフェースを使う事にします。そうすれば、今後は多少は引越しが簡単になるのではないでしょうか。全般的に非常に便利になっていて、乗り換えてよかったです。とくに、ファイルマネージャからモノを drag してくるとファイルやdiredで開いてくれたりするところとか。

しかしこう、シェルコマンドを実行した結果の文字列を取得する、というのが一行で簡単にかけないとか、まじで最近のプログラミング環境としては終わってるとしかいいようがないですよねemacs-lispはほんとまじで(以下自主規制

わしが作ったシェルコマンドの実行結果の文字列を返す関数を載せときます。標準エラーも全部拾います。実行結果を拾うために、同期プロセスを使っています。多分おそらくきっと普段使ってるお馴染みのshell codeがそのまま動くと思います。一時バッファの作り方が非常にアレですがそもそもバッファ切り替えてどうこうのところが非常にどんくさい作りなんでもうどうでもいいけんね的な。

(lambda (cmd)
 (let* ((buf (get-buffer-create (number-to-string (random)))) 
 (cbuf (current-buffer)) (ret ))
 (call-process shell-file-name nil buf nil -c cmd)
 (switch-to-buffer buf)
 (setq ret (buffer-substring (point-min) (point-max)))
 (kill-buffer buf) (switch-to-buffer cbuf) ret))

使い方ですが, この関数に do-it-in-the-shell という名前をつけたとすると, たとえばこんな感じです

(split-string (do-it-in-the-shell "cat /etc/passwd | cut -d \: -f 1") "\n")
("root" "daemon" "bin" "sys" "sync" "games" "man" "lp" "mail" "news" 以下略-

シェルの結果をどうこうという時点で非常にlispぽくない感じなんでそんなのどうでもいいといえばいいのでしょうが、プログラムというのは作者がカッコつけるために存在しているわけではなく動いてなんぼですから。これがRubyならこんな感じですかね。

`cat /etc/passwd | cut -d \: -f 1`.split("\n")

「clojure なら aws でそのまま動くぜー」みたいな話が無きゃ今更こんなことやることもなかったと思われ、そうしたら一生 XEmacs と canna を使い続けていたかもしれず、それは大変恐ろしいことなのでやっぱり新しいことを覚えるのはいいことだと思った。 clojure はわりと普通に lisp なのであんまし新しいプログラミング言語という気はしないですけど、関数プログラミングで並列処理とかは、私にとっては目新しいところです。

祝 gnome-terminal 復活

しばらくterminatorという端末エミュレータを使っていましたが、いま操作してみたらgnome-terminalが普通に動くようになっていたので常用端末エミュレータをこっちに戻しました。フォルダをdragしてenterキーをタイプしたらそこにcdするとか(これはどっちかというとzshの機能ですけど)複数ファイルをつかんでdragしたらファイル名が全部入力されるなど、gnome-terminalはなかなか優れているので、やはり普通に動くのであればこっちを使いたい。

どうもinput methodの関係で調子がおかしくなっていたのですが治ってよかったです。なんでしょうね。いろいろ入ってたのをどけてibusに一本化したのがよかったのでしょうか。

端末エミュレータのgui親和性って案外重要でっせ。ファイルのプレビューみながらまとめて作業するshell codeを書いたりできるんで。

fontはemacsと共通にterminusというのを使っています。これはl1I0Oなどありがちに紛らわしい文字がよく識別できてありがたい。

Emacs23ほげり

* でmarkしたfileを全部まとめて読み込むとか普通に考えてできるはずなのだが Emacs23でどうやってそれをやったらいいのか判らないのでしょうがないから作ったのだが、これがえらい難儀した。

普通に考えるとmarkされているファイルのリストを取得するか、もしくはそのリストをmapする関数が用意されていて、これを使えばいい。これは、markされているもの全部について何らかの操作をするような関数を調べれば見つかるわけで、どうも

dired-map-over-marks-check

というのを使えばよいようだ。この関数はmapの中身に使う引数として function symbol をとるようになっている。しかしその関数にあたえる引数は使えない仕様というところから様子がおかしくなってくる。要するに dired-map-over-marks-check が動いている間じゅう、 dired buffer が current buffer になっている事が前提になっていて、呼んだ関数が戻った時にdired以外がcurrnet bufferになってると、そこで止まってしまうのだ。もうこうなると repl があって prefix notation だ、ってだけであとはもう(以下略 な感じなのでまじで elisp は(以下略

isearch中にcontrol-wするとisearchにyank-wordしてくれます。これはわりと便利な機能なので世話になっている人も多いと思います。これは forward-word したところから今カーソルがあるところまでを切り取って isearch の引数にしているのですが、 forward-word が思ったところに止まってくれるとは限らないわけでそんな時はムカっとくるぜ!という人も稀によく居ると思います. 目的の文字列を kill ring に一旦セーブして meta-y で yank とかクソめんどくさくて、文字列を全部手で打った方が速いぜ、となって打鍵したら間違ってマジギレ、などは稀によくある事ではないでしょうか。

あるときregionがあればそこからbuffer-substringしてyankしとけよ、と思ったので、そういう関数を作って XEmacs で使っていましたがこのあたり gnu の emacs とはだいぶ事情が違うのでこのほど新たにかきなおしました。上のコードを isearch-mode-map の control-w に割り当てれば region が無ければ従来どおり、あればそこから文字列をとってきて isearch します。 isearch-yank-internal をいきなり叩いてるところがあれですが、もっといい方法ないすかね。

(defun isearch-yank-region-or-word ()
  (interactive)
  (if (not (use-region-p)) (isearch-yank-word-or-char)
    (progn (isearch-yank-internal (lambda () (goto-char (mark)))))))

これは exif データを alist で取得するコードです. 上で書いたシェルコマンドの出力結果の文字列を取得するコードと一緒に使います. ファイル名を escape するところがアレですが, どうやったらかっこいいのか判らん. メタ文字の扱いは苦手だ.

(defun exif-info (file)
  "fetch exif info as alist"
  (mapcar
   (lambda (l) (let* ((ll (split-string l))
		      (key (car ll))
		      (val (apply 'concat (cdr (cdr (cdr ll))))))
		 (cons key val)))
   (split-string (do-it-in-the-shell (concat "exiv2 -pa " (char-to-string ?\") (expand-file-name file) (char-to-string ?\"))) "\n")))

記事リストへ