詩と創作・思索のひろば

ドキドキギュンギュンダイアリーです!!

2015年のタスク管理

今年に入ってからタスク整理のしかたを考えなおして、とりあえず数ヶ月続けてみた結果、現時点で維持はできていて悪くはないと思ってるやり方をまとめておきます。

大方針: 「やりたいこと」と「やらなければいけないこと」を分ける

これまでは Remember The Milk なり Google Tasks なりに一元管理して、日々生じる外発的なタスク(あの人に声かけて、とか、文書を準備して、とか)と突然思いつく内発的なアイデア(こんなウェブサービス、ツールを作る、○○について調べる)を一カ所に投げ込んでいたのがよくなくて、もちろんツールの機能で分けることはしていたとはいえ、今ひとつ整理された見た目にならなくてだんだん足が遠のいてしまっていた問題があった。というかそもそも整理したくないというのもある。そこで今年はこれらのタスクやアイデアを二つの場所に分けて管理してみることにした。

  • やらなければならないこと、特に締切のあるものは Todoist
  • やりたいこと、やらなくてもいいこと、いつやってもいいことは Trello

という風に分けた。これで基本的には日中は Todoist を見ていて、やる気をだしたいときには Trello を見るという運用になった。

Todoist

ここはやらなければならないタスクを放りこむところ。Todoist はいわゆる TODO 管理サービスで、他の競合と較べたときの長所があるかどうかは知らないのだけれど、なかなか使い心地がよくて、今年のはじめから使い続けている。とうぜんスマートフォンアプリはあるのだけど、OSX アプリがある(Chrome アプリもある)のがよくて、ホットキーから即座にタスクを追加できるのが便利だった。

f:id:motemen:20150420202007p:plain

「締切」のところに「tom」と入力して明日、「mon」と入力して来週月曜日、というのをよく使ってる。また、「プロジェクト」というタスクを分類する機能があるけど、これ系は使いこなせないことがわかっているので、締切オンリーで運用している。また基本的に期限なしのタスクは入れない。

Trello

ここはやりたいことを溜めておくところ。Trello はカンバン式のタスク管理サービス。正直そんなに使いやすいとは思ってないのだけど、タスクの進行状況を一覧できて他サービスとの連携ができるサービスを他に知らないので、前からなんとなく使っていたこれをきちんと使ってみることにしてる。ボードは以下のように分けている。

  • Ideas … なんでもいいので思いついたことが入るところ。ウェブサービスやツールのアイデア、調べ物、おもしろツイートなど。
  • WIP … 着手しはじめた=プロジェクトのディレクトリを作った。
  • To Publish … だいたいできたのでブログに書く。
  • Done … ひと通りおわった。

この運用は去年からしていて、その成果が 【想定はてブ数つき】2014 年のボツネタを一挙公開!!! - 詩と創作・思索のひろば です。

メールは最高

一般的に敵視されがちな感じのあるメールだけど、自分の場合仕事のやりとりに使うわけではなくて、メールは通知の受信用なので、非常に便利だと思うようになった。

Inbox Zero

「Inbox Zero」のオリジナルがどこか知らないのでリンクできないし考え方も本当は知らないのだけど、この名前にしたがって、今年のはじめに受信箱のメールを全部アーカイブした。Gmail は検索でなんでもカバーできるのでそんなに心理的な負担もなく、スッキリしました。また、メールを既読にする際は何かしらのアクションを取る、というルールを設けた。たいてい何か返事をするとか、何もしなくてよいことを確認する、といった風になるけれど、ときどき少し重めであとで確認することにしたい、というものがある。そういう時に、スヌーズ機能のあるメーラが便利。

Mailbox

最近メーラーには Mailbox を使ってる。これが便利なのはメールをアーカイブするだけでなく、「スヌーズ」できる点で、受信箱からとりあえず消し去るけどまたあとで参照したい、というメールを「明日」とか「来週」まで受信箱から外しておくことができる。これで、だいたい一日の終わりには受信箱が空になっている状態にできている。空になるとご褒美画像が見られます。

f:id:motemen:20150420202220p:plain:h400

正直別に使いやすいと思ってはいなくて、Inbox by Gmail でも同じようなことができるし見た目も好きなんだけれど、OSX アプリがあるのが大きく、こちらを使っている。

タスクの追加

上に挙げたようにタスクを置く場所が 2 箇所になったのだけど、スマートフォンから追加するときには、素早く行えるよう IFTTT の Do Note を使っている。

使っているレシピは以下の 2 つ。

タスクを一覧する

