ひ孫

犬のこととか書いていきたい

hubotを環境変数を気にせず呼ぶやり方

github社製のhubot。
botとして簡単に扱えそうで既存スクリプトが多いとかnode.jsで動いてるとかgithubをあれこれするのに相性よさそうとかの理由で触り出した。
基本的な起動方法とかは
http://tech.kayac.com/archive/15_hubottechkayaccom_advent_calendar_2012.html
http://d.hatena.ne.jp/anatoo/20120204/1328368042
らへんにあるように環境変数に色々設定するのが普通みたい。

しかしせっかくnodeで動いてるのに起動用にshell script書くのも負けた気がするので
node.jsでなんとかしたくなったのでなんとかした

こんな感じ。
node.jsにはchild_processという子プロセスを起動するのがあったのでそれを利用。envという引数で環境引数なんかを渡せた。
この程度なのであんまりいらないかもしれないけどせっかくなので
ちょっと形を整えてnpmモジュール化もした。

node moduleを作ってnpmに公開するまでの小ネタまとめ

基本的な公開までの手順はこことかこことか

そういうとこに乗ってなかった小ネタがちょこちょあったのでまとめ。

開発前

gitを使いましょう

バージョン管理をしましょうという話は当然ですが

$ npm install gitのurl

というgitのurlでインストール出来たりと色々利点が多いのでgitを使うと捗ります。

npm init しましょう

git initと同じタイミングでやっちゃいましょう。

$ git init
$ npm init

色々聞かれます。答えるとpackage.jsonができます。便利。
手動で作ると色々間違うのでこっちを使いましょう。

開発中

プラグインのインストール時は --saveオプションを使いましょう
$ npm install --save hoge
    • saveをつけると自動的にpackage.jsonに保存されます。便利。

開発中しか使わないテストツールのようなものは--save-devをつけましょう。

公開前

使わなかったプラグインはdependenciesから削りましょう。

開発中はあれないかこれないかと色々プラグインを入れるでしょう。
で、最終的に使わないのとか出てきます。
package.jsonからdependenciesから削りましょう。
dependenciesがいっぱいあって困るのは他の人がinstallした時に重くなるという事ぐらいですがなるべく剤っときましょう。
削ったら

npm prune

をしましょう。自動でnode_modulesから消えてくれます。

他の人がインストールした時のテストをしましょう。

空のディレクトリかなんかを作って

$ npm install 自分のgitのurl

を実行しましょう。
そして他の人が使う時の挙動を確認しましょう。
package.jsonに書いてたmainの指定スクリプトが違ってた!とか無いように。
binをつけたコマンドラインのパッケージなら

$ npm install -g 自分のgitのurl

でもいいですね。
*1

publishはurl指定でやりましょう

package.jsonの中にはrepositoryという項目がありますが

npm publish

を指定した場合にはこれは見てくれるわけではなく、そのカレントディレクトリをパッケージ化してアップするようです。

.npmignoreという.gitignoreと同じようなものもありますが、gitignoreと違ってglobalな設定は出来ない模様なので*2油断するとIDEの設定ファイルなんかがひょいと上がってしまいます。

なので

npm publish 自分のgitのurl

とするのが安全です。これならgitに上がったものだけをそのまま使ってくれます。
gitには上げてるけど更にnpmにだけ上げたくないものだけ.npmignoreに記述してgitにアップするよ良いでしょう*3

*1:これに関してはなんかもうちょっとスマートなテストの仕方がありそうな気もするけどなあ・・・

