Emacs Lisp 超初心者がコマンドを作ってみる 〜バッファーにカキコ〜

関数をとりあえず作って見ましたが、ミニバッファーに表示するだけではあんまりおもしろくない。そこで、ミニバッファーに表示する代わりに結果をバッファーに書き込んでみましょう。

::: note info
前回と同様、サンプルファイル rev-list-options.po を開いておきます。
:::

# 結果を \*scratch\* バッファーに書き込む

前回作った関数を再掲します:
````common_lisp:po-ediff-previous-msgid.el
(defun po-ediff-previous-msgid ()
  "Ediff previous msgid (marked #| ) and msgid."
  (po-find-span-of-entry)
  (po-get-msgid))
````

今度はこれを改造して msgid を \*scratch\* バッファに書き込んでみましょう。

````common_lisp:po-ediff-previous.msgid.el
(defun po-ediff-previous-msgid ()
  "Ediff previous msgid (marked #| ) and msgid."
  (po-find-span-of-entry)
  (let ((msgid (po-get-msgid)))
    (with-current-buffer "*scratch*"
      (insert msgid))))
````

これを先程と同様に M-: (po-ediff-previous-msgid)
で実行します。そうすると \*scratch\* バッファに msgidの内容が挿入されます。

po-find-span-of-entry カーソル位置のエントリを認識し、様々変数をセットします(たぶん)

with-current-buffer の中で \*scratch\* バッファを一時的にカレントバッファにして msgid の内容を カレントバッファに insert するのですけど、 

with-current-buffer の中では既にカレントバッファーは \*scratch\* になっちゃってるので po-get-msgid を走らせてもエラーになります。

そこで、let の ところで msgid に po-get-msgid の実行結果の文字列を代入(バインド)してから、 with-current-buffer の中では (insert msgid) としています。

po-get-msgid は msgid の内容を unquote (行の前後のダブルクォーテーションを取り除き、行を繋げて、文字等のエスケープを戻した上で) してから返します。


# 新しく作った専用バッファーに書き込む

今度はこれをまっさらのバッファーに書き込んでみましょう。
新規に作ったバッファーに書き込むか、あるいは、以前作ったバッファーの内容をクリアして書き込みます。

````common_lisp:po-ediff-previous.msgid.el
(defcustom po-ediff-previous-msgid-buffer-a-name "*pepm-previous-msgid*"
  "po-ediff-previous-msgid BUFFER A name. pepm is PoEdiffPreviousMsgid"
  :type 'string
  :require 'po-mode
  :group 'po)

(defcustom po-ediff-previous-msgid-buffer-b-name "*pepm-now-msgid*"
  "po-ediff-previous-msgid BUFFER A name. pepm is PoEdiffPreviousMsgid"
  :type 'string
  :require 'po-mode
  :group 'po)


(defun po-ediff-previous-msgid ()
  "Ediff previous msgid (marked #| ) and msgid."
  (po-find-span-of-entry)
  (let (
	(msgid (po-get-msgid))
	)
    (save-current-buffer
      (set-buffer (get-buffer-create
		   po-ediff-previous-msgid-buffer-b-name))
      (setq buffer-read-only nil)
      (erase-buffer)
      (insert msgid)
      (restore-buffer-modified-p nil)
      (setq buffer-read-only t))))
````

defcustom は 定数の代わりにユーザーが変更できる値として BUFFER A と BUFFER B 用のバッファー名を定義しています。
別のシステムと競合した場合はここを変更することになります。
なるべく競合しなさそうな名前にしてみましたけど、どうでしょうか。

save-current-buffer カレントバッファの情報を一旦退避してここを抜けた後に復元するものです。

バッファ操作に関しては Emacs の作りというかクセっぽいのがこの部分で、多くの操作はカレントバッファに対してしかできない作りになっているため、一時的にカレントバッファを退避して、指定のバッファをカレントバッファにして操作を行い、元のカレントバッファに戻します。

save-current-buffer や with-current-buffer は python の with のようなもので、途中でエラー等になっても元のカレントバッファを復旧できるようになっています。

get-buffer-create は 無ければ新規作成し、あればそれをそのまま使います。

erase-buffer は既存の場合に内容を空にします。

insert は msgid の内容をカレントバッファーに挿入します。

 (restore-buffer-modified-p nil) は編集済(モードラインに * が表示される)を消します。  set-buffer-modified-p と違ってモードラインの強制更新をしないので、当該バッファーを表示して見ていても変化が無いように見えるかもしれません。一度バッファーを消して再度表示(または再描画)すれば編集済マーク(*)が消えているのがわかります。



# 登録
ちょっと記述が増えたので M-x eval-buffer で .el バッファ全体を評価します。

# 実行

サンプルファイルで M-: (eval) (po-ediff-previous-msgid) で実行します。

バッファーリストから *pepm-now-msgid* を探して表示します。msgidの内容が入っています。

実行結果(参考)
![buffer-pepm-now-msgid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435164/a390c85a-a6b0-2291-2da8-332632eb7194.png)

それでは再度実行してみてください。 M-: (eval) (po-ediff-previous-msgid) 
内容は同じです。これは毎回 erase-buffer で内容を消去してから msgidの内容を追加しているからです。

今回はここまで。