前述のように Todoist/Trello とタスクを分けたのだけど、これら以外にも使っているサービスはあるので何かしら集約の手立てを考える必要がある。

Sunrise

Sunrise はカレンダーサービスで、いろいろなサービスと連携できる。これも OSX アプリがある(Chrome アプリもある)。Google カレンダーが表示できるのに加え、Todoist のタスクもカレンダーに表示できるので今日やること、今週やることなんて単位で把握するのに便利。使い出してすぐに Microsoft に買収された

Taco

Taco は TODO 集約サービス。Todoist、Trello だけにとどまらず多くのサービスのタスクを Taco 上で並べることができる(下も参照)。Taco 上で✓すると対応サービスでも完了状態にできるのが便利。このビューでも優先順位付けというかソートができるのだけど、二重管理になるのであまりやっていない。Chrome の新しいタブを Taco にするっていう拡張があって、自然と TODO を目にすることになるのがよい。といいつつ最近は目が滑ってあんまり見てない。

その他の場所で管理されているタスク

Pocket

Pocket はあとで読むサービス。Android のインテントひとつで URL をメモっておくことができるのが便利。これも一種の TODO であるので Taco に表示しておきたいと思ったのだけど未対応だったので、秘密の URL で Pocket の未読を RSS 化できるサービスを作った(Taco はフィードには対応している)。

GitHub Issues

もうひとつ舞い込んでくるタスクは自分の GitHub プロジェクトへのプルリクエストやイシュー。これは把握しているつもりでも見落としてしまっていた問題があったのだけれど、Taco は自分にアサインされたイシューをひとつのタスクとして表示できるので、「GitHub の通知メールをアーカイブする際にはそのプルリクエストやイシューを自分にアサインする」というルールを自分に課すことで、ひとまずその案件については忘れることができた。何かやることを探すモードになったら Taco なり GitHub なりを見ればそのイシューに辿り着けるってわけだ。

以上

とくに

  • タスクのある場所を 2 つ用意する
  • Inbox Zero を目指す
    • スヌーズできるメーラを使う

というのを試してみて、結構気に入ってる。

まだまだ完全に満足はしていなくて、

  • Trello 的な使い方ができてもっとよいもの
  • Evernote のうまい使い方(連携サービスが多いのでうまく使えると楽しそう)

などなど、よりよい知見をお持ちの方は教えてください。

完訳 7つの習慣 人格主義の回復

完訳 7つの習慣 人格主義の回復

go-cli: ドキュメントとともにコマンドラインツールを作る

Go

hub-pr を作るとき、(ghq などで使っていた)codegangsta/cli ではなく新しいライブラリを試してみようと思って mitchellh/cli を使ってみたけど、何かしっくりこないものがあったので、せっかくだし、と自作してみた。今回の要件は以下のとおり。

  • gogit のように)サブコマンドがある
  • コマンドラインオプションの解析には標準の flag パッケージをつかう
  • コマンドを追加するのが面倒でない

で、go-cliドキュメント)。

コマンドの実装

hub-pr のソースコードが一番のサンプルだけど、コマンドは以下のような関数で表現される。

