Emacs Lisp 超初心者がコマンドを作ってみる 〜previous msgid が無い時は処理しない〜

# はじめに

コマンドとして動くようになりましたけど、

previous msgid (#| でマークされた領域)はどのエントリにでもあるわけでありません。

無いエントリもあります。 翻訳済や未翻訳のエントリには存在しません。その場合、 空の BUFFER-A が表示されます。 まぁ、見りゃ分かるし、エラーで落ちる訳ではないので必須というわけではないのですが、 改良して previous msgid が無かったら処理は行わないようにします。

# 調べる

まずはどういう動きをしているのか調べます。 サンプルファイルを開いて、 previous msgid が「ない」エントリに移動します。
````

#. type: Plain text
#: ../Documentation-sedout/rev-list-options.txt:952
msgid "The form '--filter=blob:none' omits all blobs."
msgstr "`--filter=blob:none` の形式では、すべてのブロブが省略されます。"

````

そして M-: (eval):(progn (po-find-span-of-entry) (po-previous-untranslated-regions)) とすると

nil

が出てきます。 previous msgid 無い時は nil を返すようです。

# 実装

previous msgid 無い時は nil を返した時はエラーメッセージを出して終了するようにしましょう。

````elisp
;; nothing previous msgid then exit
(if (not untranslated-regions)
    (error "Nothing previous msgid."))
````

(完全なプログラムは下記 プログラム をご覧ください)

# 参考

いつも参考にさせてもらってるこちら

https://ayatakesi.github.io/lispref/29.4/elisp-ja.html

エラー処理の項目は

11 制御構造
の
11.7 非ローカル脱出
の
11.7.3 エラー

にあります。

# プログラム
````elisp:po-ediff-previous-msgid.el
;;; po-ediff-previous-msgid.el --- ediff previous-msgid & msgid.
;;; Author: kuma35
;;; Created: 2024/12/18
;;; Commentary:
;; In po-mode,
;; previous msgid is  '#|' marked in comment.
;; msgid is soruce sentence.
;; (msgstr is translated sentence.)
;; PEPM is my generate word.  PoEdiffPreviousMsgid.
;; Ediff-ing previous-msgid and msgid.
;;; Code:

(declare-function
 po-extract-unquoted "po-mode" (buffer start end))
(declare-function po-find-span-of-entry "po-mode" ())
(declare-function po-get-msgid "po-mode" ())
(declare-function po-previous-untranslated-regions "po-mode" ())
(declare-function
 ediff-regions-internal "ediff"
 (buffer-A beg-A end-A buffer-B beg-B end-B
	   startup-hooks job-name word-mode setup-parameters))

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

(defcustom po-pepm-buf-b-name "*pepm-now-msgid*"
  "BUFFER B name for `po-ediff-previous-msgid` .
PEPM is PoEdiffPreviousMsgid."
  :type 'string
  :require 'po-mode
  :group 'po)


(defun po-extract-previous-msgid (buffer start end)
  "Delete '#|' marker and unquote text from BUFFER START END.
delete '^#| ' each line.  then unquote.
return is String with property."
  (require 'po-mode)
  (with-temp-buffer
    (insert-buffer-substring buffer start end)
    (goto-char (point-min))
    (while (re-search-forward "^#\\(~\\)?|[ \t]*" nil t)
      (replace-match "" t t))
    (po-extract-unquoted
     (current-buffer) (point-min) (point-max))
    )
  )

(defun po-ediff-previous-msgid ()
  "Ediff previous msgid (marked #| ) and msgid."
  (interactive)
  (require 'po-mode)
  (require 'ediff)
  (po-find-span-of-entry)
  (let (
	(oldbuf (current-buffer))
	(msgid (po-get-msgid))
	(untranslated-regions
	 (po-previous-untranslated-regions))
        (beg-A) (end-A)  ; BUF-A for ediff-regions-internal
	(beg-B) (end-B)  ; BUF-B for ediff-regions-internal
	)
    ;; nothing previous msgid then exit
    (if (not untranslated-regions)
	(error "Nothing previous msgid."))
    ;; source buffer for buffer-A
    (save-current-buffer
      (set-buffer (get-buffer-create
		   po-pepm-buf-a-name))
      (setq buffer-read-only nil)
      (erase-buffer)
      (dolist (region untranslated-regions)
	(insert (po-extract-previous-msgid
		 oldbuf (car region) (cdr region)))
	)
      (goto-char (setq beg-A (point-min)))
      (push-mark (setq end-A (point-max)) t t)
      (setq buffer-read-only t)
      (restore-buffer-modified-p nil))
    ;; source buffer for buffer-B
    (save-current-buffer
      (set-buffer (get-buffer-create
		   po-pepm-buf-b-name))
      (setq buffer-read-only nil)
      (erase-buffer)
      (insert msgid)
      (goto-char (setq beg-B (point-min)))
      (push-mark (setq end-B (point-max)) t t)
      (setq buffer-read-only t)
      (restore-buffer-modified-p nil))
    ;; run ediff
    (ediff-regions-internal
     (get-buffer po-pepm-buf-a-name) beg-A end-A
     (get-buffer po-pepm-buf-b-name) beg-B end-B
     nil 'ediff-regions-wordwise 'word-mode nil)
    )  ; end of let
  )

(provide 'po-ediff-previous-msgid)
;;; po-ediff-previous-msgid.el ends here
````