BitBarで自分のやるべきタスクを常に意識する

# はじめに

皆さんは今日こなすべきタスクを覚えていますか？私はもう40歳を過ぎまして、大事なことすらまともに覚えていられません。出勤したらまず今日こなすべきタスクを整理しますが、タスクが切り替わる度に「何しなきゃいけないんだっけ？」とつぶやきながらタスクを見直しています。どうすれば常にやるべきタスクを意識することができるのでしょうか？

# タスク管理ツール

世の中にはタスク管理ツールが溢れています。開発のタスクはJIRAで管理してます。開発以外の仕事のタスクはAsanaで管理しています。プライベートのタスクはRemember The Milkで管理しています。それぞれとても素晴らしい製品ですが、共通して私にフィットしないことが2つあります。それは、タスクを確認するためにWebページ（またはスマホアプリ）を開かなければいけないということと、作成されるタスクの粒度が私の脳のバッファサイズより大きすぎるということです。

## Webページを開くのに時間がかかる

Webページを開く手間を惜しむ私は愚かでしょうか？しかし素晴らしいタスク管理ツールほどそのページサイズはそれなりに巨大で、読み込みに時間がかかります。開きっぱなしにしておいても良いのですが、最新の状態に更新するために往々にして再読み込みさせる必要があり、やっぱり地味に時間がかかります。

また複数のブラウザウィンドウの中の複数のタブの中の目的のタブを探すというのも地味に時間がかかります。そんなにタブを開くなという話もありますが、作業をしているといつの間にか膨大な数になっているものです。

タスクリストは一日に何度も見るものですし、タスクを表示するまでの時間は非常に重要です。

## ツールで管理するほどでもない細かすぎるタスク

「○○の不具合を解消する」というタスクがあるとします。しかしこのようなタスクには往々にして次のような細かいタスクに分割することが可能です。

- 原因を調査する
- 修正を試みる
- 不足しているテストを書く
- Pull Requestを書く
- コードレビューのコメントに対応する
- リリースのタイミングについて企画と調整する
- リリースのタイミングについて営業と調整する
- リリースマネージャーに声をかける
- リリース後に挙動を確認する

分割することは可能ですが、分割したこれらのタスクををすべてタスク管理ツールに入れますか？少なくとも同僚と共有するJIRAなどには入れませんね。プライベートのものでも、やはりそれは粒度が細かすぎるので入れません。しかしそうなると、実際にどこまで進めたのかや、抜けもれなくやっているかを常に覚えていなければいけなくなり、すぐに脳のバッファを溢れてしまいます。

このような「ツールで管理するほどでもない細かすぎるタスク」を対象としたタスク管理ツールが私には必要です。

# BitBar