func doCheckout(flags *flag.FlagSet, args []string) error {

各コマンドの実装は初期化された *flag.FlagSet とコマンドの引数(プログラムの第1引数がコマンド名になるので os.Args[2:])を受けとる。フラグの管理と引数の処理をおこなうのはそれぞれの関数の責任。まったくおこなわなくてもよい。

    flags.StringVar(&tmpl, "f", tmpl, "branch name format")
    flags.Parse(args)

また、各関数は error を返すことで異常終了するよう cli に指示できる。とくに cli.ErrUsage は使用方法がおかしいことを示し、flags を利用しつつ呼び出し側でいい感じにエラーを表示してくれる。

% hub-pr checkout
Usage: checkout [-f TEMPLATE] PULL_REQUEST_NUMBER

Checks out a branch corresponding to given pull request number.  The branch
name is based on the template, which defaults to
'#{{.Number}}-{{.Head.Repo.Owner.Login}}/{{.Head.Ref}}'.

Options:
  -f="#{{.Number}}-{{.Head.Repo.Owner.Login}}/{{.Head.Ref}}": branch name format

コマンドの登録・実行

コマンドを登録し、実行するには以下のようにする。

    cli.Use(
        &cli.Command{
            Name:   "checkout",
            Action: doCheckout,
            Short:  "Checkout a branch for a pull request",
            Long:   "checkout [-f TEMPLATE] ...",
        },
    )
    cli.Run(os.Args[1:])

で、この Name やら Long やら、ヘルプを書くのが面倒なんですよ……。とくに文字列リテラルとして書かなければならないあたりになんとなくストレスを感じる。ドキュメントなのだから普通に書きたい。そこでコメントを使う。

// +command checkout - Checkout a branch for a pull request
//
//   checkout [-f TEMPLATE] PULL_REQUEST_NUMBER
//
// Checks out a branch corresponding to given pull request
// ...
func doCheckout(flags *flag.FlagSet, args []string) error {

以上のように、コマンドに対応する関数のドキュメントに "+command" で始まるヘルプを含めてやるというルールにする。普通の文字列リテラルにくらべて、コメントでドキュメントを書くほうがメンテしやすいしコードを書くときにも参照しやすい。はず。

コメントからコマンドの登録コードを生成する

このコメントどう使うのって話だけど、ここから先に挙げたような cli.Use() の形のコードを生成するための(雑な) API を go-cli/gen として提供している。

hub-pr では _tools/gen_commands.go から利用している。ドキュメントを更新したら go run _tools/gen_commands.go すれば commands.go が自動生成される。実際には go generatable にしている。プロジェクトにあわせて自由に使えるように、ツールの形では提供していない。

go-cli

オレ流 Pull Request 作業フロー

チームで作業する同じリポジトリの中で Pull Request を送り合うのではなく、オープンソースプロジェクトに外部から PR がやってくる場合の話です。

最近のフロー

送られてきた PR に対しては、大まかには仕様の話、実装方針の話、具体的な実装の話を詰めながらマージできるように持っていくわけだけれど、それがほとんど満足いく状態になっていてマージしたいと思うタイミングになっても、変数の名前付けだとか、ちょっとした処理の書き方だとかで、相手にお願いするよりは自分で手を加えてからマージした方が手っ取り早いことがある。そういう時は PR 元のブランチを手元にチェックアウトして、そのブランチを自分の変更で進めた上で master にマージするようにすると、push 時に PR も閉じられて便利です。

motemen/lgtm.sh#1 の例。分かりにくいれど、PR にさらに 1 コミット足してからマージしてる。

この際コードは fork された外部のリポジトリにあるから、たんに git checkout すればいいわけではなく予め git fetch なりする必要がある。

で、最近いろいろ試行錯誤した結果、以下のようにするとよさそうだった。

1. フォークされたリポジトリを、そのオーナー名で remote に登録する

git remote add -f jwerle https://github.com/jwerle/lgtm.sh.git

-f オプションで、登録後 git fetch する。

2. PR 元のリモートブランチを、ローカルにチェックアウトする

git checkout -b '#1-jwerle/master' --track remotes/jwerle/master

この際 #xxx をブランチ名に入れておくと、コミットメッセージなどにブランチ名が入った時に自動的にリンクになって便利(ありがたいことに # はブランチ名に使える)。また、このブランチで git pull すると、PR が更新されたときに最新のコードを取得できる。

3. ローカルにチェックアウトされたブランチの push 先を自分のリポジトリに変更

git config --local 'branch.#1-jwerle/master.pushremote' origin

これで、このブランチを変更したときに、自分のリポジトリに push することができる。この設定後も依然として git pull は相手のリポジトリから行われる。

hub-pr

一度以上のようにしてしまうと結構便利なわけだけど、セットアップに少し面倒がある。最近 PR を受け取ることが重なったこともあり、このへんの作業はもうフローが決まってるのでコマンド化することにした。ホントはちょっとしたシェルスクリプトに収めるつもりだったのだけど、なぜか色気を出してしまった……。yak shaving だけが人生だ。

motemen/hub-pr · GitHub

go get github.com/motemen/hub-pr で入手できます。

使い方

hub-pr checkout PULL_REQUEST_NUMBER

PR 番号を与えると、以上に書いたフローでブランチを作ってくれる。zsh 用の補完を用意してるので以外と簡単なのです。

f:id:motemen:20150324003457g:plain

あとは普通にマージしてやればいいのだけど、手元でマージするとあの GitHub おなじみのマージメッセージにならないので、それと同じものを生成するコマンドも用意しておいた。

hub-pr merge BRANCH

これであたかもマージボタンを押したかのようなコミットメッセージでもってマージされます。なんか便利ですね。ほかにも hub-pr browse っていう便利なのもありますが、オマケです。コンソールから PR やイシューを扱うなら、ghi ってのが圧倒的に便利。


このフローで作業したいと思う人がいるかどうかは分かりませんが……、どうぞご利用下さい。verbose output 的なオプションがないのでわりとブラックボックス感が高い。

Go で GitHub 用のツールを書く時は github.com/github/hub 以下のパッケージを使うとなかなか快適に行えるようでした。まあそりゃそうか。

GitHub実践入門 ~Pull Requestによる開発の変革 (WEB+DB PRESS plus)

GitHub実践入門 ~Pull Requestによる開発の変革 (WEB+DB PRESS plus)

秒速でLGTMするコマンド

LGTM するときはよさげなアニメーション GIF を探し出してきて lgtm.herokuapp.com にかけるのがデファクト[要出典]だけどこの「よさげなアニメーション GIF を探し出す」というのがくせ者で、大量のアニメーション GIF をブラウザで開くと CPU パワーを浪費するし選択にかける人的な労力もばかにならない。エコではない。そこで Tumblr のランダムな画像を LGTM 化するコマンドラインツールを書いた。その名も lgtm.sh だ。Tumblr には /random というエンドポイントがあるのでこれを利用して特定の Tumblr ブログ群からランダムに画像 URL を得ている。

./lgtm.sh -m | pbcopy

-m オプションをつけると Markdown フォーマットで出力する。つけない場合は画像 URL のみ。

LGTM

/random へのアクセスには少し時間がかかるのだけど、これを軽減するため、コマンドの毎実行時に同期的にアクセスするのではなく、実行後にバックグラウンドで HTTP GET してキャッシュ(次回の結果)を生成するようにしている。秒速たるゆえんだ。

実装は簡単なシェルスクリプトで、sites 変数を好きな Tumblr のリストにすることで生成される画像をカスタマイズできる。デフォルトではパブリックドメインのアニメーション GIF を利用するようになっているので、自分好みに編集してうまく活用してもらいたい。

motemen/lgtm.sh · GitHub

Go でコードを書く時のかゆいところに手が届く goquickfix というのを書いた

Go

go rungo test でコードを試しながら書きながら……というフェーズでは、以下のような状況によく遭遇することと思います:

  • デバッグプリント用のコードを削除したら、"log" や "fmt" パッケージが不要になって imported and not used: "log" と言われた。まだ使うかもしれないのでいちいち消したくない。
  • 同様に、コードを整理したところ使っていない変数がでてきて i declared and not used と言われた。まだ使うかも(ry

出来上がりのコードの品質を高く保つには便利な機能ですが、試行錯誤をしている段階ではけっこうな障害になります。そこで goquickfix

go build が通らないコードに goquickfix をかければ、コードを書き換えて go build 可能にしてくれます:

goquickfix -w hoge.go

やっていることは簡単で、エラーを起こす識別子の登場を blank identifier _ で抑制するだけです。 例えば以下のようなコードは、

package main

import (
    "fmt"
    "log" // <- imported and not used: "log"
)

func main() {
    nums := []int{3, 1, 4, 1, 5}
    for i, n := range nums { // <- i declared and not used
        fmt.Println(n)
    }
}

goquickfix -w 後以下のようなコードになります。

package main

import (
    "fmt"
    _ "log" // <- インポート文は残すけど名前を使用しない
)

func main() {
    nums := []int{3, 1, 4, 1, 5}
    for i, n := range nums {
        fmt.Println(n)
        _ = i // <- i はここで登場するのでエラーにならない
    }
}

goimports を愛用している人には、インポート文の書き換えは不要かもしれませんね。

もちろんその場しのぎの対処で、最終的には消したいコードです。-revert オプションを与えることで、goquickfix によって導入されたと思しきコードを取り除きます(たぶんそうだろうというコードを修正するようになっているので、完全に戻るとは限りません):

goquickfix -revert -w hoge.go

シンプルかつ便利ですね。

どうぞご利用下さい。これは gore の副産物でした。

motemen/go-quickfix · GitHub

The Go Programming Language (Addison-Wesley Professional Computing Series)

The Go Programming Language (Addison-Wesley Professional Computing Series)

コード補完もできる Go の REPL「gore」を作った

Go

タイトルの通りです。Go は LL 的に使える、とはよく申しますが、そういう意識で使っていると REPL 的なことをしたいときに困りがちですよね。そこで作りました。gore。いい名前ですね。

motemen/gore · GitHub

以下のスクリーンキャストでだいたいの雰囲気をお察し下さい。

gore screencast

(スクリーンキャストは cho45/KeyCast を使って撮影しました)

特徴

gore の特徴は以下の通りです。

  • ラインエディタと履歴
  • 複数行入力
  • パッケージのインポート、補完つき
  • 式および文を実行可能
  • コード補完(nsf/gocode を利用)
  • プリティプリント(k0kubun/ppdavecgh/go-spew がおすすめ)
  • ドキュメントも引ける(godoc が必要)

以上のように、非常に便利なものになっております。むしろこの程度 REPL には当然あってほしい機能だとも言える。

インストール

利用には Go 本体が必要なため、バイナリの配布はしていません。

go get github.com/motemen/gore

完全な機能のために、以下のライブラリも別途 go get しておくことをお薦めします。

go get github.com/nsf/gocode # 入力補完に
go get github.com/k0kubun/pp # プリティプリントに
go get golang.org/x/tools/cmd/godoc # ドキュメントに

使い方・機能

gore で起動すると、プロンプトが表示されます。Go の式や文を入力してください。入力された内容が値を返す式や変数の代入となる文であった場合には、よしなに値が印字されます。

gore> n := 1
1
gore> n+1
2

入力がうまく解析できなかったときはプロンプトが ..... となり、続けて入力できます。EOF(^D)でキャンセルします。

gore> even := func(n int) bool {
..... return n % 2 == 0
..... }
func(int) bool {...}
gore> even(4)
true

Go のコードではない指示は、コロンで始まるコマンドで入力できます。:help ですべてのコマンドを一覧できますが、よく使うのはパッケージのインポートを行う :import でしょう。

gore> :import strings
gore> strings.TrimSpace(" foo ")
"foo"

また :write コマンドで、REPL セッションで生成されたコードをファイルに保存することができます。

コード補完

エディタで Go を書いている人は gocode をインストールしていることと思いますが、gore もこれを利用してコード補完を行います。スクリーンキャストにあるように、適当なところで Tab キーを押すことでコードの補完がいい感じになされます。

プリティプリント

ppspew がインポートできる環境であれば、これらを利用して値の表示をおこないます。なければ fmt.Printf("%#v", ...) にフォールバックします。

ドキュメントを引く

:doc コマンドでドキュメントを引けます。名前だけでなく型も見てるので、ある変数のメソッドからドキュメントを引くということもできます。godoc コマンドが必要。

gore> :import encoding/json
gore> :doc json.Decoder
(godoc encoding/json Decoder)
gore> d := json.NewDecoder(nil)
...
gore> :doc d.Decode
(godoc encoding/json Decode)

他の REPL 実装との比較

Go の REPL を作ろうという試みは人類共通のようで、すでにいくつかの実装が存在しています:

以下、これらにの機能について簡単に gore と比較をした表です。

実装 値の表示 インポート 文の入力 アンドゥ 行編集 複数行入力
gore
go-repl
rango
igo
play.golang.org

補足

  • 「値の表示」とは 1 + 1 などと入力したときにその値が表示できること。対応していない実装では "1 + 1 evaluated but not used" などのエラーが表示され、fmt.Println(1 + 1) などとしなければいけません。
  • コード補完、色付きプリティプリントに対応しているのは gore のみです。

注意点

  • REPL といいつつ実は裏ではそれまでの入力を順番に実行するソースコードを生成して go run しているだけなので、どこかの時点で評価に時間のかかるコードを入力すると、その後の入力の評価にも時間がかかるようになります。

以上

紹介した機能のほかに、Go ではインポートしたパッケージが利用されていなかったり未使用の変数があったりするとエラーになる件の回避など、快適な REPL 体験のために細かく調整しています。どうぞご利用下さい。

いつも通りコードは GitHub 上にあります。不審な挙動があったら Issues よりお知らせください。

https://github.com/motemen/gore

Pocket の未読フィードを秘密の URL で公開するウェブサービスを作った

Pocket はあとで読むサービスで、とりあえずの URL を放り込むところとして使っているんだけど、これをほかのサービスとうまく連携しようとすると、IFTTT に対応していないところでは意外と面倒なときがある。今回は未読アイテムのフィードが欲しかった。

Pocket には RSS フィード形式で未読リストにアクセスできる機能がある(ヘルプ)のだけど、これは http://getpocket.com/users/username/feed/unread という URL に Basic 認証でアカウント名とパスワードを入力させるという形であったので、うーん……ちょっと使いたくない。認証を解除して全公開することも選べるが、自分がリストに何を入れているか知ってほしいわけでもない。こういう時はリセット可能な秘密の URL を作ってくれれば取り扱いしやすいだろ、というわけで作った。Pocket の API はシンプルでよい。

作ったのは Pocket Expose というウェブサービス。ログインすると自分用の URL が生成されます。プレーンテキスト(全件)、Atom フィード(最新 20 件)に対応。URL のリセットも情報の消去も簡単にできる。デザインは面倒なので Markdown 風です(笑)

ソースコードは GitHub に。

motemen/pocket-expose-web · GitHub