org agendaをday plannerとして使って1日のタスクを可視化する


兼ねてより個人的なタスク管理はObsidianのday plannerプラグインを使っています。
このプラグインはその日のタスクを時間を決めて登録し、小学校の時間割のような形でタスクをこなすことができます。

![dayplanner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549004/a3c3a78e-22a9-8e75-cc37-fb426e430c69.png)

[https://github.com/ivan-lednev/obsidian-day-planner](https://github.com/ivan-lednev/obsidian-day-planner)

Day plannerを使ったタスク管理にだいぶ慣れた頃、会社のタスクをこなすために使いたいなと思うようになりました。
ところが、Obsidianはビジネス利用にはライセンスを購入しなくてはなりません。年間50ドルとそれなりにします。

[商用ライセンス](https://publish.obsidian.md/help-ja/%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9%E3%81%A8%E3%82%A2%E3%83%89%E3%82%AA%E3%83%B3%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9/%E5%95%86%E7%94%A8%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9)

そこで、Emacsにも似たような機能があるのではないかと思い、様々調べてみるとorg-agendaが用途して近いことがわかりました。
そのまま使うにはobisidian day plannerと使い勝手が異なっていたので、カスタマイズして使っています。

## コード

こちらがorg-agendaをday plannerライクに使うための設定です。
```lisp
(use-package org
  :bind (("\C-ce" . create-daily-org-file) ;; 今日の日付のorgファイルを作成、既にある場合はファイルを開く
         ("\C-cp" . org-agenda-list));; org agendaの今日の予定を表示する

  :config
  ;; デフォルトで週の予定が表示されるので今日の予定のみを表示する
  (setq org-agenda-span 'day)

  ;; 標準の祝日を利用しない
  (setq calendar-holidays nil)

  ;; DONEの時刻を記録
  (setq org-log-done 'time)

  ;; アジェンダ表示で下線を用いる
  (add-hook 'org-agenda-mode-hook '(lambda () (hl-line-mode 1)))
  (setq hl-line-face 'underline)

  ;; TODO状態
  (setq org-todo-keywords
    '((sequence "TODO(t)" "WAIT(w)" "REMIND(r)" "|" "DONE(d)")))

  ;; タグリスト
  (setq org-tag-alist '(("work" . ?w) ("meeting" . ?m) ("office work" . ?o)))

  ;; org/agendaフォルダに今日の日付のorgファイルがあればorg agendaとしてロードする
  (setq org-agenda-files
    (let* ((current-day (format-time-string "%Y-%m-%d"))
            (org-file (expand-file-name (concat "~/.emacs.d/org/agenda/" current-day ".org"))))
      (when (file-exists-p org-file)
        (list org-file))))

  ;; org/agendaフォルダに今日の日付のorgファイルを作成、保存する
  (defun create-daily-org-file ()
    "Create an org file in ~/.emacs.d/org/agenda/ with today's date."
    (interactive)
    (let* ((dir (expand-file-name "~/.emacs.d/org/agenda/"))
            (path (concat dir (format-time-string "%Y-%m-%d") ".org")))
      (find-file path)
      (save-buffer)
      (setq org-agenda-files (list path))))

  ;; 60秒毎にorg-agendaのnowの情報を更新する
  ;; current-positionはorg-agenda-redoを実行した際にカーソルが行頭に移動するのを防いでいる
  (run-with-timer 0 60 (lambda ()
                         (condition-case nil
                           (when (get-buffer "*Org Agenda*")
                             (with-current-buffer "*Org Agenda*"
                               (let ((current-position (point)))
                                 (org-agenda-redo)
                                 (goto-char current-position))))
                           (error (message "An error occurred while updating the *Org Agenda* buffer"))))))
```

## 方針

### 日別のorgファイルを作りタスクを書き込みたい

obsidianはその日の事をなんでも書き込むデイリーノートと言うマークダウンファイルがあります。
obsidianのday plannerはその日のタスクをデイリーノートに自動的に挿入します。
デイリーノートのファイル名は日付でユニークなので後から探すのも簡単です！

org-agendaでも同じような運用にしたいと思い、`~/.emacs.d/org/agenda/2013-01-01.org`の様なファイルを作成し、1日のタスクを加えていきます。

### 今日のorgファイルだけロードしたい

デイリーノートとしてorgファイルを分割しているせいで、org-agendaで普通にタスクを読み込んだ場合、`~/.emacs.d/org/agenda/`内にある全てのファイルをバッファに展開してしまいます。

![loaded.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549004/9512a142-a421-c24f-a0a0-def140ba9fcf.png)


バッファが展開されすぎると、他の作業の邪魔になるので、設定を変更し今日のorgファイルだけを読み込みます。
これにはデメリットもあり、過去の日付のファイルをorg-agendaに喰わせられないので、過去のタスクが表示されません。
デイリーノートの目的は今日のタスクの管理なので今の利用範囲においては問題ありません。

![clean.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549004/69091025-d9e9-2e9b-89fd-a6892c8fd9e5.png)


### 現在時刻をリアルタイムで表示したい

Org Agendaのバッファを開くと、`now-----`という現在のラインが表示されます。
nowの時刻は再度org-agenda-listを実行しないと更新さません。
それでは不便なので、60秒で再描画させます。
しかし、不完全な実装でたまに止まります。目安程度に使ってもらえればと思います。

![progress.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549004/4b559dbc-aeb3-a7ba-4eaa-e228add80076.png)

## 使い方

emacsを開きます。

```bash
emacs
```

`C-c e`で今日のタスクを管理するためのorgファイルを作成します。既にある場合はファイルが開きます。

![day.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549004/88c30744-36c1-5f1f-f575-ca12c2741f5e.png)

その日にやる予定のタスクを追加します。

```org
* TODO Twitter<2023-12-03 日 14:00>
* TODO 散歩<2023-12-03 日 14:30>
```

上の記述を見ても分かる通り、orgのタスク登録はかなり面倒です。
キーバインドを駆使したり、org-captureを使ったりしたのですがどれも微妙でした。
私は入力にyasnippetを使っています。以下のようなスニペットを` ~/.emacs.d/snippets/org-mode/task`ファイルに登録しておきます。

```lisp
 # -*- mode: snippet -*-
 # name: task
 # key: t
 # --
 * TODO $1<`(format-time-string "%Y-%m-%d %a")` $2:$3>
```

orgファイル内で`t`と入力した後、タブを押せばスニペットが展開され、入力、タブ、入力、タブでタスクを登録できます。

![td.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549004/2c49b186-9d3a-8155-b530-3fd178f48c36.png)

タスクが書き込めたら、`C-c p`でorg-agendaを起動します。

![cp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549004/c8170a99-9b96-eb41-b4db-ed7447e57a58.png)


- `n`で下に移動し、`p`で上にカーソルを移動できます。
- タスクの時間やタイトルを変更したい場合は、対象のタスクにカーソルを合わせてエンターを押すと、orgファイルが開きます。
- タスクが完了した場合は、カーソルを対象のタスクの上に合わせて、`t` を押します。ステータスの一覧が表示されるので`d`とタイプすると状態がDONEに変わります。

![change.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549004/6795aa5c-9367-208c-2bc2-84a6eed085cd.png)

以上が基本的な使い方です。

## まとめ

day plannerを使うことで1日のどのタイミングでタスクをこなしたら良いか客観的に把握できる様になります。ステータスを使う事でどのタスクがTODOとして残っているのか、DONEで終わっているのか簡単に把握できます。忙しい方ほどday plannerを使って日々のタスクを可視化して消化していきましょう！