動機
Emacsのカスタマイズをした。Blogを書くときは自作のEditorモードを用いて いる。これは書いた内容を特定のディレクトリに配置してGitに登録するツー ルだ。使ってくと2つのパターンでファイルを作成したくなることに気づいた。 今回はそれぞれのパターンに対応できるようにEmacsをカスタマイズした。
2つのパターン
ファイルスタイル
今までのスタイルでXXXX.orgのようにURLとして用いられるファイル名に直接 拡張子がついたものである。これを便宜的にファイルスタイルと呼ぶことにす る。
例えば短文のコメントであったり、複数のファイルを作る必要のないようなシ ンプルな記事の場合に用いられる。
ディレクトリスタイル
これはXXXX/index.orgのようにURLとして用いられる部分がディレクトリ名に なっており、その配下にindex.orgというファイルを作成するものである。こ れを便宜的にディレクトリスタイルと呼ぶことにする。
例えばサンプルコードとして別ファイルを作成したり、画像を配置したりする 場合に用いられる。
2つのパターンに対応する
主にeditor-save-as-kill関数を修正しeditor-file-path-directory-styleの 値で挙動を変更できるようにした。コマンドUIとしてtransientを用いている ので、fでファイルスタイル、dでディレクトリスタイル、sでデフォルトのス タイルとして保存できるように修正した。
全文を載せておく。
(defvar editor-buffer-name "*EDITOR*")
(defvar editor-map (make-sparse-keymap))
(defun editor-refresh-export-option-date ()
"DATEエクスポートオプションの更新"
(interactive)
(let* ((timestamp (format-time-string "%+FT%T%z"))
(pattern (format "s/^\#+DATE:.*$/#+DATE: %s/g" timestamp)))
(call-process-region (point-min) (point-max) "sed" t t t "-e" pattern)))
(defun editor-create-buffer ()
(interactive)
(let ((buf-name editor-buffer-name))
(with-current-buffer (get-buffer-create buf-name)
(if (= 0 (buffer-size))
(progn
;; エクスポートオプションの追加
(save-excursion
(goto-char 0)
(insert "#+DATE:\n#+TAGS[]: comment\n\n"))
(editor-refresh-export-option-date)))
(kill-all-local-variables)
(use-local-map editor-map)
(editor-mode))
(switch-to-buffer buf-name)))
(define-derived-mode editor-mode org-mode
"Editor mode"
nil)
(defun editor-make-new-file-path ()
"エディターモードの保存先ファイルのパス返す。
通常ではファイルスタイルorgファイル (XXXX.org) のパスを返す。
`editor-file-path-directory-style` をNONE NILにするとディレクトリスタ
イルのパス(XXXX/index.org)を返す。
"
(let ((file-style-path (concat (directory-file-name editor-base-directory)
(format "/%s.org" (truncate (float-time))))))
(if editor-file-path-directory-style
(concat (directory-file-name (file-name-sans-extension file-style-path)) "/index.org")
file-style-path)))
(defcustom editor-base-directory "/ng/symdon/pages/posts")
(defcustom editor-file-path-directory-style nil)
(defcustom editor-new-file-path #'editor-make-new-file-path)
(defun editor-save-as-kill ()
"エディターバッファの内容をファイルに保存してgit commitする"
(interactive)
(let ((new-file-path (funcall editor-new-file-path)))
;; Create parent directory.
(make-directory (file-name-directory new-file-path) t)
;; Copy buffer content
(switch-to-buffer
(with-current-buffer (find-file-noselect new-file-path)
(insert-buffer-substring (get-buffer editor-buffer-name))
(save-buffer)
(current-buffer)))
;; Git commit
(let ((default-directory (file-name-directory new-file-path)))
(shell-command (format "git add %s" new-file-path))
(shell-command (format "git commit -m 'Add comment.' %s" new-file-path))))
(kill-buffer editor-buffer-name))
(defun editor-save-as-kill-file-style ()
"ファイルスタイルでエディターバッファの内容を保存する"
(interactive)
(let ((editor-file-path-directory-style nil))
(editor-save-as-kill)))
(defun editor-save-as-kill-directory-style ()
"ディレクトリスタイルでエディターバッファの内容を保存する"
(interactive)
(let ((editor-file-path-directory-style t))
(editor-save-as-kill)))
(transient-define-prefix editor-save-as ()
"Editor mode save as..."
["Save as"
("f" "Save as file style" editor-save-as-kill-file-style)
("d" "Save as directory style" editor-save-as-kill-directory-style)
("s" "Save as default" editor-save-as-kill)
])
(bind-keys :map editor-mode-map
("C-x C-s" . editor-save-as))
(bind-key* "C-t C-w" 'editor-create-buffer)