わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

「今日のファイル」「昨日のファイル」「数日前のファイル」を開く

だいぶまえに,2ストロークで「今日のファイル」を開くというのを書いたのですが,修正版を作りました.

(setq find-today-file-base "ディレクトリ名/")
(setq find-today-file-suffix ".txt")
(if (file-exists-p find-today-file-base)
    (progn
      (defun find-file-today (arg)
        "Find the file of today or the past"
        (interactive "P")
        (let ((time1 (current-time)))
          (let ((time2 (car time1))
                (time3 (- (car (cdr time1))
                          (* 86400 (if (integerp arg) arg 0)))))
            (while (< time3 0)
              (setq time2 (1- time2))
              (setq time3 (+ time3 65536)))
            (find-file (concat
                        find-today-file-base
                        (format-time-string "%Y%m%d" (list time2 time3 0))
                        find-today-file-suffix)))))
      (global-set-key "\C-xf" 'find-file-today)))

C-x fで,今日の日付のテキストファイルを開きます.なければ新規作成します.
M-1 C-x fで,1日前すなわち昨日の日付のテキストファイルを開きます.
M-7 C-x fなら1週間前です.
このように,「M-数字」を取得しているのは,引数のargと,「(interactive "P")」の組み合わせです.なお,「(interactive "p")」とし,time3への代入を

(let (() (time3 (- (car (cdr time1)) (* 86400 arg)))) ())

とした場合,C-x fを実行したときにargには1が代入され*1,前日のファイルを開いてしまいます.
久しぶりのEmacs Lispなので,いろいろ苦労しました.

  • interactiveについては,20.2 コマンドの定義(GNU Emacs Lispリファレンスマニュアル)を見ました.
  • Cだと,ブロック開始の直後に変数宣言を列挙する際,前に宣言した変数の名前を,後ろの変数の初期化で使用できますが,Emacs Lispでは使用できないようなので,time1と,time2,time3の変数を別々のletで定義しています.
  • 37.5 時刻(GNU Emacs Lispリファレンスマニュアル)によると,(current-time)により得られる値は「(high low microsec)」という3つ組で,high * 65536 + lowがいわゆるUNIX時間になります.ということで,この値を求めてから,日数(の秒数)を減らし,除算・剰余の演算子を使って,新たな3つ組を作ってみたところ,1975年の日付を出してきました.途中のUNIX時間を書き出すと,上位ビットが落ちてしまっていることが分かりました.結局,highとlowを別々にしたまま,lowが非負整数になるよう,whileを使って調整しました.
  • format-time-stringを使用する際,「(high low microsec)」の形のリストが必要ですが,当初「'(time2 time3 0)」と書いていて,実行したら「Wrong type argument: integerp, time2」と出ていました.リストの基本の基本が分かっていませんでした.5.5 コンスセルとリストの構築(GNU Emacs Lispリファレンスマニュアル)に書かれているいくつかの関数の中で,listを使えばよいようで,「(list time2 time3 0)」として解決しました.

*1:C-x fとM-1 C-x fが同じとなるわけですね.