LoginSignup
16
7

More than 3 years have passed since last update.

簡略フローで doing 再び

Last updated at Posted at 2019-12-13

はじめに

Emacs Org mode には,工数を計測するための機能が標準で備わっています.基本的な使い方は,時間を計測したいタスクで M-x org-clock-in して,作業を終えたら M-x org-clock-out する操作です.そうして記録した各タスクの計測時間は,後から簡単に集計でき,表として出力できるため,工数記録とレポート作成に重宝しているユーザも多いようです.

そんな便利な計測機能ですが,避けられない欠点があります.それは org-clock-in し忘れる ことです.記録を開始しなければ,記録されることはない…

そこで本記事は, org-clock-inorg-clock-out を可能な限り自動化するためのパッケージと設定を紹介します.ポイントは, Doingタグの付いたタスクを,Emacs全体で1つに維持 して,「Doingタグが付いたタスク」= 「計測中のタスク」にすることです.

なおこの記事は Org mode で書かれており,ソースも公開しています.また本記事以外の設定集も公開しています.

計測開始を自動化・半自動化する

org-clock-in し忘れる?なら常に記録すれば良いじゃんか」と,結論を安直に導くことも可能ですが,実際の運用はそう簡単ではありません.なぜなら,Org modeの各 heading は,常に計測を目的としている heading とは限らないためです.計測対象ではない単なるメモも同じバッファに存在しえます.そしてやはり理想的なのは,「自分は今からこのタスクに集中する」と確定したものだけを計測・記録することです.

そう考えると,本当に必要なのは「空気を読んで org-clock-in を実行してくれるツール」になります.そんなのあるの?ないの?ということで,作りました.なお,スピードコマンドを有効にしている場合は, I (org-clock-in) と O (org-clock-out) の押下で済ませることができます.ただし「忘れる問題」は解決しません.

takaxp/org-onit: Recording your task all the time

このツールを使えば,

  • シングルアクションで org-clock-inorg-clock-out を実行

    • トグルコマンド(org-onit-toggle-doing)の提供
    • Unfold( heading のコンテンツを <tab> で開く)したら org-clock-in の発行
  • 所定の条件を満たす heading に移動したら,自動的に org-clock-in を発行

を実現できます.これで org-clock-in のし忘れは大幅に減るでしょう.

さらに,最も可能性の高い使い方として「ある heading で工数計測をしながら,他の heading の内容を編集する」という作業スタイルが考えられます.この場合は,計測中の heading と編集中の heading を簡単に往復できると幸せになれるので, org-onit.el は, org-clock-goto を発行した場所にすぐ戻るためのコマンド(org-onit-goto-anchor)も実装しています.

インストールと設定

インストール

いつものようにダウンロードして load-path に配置してください.

(with-eval-after-load "org"
  (require 'org-onit nil t))

としておけば,確実に読み込まれるでしょう.

package.el などのパッケージ管理ツールを使用している場合は,特に require せずとも大丈夫です.

推奨追加パッケージ

org-bookmark-heading.el

ビルトインではないパッケージへの依存としてorg-bookmark-heading.elを想定してます.インストールしなくても動作します.ただ,ブックマークの精度を向上させる効果があるため,導入をおすすめします.

org-clock-today.el

標準の工数計測では,あるタスクについての「過去費やした累計時間」を簡単にタイトルバーに表示できますが, org-clock-today.el を使うと,さらに2種類の 本日費やした合計時間 を集計してタイトルバー(或いはモードライン)に出すことができます.こちらのパッケージも必須ではないです

基本設定

org-onit.el についてはほぼ設定無しで使えると思います.

むしろ,工数計測の機能を提供する org-clock.el の設定が必要になります.

(with-eval-after-load "org-clock"
  ;; 1分未満は記録しない
  (setq org-clock-out-remove-zero-time-clocks t)

  ;; org-clock の計測時間をモードラインではなくタイトルに表示する
  ;; 'both にすると,モードラインとタトルバーの両方に表示される
  (setq org-clock-clocked-in-display 'frame-title)

  ;; "Doing" タグの色を見やすい変える
  (add-to-list 'org-tag-faces '("Doing" :foreground "#FF0000"))

  ;; タイトルに表示する文字列のフォーマット(例)
  (setq org-clock-frame-title-format
        '((:eval (format "%s|%s| %s"
                         (if org-onit--auto-clocking "Auto " "")
                         (org-onit-get-sign)
                         org-mode-line-string)))))

加えて heading の <tab> 押下で clock-in できるようにします.

