詩と創作・思索のひろば

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

Fork me on GitHub

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

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

はてなで一緒に働きませんか?