「GitHub」と一致するもの

当然のことながら普段コーディングはPCで行っています。 ところが、電車の中などちょっとした隙間時間にコーディングができるといいなと思うことがあります。 ちょっとアイデアを思いついた時や、バグに気づいて修正したいときなどがしばしばあります。 もしかしたら、ゼロからプロジェクトを作りたいこともあるかもしれません。

iPhoneアプリで、GitHubのクライアントはいくつかあります。 そのうちのいくつかはエディタ機能を備えているものもあります。 しかし、試した範囲ではとても使いたくなるようなエディタではありませんでした。 やはり、iPhoneで楽しくコーディングしたいものです。 iPhoneのような小さい画面でも楽しくコーディングできるようなインタフェースはありえるのではないでしょうか。

無いものは自分で作ろうの精神で作ってみました。 今のところ、GitHub限定です。 色々なライブラリを組み合わせて、Webアプリとして作りました。 特に、ace editorの恩恵が大きいです。 aceは、基本的にはiPhone/iPadでも動くようになっています。 それをさらに使いやすくするため、表示領域を大きくしたり(パフォーマンスの問題は残るのですが) 「コマンドモード」を導入して、vimのようにカーソル移動ができるようにしました。 カーソルキー問題は、Androidではないでしょうから、iPhone特有の問題かもしれません。

作ったWebアプリの名称は、CodeOnMobileです。 mobile codingにしてしまうと、モバイル向けアプリのコーディングの意味になることが多いので、 coding on mobile (devices)から命名しました。

Webアプリは、

http://codeonmobile.axlight.com/

からアクセスしてください。

その前に、GitHubのプロジェクトページ

https://github.com/dai-shi/codeonmobile

を見てみるとよいでしょう。簡単なスクリーンキャストを載せてあります。 ちょっと長いですが、辛抱強く見ていただけるとうれしいです。

それでは、モバイルでのコーディングを楽しみましょう。

最近、簡単なスライドをWebにアップするときにgistを使っているので、紹介します。

gistを使うと、スライド内のテキストをちょっといじるときなどにブラウザで作業できるので便利かなと思いました。実際はそれほどでもないのですが。

gistを使ってプレゼン資料を作るコツは二つです。

  • reveal.jsを使って1つのHTMLファイルだけで完結させる
  • http://rawgit.com/を使ってブラウザから開けるようにする

reveal.jsは以前紹介したので省略します。

rawgitはgithubのraw fileにcontent-typeをつけたり、cdnでキャッシュしてくれるサービスです。すばらしいですが、永続性は不明です。しかし、代替サービスがあれば乗り換えればよいだけとも言えます。

具体的なサンプルを見た方が早いかもしれません。以下に示すサンプルは、1つのHTMLファイルで、reveal.jsを読み込んで、そのHTML内でJavaScriptを書いて、Markdownを書いています。

まず、ソースはこちらのgistです。

次に、rawgitで開けるようにしたものがこちらです。

「実際はそれほどでもない」と言った理由は、gistを編集するとリビジョンが上がり、rawgitのURLも変わるからです。キャッシュされるのでそうでないと困るのですが。

なんか時代に逆行している感じなので、あまり受けないかもしれません。

MeteorでJadeのススメ

  • 投稿日:
  • by

Meteorのお話です。

Node.jsではExpressでよくjadeを使っています。

http://jade-lang.com/

なぜかjadeは好きです。RubyでHamlは使ったことがありますが、それほど好感を持った覚えはありません。なぜでしょう、%があると見栄えが悪いからでしょうか。

Meteorにもjadeのパッケージを作った人がいるようです。

https://atmospherejs.com/mquandalle/jade

これが思いのほか出来がよくて、気に入りました。 単にjadeの変換を再現しただけではなくて、Meteor用にチューンされている感じです。

インストールは、

$  meteor add mquandalle:jade

とするだけで、*.jadeファイルで書けばあとはよろしくやってくれます。上記ページに使い方は書いてありますが、いくつか転記します。

まず、テンプレート呼び出しの

{{> hello}}

は、

+hello

になります。最初はちょっと分かりにくいと思いました。慣れれば普通です。

次に、if文は、

