詩と創作・思索のひろば

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

GitHub でイシューからイシューを作るときに便利な userscript

とくに GitHub を使って仕事をしていると、あるイシューからそのサブイシューを生成する機会がよくあって、そういう時はサブイシューから親イシューを(#765 のようにして)参照しておくと便利なのだけれど、イシューをまとめて整理しているときにはこの細かい作業が面倒。そこで userscript を書いた。

github-userscripts/refer-issue-when-creating at master · motemen/github-userscripts · GitHub

挙動は簡単で、GitHub 上のイシューや Pull Request のページ内にある「New Issue」ボタンをクリックしたとき、イシュー作成フォームの本文やタイトルに、もともとのイシューを参照するような内容がフィルインされるというもの。本文にはイシュー番号、タイトルには元のイシューの名前が入ります。このへんは人の好き好きだと思うので、各自カスタマイズするとよいと思う。また、ボタンのクリック時に選択していた内容がタイトルに付与されるというのもおまけでついてます。

以下のアニメーション GIF を見ればわかりやすい。

f:id:motemen:20150123135611g:plain

いつもどおり、利用するには chrome://extension に .user.js をドラッグ&ドロップすればよい(Chrome の場合)。どうぞご利用ください。

ウェブサイトの Windows 8.1 用ライブタイルを提供する

ライブタイルってのは Windows 8 のスタート画面に表示されてるタイルで、その内容がときどき更新されるものです。アプリをスタート画面にピン留めしておくと、アプリを起動することなしにニュースとか株価とかが表示できるって便利なやつです。Android で言うならウィジェットみたいな感じかな。

Windows ストアアプリでないとこれを提供することはできないと思っていたんだけど、実は Internet Explorer 11 の機能で、ウェブサイトをピン留めし、ライブタイルを表示できることを知ったのでやってみた。

IE11 での Web サイト用ライブ タイルの作成 (Windows) に詳しいドキュメントがある。やることは簡単で、

  1. ライブタイルに表示するための情報を提供する XML (と、それにアクセスするための URL)を用意する
  2. ウェブサイトからその XML をポイントするなど、(ライブ)タイルに関する情報を提供する

ウェブサイトがフィードを提供する場合と似たような感じなので、難しさはない。1. で指定できるタイルの種類は https://msdn.microsoft.com/ja-jp/library/ie/dn456348(v=vs.85).aspx にいろいろ書いてある。2. で URL やポーリング間隔を指定できる。これに関しては

  • meta タグをいくつか書く
  • JavaScript を書く
  • 設定リソースをポイントする

の 3 つの方法がある(https://msdn.microsoft.com/ja-jp/library/ie/bg183312(v=vs.85).aspx)。

実例

次の連休 という、次の連休まであと何日か知ることの出来るウェブアプリで試してみた。次の連休まであと何日か、ウェブサイトにアクセスせずに確認できれば便利なはずである。簡単そうな meta タグによる実装。

meta タグを書き、

<meta name="application-name" content="次の連休">
<meta name="msapplication-notification" content="frequency=60; polling-uri=http://japanese-long-weekends.herokuapp.com/ietile.xml">

XML を提供する: http://japanese-long-weekends.herokuapp.com/ietile.xml

あとは IE でウェブサイトにアクセスし、デスクトップにピン留めすると、

f:id:motemen:20150121135525p:plain

無事スタート画面に次の連休までの日数が表示される……

f:id:motemen:20150121134301p:plain

次の連休は 101 日後です(´;ω;`)ブワッ

格安 Windows タブレットのセットアップ

正月の気の緩みで Windows タブレットを買ってしまった。定価でも 2 万円台、Office のライセンスのないマーケットプレイス出品なら 1 万円台で最新の Windows とタブレットが手に入るのは異様に安い。毎日再起動してるけど、満足の日々を送っている。

所感

  • フル機能の Windows を楽しめるのでとてもよい。
  • Modern UI が結構使いやすい。
    • 画面端からのスワイプが便利。軽快である。
    • 特に Windows ストアアプリはスマートフォンやタブレット向けに全画面表示されるのだけど、画面を分割して表示させることもできる。
    • 画像は Pocket リーダーから URL を開いたら画面が分割されて Internet Explorer が起動したところ。アプリ内ブラウザなんていらんかったんや!という気分になる。
    • f:id:motemen:20150114130323p:plain

  • アプリ(Windows ストアアプリ)があまり充実してない気がする。少なくとも Kindle はない。
    • Twitter などメジャーどころでも評価の低いものが多いのも気になる。
  • Internet Explorer も Modern UI 使ってるけど普通に使えるのでほかのブラウザはインストールしていない。
  • ときどき反応がなくなるので再起動してる。

chocolately でパッケージ管理

Chocolatey Gallery

たぶん Windows 用の Homebrew 的なもの。だいたい Windows はアプリの管理ができなくて大変なことになるので、これを使いたい。メジャーかどうかは判断しかねる。

以下これを使ってインストールしたもの。

  • 7zip
  • autohotkey.portable
    • dropbox のインストールに必要だった。
  • avgantivirusfree
    • 同梱のマカフィーをアンインストールして、こちらを導入。
  • ConEmu
  • dropbox
  • git
  • golang
  • rktools.2003
  • vagrant
  • virtualbox
    • Windows で開発するぜ! と意気込んでいたけど、念のため入れといた。念のためな。

Windows ストアアプリをインストール

その他インストールしたもの

  • gVim は香り屋版がいいだろ、と思うのでこちらからダウンロード。
  • Kindle アプリがないので Kindle Cloud Reader をホーム画面にピン留め。タブレットで読みたいのはだいたい漫画なので、小説が読めないのはまあ我慢できるかな……。TAPL が読めないのにはまいった。

ゲーム

Windows 機ってことはゲームができるんですよ! 8 インチタブレットで普通にプレイできてしまうので感激。

  • 鬼哭街
    • 鬼哭街

      鬼哭街

    • これなんか特に、ただ読むだけなので横画面にして寝っ転がりながら遊べる(読める)。
  • 3Dカスタム少女
    • 低スペック PC でもわりと軽快に動作する救世主。20+ FPS くらいは出ます。

これからセットアップする人に注意! 初回セットアップ時、Microsoft アカウントと連携してはいけない

そして最後に、これが面倒な点。素直な性格なのでセットアップ時に Microsoft アカウントと連携してしまったが、その結果ホームディレクトリのパスに日本語が混じってしまい、以下のような弊害があった。

  • go test できない
    • 作業ディレクトリに日本語が混じってパッケージが発見できなくなる。TMP 環境変数を書き換えればなんとかなる。
    • C:\Users\����\AppData\Local\temp\go-build186010647\github.com\motemen\ghq\_t est\_testmain.go:12: can't find import: "github.com/motemen/ghq" みたいになる。
  • vagrant up できない
    • 文字コード関係のエラーが出るけど日本語が混じってるのがいけないらしい。
    • C:/HashiCorp/Vagrant/embedded/gems/gems/childprocess-0.5.5/lib/childprocess/windows/process_builder.rb:43:in ``join': incompatible character encodings: Windows-31J and UTF-8 (Encoding::CompatibilityError)

途中から変更できないらしいのでこれから再インストールします^^

まとめ

安価に Windows 環境を手に入れました。そして Windows 8.1 けっこう良い。楽しい!

PowerShell を使って .exe ファイルを Windows サービスとして登録する

Windows にはサービスという概念があって、UNIX でいうデーモン的なことはこれを使えば実現できる(MSDNWikipedia)。サービスにはその停止や再起動などの要求に答える責任があるので、それらに対応していないアプリケーションをそのままサービスとして登録することはできないのだけど、任意のアプリケーションのラッパーとなるサービスアプリケーションが Microsoft によって提供されているので、これを使えば実現できる。

前準備

サービスとして登録する PowerShell スクリプト

汎用化はできてなくて、決め打ち。

install-mackerel-agent-service.ps1

これを実行する(PowerShell コンソールを起動して、\Path\To\Script.ps1)と、管理者権限を求める UAC ダイアログが表示されたあと、管理者権限のコンソールが開き、自動で MackerelAgentService というサービスがインストールされる(起動はしない)。表示されたままのコンソールは閉じてもいいし、

sc.exe start MackerelAgentService

でサービスを起動することもできる。

ちなみにサービスの削除は sc.exe delete で可能。

f:id:motemen:20150111145459p:plain

Mackerel への PC の登録、メトリックの投稿ができました。

解説

  • PowerShell の New-Service コマンドレットを使って MackerelAgentService という名前で srvany.exe を登録する。
  • その後レジストリを操作して srvany.exe に渡すパラメータを登録する。このパラメータが、サービス化したいコマンドになってればいいらしい。
    • New-Item と Set-ItemProperty でレジストリを操作できる。これはファイルシステムに対しても同じように使える汎用的なコマンドレット。
  • Start-Process コマンドレットに -Verb RunAs を指定すると、指定したコマンドを管理者権限で実行できる。
  • powershell.exe は -Command "& {<command>}" を指定することで
  • { … } はスクリプトブロックと呼ばれる構文らしい。たぶん文字列化して渡してる気がするんだけど、この辺の正確な理解ができていない……。

参考

ちなみに NSSM - the Non-Sucking Service Manager ってのもあるらしい。

会社は何のためにあるのか: 『ビジョナリー・カンパニー』を読んだ

ビジョナリー・カンパニー ― 時代を超える生存の原則

ビジョナリー・カンパニー ― 時代を超える生存の原則

世界を見わたして長いこと生き残り、また業界で抜きん出ている会社(ビジョナリー・カンパニー)を取りあげて、それが他の会社と違っている点は何なのか分析した本。半世紀以上も経てば世界の状況は変わり、経営者以下みな代替わりしてゆくものだけど、それでも会社として生き残った、そしてこれからもそうであろうと思える理由というのは何なのかってのを見ていく。

それは経営者の資質だとか主力製品などでは決してない。それらに依存しているような会社は、たとえその時は栄華をものにできたとしても、やがて訪れる避けられない市場の変化や人物の不在という事態には耐えられない。必要なのはすぐれた人物や製品よりも、すぐれた組織づくりの方だ。会社が作り出す究極の作品は、その会社自身なのだとこの本ではいっている。

価値観と目的

では状況の変化に耐えながら会社が生き残る秘訣は何か。それは組織の基本理念をはっきりと定め、自覚することだ。すべての決定がそれに則っておこなわれ、それ以外のことが変わってもこれだけは変わらない、そんな理念を組織の背骨に据えなければいけない。

基本理念は基本的価値観と目的とで構成される。基本的価値観は時代を越えて不変の主義であり、短期的な利益や事情で曲がらない。目的は組織の存在理由になるもの。これは組織の内側に向けた価値観と、外向きの目的と分類できると思う。

基本的価値観を会社の中心に据え、それでも時間の経過に耐えるには進歩への意欲、変化を許す風土が必要だ。そしてそれらは仕組みとして定着させなければいけない。そうでなければ時代とともに失われてしまうからだ。

本を読むと各社がどんな行動を取ってきたのかという例がたくさん載っている。なるほどこの原則に即していると思う。もちろん盲目的に従えばよいというものではないけれど、大企業とよばれるような会社が今にいたるまでどんな決断をくだしてきたのかを知るだけでも面白い。

会社は何のためにあるのか

基本理念を達成することで会社が生き残り、そのプロセスがずっと続くのならば、人びとが集まって会社を動かすことの意味は、会社の考えるような、人間ひとりではとうてい実現できない大きな善を生み出して、価値観を維持していくことにある。そしてそのことに本当に意味があるのなら、その営みはずっと続いていくだろうし、会社で働くことも無駄ではないだろう。

……と思えたので、いい本だった。別に経営者のためだけに道を示してくれるのではなく、規模や時間的なスケールの違いはあれど、ある程度以上の人間が入れ代わりながら関わる組織(それこそ、社内のチームとか)であればこの精神を活かすことはできるはずだ。

Kindle 版もあった。

ビジョナリー・カンパニー 時代を超える生存の原則

ビジョナリー・カンパニー 時代を超える生存の原則

おまけ。陳腐な表現だけど、組織は生物のようだと思ったのだった。

生命とは何か―物理的にみた生細胞 (岩波文庫)

生命とは何か―物理的にみた生細胞 (岩波文庫)

Go で reflect パッケージを使わずにジェネリックな関数を実現する

Go

あけおめ〜。Go 界においてジェネリクスを求めるのは(今のところ)はかない望みでしかないし、もちろん重々承知していることですが、それでもときどき複雑なものを書こうとするとどうしても複数の型に対応する関数が欲しくなる。そこでこの冬休みになにかうまい方法はないかと考えて、作ってみました。

要件

今回はこんな関数が実現したくなりました。(擬似コードです)

// map[string]int とか map[string]foo.Bar を受けつける
func keys(m map[string]T) []string {
    keys := make([]string, 0, len(m))
    for k := range m {
        keys = append(keys, k)
    }
    return keys
}

そしてこれを実現するためのアプローチを以下のように定めました。

  1. reflect パッケージを使わず、コード生成で対応する。
  2. コード生成前のコードもコンパイルできるようにする。
    • 書いている途中でも補完などが効くように。
  3. コード生成の際、対象の関数以外には手を加えない。
    • 呼び出し元はすべて同じ keys 関数の呼び出しになっていて、keys_bool(m) とか keys(wrapper(m)) とかに書き換えられない。

コンパイルできるが実行時にエラーとなるコードを、コンパイルできて実行時にもエラーとならないコードに変換する、という寸法です。実行時の安全性は変換器によって保証します。

1 を実現しているツールとして、例えば gengen があります。

方法

上記の keys 関数のシグネチャでは汎用的な型の引数を受け付けられないので interface{} に変更し、代わりに型を type switch で指定するように変更します。以下はそのスタイルで書いた完全なコードです。

// keys.go
package main

import “fmt”

type T interface{}

func keys(m interface{}) []string {
    switch m := m.(type) {
    case map[string]T:
        keys := make([]string, 0, len(m))
        for key := range m {
            keys = append(keys, key)
        }
        return keys
    default:
        panic(fmt.Sprintf("unexpected value of type %T", m))
    }
}

プレースホルダ的な型として、interface{} である T という型を定義します。(interface{} である、大文字で構成された型をプレースホルダとみなすことにします。)

これは他の場所から keys(map[string]bool{}) のように呼び出してもコンパイルできるコードになっていて、実行時に panic します。ならばあとは case 節を実際の型にあわせて増やせばよい、というわけでコード生成の出番です。この関数がどんな引数で呼び出されているかを解析し、それにあわせて case 節を増やしてやります。

実装

ここまでの話を実装したのが motemen/go-typeswitch-gen です。これに tsgen というコマンドが含まれています:

go get github.com/motemen/go-typeswitch-gen/cmd/tsgen

使い方は簡単で、汎用化したい、type switch を含んだ関数の定義されているファイルをコマンド引数として渡します。

tsgen keys.go

自動的に同じパッケージからの呼び出しを検出し、型のパターン(map[string]T など)を実際の引数の型(map[string]bool など)と突き合わせて case 節を追加した type switch を生成し、変更後のファイルの内容を標準出力に印字します。また -w を与えるとファイルを直接書き換えます。

上の keys の例だと、以下のように展開されます。

func keys(m interface{}) []string {
    switch m := m.(type) {
    case map[string]bool:
        keys := make([]string, 0, len(m))
        for key := range m {
            keys = append(keys, key)
        }
        return keys
    case map[string]T:
        keys := make([]string, 0, len(m))
        for key := range m {
            keys = append(keys, key)
        }
        return keys
    default:
        panic(fmt.Sprintf("unexpected value of type %T", m))
    }
}

またあまり出番はないかもしれませんが var x T のように書いてあった場合も var x bool として展開されます。

リポジトリの _example ディレクトリに例が同梱されているので、それを使ってみると簡単です:

% ghq get motemen/go-typeswitch-gen
% ghq look motemen/go-typeswitch-gen
% cd _example/keys
% tsgen -w keys.go
% git diff

また呼び出し元の解析のためには main 関数かテストが必要なので、対象のファイルと同一パッケージにそれらがない場合には -main 引数で指定します。

% tsgen -main github.com/motemen/foo ./util/util.go

go generate と組み合わせる

Go 1.4 から導入された go generate と組み合わせて使うのも簡単です。ファイルの先頭に以下のように書くだけ:

//go:generate tsgen -w $GOFILE

go generate すると当該のファイルが書き換わります。

既知の問題・今後の課題

import が自動的に増えない

Tio.Reader などがマッチした場合 case io.Reader: が生えますが、import "io" は追加されません。とりあえず goimports でしのげます。

コメントの位置が変になる

ベースとなる case 節にコメントを書いていた場合、生成後のコードでコメントの位置が変になります。

返り値を汎用化できない

さまざまな引数の型で同じ関数を呼び出せるようにしている都合上、返り値を汎用化させることはできません。呼び出し元の type assertion を解析するというのはできそう。 現在のところはコールバック関数を引数として与えることで任意の型を受け取れます。foreach の例:

func foreach(a interface{}, cb interface{}) {
    switch a := a.(type) {
    case []T:
        switch cb := cb.(type) {
        case func(int, T):
            for i, e := range a {
                cb(i, e)
            }
        }
}

「任意の数値型」のようなプレースホルダを定義できない

プレースホルダが interface{} だと加算が定義されていないので、数値の配列の総和、のような関数が定義できません。たぶんプレースホルダを type NumberT float64 のように定義できればよさそうだと思ってます。

終わり

tsgen で、既存の関数をベースにしてさまざまな引数の型に対して同じような処理を行える関数を生成できることを紹介しました。Go の静的解析ネタ、いろいろあるのでどこかで書くか話すかできればよいなと思ってます。

みなさま 2015 年もよろしくお願いいたします。

The Way to Go: A Thorough Introduction to the Go Programming Language (English Edition)

The Way to Go: A Thorough Introduction to the Go Programming Language (English Edition)

【想定はてブ数つき】2014 年のボツネタを一挙公開!!!

photo by Keoni Cabral

飽きっぽい性格がそうさせるのか、何かこれをやるぞ! と決めたことをやっている間に他のことを思いついてとりあえずメモっている間にどんどん積み上がっていって、果たせないままに今年も大晦日が近づいてきました。残された人生の時間と話し合って、自分が手を出すのはやめとこうと思ったアイデアをここに記しておきます。ブログに書くときの記事タイトルと想定はてブ数を併記しますので、参考にしてください。

「Perl プログラムを変数名で静的解析する」67 users

YAPC::Asia 2013 で Perl の静的解析の話が盛り上がっていて考えた。Perl のような言語に静的解析のために型アノーテーションをつけるのは煩雑で間違いを起こしやすいと考えられるけれど、静的型のない言語は名前付けが相対的に重要であることを利用して、変数名を型アノーテーション代わりに使用するというもの。例をあげると

sub get_req {
    ...
    return $req;
}

my $res = get_req(); # return $req された変数を <del>$req</del>$res で受けている!

というような齟齬を静的解析によって検出できないか、というもの。

  • やらなかった理由: Perl 最近書いてなかった。
  • ブクマ数の根拠: Perl を題材にしたのがよくなかった。Ruby か JavaScript ならもうちょっとブックマークがついたはずである。

「ソビエトロシアではブラウザがあなたをオートメーションする! または humandriver で自動テストを手動化する」44 users

ブラウザ拡張。ブラウザオートメーションの API である WebDriver の実装を人間が行う。WebDriver API では E2E テストなどで、クライアントが送る「このセレクタで得られる要素をクリックして」みたいな要求を実際にブラウザを(プログラム的に)操作することで達成する。この「プログラム的に」という部分を人間が実際に行うことで機械に使われてる感じがして面白い……だけでなく、WebDriver を使うスクリプトの検証に利用できる。

動作イメージはこんな感じ。

// 雰囲気コード
driver.findElement('button#submit').click();

たとえば E2E テストで上のように書かれていたとすると、起動中の Chrome にポップアップなどで「button#submit をクリックしてください; OK」と通知される。その通りに実行したのち OK を押すとクライアント側に操作が戻りテストが進む。

  • やらなかった理由: WebDriver API を尽くすのが大変そうだった。
  • ブクマ数の根拠: 記事タイトルがややウケだったが、実用性があまり認められず伸び悩んだ。

「機械にレシピを生成させ、食べる」229 users

機械にレシピを生成させてクックパッドに投稿し、つくれぽを教師として学習し、新たなレシピを考案する。飲んでる最中のアイデアだったけど同僚が即座にこういう文献があるね、と出してきたのが面白かった。

  • やらなかった理由: 調理中の画像を用意するのが面倒そうだった。怒られそう。
  • ブクマ数の根拠: 誰もが知っているウェブサービスと、料理という馴染み深い題材による裾野の広さでエンジニア以外にも注目された。初期のいかにもまずそうなレシピにつくれぽがつかなかったため自分たちで作って食べた、というエピソードもうけた。

「Go でジェネリクス的なことを実現する(import を利用して)」89 users

go get は Git リポジトリなりからコードを取得するので、Git サーバを自作すれば動的にコード生成することができる。そこで import 時に適当なパラメータを与えることで書き換えられたコードをダウンロードさせることができないか……と考えた。

  • やらなかった理由: Idiomatic Generics in Go とかぶった……。
  • ブクマ数の根拠: なかなか面白いアイデアだったけど、実用的にはあまり広がりがなかった。

「hubot-ramen で定時退社を促進する」51 users

hubot を使い出したので考えたやつ。Tumblr の ramen タグ からラーメン画像を探しだして、チャットに投稿する。定時とともにラーメン画像を投稿することで仕事のやる気をなくし、結果的に定時退社を促進するというソリューションの提案。

  • やらなかった理由: やりゃあ一瞬だが別にそんなにラーメン好きではないのだった。
  • ブクマ数の根拠: お前らラーメンとか好きなんだろ? という態度が透けて見え、かえって反感を誘ってしまった。

以上、総計 500 ブクマ(想定)ちかいエントリたちの紹介でした。いかがでしたか? もし気に入って実現してみた人は僕と飲みましょう! その際にはおごっていただけると幸いです。

またこのエントリを書く際にいくつかのアイデアをサルベージし、やる気を復活させることができました。みなさんもこの年末、過去のアイデアを棚卸ししてみてはいかがでしょうか?

よなよなエール 350ml×24本

よなよなエール 350ml×24本

http://www.amazon.co.jp/gp/registry/wishlist/3OFWD7Q729FDR/