2022-10-30 ,

Org Agendaの長い見出しにインデントを適用する

org-modeでAgenda Viewを見ていたときに、長い見出しが折り返されているのが見づらいことに気がついた。(私は普段org-startup-truncatedをnilにして使っているのでそうなるのだと思う。表の部分にはphscrollを使用している)

Org Agendaで長い見出しが折り返されている様子
図1: Org Agendaで長い見出しが折り返されている様子

折り返し後のテキストを字下げする機能はEmacsに既にあって、wrap-prefixテキストプロパティを使えば良い。

org-agenda.elのorg-agenda-format-item関数を次のように修正する。

        ;; Evaluate the compiled format
-       (setq rtn (concat (eval formatter t) txt))
+       (let ((prefix (eval formatter t)))
+         (setq rtn (concat prefix txt))
  
        ;; And finally add the text properties
-       (remove-text-properties 0 (length rtn) '(line-prefix t wrap-prefix t) rtn)
+         (remove-text-properties 0 (length rtn) '(line-prefix t wrap-prefix t) rtn)
+         (put-text-property 0 (length rtn) 'wrap-prefix (make-string (length prefix) ? ) rtn))
        (org-add-props rtn nil
          'org-category category
            'tags tags
            'org-priority-highest org-priority-highest

すると次のようにスッキリした見た目になった。

Org Agendaの長い見出しにインデントを適用した様子
図2: Org Agendaの長い見出しにインデントを適用した様子

関数を直接修正するとorg-modeのバージョンアップによって壊れる可能性が高いので、せめてadvice-addを使うなどして動作を変えたいところ。なので次のようにしてみた。

(defvar my-org-agenda-format-item-prefix "") ;;formatterが返した値を取っておくための変数。

(defun my-org-agenda-format-item (orig-fun &rest args)
  ;; 元のorg-agenda-format-itemを呼び出す前に
  ;; org-prefix-format-compiledを一時的に書き替える。
  (let* ((org-prefix-format-compiled
          (list
           (car org-prefix-format-compiled)
           ;; formatterを書き替えてしまう。
           ;; 結果を my-org-agenda-format-item-prefix に書き込むように。
           (list 'setq 'my-org-agenda-format-item-prefix (cadr org-prefix-format-compiled))))
         ;; 元のorg-agenda-format-itemを呼び出す。
         (rv (apply orig-fun args)))
    ;; 戻り値にwrap-prefixテキストプロパティを追加する。
    ;; インデントの深さはformatterが返した文字列(prefix)の長さとする。
    (put-text-property 0 (length rv) 'wrap-prefix (make-string (length my-org-agenda-format-item-prefix) ? ) rv)
    rv))

(advice-add #'org-agenda-format-item :around #'my-org-agenda-format-item)

もちろんOrg Agendaバッファのtruncate-linesをtにするという手もある。はみ出した見出しはスクロールしなければ見えなくなるが。