自宅のWindowsマシンではMUAはThunerbirdを使っている(最近Becky!から乗り換えた)
会社では、emacsでWanderlustを使っている。
これは、会社のメールはいろいろなところから読むため、sshでログインしてテキスト端末から読みたいから。
で、最近単なるテキストを添付したメールが読めなくて困っている。
具体的には、multipart/mixed なメールで、メール本文は
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit
で、添付ファイルはSJISのくせに(Thunderbirdの場合)
Content-Type: text/plain;
 name="hoge.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="hoge.txt"
だったり、(Becky!の場合)
Content-Type: application/octet-stream;
 name="hoge.txt"
Content-Disposition: attachment;
 filename="hoge.txt"
Content-Transfer-Encoding: base64
だったりする。
Wanderlustで見ると、前者は添付ファイル部分が文字化けして見え、後者は添付部分は表示されない。
いずれも、添付部分をeとかvで保存してemacsで開き直せば読める。
この辺は、ちゃんと Content-Type に charset を付けない送信側のメーラが悪いのだと思う(ちなみに、Wanderlustで同じことをやるとSJISなのに charset=US-ASCIIとかつけるらしい)けど、どうせ相手は直してくれないので読む側でなんとかするしかない。
んで、なんとかならないかな~と思ってぐぐって見たけどそれっぽい解を見つけられず、さらにWanderlustとかSEMIとかFLIMはどうも最近開発が停滞してるっぽいことを発見した。(たとえば、EMYを使うと文字化けパートを再変換できそうな記述を見つけたけど、EMYは既に開発されてなさそう)
とりあえず charset がないパートは文字コードを判別して変換してやれば良さそうだと思ってSEMIとかFLIMのソースを読み始めたけれど、emacs lisp がさっぱりわからないのでちっとも進まない。