*2:npm configに[https://npmjs.org/doc/config.html#globalignorefile:title=globalignorefile]というのがあった・・・

*3:ちなみに.npmignoreは空にしとくと.gitignoreを見てくれるらしい。へー。

junitのsetupでmethodに仕掛けた自作アノテーションを取得する

junit4で環境に依存してしまうテストを書きたい時どうするんだろう
と思ってちょっと調べたらこんな記事に出会った。
なるほど確かにアノテーションなら解決できる。

しかしRunnerを自作するのはちょいと重そうだし、後半の解決策として出ているCategoryもSuiteで管理するようなものっぽい。
もうちょい手軽にSetup時にちょちょいとやれるぐらいでいいよなあと思ってこんなコードができた。


*1
肝になったのはTestNmaeというRule。
通常Annotation取得するには

Thread.currentThread().getStackTrace() 

みたいな感じでやるけども。junitの場合だとリフレクションでテストメソッドが呼び出されているらしく
これでは呼び出されている現在のメソッドが何なのかわからなかった。
で、どうにかならんかと悩んでいたら出てきたのがこいつ。
単純に自身のメソッド名を格納してくれるらしい*2
それができてしまえばあとはこっちのもん。

 Method method = this.getClass().getMethod(this.name.getMethodName(), new Class[0]);

でさっくりMethodを取得!そのまま流れでAnnotation取得!

結構色々使えそう

*1:いくらembed貼ってもgistが表示されなくて困った。出たり出なかったり。これどういう条件なんだろう?

*2:[http://stackoverflow.com/questions/473401/get-name-of-currently-executing-test-in-junit-4:title=Stackoverflowさんに教えてもらった]

posh-gitをインストール

Github on windowsのシェルモードをいつでも使えるようにしたくて
posh-gitを入れたけどちょっとinstallのとこに書いているのだけだと躓いた箇所があったのでメモ

以下powershellで実行。
まずは色々確認

  • power shellのバージョン
$PSVersionTable.PSVersion

これで2.0以上なら問題なし

  • gitのインストール

gitにパスが通っているか。msysgitとか入れるの嫌だけどここは我慢。*1

git

ここから実行したこと

  • 1. 実行ポリシーの修正
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Confirm
  • 2. 適当なディレクトリにposh-gitのクローン
git clone https://github.com/dahlbyk/posh-git.git
  • 3. インストール
.\posh-git\install.ps1
  • 4. 設定のリロード *2
. $PROFILE

ちなみにpowershellをエクスプローラーから開くのには
Alt+Dを押して「powershell」と入力すると簡単に開いてくれる

*1:今思ったけどportable-gitだけでも十分だったのかも

*2:上記実行時にはこれ実行しろとは書いてあるんだけどREADMEにはなくてうっかり見逃した

/// reference path やだー

typescript大好き。
でも、許せなことがひとつある。

/// <reference path="node.d.ts">

↑こいつ。

何をする時に使うかって言うと他のtsファイルを参照している時に使うものだ。
どうやら出典としてはVisual Studioあたりで/// みたいなことをすると補完してくれるというところからっぽい。

しかし結局補完のされない普通のエディタでやってる分には恩恵がない。(typescriptオンリーで使う分には正直visual studioは使いものにならない・・)
が、こいつが無いとコンパイルが通らなかったりする。(正確には通すこともできたけど)

なんとかならんかとちょっと調べてみた。

そもそも reference path とは

公式ドキュメントを読んでも上記の構文が出てくるのは一箇所だけで、ファイルの依存関係を解決するものだよとの事。
更に非公式なとこでの情報だがこれは別にjs変換後まで保たれるわけじゃないのでそこらへんは知らんよという事らしい。

使わなくても良いパターン

exportでモジュールを書いてそれを呼び出し先でimportするやり方の場合、reference pathはいらない(内部でちゃんと解決してくれる)
例えばこんなかんじ
module.js

export class hoge{
   fuga(){
     console.log("aaa");
   }
}

main.js

import mod = module('module');
new mod.hoge().fuga() // aaa

*1

module('module_path')はパスをたどってくれたりもするので、自分で組む分には全部上記の様な感じでexportとimportで書くと良い。

が、やっぱりこれでは解決しない問題がある。
それが例にあげたようなnode.d.tsとか。
http://typescript.codeplex.com/SourceControl/changeset/view/fe3bc0bfce1f#samples%2fnode%2fnode.d.ts
サンプルコードを掲示する。
見ると、exportされていない。
ひたすらにdecrareが書かれている。

色々調べたり試行錯誤したりしていると幾つか打開策が見つかった

打開策その1

特定プロジェクト下のtsファイル全てにインポートするファイルのを埋め込むスクリプトを書く!

打開策その2
tsc hoge.ts node.d.ts

つまりコンパイル時にまとめてコンパイルしちゃえばいい!
毎回コンパイルするスクリプトをバッチ化しておけば問題無さそう。
「必ずgruntjsでコンパイルしましょう」ってルールとかにしちゃうとかすればありかも。

打開策その3

完全にやる必要が無いレベル。だけどちょっと面白いなあと思ったのでメモ

grunt-typescriptのソースを読んで
あれあれ?これだったらいけちゃうんじゃない?と思った部分がこのへん

 compiler.addUnit(unit.code, unit.fileName, false);

本家のtypescriptのコードを見てみてもlib.d.tsを読み込んでるとこでも使ってるみたい。
こうやって複数ファイルを読み込んでるんだったら先にライブラリ系のやつをモリモリ食わせておいたコンパイラー作っとけばよくね?
ということでこれを応用すれば最初からいろんな物を増々にした独自Typescriptコンパイラーが作れるのでは!と思いました。
https://gist.github.com/4061517

結局打開策2でやってることとほとんど変わんねーじゃんっていう話な気がしました。
馬鹿でかくなった時1ファイルごとにライブラリ全部読んでコンパイルとかよりはもしかして高速になるんじゃないかなあ(願望)

まとめ

そもそもreference pathsってなくていいの?という疑問は未だ払拭できていません。
正直ドキュメントを見た感じだと必ず書きなさいって具合なのかどうかはちょっとわからない。
結局書かなくても通ってしまうし動きは変わらないのだから良いんじゃないか(逆に言うともしダメならコンパイラの段階でこかさないといかんのでは?)
と思うしlib.d.tsはコンパイラがreference path無しでも読み込んでいるんだから他のファイルがそういうふうになってたっていいじゃないか!
とは思ったりします。(そもそもreference pathがきもいなーと思っている人自体少ないかもしれないですね。今更)
オープンなプロジェクトだったりしたらやめたほうがいいのかもしれないですね。

*1:requireが有効なnode環境などじゃないとちゃんと動かないコード

いろいろいじって出た疑問とか

Typescriptがふと読んでみたらとてもよさそうだったので軽く触ってみた。
いろいろサンプルスクリプトとか見てこれなんだろう?的に気になった疑問と自分なりの理解をまとめた。

前置き

環境について

TypeScript - Playgroundみたいな環境をローカルで再現仕様とすると、Visual Studio 2012 Express for Webでtsファイルを単体で開いて編集し、結果のコードはtcsvを使ってリアルタイムプレビューをする。
という状態がよさそうだ。

Visual Studioは変換後と見比べるような機能は無く、変換もビルド実行しないと行われない模様。
インストールもiso形式でDLされるのでいちいちディスクに焼いたりしないといけないしクッソ時間かかったりでVS愛がある人以外にはあまりおすすめできない。*1

公式ドキュメント

なんだか迷わされたがここにあった。
一応ここ読みつつ色々試した。

declareってなんだ?

突然現れたdeclareに戸惑ったが、なんてことはない、変換時に「これはもう存在してますよ」的なことを宣言しているらしい。
jqueryとかの外部ライブラリを使いたい時、そのまま

$.ajax({
})

みたいに書くとコンパイルで怒られてしまう。
なので

declare var $;
$.ajax({
})

とするとコンパイルが通るようになる。

ただこのままだと補完が効かなかったりする。
もし補完がほしいならばTypeScriptのコマンドで下記のようにすると
〜.d.tsというインターフェースを抽出したコードが生成できる。

# ↓hoge.d.tsが生成される。
$tsc --declarations hoge.js 

追記:declare でclassやinterfaceを定義するときはその中身も書かないとダメな模様*2
〜.d.tsはdeclareで外部のjsライブラリのクラスなんかを宣言したいときに使うものみたい。
(けど実際自分が既存のjsを移植しようってなったらany型に頼っちゃうよなあ・・・)

() => ってなんだ

サンプルとかを眺めていると

var getHue = () => { return this.hue(); };

なんてのを見つけた。え、なに、これは。
色々悩みながら調べてくうちにEcma script6で使われるらしいarrow functionというものの実装らしい。
じゃあ普通のfunctionと何が違うんだっていうと、thisの扱いが違うらしい。
下記のようなコードをコンパイルしてみるとわかりやすい

class cls {
    func() {
        var log1 = function () {
            console.log("hoge" + this);
        }
        var log2 = () => {
            console.log("hoge" + this);
        }
    }
}

var cls = (function () {
    function cls() { }
    cls.prototype.func = function () {
        var _this = this;
        var log1 = function () {
            //functionだとthisをそのまま使う
            console.log("hoge" + this);
        };
        var log2 = function () {
            //allow functionだとthisをクラスとして扱う。
            console.log("hoge" + _this);
        };
    };
    return cls;
})();

allow functionで書いた関数内のthisはクラス自身を引き継ぐ模様。
ちなみにブロックで囲んだ時と囲まなかった時の挙動も違うみたい。

var func1 = (x) => x * x ;    //returnする
var func2 = (x) => { x * x }; //returnしない

var func1 = function (x) { //returnする
    return x * x;
};
var func2 = function (x) { //returnしない
    x * x;
};

なんとなくわかった。きがする。

*1:でもintellisenceはほんとに良い感じに補完してくれる

*2:というかじゃないとclassとかはdeclareする意味無いですね

Pigで複数ファイルを読み込む

Hadoopのpigでファイルを複数読み込むのどうすればいいか。

なんだか色々遠回りしてusingしなきゃいけないのかとか考えたけど結局

log = LOAD '/directory/some-date/data-[0-9].txt';
log = LOAD '/directory/some-date/data-{a,b}.txt';

のようにglob形式で書けば良いというだけの話だった。

ちなみに下記のようにすればファイルが対象になるか確認できる。

$ hadoop fs -ls '/directory/some-date/data-{a,b}.txt'