ツリーのカットペースト時に統計情報を更新する

org-refile を使ってサブツリーを移動するのもいいですが、シンプルにサブツリーをカット&ペーストするのも直感的で良いですよね。

スピードコマンドを有効にしていれば、カット&ペーストは、ツリー(見出し)の行頭で ky で簡単できます( yorg-yank を呼ぶ設定は自分で追加が必要です)。

今回は、下記ように org-cut-subtreeorg-yank に advice する設定を加えることで、カットまたはペースト時に、親ツリーの見出しに表示している統計情報を更新するようにしました。

(with-eval-after-load "org"

  ;; "k" でツリーをカットする時に、カレントサブツリーと親の統計情報を更新する
  (defun my-k-update-todo-statistics (f &rest n)
    (org-update-statistics-cookies nil)
    (let ((p (point))
          (not-last-subtree-p (funcall 'org-get-next-sibling)))
      (goto-char p)
      (apply f n)
      (if not-last-subtree-p
          (org-update-parent-todo-statistics)
        (org-previous-visible-heading 1)
        (org-update-parent-todo-statistics)
        (org-next-visible-heading 1))))
  (advice-add 'org-cut-subtree :around #'my-k-update-todo-statistics)

  ;; "y" でツリーをペーストする時に、カレントサブツリーと親の統計情報を更新する
  (defun my-y-update-todo-statistics (&optional _arg)
    (when (and (org-kill-is-subtree-p)
               (or (bolp)
                   (and (looking-at "[ \t]*$")
                        (string-match
                         "\\`\\*+\\'"
                         (buffer-substring (point-at-bol) (point))))))
      (org-previous-visible-heading 1)
      (org-update-statistics-cookies nil)
      (org-update-parent-todo-statistics)
      (org-next-visible-heading 1)))
  (advice-add 'org-yank :after #'my-y-update-todo-statistics))

次のコマンドを使えば、バッファ全体で統計情報を更新できますが、数万行のファイルの場合は重くて頻繁に使えません。今回加えた設定のように、細かい単位で変化のあったツリーの統計情報を適宜更新するのが良さそうです。

(org-update-statistics-cookies 'all)
amazon_banner_large
amazon_banner_small