[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

37. テンプレートと更新時刻の入力 (2007/12/19)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=template"
"MeadowMemo/テンプレートと更新時刻の入力"へのコメント(無し)
検索全文Elisp


この章で紹介していること



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

37.1 更新時間を自動で入力 ― time-stamp (2004/02/03)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=time-stamp"
"MeadowMemo/更新時間を自動で入力―time-stamp"へのコメント(無し)
検索全文Elisp

お勧め度:★★★★★.これはよく使う.標準機能か関数を使うかは,用途による.標準 機能の方が,モードによりカスタマイズしやすい.

標準機能と関数を紹介します.

37.1.1 Meadow に付属の time-stamp (2004/02/03)  
37.1.2 time-stamp を入力する関数 (2003/09/27)  
37.1.3 現在の時刻を入力 (2004/02/01)  
37.1.4 複数の書式で日付けを入力 ― instamp (2004/02/01)  



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

37.1.1 Meadow に付属の time-stamp (2004/02/03)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=meadow%20time-stamp"
"MeadowMemo/Meadowに付属のtime-stamp"へのコメント(無し)
検索全文Elisp

何が問題なのか?

ファイルに

Time-stamp: <2003 年/09 月/27 日>
更新時刻 "2003 年/09 月/27 日 22 時 28 分 50 秒"

のように更新時刻を入れたい時があります.しかし,これらの書式はモードによってばら ばらなのが普通です.

しかし,そのたびに毎回手で入力するのは面倒すぎます.

何ができるのか?

ファイルに更新時刻を自動で入力できます.

インストール方法

Meadow に付属しています.

どうやって動くのか

更新時刻の挿入は time-stamp.el で行います.

これがどのように動くのかを理解すると,設定が分かりやすくなりますので,説明してお きます.

ただし,以降の説明はあくまで概念です.実際に Elisp がそうなっているわけではありま せん.

設定すべき項目

基本的な動作を追うと分かるように,設定すべきものは

です.

開始/終了文字の設定

開始/終了文字を正規表現で指定します.

例えば

Time-stamp: <2003/09/27 22:26:04>

であれば,

 
(setq time-stamp-start "Time-stamp:[ \t]*<")
(setq time-stamp-end ">")

となります.「 [ \t]+ 」 はスペースかタブが 0 回以上繰り返されていることを意味します. 要はスペースがあってもなくても関係ないようにしています.

「 Time-stamp:」の部分を変えれば,開始文字は好きに変更できますし, 「 time-stamp-start 」と「 time-stamp-end 」の「<>」を変更すれば,更新時刻の前後の文 字も自由に変更できます.

更新時刻の書式

まずはサンプルです

 
(setq time-stamp-format "%:y 年/%02m 月/%02d 日 %02H 時%02M 分%02S 秒")

これで,「 2003 年/09 月/27 日 22 時 28 分 50 秒」という書式になります.日付であ れば,これを参考に編集すれば簡単に書くことができます.

対応させれば分かるように「%」で始まる部分がそれぞれ書式になっています.例えば 「%:y 」で「 2003 」のような年を出力でき,「%02m 」で「 09 」のような月になります.

「%:y 」と「%02m 」は書式が違いますね.「%:m 」でいいのでは? と感じるかもしれませ ん.これはその通りで,「%:m 」のように「 02 」を「:」に変えても動作します.ただし, 出力は少し違い,「%02m 」では「 09 」に,「%:m 」では「 9 」になります.

つまり,「 02 」は桁数を表しているのです.そして,「 0 」の部分は空いた部分を「 09 」 のように 0 で埋めることを意味しています.これを「%2m 」とすると, 1 桁の時には空いた 部分はスペースになります.

以降で他の書式についても簡単に説明しておきます.

更新時刻の自動挿入

ここまでで指定すべき 3 つの変数は設定できると思います.設定したら,早速ファイルの 先頭に

Time-stamp: <>

のように指定した書式を入れてみましょう.そして,M-x time-stampとします.こ れで,タイムスタンプが挿入されます.

しかし,これでは毎回コマンドを入力する必要があり面倒です.そこで,以下を.emacs に 追加します.

 
(if (not (memq 'time-stamp write-file-hooks))
    (setq write-file-hooks
          (cons 'time-stamp write-file-hooks)))

これで,ファイルを保存するだけで,タイムスタンプを変更してくれます.

モード毎に書式を変えたい

まず12.2 フックの意味と探し方 (2004/01/24)を参考にフックを探します.そして,

 
 (add-hook 'yahtml-mode-hook
           '(lambda ()
              (setq time-stamp-start "Time-stamp:[ \t]+<")
              (setq time-stamp-end ">")
              (setq time-stamp-format "%:y 年/%02m 月/%02d 日")
              ))

のように探したフック (例では yahtml-mode-hook) に対して設定を行います.

ファイル毎に書式を変えたい

ファイルの末尾に

@c Local Variables:
@c time-stamp-start: "Time-stamp:[ \t]+<"
@c time-stamp-end: ">"
@c time-stamp-format: "%:y 年/%02m 月/%02d 日 %:S"
@c buffer-file-coding-system: euc-jp
@c End:

のように追加します.これは Texinfo の例です.

テキストファイルなら

Local Variables:
time-stamp-start: "Time-stamp:[ \t]+<"
time-stamp-end: ">"
time-stamp-format: "%:y 年/%02m 月/%02d 日 %:S"
buffer-file-coding-system: euc-jp
End:

HTML なら

<!-- Local Variables: -->
<!-- time-stamp-start: "Time-stamp:[ \t]+<" -->
<!-- time-stamp-end: ">" -->
<!-- time-stamp-format: "%:y 年/%02m 月/%02d 日 %:S" -->
<!-- buffer-file-coding-system: euc-jp -->
<!-- End: -->

という風に適当に変える必要があります.

カスタマイズ

動作を追うと不満な点は 2 箇所でしょうか.

書式をもっと変更したい

書式は

 
(setq time-stamp-format
   '(time-stamp-yyyy/mm/dd time-stamp-hh:mm:ss))

のようにも指定できます.「 time-stamp-yyyy/mm/dd 」という部分は関数名で, 「 time-stamp.el 」内で

 
(defun time-stamp-yyyy/mm/dd ()
  "Return the current date as a string in \"YYYY/MM/DD\" form."
  (format-time-string "%Y/%m/%d"))

のように定義されてます.単純ですね.

例えば,

 
(defun time-stamp-japanese-a ()
  "Return a day of the week"
  (let ((aw (string-to-number (format-time-string "%w" (current-time)))))
    (cond
     ((= aw 0)
      "日曜日")
     ((= aw 1)
      "月曜日")
     ((= aw 2)
      "火曜日")
     ((= aw 3)
      "水曜日")
     ((= aw 4)
      "木曜日")
     ((= aw 5)
      "金曜日")
     ((= aw 6)
      "土曜日"))))


(setq time-stamp-format
      '(time-stamp-yyyy/mm/dd time-stamp-hh:mm:ss
                              time-stamp-japanese-a))

「 2003/09/28 16:43:08 日曜日」という書式になります.関数が書ける人であれば,あ りとあらゆる書式を設定できます.

format-time-string の書式は 時刻の変換 が参考になります.



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

37.1.2 time-stamp を入力する関数 (2003/09/27)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=myfunc%20time-stamp"
"MeadowMemo/time-stampを入力する関数"へのコメント(無し)
検索全文Elisp

何ができるのか?

$Lastupdate: 2004/02/01 10:00:33 $

という行があれば探して, 更新時間を書き換えてくれます.

設定方法

以下を.emacs に追加します.

フォーマットは適当に変更できます.

 
(defvar my-save-buffer-hook nil)
(defun save-buffer-wrapper ()
  (interactive)
  (let ((tostr (concat "$Lastupdate: " (format-time-string "%Y/%m/%d %k:%M:%S") " $")))
    (save-excursion
        (goto-char (point-min))
        (while (re-search-forward
                "\\$Lastupdate\\([0-9/: ]*\\)?\\$" nil t)
          (replace-match tostr nil t)))
    (run-hooks 'my-save-buffer-hook)
    (save-buffer)))

(global-set-key "\C-x\C-s" 'save-buffer-wrapper)



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

37.1.3 現在の時刻を入力 (2004/02/01)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=time%20string"
"MeadowMemo/現在の時刻を入力"へのコメント(無し)
検索全文Elisp

何ができるのか?

特に自動でなくて構わないが,特定の書式で時間を入力したいという場合には自分で作る のが簡単です.

設定方法

簡単なサンプルは以下のようになります.

 
(defun my-insert-time ()
  (interactive)
  (insert (concat
           "Time:" (format-time-string "%H:%M:%S"))))

詳しい使い方

上記を.emacs に追加して,M-x my-insert-time とすると,

Time:20:15:12

のように現在時刻が入力されます.日付けの入力や時刻の書式を変えたい場合には, 「%H:%M:%S 」の部分を変更します.

書式に関しては, マニュアルの書式の変換が参考になります.

現在時刻を挿入するコマンド

上記のことを使うと,以下のようなコマンドを作ることができます.

これで

C-x T → Sat Aug 02 12:55:42 2003
C-u C-x T → 2003 年 8 月 02 日 12 時 55 分 55 秒 (土曜日)

という風に時刻が挿入されます.

 
;;; -*- Emacs-Lisp  ; Coding: iso-2022-jp -*-
;; Masatake YAMATO <jet@airlab.cs.ritsumei.ac.jp>;; Insert current time string;;
;; C-x T でこんな風に: Thu Apr 25 09:58:35 1996
;; C-u C-x T で日本語で: 1996 年 4 月 25 日 09 時 58 分 52 秒 (木曜日)
;; な風に現在時刻が入ります。
;;
;; 日本語に変換する時に current-time-string を分解しているので,
;; そこを変えればお好みのスタイルに加工できると思います。
(define-key ctl-x-map "T" 'insert-time)
(defun insert-time (arg)
  "Insert current time.
With prefix argumet ARG, insert current time string in Japanese."
  (interactive "P")
  (if arg
      (insert (current-time-japanese-string))
    (insert (current-time-string))))
(defun current-time-japanese-string ()
  "Return the current time, as a human-readable JAPANESE string."
  (let ((base (current-time-string))
        (time-j-table
         '(("Jan" . "1") ("Feb" . "2") ("Mar" . "3")
           ("Apr" . "4") ("May" . "5") ("Jun" . "6")
           ("Jul" . "7") ("Aug" . "8") ("Sep" . "9")
           ("Oct" . "10") ("Nov" . "11") ("Dec" . "12")
           ("Mon" . "月") ("Tue" . "火") ("Wed" . "水")
           ("Thu" . "木") ("Fri" . "金") ("Sat" . "土")
           ("Sun" . "日")))
        jadotw jmonth jday jhour jmin jsec jyear
        last)
    (string-match
       (mapconcat
        (lambda (f) f)
        '(
          "\\([a-zA-Z]+\\)\\W+"
          "\\([a-zA-Z]+\\)\\W+"
          "\\([0-9]+\\)\\W+"
          "\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)"
          "\\W+\\([0-9]+\\)"
          ) "")
     base)
    (setq jadotw (substring base (match-beginning 1) (match-end 1)))
    (setq jmonth (substring base (match-beginning 2) (match-end 2)))
    (setq jday (substring base (match-beginning 3) (match-end 3)))
    (setq jhour (substring base (match-beginning 4) (match-end 4)))
    (setq jmin (substring base (match-beginning 5) (match-end 5)))
    (setq jsec (substring base (match-beginning 6) (match-end 6)))
    (setq jyear (substring base (match-beginning 7) (match-end 7)))
    (setq last (concat jyear "年 "))
    (setq last (concat last (cdr (assoc jmonth time-j-table)) "月 "))
    (setq last (concat last jday "日 "))
    (setq last (concat last jhour "時 "))
    (setq last (concat last jmin "分 "))
    (setq last (concat last jsec "秒 "))
    (setq last (concat last "(" (cdr (assoc jadotw time-j-table)) "曜日)"))
    last))



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

37.1.4 複数の書式で日付けを入力 ― instamp (2004/02/01)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=instamp"
"MeadowMemo/複数の書式で日付けを入力―instamp"へのコメント(無し)
検索全文Elisp

要約

日付けや時刻を設定しておいた書式で入力できます.

情報源

作者様の日記より.

何が問題なのか?

日付けや時刻を入力したくなる時があります.他で紹介した方法を使うこともできますが, これらの方法では書式を変更するために毎回ソースを変更する必要があります.

何ができるのか?

4-2-1 (Sun)
2/1 (Sun)
2004/2/1

などの書式で日付けを入力できます.しかも,これらの書式は簡単に切り替えることがで きます.

インストール方法

instamp.elをダウンロード してロードパスの通ったところに置きます.

設定方法

以下を.emacs に追加します.キーバインドは好みに合わせて変更してください.

 
(autoload 'instamp
  "instamp" "Insert TimeStamp on the point" t)
(define-key global-map "\C-cs" 'instamp)

詳しい使い方

C-cs で日付けを入力できます.その直後にC-nC-p とすると,書式 を変更することができます.一度ある書式で入力すると,次回にはC-csとするだけ で,その書式が呼び出されます.また,C-cs後にz とすると,「 2004/2/1 (日) 」が「 2004/02/01 (日) 」のようになります.



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

37.2 テンプレート機能 (2007/12/19)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=new%20file"
"MeadowMemo/テンプレート機能"へのコメント(無し)
検索全文Elisp

ファイルを新規に作る時などに便利なものを紹介します.

37.2.1 多彩なテンプレート機能 ― autoinsert (2004/02/01)  
37.2.2 定型文を選択して入力  



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

37.2.1 多彩なテンプレート機能 ― autoinsert (2004/02/01)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=autoinsert"
"MeadowMemo/多彩なテンプレート機能―autoinsert"へのコメント(無し)
検索全文Elisp

ワードなどでは,テンプレート機能があります.これは,共通の部分だけを書いたファイ ルを用意しておき,自動的に挿入する機能です.

Meadow にもこの機能があります.ただし,もっと多彩なことができるようになっています.

まずは,共通の設定項目です.以下を入れておくと,テンプレートがあれば,自動的に挿 入するようになります.

 
;; テンプレートの保存先
(setq auto-insert-directory "~/insert/")
(auto-insert-mode 1)
;; テンプレート挿入時に尋ねない
;; デフォルトは 'function
(setq auto-insert-query nil)

それでは,テンプレートの指定方法を紹介します.

37.2.1.1 指定したファイルを挿入する (2003/02/24)  
37.2.1.2 対話的にテンプレートを挿入 (2004/02/01)  
37.2.1.3 テンプレートとして関数を設定 (2003/02/24)  



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

37.2.1.1 指定したファイルを挿入する (2003/02/24)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=autoinsert%20normal"
"MeadowMemo/指定したファイルを挿入する"へのコメント(無し)
検索全文Elisp

最も基本的なテンプレート機能です.

機能は単純で,指定したファイルをそのまま挿入するというものです.

これは,以下のように設定します.

 
(setq auto-insert-alist
      (append
       '(
         ;; モード名で指定
         (yahtml-mode . "test.html")
         ;; ファイル名で指定
         ("\\.html$" . "test.html")
         )
       auto-insert-alist))

そして,「~/insert/test.html 」を作成しておきます.これで, HTML を編集する時には自 動的に,テンプレートファイル「~/insert/test.html 」を挿入してくれるようになります.

モードや名前に応じて設定しておくと非常に便利です.



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

37.2.1.2 対話的にテンプレートを挿入 (2004/02/01)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=autoinsert%20rec"
"MeadowMemo/対話的にテンプレートを挿入"へのコメント(無し)
検索全文Elisp

さて,テンプレートファイルによるテンプレートも便利なのですが,

といった不満があると思います.その場合,ファイルによるテンプレートでは,変更箇所 を探して,編集する必要があり少し面倒です.

そこで,少し複雑になりますが,以下のようなテンプレートを使います.

 
(setq auto-insert-alist
  (append
   '(
     (yahtml-mode
      "<!doctype html public \"-//W3C//DTD HTML 3.2//EN\">\n"
      "<html>\n"
      "<head>\n"
      "<title>" (read-string "タイトル: ") "\n"
      "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-2022-JP\">\n"
      "</head>\n"
      "<BODY BGCOLOR=\"#" (read-string "背景色: ") "\""
      " TEXT=\"#" (read-string "文字色: ")"\">\n\n"
      "メールアドレス:"
      (concat user-mail-address)
     "\n\n\n"
      "</html>\n")
     )
   auto-insert-alist))

見ての通り,基本的には文字を「""」で括っているだけです.ただし,「"」を入力した い時には,「\"」,改行は「\n 」とします.「\」は「\\」,タブは「\t 」になります.

また,この中で関数を使うこともできます.

 
(read-string "タイトル: ")

などとしているのが,いい例でしょう.

これは,ここまでテンプレートを挿入すると,ミニバッファ に「タイトル: 」と表示し,ユーザに文字入力を求めます.そして,入力された文字を, そこへ入れることができます.こういう風にファイルによって変わる文字も簡単にテンプ レートとして扱うことができます.

また,メールアドレスは「 user-mail-address 」という変数で設定されていますので,

 
(concat user-mail-address)

とすると,指定した箇所にメールアドレスを入力できます.



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

37.2.1.3 テンプレートとして関数を設定 (2003/02/24)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=autoinsert%20func"
"MeadowMemo/テンプレートとして関数を設定"へのコメント(無し)
検索全文Elisp

ここまでの機能ではまだ満足できない.もっと自由に設定したいという人は,自分で関数 を書くといいでしょう.

設定はこんな風にします.

この例は単純な例ですが,用途に応じて自由に書くことができるので,どんなテンプレー トでも作ることができます.

 
(setq auto-insert-alist
      (append
       '(
         ;; ファイル名が「 time 」に一致したら,
         ;; my-date を実行する
         ("time" . my-date)
         )
       auto-insert-alist))

(defun my-date ()
  (insert (format-time-string "%D" (current-time))))



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

37.2.2 定型文を選択して入力

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=my-template"
"MeadowMemo/定型文を選択して入力"へのコメント(無し)
検索全文Elisp
要約

あらかじめ設定しておいた文章などを簡単に入力できます.

情報源

2ちゃんねる

何が問題なのか?

よく入力する文章やコードなどがあります.レジスタなどを使えば,こうした文章などを 貼り付けることはできますが,どこに何をコピーしたか覚えておかなければなりません.

何ができるのか?

あらかじめ指定しておいた文章などのリストが表示され,そのリストから選択して挿入で きます.

設定済みMeadowでは

設定していません.

設定方法

以下を .emacs に追加します.

 
(defvar my-template-text-file "~/.template")
(defvar my-template-buffer nil)
(defvar my-template-point nil)

(defun my-template-insert ()
  (interactive)
  (let (content)
    (when (setq
           content
           (get-text-property (point) :content))
      (save-excursion
        (set-buffer my-template-buffer)
        (save-excursion
          (goto-char my-template-point)
          (insert content))))))

(defun my-template-select ()
  (interactive)
  (let ((buffer
         (get-buffer-create "*select template*"))
        templates begin template-map text)
    (setq my-template-buffer (current-buffer)
          my-template-point  (point))
    (unless (file-readable-p my-template-text-file)
      (error "Couldn't read template file: %s"))
    (with-temp-buffer
      (insert-file-contents my-template-text-file)
      (goto-char (point-min))
      (while (re-search-forward "^\\*\\(.*\\)$" nil t)
        (when begin
          (setq templates
                (cons
                 (cons
                  (car templates)
                  (buffer-substring
                   begin (1- (match-beginning 0))))
                 (cdr templates))))
        (setq templates (cons (match-string 1) templates))
        (setq begin (1+ (match-end 0))))
      (when begin
        (setq templates
              (cons
               (cons
                (car templates)
                (buffer-substring begin (point-max)))
               (cdr templates)))))
    (pop-to-buffer buffer)
    (setq buffer-read-only nil
          major-mode       'template-select-mode
          mode-name        "Select Template"
          template-map     (make-keymap))
    (suppress-keymap template-map)
    (define-key template-map " "    'my-template-insert)
    (define-key template-map "\C-m" 'my-template-insert)
    (define-key template-map "n"    'next-line)
    (define-key template-map "p"    'previous-line)
    (define-key template-map "q"    'kill-buffer-and-window)
    (use-local-map template-map)
    (buffer-disable-undo)
    (delete-region (point-min) (point-max))
    (dolist (tt templates)
      (setq text (concat (car tt) "\n"))
      (put-text-property
       0 (length text) :content (cdr tt) text)
      (insert text)
      (goto-char (point-min)))
    (delete-region (1- (point-max)) (point-max))
    (setq buffer-read-only t)
    (set-buffer-modified-p nil)))

詳しい使い方

入力したい文章を my-template-text-file で指定したファイル(デフォルトは ~/.template )に入力します.

例えば以下のように.

*あいさつ
こんにちは・・・・

*おわび
このたびは・・・の件につき御迷惑をおかけてして・・・

「*」で始まる行が名前になり,それ以外が入力される文章となります.

こうしておいて,M-x my-template-select とすると,別ウィンドウに

あいさつ
おわび

と表示されます.

で,例えば,「あいさつ」にカーソルをあわせてRETとすると,その名前の文章が 入力されます.

q でそのバッファは閉じることができます.


[ << ] [ >> ]           [表紙] [目次] [索引] [検索] [上端 / 下端] [?]