Emacsではdoc-view-modeが標準で提供されているため、画像やPDFはファイルを開くだけで描画される。この当たり前の機能は、オーバーレイによって実装されており、表示を切り替える事で生の状態のデータをバッファに表示する事もできる。そのため、ファイルのデータ自体を直接編集する事もできる。
PDFでのdoc-view-modeの挙動を確認してみた所、概ね以下のような順序で処理が行われていた。
- PDFから画像を作成する。
- オーバーレイを作成する。
- オーバーレイに画像を紐付け、バッファに挿入する。
PDFから画像を作成する際、その環境にインストールされている外部プログラムを使用する。僕の環境では mudraw
が使われていた1。
GnuPGで暗号化されたファイルの場合、一度GnuPGで復号化した後、そのデータを描画する必要がある。注意したい点としては、GnuPGで暗号化されたファイルというものは、誰かに盗まれたくないデータであるため暗号化しているのであって、復号化したデータをできるだけファイルには書き出さない、又はちゃんと削除するという事を実施したい。
まず mudraw
の機能について確認していく。ポイントとしては2つある。1つ目は標準入力からのデータを受け付けるか、2つ目は標準出力に結果を出力できるかだ。確認した所、この2点については mudraw
はサポートしてないようだった2。仕方がないので、一時ファイルに書き出して処理を行うようにする。
gpg
を使い、指定したファイルを復号化し、PDFを書き出す。gpg -o temp.pdf --decrypt sample_copy.pdf.gpg
mudraw
を使い、PNGファイルを書き出す。mutool draw -o temp.png temp.pdf
表示用のバッファを作成する。
(get-buffer-create "*Doc View: PDF GPG*")
PNGファイルからEmacsの画像データを
create-image
で作成する。(setq-local current-image (create-image (expand-file-name "./temp.png")))
オーバーレイを作成する。
(insert " ") (setq-local current-overlay (make-overlay (point-min) (1+ (point-min))))
オーバーレイに画像を関連付け、表示する。
(overlay-put current-overlay 'display current-image)
この一連の処理をdiredでファイルを開こうとした時に実施できれば良い。 dired
でファイルを開く時は、 dired-find-file
が呼び出される。この時に、先程の処理をする必要がある。
少し頭の中を整理すると、gpgと拡張子が付いているファイルを開く場合、Emacsは復号化しようとしてくれるため、手動で復号化をする必要はなかった。そこでファイルを開いた後のバッファの内容を一時ファイルに書き出し、それを開いた後、ファイル自体を削除してしまえばいいという結論になった。
(defun display-pdf ()
(interactive)
(let ((current-dir default-directory)
(temp-file-path (make-temp-file "testing" nil ".pdf")))
(write-region (point-min) (point-max) temp-file-path)
(find-file temp-file-path)
(delete-file temp-file-path)))
save-file
を呼び出してしまうと、復号済みのファイルが保存されてしまうけれど、一旦はこれで良しとする。
mudrawはMuPDFに梱包されているプログラム。
mupdfのドキュメントには、出力ファイルの指定を省略した場合、標準出力に出力するという記述があるが、 Homebrew
でインストールした mudraw version 1.23.7
では、出力ファイルの指定を省略しても、標準出力には何も出力されなかった。https://mupdf.readthedocs.io/en/latest/mutool-draw.html