そこで、Programming in Emacs Lispを見ながらemacs lisp再入門することにした。
読んでいくと、ふんふんなるほど!と思うのだけれど、読み進めていくそばから忘れて行きそうなので、ポイントと言うか、関心したところをメモって行くことにする。

  1. ";"から行末まではコメント
  2. ()で囲んで空白文字で区切った要素を並べたものがリスト
  3. リストをその場で評価したくないときは ' を前置する
  4. 変数の宣言(シンボルへの値のバインド)はset
    (set 'hoge "hoge") ←評価するとシンボルhogeに値"hoge"が入って式の結果は"hoge"
    
  5. setqを使うと、シンボルに前置 ' がいらない上に複数同時に宣言できる
    (setq hoge "hoge")
    (setq moge "moge"
             uha "uha") ←二つ同時に宣言
    
  6. リストを評価すると最初の要素を関数として実行する。リストの残りの要素は引数となる。
    (* 2 3 4) ← 評価すると 24
    (*) ← 評価すると 1
    
  7. 関数の定義は defun を使う。
    (defun hoge (arg1 arg2 arg3) ;← 引数がないときは空リスト()
    "hogeと言う関数の説明. ←説明の1行目は簡潔に
    これは○○する関数なのだよ。"
    (interactive "p") ;←省略可能。interactiveがあるとM-xで呼び出したり、キー割り当てが可能。
    ; "p"は前置引数を取ると言う意味で、他にもいろいろ指定可能
    関数本体
    )
    
  8. letは、perlで言うmyみたいなもん。と思ったけどちょっと違うか。letでバインドした変数は、letの本文の中のみのスコープを持つ。
    (setq hoge "hoge") ; 変数 hoge に値"hoge"をバインド。
    (let ((hoge "moge") moge) (message "hoge=%s moge=%s" hoge moge))
    ; 評価すると、hoge=moge moge=nil とメッセージバッファに表示される。
    hoge ; 評価すると、"hoge" になる。
    
  9. letを使わないで関数内でsetqを使うと外の変数を変えてしまう。
    (defun hoge () (setq hoge "moge"))
    (setq hoge "hoge")
    hoge ; ← 評価すると "hoge"
    (hoge) ; ← 関数 hoge の呼びだしにより、変数 hoge が変化
    hoge ; ← 評価すると "moge"
    
  10. 条件判断は if を使う
    (if 条件式 真のときの動作 偽のときの動作) ; 偽のときの動作は省略可
    
    ※ lispでは、nilのときが偽、それ以外は真。空リスト()とnilは同義。
  11. save-excursion は現在のpoint(カーソル位置)とmark(Ctrl + space)を記録し、抜けるときに戻す。
    (let 変数リスト
      (save-excursion
        本体...)) ; ←みたいな形でセットで使うことが多いらしい。
    
  12. carはリストの最初の要素、cdrはリストの最初の要素を除いた残りの要素のリスト。両方とも非破壊的。
    (setq hoge '(a b c d))
    (car hoge) ; ←評価すると a
    (cdr hoge) ; ←評価すると (b c d)
    
  13. cons はリストの先頭に1要素追加する。
    (cons 'k '(a b c d)) ; ←評価すると (k a b c d)
    
  14. length はリストの長さを返す
    (length '(a b c d)) ; ←評価すると 4
    
  15. nthcdr は最初のn個の要素を除いた残りの要素のリストを返す。非破壊的。
    (nthcdr 2 '(a b c d)) ; ←評価すると (c d)
    
  16. setcarはリストの最初の要素を置き換える。
    (setq hoge '(a b c d))
    (setq moge hoge)
    (setcar hoge 'k) ; ←評価すると k
    hoge ; ← 評価すると (k b c d)
    moge ; ← 評価すると (k b c d)
    
    ※ この結果から、リストを変数にバインドした場合は、ポインタのようなものであることがわかる。
  17. ついでに実験
    (defun hoge (arg0) (setcar arg0 'k))
    (setq hoge '(a b c d))
    (hoge hoge)
    hoge ; ← (k b c d) になるので、関数内で変更される
    
    (defun hoge (arg0) (setq arg0 "changed"))
    (setq hoge "original")
    (hoge hoge)
    hoge ; ← "original" になるので、関数内で変更されない。
    
    ※ この結果から、関数の仮引数はCのポインタやJavaの参照のようなものであることがわかる。仮引数自体は関数ローカルなので、ポイントする先を変更しても呼びだし元に影響しないが、ポイントする先のオブジェクト自体を変更すると呼びだし元に影響する。
  18. setcdr は名前から類推できるので省略。
  19. while
    (while 真偽テスト 本体)
    
  20. インクリメンタ/デクリメンタ
    (setq c 1)
    (setq c (1+ c)) ; c++ (setq c (+ 1 c)) でも同じ
    (setq c (1- c)) ; c-- (setq c (- 1 c)) でも同じ
    
  21. 再帰もできるよ(省略)
  22. cond を使うと if - elseif - elseif - else みたいなのができる
    (cond
      (条件1 結果1)
      (条件2 結果2)
      (条件3 結果3)
    )
    
    ※ 必ず条件と結果をセットにするので、最後を条件なしの else にしたければ必ず真になる条件(tとか1とか)を書けば良い。
    ※ 上から順番に条件が評価され、最初に真になったところの結果だけが評価される。全ての条件が偽になった場合は (cond)の結果はnil。
  23. lambdaは無名関数の定義。defun 関数名の代わりにlambda。
とりあえず、言語仕様についてはこのくらいで。
次のエントリでは、emacs特有の組込関数について見ていきたい。(既にsave-excursionはemacs特有だけど)

@hitoriblog さんから入門書を紹介していただきました。

カテゴリ

トラックバック(0)

このブログ記事を参照しているブログ一覧: emacs lispのお勉強(1)

このブログ記事に対するトラックバックURL: https://www.wizard-limit.net/cgi-bin/mt/mt-tb.cgi/2597

コメントする

このブログ記事について

このページは、falseが2011年4月 6日 15:06に書いたブログ記事です。

ひとつ前のブログ記事は「emacs23の設定を見直す」です。

次のブログ記事は「emacs lispのお勉強(2)」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

広告

Powered by Movable Type 6.1.1