0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Emacs LispAdvent Calendar 2024

Day 20

Emacs Lisp 超初心者がコマンドを作ってみる 〜 別Ediffセッション実行中なら処理しない 〜

Last updated at Posted at 2024-12-24

はじめに

前回までで、 別フレームに表示できるようになっていました。

Processing difference regions ... と警告が出て結果がおかしい

一度実行してから Ediff セッションを終了していない(q)とか、別で Ediff 実行して Ediff セッション終了してない場合に

Processing difference regions ...

と警告が出て、 Ediff の表示もおかしくなります。

AI さんに聞いてみる

Bing Microsoft Copilot (無料のやつ) に聞くと、何をどう聞いてもこの結果出てきます... 手元では使えませんでしたorz
課金するとマトモな結果が返ってくるんだろうか…

ediff-regions-wordwise を実行中かどうかを判定する方法

ediff-regions-wordwiseは、Emacs Lispで異なるリージョンを単語単位で比較するための関数ですね。これを実行中かどうかを判定する方法については、以下のコードスニペットが役立つかもしれません。

(defun my-ediff-wordwise-active-p ()
  "Check if `ediff-regions-wordwise' is currently running."
  (and (boundp 'ediff-buffer-A) 
       (boundp 'ediff-buffer-B) 
       (not (null ediff-buffer-A)) 
       (not (null ediff-buffer-B))
       (eq major-mode 'ediff-mode)))

泣く泣く Ediff のソースを追う

Ediff の ドキュメント https://www.gnu.org/software/emacs/manual/html_mono/ediff.html

とか、 ソース(手元では
/usr/share/emacs/29.3/elisp/vc/ediff-*.el.gz )
を追って調べた所、見つけました。 M-x eregistry の処理を行っている一部。

vc/ediff-mult.el.gz(抜粋)
defun ediff-redraw-registry-buffer 
(前略)
(if (null ediff-session-registry)
	  (insert "       ******* No active Ediff sessions *******\n"))
(後略)

たぶん ediff-session-registry というリストをチェックすればよいらしい。 非nil だと何かしら他で走ってる。

ということで追記箇所

;; nothing previous msgid then exit
(if (not untranslated-regions)
(error "Nothing previous msgid"))
(if (not (null ediff-session-registry))    ; ←追記
; already exist ediff session              ; ←追記
(error "Please quit other Ediff session")) ; ←追記
;; source buffer for buffer-A
(save-current-buffer
    (set-buffer (get-buffer-create

今の所意図通り動いていはいます。既に処理中の Ediff セッションがあればエラーメッセージを出して処理せずに終了します。

プログラム

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)

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


(defun po-popm-frame-named-list (name)
  "List if a frame with the given NAME exists."
  (let ((frames (frame-list))
        (result '())
	)
    (dolist (frame frames)
      (when (string= (frame-parameter frame 'name) name)
        (push frame result)
	)
      )
    result
    )
  )

(defun po-pepm-get-frame-create (name)
  "If NAME's frame is exist then return exists list.
Else is not exist then create frame by NAME."
  (let ((frames (po-popm-frame-named-list name))
	)
    (if frames
        frames
      (list (make-frame
	     `(
	       (name . ,name)
	       (fullscreen . maximized)
	       )
	     )
	    )
      )
    )
  )

(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
	(frames          ; ediff target frames
	 (po-pepm-get-frame-create po-pepm-frame-name))
	(frame)
	)
    ;; nothing previous msgid then exit
    (if (not untranslated-regions)
	(error "Nothing previous msgid"))
    (if (not (null ediff-session-registry))
	; already exist ediff session
	(error "Please quit other Ediff session"))
    ;; 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))
    ;; chek frames and get a frame
    (if (> (length frame) 1)
      (progn
	(ding)
	(message "Multiple %s frames exist!"
		 po-pepm-frame-name)
	)
      )
    (with-selected-frame (car frames)
      ;; 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

今回はここまで。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?