読者です 読者をやめる 読者になる 読者になる

ひ孫

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

ReactでautoKanaみたいなことやるやつ作った

まだまだβな感じだけどあらかた出来たので晒していく。

できたもの

React以外では試していないが、おそらくcoreとして独立させたhistorykana方は他の2way-bindingなフレームワークでも使える気がする。

作った動機

  • この記事で紹介されているような自動カナ入力を、Reactでやりたいと思った。
  • 頑張ればjquery.autokanaを使うことも出来そうかなとも後で思ったけど、割りと最終手段感がある。
  • autokana, autoruby共にモバイル時代のものではないので、スマホの入力に耐えられるものではなさそうだった。

使い方

Readmeにざっくりソースは書いたが、重要な所を抜粋するとこんな感じ

var Example = React.createClass({
  onUpdateKana(data){
    this.setState({
      kana : data.kana
    })
  },
  render(){
    return (
      <div>
        <div>
          <AutoKana onUpdate={this.onUpdateKana} />
          <input value={this.state.kana} />
        </div>
      </div>
    )
  }
})
  • AutoKanaのモジュールの中身はInput。ただしそのinput自体はカナの変換元(例えば漢字の名前)が入力される想定
    • 正直ここのあたりは若干悩んだ。AutoKanaといいつつカナを入力するフィールドがあるわけではないんだよなあという。
    • 結果、カナが入力されるようなinputフィールドまでAutoKana側で持ってしまうと若干重い気がしたのでカナ自体は外で受け取る形にした。
  • <AutoKana>がカナを特定した際にonUpdateが発火され、kanaというプロパティでカナ入力を受け取れる仕組み。あとは外でお好きにという感じ。
  • 今のところカタカナにするオプションはつけていない
    • japaneseモジュールを使えば簡易にカタカナに変換できる。

以下おまけ

historykana(coreライブラリ)でやっていること

今回実装する上で、下記の思想にもとづいて実装を考えた

  • Reactであれば、全ての連続的な入力が取得できる。
  • 入力履歴を全て追っかければふりがなが抽出できるはず。
    • 全てといっても前提としてそんなにふりがなとして組み立てる文字数は長くないはず(履歴といってもたかが知れているはず)

なのでcoreライブラリは、 入力履歴をもらってふりがなを抽出する。 というシンプルな仕組みにしている 当然これは元祖のautoKanaやautoRubyとはだいぶ違っているし、富豪的なプログラミングの仕方をしている。

だいたいの処理の流れ

下記のような感じで入力の履歴をバババッととっていく。

["", "あ", "あk", "あか", "赤", "赤あ", "赤あお", "赤青", "赤k青", "赤き青", "赤きい青", "赤きいr青", "赤きいろ青", "赤黄色青"]

これをなんやかんやして、各漢字の変換の区切り位置を抽出する。 だいたいこんな感じ

[ [ '赤', 'あか', 'あk', 'あ', '' ],
  [ '黄色', 'きいろ', 'きいr', 'きい', 'き', 'k' ],
  [ '青', 'あお', 'あ' ] ]

ここから各要素のひらがなで一番最新のを抽出すると、こうなる

あかきいろあお

やった!ひらがなが取り出せた!こんな感じ。

Google IMEなどでは「よしお」などの変換候補の中に「よしを」があったりする部分など、細かい問題はなるべくはうまいこと補正をかけたりしている。 作成途中にそれなりにパターンは試したのでそれほどおかしな挙動はしない・・・はず・・・

学びとか感想とか

  • Reactのテストは思ったよりスマートでもなかった。けどできるのはやっぱ良い。
  • Reactのパッケージ、そのままjsxで配布している形にしているけどあっているのか割りと不安。
  • 日本語入力、世界で多分このモジュールが必要なの日本語だけ?なので情報が当然無い。
  • しかし意外と日本語関連のモジュールはnpmで充実していたりする。

turbolinksのdata属性がjquery.onだと受け取れない件

turbolinksのpage:fetchなど、ソースを見るとdata属性として次のurlを出しているのだけど、jqueryだとこれが取れなくて軽くはまった

$(document).on("page:fetch", function(e){
  console.log(e.data) // undefined
})
document.addEventListener("page:fetch", function(e){
  console.log(e.data) // Object
})

なんだろうこれと思ったけどoriginalEventからとれた

$(document).on("page:fetch", function(e){
  console.log(e.originalEvent.data)
})

そういえばそんなんありましたねjqueryさん

browserifyの使い方がちょっとだけわかった

モジュール管理として勢いのあるbrowserify。 なんとなくコマンドを走らせて見るとそれっぽいjsが出てくるのはわかってたけどどうするもんなのかいまいちわかってなかったけどちょっとだけわかったのでメモ

例としてhttps://www.npmjs.org/package/bizzfuzzを使ってfizzbuzzしたいとしてみたとき

$ npm install bizzfuzz
$ browserify node_modules/bizzfuzz/index.js > browserify.js

とか今までしてchromeのコンソールから読んでみてもうまくいかないなあ・・・とかやっていた。

で、どうやらnpmモジュールを直接呼んでいるのがそもそも根本的に勘違いしていそうだと気づいた。

ここから先あっているかちょっと不安だが、ひとまず lib/main.js みたいなものを用意して

var Bizzfuzz = require('buzzfizz')
window.Bizzfuzz = Bizzfuzz
$ browserify lib/main.js > browserify.js