{{if hoge}}
  <div>hello</div>
{{else}}
  <div>bye</div>
{{/if}

が、

+if hoge
  div hello
+else
  div bye

になります。この接頭辞+は省略もできるようですが、個人的には残しておいたほうが制御ブロックであることが見た目で分かりやすくてよいと思いました。else ifも独自実装しているようです。シンタックスシュガーとして。

最後にまだ実装されていないと書いてありますが、anonymous helperというのが載っています。

+if len > 0

みたいなことが書けるようになるそうです。これはとても実装されて欲しい機能です。これだけのためにhelperを書くのは手間でしょう。

以上、Meteorでjadeがすんなり使えるというお話でした。

ついでに、jade系で気になるツールを紹介します。

https://github.com/donpark/html2jade

HTMLをjadeに戻せるようです。まだ試していませんが、 これはいいですね。過去に書いたHTMLをjade化したくなります。 もし安定して使えるなら、人が書いたHTMLを一度jadeにしてから 編集して、再度HTMLに戻すということもできるかもしれません。

さらに、余談ですが、html2jadeを検索していたら、

https://github.com/vidalab/meteor-html2jade

を見つけました。何かと思ったら、html2jadeをwebで使えるようにしたMeteorアプリのようです。

最近、Angular以外も試そうと思って、2012年春にオープンソースになったときから気になっていたMeteorを使うことにしました。 当時は、FirefoxかChromeかどちらかでしか動かず、動かない方で見ると、背景画像しか見えないというすさまじいものでした。 一方、そのコンセプトはとても共感できて、social-cms-backendを自分で開発したときも同じではないものの似た問題意識でした。

さて、Meteorのサイトは、

http://meteor.com/

です。いいドメイン持ってますね。Meteorの発音は「ミーティア」です。 T.M.Revolutionの歌にありましたね。よし、それを聞きながらコーディングしよう。

さて、Meteorの基本的な説明は他に任せるとして、今回はちょっと変わった使い方をしようと思います。そもそも、普通のWebアプリを作るなら慣れたAngularの方が早いのですが、canvasベースのアプリを作りたいと思ったのがきっかけでした。canvasベースのアプリだとAngularの恩恵があまり得られないので、Angular以外を試してみようと。細かい経緯は省きますが、下記のサイトを見てやってみようと思いました。

http://www.html5gamedevs.com/topic/4886-how-to-use-phaser-with-meteor/

Phaserというのはhttp://phaser.io/で、WebGL/Canvasでゲームを作るフレームワークです。Phaserの説明も他に任せます。上記の記事はちょっと古くて、今では、

https://atmospherejs.com/robertlowe/meteor-phaser

が使えます。MeteorのパッケージがAtmosphereというのは、かっこいいですが、慣れるまでは戸惑いそうですね。

さて、お題は1bitコミュニケーションツールを考えています。 夏の暑いときに作った「暑さをみんなでふっとばせ!」というアプリを移植してみようと思います。このアプリについては、下記を参照。

1bitで使い捨てで匿名のコミュニケーションツールを作ってみた

Famo.us/AngularのサンプルアプリをGitHubに置きました

これは、Famo.us/Angularで作りました。とてもお手軽だったのですが、ちょっとゲームのようなものに使うにはパフォーマンスに難がありました。そこで今回は同じものをMeteor/Phaserで作ってみようと思います。

この記事を書きながらコーディングするのでうまく行くか分かりません。また、読みにくくなってしまうかもしれませんがご了承ください。

さて、まずはMeteorをインストールします。https://www.meteor.com/installに従います。このチュートリアルはよくできてますね。

$ curl https://install.meteor.com/ | sh

1.0.1になってroot権限も要求しなくなりました。1.0のときも、sudoのパスワードを入れなければ同じだったのですが、これはシンプルでよいです。

冬なのでアプリは「寒さをみんなでふっとばせ!」にします。ちょっとふっとばすというのは合わないかもしれませんが。アプリ名はsamufutにします。

$ meteor create samufut
$ cd samufut

チュートリアル通りです。ここで、phaserのライブラリを入れてしまいます。

$  meteor add robertlowe:meteor-phaser

これができるようになったのは最近のようですね。

$ meteor &

で起動して準備完了です。コーディング開始。


とりあえず、Phaserを使ったコードを書くところで時間がかかっています。これはあまりMeteorは関係ないところです。 一つだけ気になったこととして、本体のjsを編集すると毎回パッケージのアップデートをしようとして遅いので、Phaserのコードはclient配下に移動しました。この場合はrefreshするだけなので比較的早いです。

Meteorの話が出てくるのは明日になりそうなので、本記事はとりあえず一時保存します。


さて、一日経過しました。その後、Phaserのコードはほぼ完成し、次に通信部分のコードに着手します。Meteorは既にsockjsを使って通信を行う仕組みになっているのですが、それをアプリからも使えるとよいです。調べたところ、

http://arunoda.github.io/meteor-streams/

というのがありました。パッケージはこちらですね。

$ meteor add lepozepo:streams

でインストールします。簡単です。サンプルコードもそのまま貼り付けます。

chatStream = new Meteor.Stream('chat');

if(Meteor.isClient) {
  sendChat = function(message) {
    chatStream.emit('message', message);
    console.log('me: ' + message);
  };

  chatStream.on('message', function(message) {
    console.log('user: ' + message);
  });
}

直感的ですね。これで実装してみましょう。今回はinsecureは入れたままにします。

完成しました。コードは237行でした。 それでは、デプロイしてみます。

% meteor deploy samufut.meteor.com

できました。メールアドレスが要求されました。

しかし、このURLはgithub pagesやherokuと同じように問題になるのではないでしょうか。そのうち、*.meteorapp.comとかになるかもしれませんね。

デプロイされたサイトは、

http://samufut.meteor.com/

です。ぜひ、遊んでみてください。使い方は書きませんでしたので、暑さをみんなでふっとばせ!の方を参照してください。

少し試した範囲だと、環境によっては通信がうまく行かないケースがあるようです。遅延というか、反映されないのです。またの機会に調べましょう。

ソースコードは下記にアップしました。

https://github.com/dai-shi/samufut

当初は、もっとMeteorのことを書こうと思っていたのですが、苦労したのはPhaserまわりだったのであまり書くことがなくなってしまいました。まだ、やったことないですが、insecureを外してまじめに実装するといろいろコード量が増えて、結局大変っていうことにならないか心配です。それでも、プロトタイプが手軽に作れるのは利点だと思います。

気になったことを一つ思い出しました。普段非同期処理で書くことが多く、比較的好んでいるのですが、Meteorのクライアント側のmongoは同期的なので戸惑いました。キャッシュされているからなせるわざなのでしょうか。事前にpublishできないようなデータの場合どうなるかなど気になります。もう少し勉強しなければいけません。

それでは、Meteorの今後に期待します。


12/28追記。

sudoがいらないと思ったのは勘違いでした。たまたま、その時の環境が/usr/local/binにwrite権限があったため。

GitHub便利です。その一つが、Compare ViewのDiffです。Pull Requestを確認するときもよく見ます。コマンドラインでgit diffと普通にやるより見やすいです。

さて、背景は省略しますが、HTMLでdiffを表示したいと思いました。AngularJSでの利用を想定しているので、JavaScriptのライブラリが欲しいです。

ところが探してもあまり見つかりません。よくまとまっているのはこちら。

http://stackoverflow.com/questions/3053587/javascript-based-diff-utility

ちょっと古い投稿ですが。一番人気なのは、これです。

https://github.com/cemerick/jsdifflib

オンラインデモはこちら。

http://cemerick.github.io/jsdifflib/demo.html

だいぶ求めているもののイメージに近いです。 コードも枯れているらしい。 HTMLが出力されるので、Angularで使うならdirectiveを書かなければいけないですが、それは仕方ないですね。

これで行こうかと思ったところでしたが、なにか物足りません。 なんというか、見た目がワクワクしないのです。 改めてGitHubのDiffと比較してみると、全体的に色が濃すぎる。 あと、単語の差分がハイライトされない。色については自分でcssを書いて調整すればよいでしょうが、単語のハイライトはそれでは済みません。

というわけで、もう一度検索しました。見つけたのがこちらです。

https://github.com/rtfpessoa/diff2html

オンラインデモはこちら。

http://rtfpessoa.github.io/diff2html/

おお、おしゃれ。これですよこれ。なんとStar数は3でした。まったく注目されていません。コードも枯れていないでしょう。まだ不具合もあります。でも、魅力的です。これを使いましょう。

ところが、使うには一つ問題がありました。diff2htmlはdiffの出力を入力としているのです。例えば、

diff --git a/foo.txt b/foo.txt
---
+++
@@ -1,4 +1,5 @@
+zero
 one
 two
-three
+tree
 four

このようなものです。つまり、次はこれを出力するライブラリを探しました。いくつかありそうでしたが、比較的すんなり結合できたのはこちらです。

https://github.com/qiao/difflib.js

入力の行が配列になることと、出力の一行目のヘッダが付かないことなど不足点はありまして、それらは自力で対応しました。

最後にこれらを全部つなげて、angular.jsのdirectiveを書いてできあがりです。下記のような感じで使えるようになりました。

<my-diff path="foo.txt" old-content="one\ntwo\nthree\nfour\n" new-content="zero\none\ntwo\n\tree\nfour\n">

便利です。ちょっと気になることと言えば、依存javascriptが3ファイルもあって、グローバルに関数を定義するようなものであることです。なにかうまく隠蔽する方法があるのでしょうか。

夏ごろに「暑さをみんなでふっとばせ!」というアプリを作りました。

1bitで使い捨てで匿名のコミュニケーションツールを作ってみた

に経緯が書いてあります。

当時は、Famo.usやF/Aのライブラリに手を入れないといけなかったのですが、その後バージョンアップして不具合が解消されました。 新しいバージョンでは読み込み速度なども改善しています。

せっかくなので、GitHubにソースをアップロードしました。 Famo.us/Angularとsocket.ioの組み合わせでこんなことができるというサンプルによいかと思います。

ついでに、「暑」を「寒」に変更する機能もつけました。タイトルはそのままですが。

GitHubのページはこちらです。

https://github.com/dai-shi/atsufut

実際に動作しているアプリのページはこちらです。

http://atsufut.axlight.com/#?color=blue&label=%E5%AF%92

AngularJSの1.3.0がリリースされました。

これまで、1.2系を使っていたのですが、これを機に1.3も試してみようと思いました。

1.0から1.2に移行したときは、はまったのですが、今回はなにも不都合がありませんでした。

ところが、e2eテストが動かなくなってしまいました。具体的には、下記のようなテストがエラーになりました。

expect(element(by.repeater('item in list').row(0).column('{{item.name}}')).getText()).toEqual('foo');

エラー文は、

NoSuchElementError: No element found using locator: ...

です。

https://github.com/angular/protractor/blob/master/docs/api.md

のドキュメントを見ても問題なさそうですし、StackOverflowなどでも話題になっているのは見つからず、途方にくれていました。

が、試しに下記のように変更したら動きました。

expect(element(by.repeater('item in list').row(0).column('item.name')).getText()).toEqual('foo');

これって正しい解決法なのでしょうか。

ProtractorでAngularアプリのE2Eテストやってみた、PhantomJS編に引き続き、 Protractorでwindow.alertをテストする方法を調べたので書いておきます。

E2Eテストを書くときに、alertの文字列を調べたいことがあると思います。 また、confirmでOKしたりCancelしたりする場合の挙動もテストできるとよいでしょう。

ちゃんとできるようです。Protractorというよりその内部のWebDriverがすごいということですね。

http://stackoverflow.com/questions/19879631/protractor-get-text-of-an-alert

に載っていました。

https://github.com/angular/protractor/commit/196c83a9d728e40fecd7a9f206bb985533550fde

が分かりやすいです。ちなみに、現時点でのHEADではnavigation_spec.jsに載っています。これによると、

var alertDialog = browser.switchTo().alert();
expect(alertDialog.getText()).toEqual('Hello');
alertDialog.accept();

と書けばいいとのことです。confirmの場合も同様です。 confirmの場合でcancelするときは、accept()の代わりにdismiss()を使えばよいようです。

ところが、PhantomJSではこれは現時点では使えないことが分かりました。PhantomJSではGhostDriverという別のWebDriverを使っているようです。

https://github.com/detro/ghostdriver/issues/20

これが問題のIssueです。皆さんから切望されていますが、まだ実装されていないようです。しかし、workaroundが記載されていました。埋め込みJavaScriptでなんとかすることができるようです。サンプルを参考に自分でもやってみましたが、うまく行きました。

コードを貼り付けておきます。

describe('alert test spec', function() {
  var ALERT_HANDLER = '(function () { var lastAlert = null; window.alert = function (message) { lastAlert = message; }; window.confirm = function(message) { lastAlert = message; return true; }; window.getLastAlert = function () { var result = lastAlert; lastAlert = null; return result; }; }());';
  var ALERT_GETTER = 'return window.getLastAlert && window.getLastAlert();';

  it('should get register page', function() {
    browser.get('alerttest.html');
    browser.executeScript(ALERT_HANDLER);
    element(by.id('thebutton')).click();
  expect(browser.executeScript(ALERT_GETTER)).toContain('Hello');
  });
});

dismiss()相当を実現するのはちょっと工夫すればできそうです。accept()/dismiss()でタイミング制御をすることは難しそうです。

過去にKarma(Testacular)を使ったことはありますが、今回やっと時代に追いついてProtractorを使ってみました。特にPhantomJSを使ってheadlessでE2Eテストするときに気づいたことをまとめます。

Protractorは、 Seleniumの WebDriverJSのラッパーで、AngularJSのE2Eテストのためのフレームワークです。

https://docs.angularjs.org/guide/e2e-testing

がエントリーポイントになるでしょう。 しかし、これだけ読んでも最終的な実行方法は分かりづらいです。 今回の目的は、コマンド一つ、例えば、

$ npm run e2e-test

でE2Eテストを実行してするための環境セットを作ることです。また、headlessで動かしたかったので、典型的に使われるChromeではなく、PhantomJSを前提にしました。サーバはExpress/Node.jsの想定ですが、それ以外の場合にも応用できるかと思います。

初めによくある環境設定です。

$ npm install protractor
$ npm install phantomjs
$ ./node_modules/.bin/webdriver-manager update

この例ではローカルディレクトリにモジュールをインストールしていますが。グローバルにインストールしたい人はそのようにどうぞ。

まず初めにはまったことはwebdriverが起動しないことでした。

$ ./node_modules/.bin/webdriver-manager start
INFO - Launching a standalone server
WARN - null
java.net.SocketException: No such device
    at java.net.NetworkInterface.isLoopback0(Native Method)

このようなエラーがでました。ワーニングかと思って無視していたらいけませんでした。どうやら、IPv6のアドレスのみを使っていてうまく行かないようだったので、Javaのオプションを追加して次のようにするとうまく行くことが分かりました。

$ env _JAVA_OPTIONS=-Djava.net.preferIPv4Stack=true ./node_modules/.bin/webdriver-manager start

さて、Protractorのチュートリアルには、webdriverをコマンドラインで手動で実行するように書いてありますが、個人的にはこれは面倒に感じます。時間はかかりますが、毎回自動で起動して欲しいです。これは簡単で、protractor.conf.jsにseleniumAddressを書かなければよいだけでした。下記に、protractor.confを載せます。

exports.config = {
  specs: [
    '*-spec.js'
  ],
  capabilities: {
    'browserName': 'phantomjs',
    'phantomjs.binary.path': './node_modules/.bin/phantomjs'
  },
  baseUrl: 'http://localhost:' + (process.env.PORT || 3000) + '/'
};

これだけで大丈夫でした。baseUrlは、specにURLをフルパスで書かなくてもよいようにするためで、expressが下記のように起動されている想定です。

app.listen(process.env.PORT || 3000);

specの細かい内容は今回は書きませんが、もっとも単純なものは例えば次のようになります。

describe('tutorial', function() {
  it('should have a title', function() {
    browser.get('index.html');
    expect(browser.getTitle()).toEqual('The Title');
  });
});

ところで、Protractorはテストのフレームワークであるもののアプリの起動には関与せず、アプリは自分で起動しなければいけません。また、テスト終了後はアプリも終了したいです。今回はお手軽にシェルスクリプトを書きました。

#!/bin/sh

export _JAVA_OPTIONS=-Djava.net.preferIPv4Stack=true
export PORT=12345
node ./app.js &
PID=$!
./node_modules/.bin/protractor ./e2e-test/protractor.conf.js
kill $PID

このスクリプトをpackage.jsonのscriptsに書いておけば、当初の目的であったnpmで一発でE2Eテストを走らせることができました。

Happy e2e testing!

Famo.us Physicsで3Dの簡単なサンプル

  • 投稿日:
  • by

もうちょっとすばやくサンプルを作ってみるつもりがのんびりしてしまいました。

前回に引き続き、famo.us Physicsを使ったサンプルです。

3次元の物理演算もできるはずなので、Z軸も使った簡単なサンプルが作れないかと思ってやってみました。

こちら

当初、普通に回したらsurfaceの裏は真っ白で、180度回ると何も見えなくなってしまいました。そこで、仕方なく、各円を反対方向に回すことで表示しました。もっといい方法があればいいのですが。

また、遠くのsurfaceを縮小表示する方法が分かりませんでした。これができればだいぶ立体感がでると思うのですが。physicsとtransformを混ぜて使ってはいけないのかもしれません。

Famo.us Universityのphysicsコースは未だcoming soonのままです。

今回のサンプルのソースコードはこちらです。