以前、[人生の残り時間を表示するBitBarプラグインを作成したことを報告](http://qiita.com/artifactsauce/items/1caca90e91c6ca90ebbf)しましたが、それ以降、BitBarの素晴らしさに心酔しています。そこで今回も、BitBarのプラグインを作り、タスクを常に意識できる仕組みを作ろうかと思います。

# 実装

今回の要件に最もフィットするものの一つが古典的なテキストファイルのメモかと思います。長期的なタスクを管理するのではなく、今日一日の分だけを書き記し、今日の分は今日の退勤時に捨てます。BitBarには[Todoトラッカーの実装がすでにあり](https://getbitbar.com/plugins/Lifestyle/todo.30s.sh)まして、テキストファイルの中身を表示するだけの大変シンプルなものですので、要件にもフィットします。

これを使うのももちろん良かったのですが、完了済みのタスクをそれらしく表示したかったり、多少は拡張したかったりと思うところもありまして、テキストファイルに書くというコンセプトは維持しつつ、別のプラグインとして実装することにしました。

そんなこんなで作成したプラグインがこちらです。

```bash:todo-md.30s.pl
#!/usr/bin/env perl

# Inspired from [Simple Todo Tracker](https://getbitbar.com/plugins/Lifestyle/todo.30s.sh)

use strict;
use warnings;

# Edit the path to the file describe your ToDo
my $file_path = "$ENV{HOME}/Dropbox/TODO.md";

# Select your editor
my $editor = "/Applications/Atom.app/Contents/Resources/app/atom.sh"; # Atom
# my $editor = "/Applications/TextMate.app/Contents/Resources/mate"; # TextMate
# my $editor = "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl"; # Sublime Text
# my $editor = "/Applications/CotEditor.app/Contents/SharedSupport/bin/cot"; # CotEditor
# my $editor = "/Applications/Emacs.app/Contents/MacOS/Emacs"; # Emacs

# Change here depending on your preference
my $font_color_finished = "#C0C0C0";
my $font_color_unfinieshed = "black";
my $menu_bar_icon = ":ballot_box_with_check:";

# <bitbar.title>Simple ToDo Tracker for Markdown</bitbar.title>
# <bitbar.version>v1.0</bitbar.version>
# <bitbar.author>Kenji Akiyama</bitbar.author>
# <bitbar.author.github>artifactsauce</bitbar.author.github>
# <bitbar.desc>Tracking ToDo list described in Markdown</bitbar.desc>
# <bitbar.image>http://i.imgur.com/nIEVIdR.png</bitbar.image>
# <bitbar.dependencies>perl</bitbar.dependencies>

my $unfinished_task_cnt = 0;
my @tasks = ();

open my $fh, "<", $file_path or die $!;
while ( <$fh> ) {
    next unless $_ =~/^(?:[\-\+\*]|\d\.?) \[(.)\] (.+)$/;
    my $task = {
        checked => ($1 eq "x"),
        title => $2,
    };
    $unfinished_task_cnt++ unless $task->{checked};
    push @tasks, $task;
}
close $fh;

print "$menu_bar_icon:$unfinished_task_cnt\n";
print "---\n";

@tasks = sort { $a->{checked} <=> $b->{checked} } @tasks;
for (my $i = 0; $i <= $#tasks; $i++) {
    my $font_color = $tasks[$i]{checked} ? $font_color_finished : $font_color_unfinieshed;
    printf "%d. %s | color=$font_color\n", $i+1, $tasks[$i]{title}
}

print "---\n";
print "Open file | bash=$editor param1=$file_path terminal=false\n";
print "Refresh | refresh=true color=#C0C0C0\n"; # enable to refresh manually
```

これをBitBarで設定したプラグインディレクトリに配置し、**実行権限をつけましょう**。ファイル名は `todo-md.30s.pl` としました。30秒毎に更新されます。

このプラグインが正常に動作すると、下のように表示されます。

![](http://i.imgur.com/nIEVIdR.png)

# 解説

## Dropbox

このプログラム中では、TODOを記したファイルの保存先をDropboxにしており、私はこれを推奨しています。これはファイルを失わないための最低限の仕組みをDropboxで担保しているということです。Proプランを契約していれば簡単な履歴管理としても使えるでしょう。

何にしろ、このPATHをご自身の環境に合わせて書き換えてから使用してください。ファイルが存在しなければ警告もせずにプラグラムが落ちるという男前の実装です。

## タスクの完了／未完了

タスクの完了／未完了の判定は、GitHub Flavor Markdownの書式に準ずることにしました。行頭に `- [ ]` とあれば未完了のタスクとし、 `- [x]` とあれば完了したタスクとして認識します。

タスクはネストしないものとし、またリスト形式になっていないものは全て無視するようにしています。男前の実装です。

## Editor

タスクリストをメニューバーですぐに見られるようにしたのに、タスクを完了にするためにタスクを記したファイルを探し回っていたのでは片手落ちです。そこで「Open file」という項目を追加しました。このメニューを選択すると予め設定しておいたエディタでタスクを記したファイルを開いてくれます。

エディタはGUIのものを使うという前提にしました。Macのモダンなエディタは全てコマンドラインから起動する手段を提供していましたので、このプログラム中ではそれぞれのエディタのコマンドラインツールへのPATHを列挙し、自分が使うもののコメントアウトを外して利用できるようにしました。

## PerlのHashリファレンスの配列のソート

PerlではHashの配列に対し、Hash内の特定のValueを用いてソートする手段を提供しています。プログラム中の該当部分はこちらです。

```perl
@tasks = sort { $a->{checked} <=> $b->{checked} } @tasks;
```

ソートの基準を第１引数にコードブロックとして渡します。数値比較か文字列比較か、どのキーの値を使ってソートするのかを記述します。上記のコードの場合は、配列の各要素がHashのリファレンスになっており、その `checked` の値で数値昇順で並べ替えるという意味になります。

具体的には、 `@tasks` の中身が下記のようであったなら、

```perl
@tasks = (
    { checked => 1, desc => 'hoge' },
    { checked => 1, desc => 'fuga' },
    { checked => 0, desc => 'foo' },
    { checked => 0, desc => 'bar' },
);
```

結果配列は下記のようになります。

```perl
@tasks = (
    { checked => 0, desc => 'foo' },
    { checked => 0, desc => 'bar' },
    { checked => 1, desc => 'hoge' },
    { checked => 1, desc => 'fuga' },
);
```

# Pull Request

今回は思い切ってこのしょうもないプラグインのPull Requestを出すことにしました。すると、わりとあっさり[受け入れてもらえました](https://github.com/matryer/bitbar-plugins/pull/586)。やってみるものです。今日現在、[プロモーションサイト](https://getbitbar.com/)の方へは反映されていないようですが、[リポジトリ](https://github.com/matryer/bitbar-plugins)からは取得することができます。前述のプログラムをコピペするのも良いですが、新たなプラグインを作成するためにcloneしておくのも悪くないでしょう。

# 最後に

これで私の「脳のバッファが少なすぎてタスクの詳細を覚えていられない」という問題がBitBarによって解決されました。効率良く仕事ができるようになったと思います。

またPull Requestが受け入れられたことで、世の中に貢献しているような錯覚を得るという素晴らしい経験もいただきました。若い人にも伝承していきたいと思います。