というようにbrowserifyがエンドポイントとして読むファイルで一旦windowに対して外部公開するようなことをすればとりあえずはアクセスできるらしい。 (((本来はすべてのjsコードがmain.jsをエンドポイントとして、外出しすることなんて考えないんだろう。今回はとりあえずどんな動きさせるとよいか知りたかったけど本来はやらないほうがいいのかも)))

requireフラグなどまだ見ていないのでもしかしたらそっちを使えばこんなことせんでもいいのかもしれないけどここから先は要調査

travis-ci + node 0.8のテストが出来なかった時の話

travis-ciをnode用のテストに使っていたらこんな感じのエラーが出てしまったのでメモ。

npm ERR! Error: No compatible version found: require@'^0.5.0'
npm ERR! Valid install targets:
npm ERR! ["0.3.1","0.3.2","0.4.0","0.4.2","0.4.4","0.4.5","0.4.6","0.4.8","0.4.9","0.5.0"]
npm ERR!     at installTargetsError (/home/travis/.nvm/v0.8.26/lib/node_modules/npm/lib/cache.js:719:10)
npm ERR!     at /home/travis/.nvm/v0.8.26/lib/node_modules/npm/lib/cache.js:641:10
npm ERR!     at saved (/home/travis/.nvm/v0.8.26/lib/node_modules/npm/node_modules/npm-registry-client/lib/get.js:138:7)
npm ERR!     at Object.oncomplete (fs.js:297:15)
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>

どうも最新のnpmでは npm install --save を使うとバージョン指定が^という新しい記法で書かれる模様。 更にプラスでtravis-ci + node0.8のnpmバージョンが古くてうまく解決してくれないっぽい。

他の人のリポジトリみたらこんな感じで指定してやると良いっぽい事がわかった。

language: node_js
node_js:
  - 0.8
  - 0.9
  - 0.10
before_install:
  - npm install -g npm@~1.4.6

うーむ、before_installなんてあったのか・・・

gruntのbeep音を止めたかった話

最近gruntからgulpに行こうかなー。おっ、broccoliなんてあんのか!

なんてことをしている時にそういえば昔gruntでbeep音鳴るのうっとおしいなーと思っていたのを思い出した。 開発をwinで最近やらなくなったけどせっかく見つけたのでまとめておく。

解決方法

https://github.com/gruntjs/grunt/issues/808

var oldout = process.stdout.write;
process.stdout.write = function(msg) {
  oldout.call(this, msg.replace('\x07', ''));
};

stdoutをグワッと変えてやればいいよって事っぽい。 後述しますが次期grunt v1.0ではもうちょっとなんとかなるようになる予定らしいです。

思い出編

まずうるさいな~と思ってissueを覗くと 同じことを思っている人がissueを出していた。

この人はデフォルトで音ならないようにすることを考えていたみたいだったけど突っぱねられていた。

じゃあ逆にデフォルトは変えなくてもいいからno-beepオプションつけてよと思ったので自分でもissueを投げてみた。

まあけどやっぱりやりたくないみたいでno-colorオプションつけるかてめーのマシンのbeep止めろっていう割りと元も子もないこと言われる結果になった。

で、最近になってあれどうなったんだろうと覗いて見たらやっぱり似たようなリクエストがつっぱねられていた

そもそもcolorオプションにbeepが混ざってること自体に割りと自分は違和感あるんだけどまあgruntチームとしてはもうそこは黒歴史だから触りたくねーよってことっぽい?

https://github.com/gruntjs/grunt/issues/808#issuecomment-20922408 このコメントを見るとgrunt-nextで何らかの形で対応予定っぽいのでそこに期待

vagrantにpingが通らなくてハマった話

vagrant環境がぶっこわれたので別リポジトリに作っていたがどうにも動かなくなってハマったので備忘録。

現象としてはvagrant ssh で中に入れることはできるんだけど何故かpingが通らないという感じ。

色々やってみるとconfig.vm.networkを変えれば動くみたいだった。

  # config.vm.network :private_network, ip: "33.33.33.10"
  config.vm.network :private_network, ip: "33.33.32.10"

単純に古いvagrantとぶつかっていた模様 *1

もう少し探っているとどうもvirtualbox側の設定を一回消してやればいいらしいことがわかった。

環境設定 -> ネットワーク とたどり ホストオンリーネットワークとしてvboxnet0とかがある。 これを一回消してもう一度vagrant upすることで解消された。

めでたしめでたし

*1:とはいっても古い方をdestroyしたり~/.vagrantファイルを消したりもしたが効果はなかった

scala specs2のbeforeではまった話。

scalaのspecで事前処理がしたくなったのでBeforeExampleを使おうと下記のようなテストを書いてみた。

class SampleExampleSpec extends Specification with BeforeExample{
  def before = {
    println("bef")
    println("for")
  }

  "foo" should {
    "baa" in {
      println("baa")
      1 must_== 1
    }
    "baz" in {
      println("baz")
      1 must_== 1
    }
  }
}

予想では bef -> for -> baa -> bef -> for -> baz となるだろうなと思っていたが結果は

bef
for
bef
for
baa
baz

beforeが先に二回実行されている・・・・?

散々悩んだが下記の様な記事にぶち当たった http://stackoverflow.com/questions/8026866/parallel-execution-of-tests

なるほど。scala specsは並列に実行されるのがデフォルトになっていると。 解除するには

sequential

をつければいいらしい。

うーん、だいぶはまってしまった。