(with-eval-after-load "org"
  (add-hook 'org-cycle-hook #'org-onit-clock-in-when-unfold))

また,計測中のタスクに集中したいという目的から narrowing を使いたい場合がありますので,スピードコマンドを有効にしておきましょう.heading で s 押下すると, narrowingwiden をトグルできます.また, d 押下で DONE にする設定も加えるとよいでしょう.

(with-eval-after-load "org"
  (setq org-use-speed-commands t)
  (add-to-list 'org-speed-commands-user '("d" org-todo "DONE")))

キーバインド

デフォルトの設定は定められていませんが,次を推奨しています.自由に変更してください.

(global-set-key (kbd "C-<f11>") 'org-clock-goto)
(with-eval-after-load "org"
  (define-key org-mode-map (kbd "<f11>") 'org-onit-toggle-doing)
  (define-key org-mode-map (kbd "M-<f11>") 'org-onit-toggle-auto)
  (define-key org-mode-map (kbd "S-<f11>") 'org-onit-goto-anchor))

基本的な使い方

使い方は,半自動で org-clock-in するか?と,全自動で org-clock-in するか?で分かれます.以下の説明は,上記の推奨キーバインドを適用していることを前提として書かれています.

半自動で計測開始する

計測を開始したい heading で <f11> を押下(或いは M-x org-onit-toggle-doing )します.見出し行にカーソルが無くても大丈夫です.モードラインに「Doing」と表示されます.

デフォルトでは,すでに DONE の heading では計測開始しませんが, org-onit-basic-options'(:wakeup both) または '(:wakeup doing) に設定している場合には計測開始します.

さらに, '(:unfold t) を設定している場合に限り, <tab> 押下で heading を unfold することで計測を開始します.ただし, :wakeup:nostate の値が優先されます.

全自動で計測開始する

M-<f11> 押下(或いは, M-x org-onit-toggle-auto )します.それ以降,heading を訪問だけで,自動的に計測が開始されます.モードラインには「Doing:auto」と表示されます.

org-onit-basic-options'(:wakeup nil) または '(:wakeup doing) を設定していると, heading が DONE である場合には発動しません.また, '(:nostate nil) または '(:nostate doing) の場合, TODO 等の todo state が設定されていない heading では発動しません.

なお全自動モードでは,内部的にすべての操作について「計測開始するか?」を判定しているので,環境によっては重く感じるかもしれません.その場合は,半自動のアプローチを利用してください.

計測中の heading と編集中のバッファを往復する

Org mode に慣れてくると,タスクリストを特定の heading に集約し,編集作業そのものは他のバッファやファイルで実施するパターンが増えると思います.

その場合は,作業時間を計測している heading と,実際に編集作業しているバッファを簡単に往復できると便利です.

フローの一例として,

  1. ある heading で <f11> 押下,計測開始
  2. 任意のバッファに移動して作業
  3. 計測している heading にメモを残したい( C-<f11> (or M-x org-clock-goto) で計測中の heading に移動)
  4. メモを取り終えたので,元のバッファに戻りたい( S-<f11> (or M-x org-onit-goto-anchor) で作業中の heading に移動)

が考えられます.

この間,継続して作業時間が計測されます.

ビジュアルフィードバック

計測後に表に計測結果をまとめるのとは別に,計測状況をリアルタイムに表示して確認できます.特に,一日に積み重ねた作業時間を確認できれば,計測時間が 08:00 を超える辺りで,おもむろにビールを飲み始めてもいいかもしれません.

集計時間の表示

モードラインやタイトルバーに,あるタスクについて「過去費やした累計時間」や,バッファ内の全タスクから集計した,或いは,あるタスクのサブ heading から集計した「本日費やした合計時間」を表示できます.

次の「本日費やした時間」は, org-clock-today.el を導入することで集計できます.

  • (バッファ内の全タスクから集計した)「本日費やした時間」
  • (あるタスクのサブ heading から集計した)「本日費やした時間」

あるタスクの「過去費やした累計時間」はデフォルトで集計されています.

集計項目 変数名
過去費やした累計時間 org-mode-line-string
本日費やした時間(バッファ内全て) org-clock-today-subtree-time
本日費やした時間(サブ heading 限定) org-clock-today-buffer-time

これらの変数を使って org-clock-frame-title-format をカスタマイズすると,タイトルバーの表示を変えられます.

例えば,こうです.

Screen_Shot_2019-08-30_at_3_39_02.png

(setq org-clock-frame-title-format
          '((:eval (format "%s%s %s"
                           (if (and (require 'org-clock-today nil t)
                                    org-clock-today-mode)
                               (if org-clock-today-count-subtree
                                   (format "%s / %s"
                                           org-clock-today-subtree-time
                                           org-clock-today-buffer-time)
                                 (format "%s" org-clock-today-buffer-time))
                             "")
                           (if org-onit--auto-clocking " Auto " "")
                           org-mode-line-string))))

表示に動きをつける

タイトルバーの表示に少し動きをつけたい場合は, (org-onit-get-sign) の戻り値を使ってください.アニメーション表示になります.表示要素は, org-onit-clocking-sign-alist を設定すれば自由に変えられます.

Untitled1.gif

(setq org-clock-frame-title-format
          '((:eval (format "%s%s |%s|%s"
                           (if (and (require 'org-clock-today nil t)
                                    org-clock-today-mode)
                               (if org-clock-today-count-subtree
                                   (format "%s / %s"
                                           org-clock-today-subtree-time
                                           org-clock-today-buffer-time)
                                 (format "%s" org-clock-today-buffer-time))
                             "")
                           (if org-onit--auto-clocking " Auto " "")
                           (org-onit-get-sign)
                           org-mode-line-string))))

その他のオプション

いくつかのユーザ設定変数があります.基本的な挙動は, org-onit-basic-options にて変更できます.必要に応じて変更してください.

Variables

変数名 デフォルト値
org-onit-todo-state org-clock-in-switch-to-state or "TODO"
org-onit-doing-tag "Doing"
org-onit-basic-options '(:wakeup nil :nostate nil :unfold nil)
org-onit-keep-no-state t
org-onit-encure-clock-out-when-exit t
org-onit-bookmark org-onit-last-clock-in
org-onit-bookmark-anchor org-onit-anchor
org-onit-clocking-sign-alist '("▁" "▂" "▃" "▄" "▅" "▆" "▇" … "▁")

ブックマーク関連は,万が一他のパッケージと衝突した場合に変えてください.

org-onit-basic-options で制御できるオプションは,次の3つです.

  • :wakeup TODO state が DONE の時に, TODO に変えて計測を開始します
  • :nostate TODO state が付いていない heading でも計測を開始します
  • :unfold heading を unfold した時に,計測を開始します

org-onit-basic-options はバッファローカル変数なので,グローバルに設定を変えたい場合は, setq-default を用いてください.

なお, org-onit-keep-no-state は, org-onit-basic-options:nostate よりも優先され,Non-nil の場合に TODO state が付いていない heading の TODO state の変更を防止します.

Hooks

いくつかの hook を準備してあります.特に org-onit-after-jump-hook を設定すると,計測中の heading にジャンプした後の挙動を変更できます.

  • org-onit-switch-task-hook 全自動モード時に,計測対象の heading が切り替わるタイミングで呼ばれます.
  • org-onit-start-autoclock-hook 全自動モードの開始時に呼ばれます.
  • org-onit-stop-autoclock-hook 全自動モードの終了時に呼ばれます.
  • org-onit-after-jump-hook ブックマークでジャンプした後で呼ばれます.
;; org-onit-after-jump-hook にぶら下げる拡張関数の例
(defun my-onit-reveal ()
  (org-reveal)
  (org-cycle-hide-drawers 'all)
  (org-show-entry)
  (show-children)
  (org-show-siblings))
(add-hook 'org-onit-after-jump-hook #'my-onit-reveal)

まとめ

本記事では,拙作の org-onit.el を導入して, Org mode の工数計測を半自動化する方法についてまとめました.

Org mdoeの工数計測機能を正しく使いこなせば,「文書・アウトライン編集」と「作業中のタスク・工数管理」の双方を同時に実行し,かつ,それらを Emacs Org mode だけで完結させることが可能です.ぜひお試しください.

References

おまけ

本記事の課題に対して以前に,org-clock-in を意識しないで作業時間を記録する - Qiitaにて, org-clock-in の自動化を試しました.この時は org-tree-slide.el を用いて narrowing をトリガーに計測を自動化しましたが,設定が少々複雑でした.また,「今,そこにあるタスク(危機)」をDoingリストで乗り切る - Qiita も書きましたが,この記事では短期集中したいタスク群を Doingタグで串刺しにしておくのが目的でした.今回はごく単純に, Doing が付いているタスクが今集中したいタスクということで,以前よりも運用しやすくなった気がします.

16
7
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
16
7