ChangeLog で Todo 管理 その2

ChangeLog で Todo 管理 - gan2 の Ruby 勉強日記で作ったやつを改良した。
前回のように、C-t で □ と ■ を切り替えられるのに加えて
□(■)のインデントを切り替えられるようにした。
言葉だけだと説明が難しいので図っぽいのを使って説明する。
C-t を押すごとに以下のように切り替わっていく。
(* が半角スペース)

  1. □ ToDo
  2. ■ ToDo
  3. **□ ToDo
  4. **■ ToDo
  5. ****□ ToDo
  6. ****■ ToDo
  7. ******□ ToDo
  8. ******■ ToDo
  9. □ ToDo


仕様を箇条書きするとこんな感じ。

  • □ があるとき、□ を ■ に切り替える。
  • ■ があるとき、半角スペース2つ分インデントをずらして ■ を □ に切り替える。
  • インデントは3レベルまでしか下がらない。4にしようとすると0に戻る。
  • 切り替わる □ と ■ は一番頭にあるもののみ。


最後にソース。
メインの処理は toggle-todo-box 関数でやってる。
let で定義されている max-level と todo-indent-level を書き換えることで
挙動を変更することができる。

(add-hook 'change-log-mode-hook
    '(lambda ()
       (define-key change-log-mode-map "\C-t" 'toggle-todo-box-at-line)))

(defun delete-insert-char(c)
  (interactive)
  (progn (delete-char 1 nil) (insert c) (backward-char 1)))

(defun swap-char-at-point(a b)
  (let ((c (char-to-string (char-after))))
    (cond
     ((string-equal c a) (delete-insert-char b))
     ((string-equal c b) (delete-insert-char a)))))

(defun toggle-todo-box ()
  "□ と ■ の切り替えとインデントの調整を行う"
  (interactive "*")
  (save-excursion
    (let ((line-end)
          (len)
          (level)
          (max-level 3)
          (todo-indent-level 2))
      (end-of-line) ; 行末にポイントを移動
      (setq line-end (point))
      (beginning-of-line)
      (re-search-forward "\\( *\\)\\([□■]\\)" line-end t)
      (goto-char (match-beginning 2))
      (swap-char-at-point "□" "■")
    (if (string= "□" (buffer-substring (match-beginning 2) (match-end 2)))
        (progn
          (setq len (length (buffer-substring (match-beginning 1) (match-end 1))))
          (setq level (/ len todo-indent-level))
          (if (> level max-level)
              (setq level 0)
            (setq level (1+ level)))
          (message "%d" level)
          (goto-char (match-beginning 1))
          (insert-char 32 (* level todo-indent-level)) ; 32 は半角スペース 参考:ASCIIコード
          (delete-region (match-beginning 1) (match-end 1))
          )))))


次は、C-u C-t したときは後ろに戻るようにしたい。
最高3レベル程度なら今のままでもあんまり困らないけども。