gist

2012年4月30日月曜日

Node.jsでメール送信

weaverさんのnode-mailは、Node.jsでメール送信できるようにするパッケージです。テキストオンリーっぽい。

$ npm install mail

mail = require('mail').Mail({
 host: 'smtp.gmail.com'
 ,username: 'Gmailのアドレス'
 ,password: 'パスワード'
})

mail.message({
 from: '差出人のメールアドレス'
 ,to: ['宛先のメールアドレス']
 ,subject: 'Hello!'
}).body('このメッセージはNodeから送られました').send (err) ->
 throw err if err
 console.log 'Sended!'

実行結果

シンプルですので、テキストメールの送信だけであれば、こちらが便利そうです。

2012年4月28日土曜日

Node.jsで顔認識してみよう

node-opencvを使うとNodeでも画像から顔認識ができます。

brewを使ってOpenCVをインストールしてから、npmでnode-opencvをインストールします。Make時にMono.frameworkが悪さをするので一旦待避。 あとカスケードファイルもコピー。

$ sudo mv /Library/Frameworks/Mono.framework /tmp
$ brew -v install --build32 opencv
$ mv /tmp/Mono.framework /Library/Frameworks/
$ npm install opencv
$ cp ../../../node_modules/opencv/data/haarcascade_frontalface_alt.xml .

以下のようにコードを書きます。

cv = require("opencv")
cv.readImage "./faces.png", (err, im) ->
  im.detectObject "./haarcascade_frontalface_alt.xml", {}, (err, faces) ->
    i = 0

    while i < faces.length
      x = faces[i]
      im.ellipse x.x + x.width / 2, x.y + x.height / 2, x.width / 2, x.height / 2
      i++
    im.save "./out.jpg"

適当に顔画像を用意します。

実行。

$ coffee sample.coffee

out.pngができているので見てみると

な感じに。若干ズレているところもありますが、Webと組み合わせると面白そうです。

2012年4月26日木曜日

これからCoffeeScriptでNode.jsする人にオススメのパッケージ「Express Coffee Template 1.2」

Express Coffee Templateは、ExpressJSのCoffeeSciprt版です。

$ git clone http://github.com/twilson63/express-coffee.git express_coffee_sampleCloning into express_coffee_sample
$ cd express_coffee_sample/
$ npm install

本家よりも多くのパッケージがインストールされます。早速起動してみます。

$ node server.js
Listening...

ブラウザで http://localhost:3000/ にアクセスします。

本家と見た目がずいぶん異なります。

本家ExpressJSと何が違うのか?

  • スタイルシートにStylusを使っている
  • スタイルシートのデフォルトテンプレートにResponsive Gridを使っている
  • connect-assetsを使っている

加えて、エントリポイントのserver.js以外、CoffeeScriptで書かれている点が違います。

$ tree .
.
├── app.coffee
├── assets
│   ├── css
│   │   └── app.styl
│   └── js
│       └── app.coffee
├── node_modules/
├── package.json
├── public
│   └── favicon.ico
├── server.js
└── views
    ├── index.jade
    └── layout.jade

assetsとresponsive gredを使っていることで、views/index.jadeが大きく変わっています。

以下はその一部

.container
  .four.columns
    div.
      <a href="http://www.flickr.com/photos/astrapica/2560897976/" title="Uk express... by astrapi, on Flickr"><img src="http://farm4.staticflickr.com/3049/2560897976_48257593b7.jpg" width="100%" height="120px" alt="Uk express..."></a>
    a.button(href="https://github.com/twilson63/express-coffee/zipball/v1.2.1") Download
    &nbsp;
    a.button(href="https://github.com/twilson63/express-coffee") Source
    :markdown
      ### About

      This template was built to make it very easy to get up and going on small little prototypes and weekend projects.

      ### Contact Us

      Have questions, or would like to contribute?

      * [Post an Issue](https://github.com/twilson63/express-coffee/issues)
      * [Submit a pull request](https://github.com/twilson63/express-coffee)
      * Follow Us on twitter! [@jackhq](http://twitter.com/jackhq)

これは画面で言えば以下の部分になります。

markdownを上手く使ってResponsive Gridと組み合わせています。

ヘッダの部分を見てみます。views/layout.jadeです。

!!! 5
//if lt IE 7 ]><html class="ie ie6" lang="en">
//if IE 7 ]><html class="ie ie7" lang="en">
//if IE 8 ]><html class="ie ie8" lang="en">
// [if (gte IE 9)|!(IE)]><!--><html lang="en"> <!--<![endif]
head
  meta(charset='utf-8')
  title Express CoffeeScript  Template
  meta(name='description', content='')
  meta(name='author', content='')
  // Mobile Specific
  meta(name="viewport", content="width=device-width, initial-scale=1.0")

  // CSS
  != css("http://wilbur.io.s3.amazonaws.com/all.css")
  != css('app')
  
body
  != body

  != js('http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js')
  != js('app')

| </html>

「!= css」「!= js」がAssetsの機能です。シンプルになっているのが分かります。

で、本命の app.coffee を見てみます。


express = require 'express'
stylus = require 'stylus'
assets = require 'connect-assets'

app = express.createServer()
app.use assets()
app.set 'view engine', 'jade'

app.get '/', (req, resp) -> resp.render 'index'

app.listen process.env.VMC_APP_PORT or 3000, -> console.log 'Listening...'

本家ExpressJSと比較して、設定がほとんど省略されています。必要に応じて追加して行きましょう。

ExpressJSをやっていて、そろそろCoffeeScriptでもやってみようかな、と思っている方にはちょうどいいパッケージ。

2012年4月25日水曜日

コードリーディングにDoccoを使うと捗るかもしれない件

Doccoは、CoffeeScriptにコメントをつけてドキュメントを出力できるパッケージです。コードとコメントを左右に表示されるスタイルです。コメントにはMarkdownが使えます。

インストール

インストールはnpm。追加でPygmentsが必要です。

$ npm install -g docco
$ sudo easy_install Pygments

使い方

先日のエントリーで紹介したブログアプリCoffee-Boxを例にコメントを書くとこうなります。

(CoffeeBoxの紹介は 『Node.js「脱」初心者!CoffeeBoxでブログの作り方を学ぼう!』を参照してください)

# ***server.coffee*** は、Coffee-Boxのエントリーポイントです。
# [express](http://expressjs.com/)を読み込みます。
express = require 'express'
# Webサーバを生成します。
app = module.exports = express.createServer()

# config/configを読み込みます。
require('./config/config') app
# config/routesを読み込みます。
require('./config/routes') app

# Webサーバを起動します。
app.listen 3000

# サーバが起動したことを出力します。
console.log "coffee-box server listening on port #{app.address().port} " +
  "in #{app.settings.env} mode"

ドキュメントを出力してみます。docsディレクトリが必要なので作成します。

$ mkdir docs
$ docco server.coffee 
docco: server.coffee -> docs/server.html

左側にコメントに書いた内容が、右側にコードが表示されます。比較しながら読める点が新鮮です。

少し本格的にCoffeeBoxのconfig/config.coffeeにコメントを書いていきます。

# **config.coffee**では、[Coffee-Box](https://github.com/qiao/coffee-box)のWebサーバを設定します。

# [express](http://expressjs.com/)を読み込みます。
express      = require 'express'
# [connect-assets](https://github.com/TrevorBurnham/connect-assets)を読み込みます。
assets       = require 'connect-assets'
# [mongoose](https://github.com/LearnBoost/mongoose)を読み込みます。
mongoose     = require 'mongoose'
# lib/require_dirを読み込んで、オブジェクトとして保持します。
{requireDir} = require '../lib/require_dir'

# ```ROOT_DIR```を読み込みます。  
# ```#{hoge}```は、CoffeeScriptの String Interpolation(文字列挿入)です。  
# ```__dirname```は、Nodeが起動したディレクトリパスを示す定数です。 
ROOT_DIR = "#{__dirname}/.."

# Webサーバを設定します。
#
# 第1引数にexpressのWebサーバappを指定します。
module.exports = (app) ->
  app.configure ->
    # アプリケーションのversionを設定します。versionの情報は、[package.json](../package.json)に記述します。
    app.set 'version', require("#{ROOT_DIR}/package.json").version
    # [site.json](../config/site.json)に記述されたkeyとvalueをすべて設定します。  
    # CoffeeSciprtの for ... of 構文です。  
    # 例えば sitename というkeyに、**Name of your site**というvalueがappに設定されます。  
    app.set k, v for k, v of require("#{ROOT_DIR}/config/site.json")
    # libディレクトリをutilsとして設定します。
    app.set 'utils', requireDir("#{ROOT_DIR}/lib")
    # app/helpersディレクトリをhelpersとして設定します。
    app.set 'helpers', requireDir("#{ROOT_DIR}/app/helpers")
    # app/modelsディレクトリをmodelsとして設定します。
    app.set 'models', requireDir("#{ROOT_DIR}/app/models")
    # app/controllersディレクトリをcontrollersGetterとして設定します。
    app.set 'controllersGetter', requireDir("#{ROOT_DIR}/app/controllers")
    # expressのviewsディレクトリをapp/viewsに設定します。
    app.set 'views', "#{ROOT_DIR}/app/views"
    # テンプレートエンジンを[jade](http://jade-lang.com/)に設定します。
    app.set 'view engine', 'jade'
    # ビューのオプションとして、layoutを設定します。
    app.set 'view options', layout: "#{ROOT_DIR}/app/views/layouts/layout"
    # expressのloggerを使います。  
    # **loggerはミドルウェアで一番最初に設定すること**
    app.use express.logger('dev')
    # リクエストの```req.body```を読み込めるように設定します。
    app.use express.bodyParser()
    # HTTPのPUTやDELETEなどのメソッドをオーバライドできるように設定します。  
    # **この設定はbodyParserの前にすること**
    app.use express.methodOverride()
    # cookieを使えるようにします。
    app.use express.cookieParser()
    # sessionを設定します。  
    # secretキーに```settings.secretKey```を設定します。
    app.use express.session(secret: app.settings.secretKey)
    # [connect-assets](https://github.com/TrevorBurnham/connect-assets)を使います。
    app.use assets(src: 'app/assets', build: true, detectChanges: false, buildDir: false)
    # staticディレクトリをpublicに設定します。  
    # このディレクトリにはJavascript, CSS, HTMLなどの静的ファイルを格納します。
    app.use express.static("#{ROOT_DIR}/public")
    # routerを設定します。  
    # app.routerは、[server.coffee](server.html)で設定されています。
    app.use app.router
    # helpersを設定します。  
    # helpersはさっき設定しました。
    app.helpers app.settings.helpers
    # [express-messages](https://github.com/visionmedia/express-messages) をダイナミックヘルパに設定します。
    app.dynamicHelpers messages: require('express-messages')
    # session をダイナミックヘルパに設定します。 
    app.dynamicHelpers session: (req, res) -> req.session

  # 開発用の設定を指定します。
  app.configure 'development', ->
    app.use express.errorHandler(dumpException: true, showStack: true)

  # 製品用の設定を指定します。
  app.configure 'production', ->
    app.use express.errorHandler()

  # MongoDbに接続します。    
  # 接続先は```app.settings.dbpath```です。  
  # errが発生した場合、コンソールにエラー出力し、Coffee-Boxを終了します。
  mongoose.connect app.settings.dbpath, (err) ->
    if err
      console.error err
      process.exit()

これを出力した結果が以下の画像です。

Doccoはコードリーディングに最適

Doccoは、左右にドキュメントとコードを並べるスタイルが最大の特徴です。「何をしているかをコードと比較できる」点でコードを理解しやすいと感じます。リーディングしながらコメントを書いていき出力を繰り返すと、「どこまで自分が理解しているか」という進捗にもDoccoが使えます。また、Markdown形式でリンクや強調などの表現もできるので「着目している点や参考にしたリンク」も加筆できます。キレイなドキュメントで出力されるのでモチベーションも保てそうです。お試しあれ。

2012年4月24日火曜日

pongで遊ぶ。

pong は、コンソールでPongできるお遊びパッケージです。

npmの説明には、

Description: Pong in your terminal. Why not?

何か文句ある?みたいに書かれております。

$ npm install -g pong

グローバルインストールをおすすめします。

pongで起動。

$ pong

Pongが起動します。

プレイヤーは左側。右側がCPUです。プレイヤーはWで上、Sで下にバーを動かせます。シフトを押しながらW,Sを押すと早く動きます。

なんだろうな。作った人がすごいのはわかるけど、一瞬虚しさが込み上げて参ります。

2012年4月23日月曜日

SublimeText2でMarkdownをプレビューするプラグイン

sublime-markdown-previewは、SublimeText2でMarkdownをプレビューできるようになるプラグインです。

このプラグインは、sublime package manager 経由でインストールします。



Sublime Package Manager インストール

まず、Sublime Package Managerのインストールから。

SublimeText2 を起動して、[Sublime Text 2]>[Preferences]>[Browse Packages]へ進みます。

Finderが起動するので、Installed Packages という名前で新しいフォルダを作成します。

ダウンロードしたPackage Control.sublime-packageInstalled Packagesにコピーします。

次に、SublimeText2でControl+` でコマンドライン入力を表示させます。

以下をコピーして、コマンドラインにペースト、Enter。

import urllib2,os; pf='Package Control.sublime-package'; ipp=sublime.installedpackagespath(); os.makedirs(ipp) if not os.path.exists(ipp) else None; urllib2.installopener(urllib2.buildopener(urllib2.ProxyHandler())); open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read()); print 'Please restart Sublime Text to finish installation'

SublimeText2を再起動します。

確認してみます。

[Sublime Text 2]>[Preferences]>[Package Control] で以下の画面が表示されたら インストール成功です。



sublime-markdown-preview のインストール

いよいよ、Sublime Text 2 MarkDown Previewのインストールです。

sublime package managerでインストールします。

Command+Shift+PでSublime Package Managerを起動し、Package Control: Install Packageを選択します。

インストールできるパッケージの一覧が表示されます。

Markdown Previewを選択します。

ネット経由でダウンロードとインストールが始まります。(ステータスバー)

しばらくするとインストールが完了します。(ステータスバー)

キーバインドを追加します。

[Sublime Text 2]>[Preferences]>[Key Bindings -User]を選択します。

以下のように書き換えます。

[ { "keys": ["alt+m"], "command": "markdown_preview", "args": {"target": "browser"} }]

これでインストールと設定が完了です。

Alt+mでMarkdownをプレビューしてみます。

ブラウザが起動し、プレビューできます。



Markdown記法で

Markdownは、プログラマには必須スキルかもしれません。テキスト形式でバージョン管理でき、レビューもしやすいです。仕様やメモ書きにもってこいです。スタイルもクールです。WordやExcelの仕様書とはおさらばして、Markdownで書きたいですね。

2012年4月22日日曜日

node-validatorを使ってみた

node-validatorは、入力値の検証(バリデーション)と無害化(サニタイズ)をしてくれるパッケージです。

$ npm install validator

node-validatorには、大きくcheckとsanitizeの機能があります。

check(検証)

check.coffee

check = require('validator').check

check('abc').isInt()

実行すると Invalid integer 例外が発生します。

$ coffee check.coffee 
Error: Invalid integer
    at [object Object].error (/Users/inouetomoyuki/node_modules/validator/lib/validator.js:7:11)
    at [object Object].isInt (/Users/inouetomoyuki/node_modules/validator/lib/validator.js:29:33)
    at Object.<anonymous> (/Users/inouetomoyuki/Projects/node/validator_sample/check.coffee:6:16)
    at Object.<anonymous> (/Users/inouetomoyuki/Projects/node/validator_sample/check.coffee:8:4)
    at Module._compile (module.js:441:26)
    at Object.run (/usr/local/lib/coffee-script/lib/coffee-script/coffee-script.js:73:25)
    at /usr/local/lib/coffee-script/lib/coffee-script/command.js:147:29
    at /usr/local/lib/coffee-script/lib/coffee-script/command.js:122:18
    at [object Object].<anonymous> (fs.js:115:5)
    at [object Object].emit (events.js:64:17)

try-catchで囲ってやります。

check.coffee

check = require('validator').check

try
    check('abc').isInt()
catch e
    console.log(e.message)
$ coffee check.coffee 
Invalid integer

エラーメッセージに変更するには、checkメソッドの第2引数に文字列を追加します。

check.coffee

check = require('validator').check

try
    check('abc', '整数を入力して下さい').isInt()
catch e
    console.log(e.message)
$ coffee check.coffee 
整数を入力して下さい

検証する内容をチェーンすることができます。

check.coffee

check = require('validator').check

try
    check('123', '4文字から12文字の整数を入力して下さい').len(4,12).isInt()
catch e
    console.log(e.message)
$ coffee check.coffee 
4文字から12文字の整数を入力して下さい

複数のエラーがあった場合、エラーの内容をまとめて取得したいことが多いです。Validatorクラスにちょっとだけメソッドを追加します。

check.coffee

Validator = require('validator').Validator

Validator.prototype.error = (msg) ->
    this._errors.push msg

Validator.prototype.getErrors = () ->
    return this._errors

validator = new Validator()

validator.check('hello', '10文字から30文字の文字列を入力して下さい').len(10,30)
validator.check('1234', '5桁以上の整数を入力してください').isInt().len(5,30)
validator.check('1234-5678', '正しいクレジットカード番号を入力して下さい').isCreditCard()
validator.check('test', '正しいメールアドレスを入力して下さい').isEmail()

errors = validator.getErrors()

console.log(errors)
$ coffee check.coffee 
[ '10文字から30文字の文字列を入力して下さい',
  '5桁以上の整数を入力してください',
  '正しいクレジットカード番号を入力して下さい',
  '正しいメールアドレスを入力して下さい' ]

クレジットカード番号は、Visa、MasterCard、American Express、Discover、Diners Club、JCBカードのフォーマットに対応しているとのことです。

checkでは、以下の検証ができます。

is()                //regex()のエイリアス
not()               //notRegex()のエイリアス
isEmail()           //メールアドレス
isUrl()         //http, https, ftpのURL
isIP()              //IPアドレス
isAlpha()           //英字
isAlphanumeric()    //英数字
isNumeric()     //数字
isInt()         //整数。0パディングはエラー。
isLowercase()       //小文字
isUppercase()       //大文字
isDecimal()     //数字
isFloat()           //isDecimal()のエイリアス
notNull()           //Nullでない
isNull()            //Null
notEmpty()          //空でないこと。ホワイトスペースだけもエラー。
equals(equals)  //等しい
contains(str)       //含む
notContains(str)    //含まない
regex(pattern, modifiers)   //正規表現にマッチ
notRegex(pattern, modifiers)    //正規表現にマッチしない
len(min, max)   //長さ
isUUID(version)     //UUIDかどうか
isDate()            //日付かどうか。Date.parseで通ること。regex使ったほうがいいかも?
isAfter(date)       //dateより未来であること
isBefore(date)  //dateより過去であること
isIn(options)       //optionsに含まれていること。arrayかstring
notIn(options)  //optionsに含まれていないこと
max(val)            //最大値
min(val)            //最小値
isArray()           //配列であること
isCreditCard()  //クレジットカード番号

sinitize(無害化とフィルター)

XSS攻撃対策として無害化/フィルターは必須の技術です。

sanitize.coffee

sanitize = require('validator').sanitize

int = sanitize('0123').toInt() console.log(int) bool = sanitize('true').toBoolean() console.log(bool) str = sanitize(' \s hello ').trim() console.log(str) str = sanitize('aaaaaaaaab').ltrim('a') console.log(str) str = sanitize('
b
').xss() console.log(str) str = sanitize('<a>').entityDecode() console.log(str)
$ coffee sanitize.coffee 
123
true
 hello
b
<div style="color:5xpression(alert&#40;'XSS2'&#41;);">b</div>
<a>

その他、無害化/フィルターには以下のようなものがあります。

trim(chars)   //ホワイトスペースや改行、タブなどのトリム。指定した文字によるトリム。
ltrim(chars)  //指定した文字で左からトリム
rtrim(chars)  //指定した文字で右からトリム
ifNull(replace)  //nullだったら置き換える
toFloat()  //floatに
toInt()    //intに
toBoolean() //booleanに。文字列長がゼロ。'0', 'false'はfalseになる
toBooleanStrict() // '1','true'以外はfalse
entityDecode()   //HTMLにデコード
entityEncode()   //HTMLをエンコード
xss()  // テキストによるXSS攻撃の無効化
xss(true) //イメージによるXSS攻撃の無効化

2012年4月21日土曜日

CoffeeLintを使ってみた

CoffeeLintは、JsLintのCoffeeScript版で、構文チェックをしてくれます。

$ npm install -g coffeelint

sample.coffee

class MyClass
 print:(msg)->
   console.log msg

Lintしてみます。

$ coffeelint sample.coffee 

  ✗ sample.coffee
     ✗ #2: Line contains inconsistent indentation. Expected 2 got 1.
     ✗ #2: Line contains tab indentation.
     ✗ #3: Line contains inconsistent indentation. Expected 2 got 1.
     ✗ #3: Line contains tab indentation.

✗ Lint! » 4 errors and 0 warnings in 1 file

カラーで表示されます。どうもタブを含んでいるらしいです。

タブをスペースに変更してもう一度。

$ coffeelint sample.coffee 

  ✓ sample.coffee

✓ Ok! » 0 errors and 0 warnings in 1 file

グリーンになりました。

設定ファイルをJSONで指定することで、エラーレベルを決められます。

$ coffeelint -f config.json sample.coffee

サンプルの設定はこんな感じになっています。

{
  "no_tabs" : {
    "level" : "error"
  },

  "no_trailing_whitespace" : {
    "level" : "error"
  },

  "max_line_length" : {
    "value": 80,
    "level" : "error"
  },

  "camel_case_classes" : {
    "level" : "error"
  },

  "indentation" : {
    "value" : 2,
    "level" : "error"
  },

  "no_implicit_braces" : {
    "level" : "ignore"
  },

  "no_trailing_semicolons" : {
    "level" : "error"
  },

  "no_plusplus" : {
    "level" : "ignore"
  },

  "no_throwing_strings" : {
    "level" : "error"
  },

  "cyclomatic_complexity" : {
    "value" : 11,
    "level" : "ignore"
  },

  "line_endings" : {
    "value" : "unix",
    "level" : "ignore"
  },

  "no_implicit_parens" : {
    "level" : "ignore"
  }

}

コードからも使えるようです。(TypeErrorで未確認)

fs = require 'fs'
coffeelint = require 'coffeelint'

source = fs.readFile 'sample.coffee'
config = fs.readFile 'config.json'
errors = coffeelint.lint source, config

console.log errors

errorsに以下のJSONが配列で戻ってきます。OKの場合は空。

JSON形式は以下のとおり。

{
    rule :      'ルール名',
    lineNumber: 'エラーが起こった行番号',
    level:      'エラーのレベル',
    message:    'エラーメッセージ',
    context:    'エラーが起きた原因(オプション)'
}

コード上から使えるのは便利なのですが、僕の場合、TypeErrorでした。今日はこれまで。

$ coffee lint.coffee 
TypeError: Cannot call method 'replace' of undefined
    at Lexer.tokenize (/Users/inouetomoyuki/.nvm/v0.6.14/lib/node_modules/coffeelint/node_modules/coffee-script/lib/coffee-script/lexer.js:24:19)
    at Object.tokens (/Users/inouetomoyuki/.nvm/v0.6.14/lib/node_modules/coffeelint/node_modules/coffee-script/lib/coffee-script/coffee-script.js:58:18)
    at new LexicalLinter (/Users/inouetomoyuki/.nvm/v0.6.14/lib/node_modules/coffeelint/lib/coffeelint.js:249:34)
    at Object.lint (/Users/inouetomoyuki/.nvm/v0.6.14/lib/node_modules/coffeelint/lib/coffeelint.js:488:21)
    at Object.<anonymous> (/Users/inouetomoyuki/Projects/node/coffeelint_sample/lint.coffee:12:23)
    at Object.<anonymous> (/Users/inouetomoyuki/Projects/node/coffeelint_sample/lint.coffee:16:4)
    at Module._compile (module.js:441:26)
    at Object.run (/usr/local/lib/coffee-script/lib/coffee-script/coffee-script.js:73:25)
    at /usr/local/lib/coffee-script/lib/coffee-script/command.js:147:29
    at /usr/local/lib/coffee-script/lib/coffee-script/command.js:122:18

2012年4月20日金曜日

commander.jsを使ってみた。

Commander.jsは、Node.jsのスクリプトへのコマンド引数を上手いことしてくれるパッケージです。(本当に上手いことしてくれます)

$ npm install commander

vocaloid.js

var program = require('commander');

program
 .version('0.0.1')
 .option('-m, --miku', '初音ミクが歌います')
 .option('-r, --rin', '鈴音リンが歌います')
 .option('-l, --len', '鈴音レンが歌います')
 .option('-s, --song [song]', '[song]を歌います', '歌')
 .parse(process.argv);

console.log('ボーカリストを選択:');
if(program.miku) console.log('  - 初音ミクが');
if(program.rin) console.log('  - 鈴音リンが');
if(program.len) console.log('  - 鈴音レンが');
console.log('  - 「%s」を歌った', program.song);

実行してみます。

$ node vocaloid.js -h

  Usage: vocaloid.js [options]

  Options:

    -h, --help         output usage information
    -V, --version      output the version number
    -m, --miku         初音ミクが歌います
    -r, --rin          鈴音リンが歌います
    -l, --len          鈴音レンが歌います
    -s, --song [song]  [song]を歌います

$ node vocaloid.js 
ボーカリストを選択:
  - 「歌」を歌った

$ node vocaloid.js -m
ボーカリストを選択:
  - 初音ミクが
  - 「歌」を歌った

$ node vocaloid.js --miku -s '初音ミクの消失'
ボーカリストを選択:
  - 初音ミクが
  - 「初音ミクの消失」を歌った

とても良くできているパッケージです。よく使われているのもうなずけます。

2012年4月18日水曜日

Macを買ったら、最低限やっておきたいbash_profile。

最近、僕の周囲でMacを買う人が増えてます。

開発者の方が多いですかね。よく「ターミナル、何とかならんか」という質問が増えてきました。

最低限、このくらいのbash_profileを書くと、幸せになれるかもしれません。あとSublimeText2を入れてリンク

PS1="\W $ "

alias ll='ls -l'
alias ..="cd .."
alias la="ls -la"

export CLICOLOR=1
export LSCOLORS=ExGxcxdxCxegedabagacad

function mkdircd() { mkdir -p "$@" && eval cd "\"\$$#\""; }

export PATH=~/bin:$PATH
export EDITOR='s -w'

会社で何も書いていないbash_profileを見ると書いてしまいます。

2012年4月17日火曜日

Sublime Text 2をターミナルから呼び出す

Sublime Text 2は、TexeMate風の軽量テキストエディタです。すっかりデフォルトのエディタとして使うようになりました。

ターミナルから Sublime Text 2を呼び出すように設定してみます。

$ mkdir ~/bin
$ ln -s "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl" ~/bin/s

bash_profileに以下を追加します。

export PATH=~/bin:$PATH
export EDITOR='s -w'

これで s コマンドだけで呼び出せるようになります。

便利。

公式ドキュメントはこちら

2012年4月16日月曜日

MacPortからHomebrewに移行してnodeが動作しない場合の対処法

今日もコツコツ、Nodeネタと思っていたのですが、npmが動作しないという状況に。

$ npm install money
dyld: Library not loaded: /opt/local/lib/libssl.1.0.0.dylib
  Referenced from: /Users/inouetomoyuki/.nvm/v0.6.14/bin/node
  Reason: image not found
Trace/BPT trap: 5

nvmもバージョンの切り替えができない状況に。

$ nvm use v0.6.14
Now using node v0.6.14
$ nvm ls
v0.4.12 v0.6.11 v0.6.12 v0.6.13 v0.6.14
current:    N/A

/opt/local/lib/libssl.1.0.0.dylib が見つかりませんというメッセージから、先日、Ruby on Rails 3.1をインストールしたときにMacPortからHomebrewへ移行した影響と思われます。

対処方法は、Nodeバージョンの削除と再インストール。

$ rm -fr ~/.nvm/v0.6.14
$ nvm install v0.6.14
(インストール)
$ nvm ls
v0.4.12 v0.6.10 v0.6.11 v0.6.12 v0.6.13 v0.6.14
current:    v0.6.14

無事、動作しました。

2012年4月15日日曜日

Ruby on Rails 3.1 をインストールする

前のエントリーで紹介したブログシステム CoffeeBox では、connect-assets というパッケージが使われていました。connect-assets は、複数のcssやjsをコンパイル(?)して数個のまとまったファイルとして提供でき、アクセス数を減らすことができます。Ruby on Rails 3.1 の新機能 Assets Pipeline をリスペクトしているらしいので、実際にRailsをインストールして触ってみようと思います。

しばらく、Ruby on Railsの環境を放っておいたので、インストール環境を含めてクリーンにインストールしてみます。

目標

  • Ruby on Rails 3.1 を起動できる

やること

  1. rvmをアンインストールする
  2. MacPortからHomebrewに移行する
  3. rbenvをインストールする
  4. Ruby, Railsをインストールする
  5. Railsを起動する

rvm をアンインストールする

rvmをアンインストールして、Mac標準のRuby環境に戻します。

$ rvm implode

本当にインストールするか聞かれるので、Yesをタイプ。

次に、bash_profileを修正します。 rvmを初期化している、以下の行を削除します。

[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"  # This loads RVM into a shell session.

削除したらターミナル再起動が、吉。

Rubyのバージョンを確認します。この時点でMac標準のRubyに戻っているはずです。

$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [universal-darwin11.0]
$ which ruby
/usr/bin/ruby

Mac標準のRubyに戻りました。 これでrvmのアンインストールは完了です。

MacPortからHomebrewに移行する

初代 MacBook Air(64GB)の私には、MacPortの容量が重いわけで。この際、Homebrewに移行しようと思います。影響大ですが、背に腹は代えられません。アンインストールします。

MacPortとHomebrewの違いは、Homebrewの導入と使い方 が参考になります。

まず、MacPortをアンインストールします。

$ sudo port -f uninstall installed
$ sudo rm -rf /opt/local \
/Applications/MacPorts \
/Applications/DarwinPorts \
/Library/Tcl/macports1.0 \
/Library/Tcl/darwinports1.0 \
/Library/LaunchDaemons/org.macports.* \
/Library/StartupItems/DarwinPortsStartup \
/Library/Receipts/MacPorts*.pkg \
/Library/Receipts/DarwinPorts*.pkg

さよならMacPort。

続いてHomebrewをインストールします。

$ ruby -e "$(/usr/bin/curl -fksSL https://raw.github.com/mxcl/homebrew/master/Library/Contributions/install_homebrew.rb)"
$ brew -v
0.9

こんにちわ。Homebrew。

rbenvをインストールする

rvmに変わるバージョン管理システムrbenvをインストールします。

$ brew install rbenv
$ brew install ruby-build

bash_profileに以下を追記します。

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

ターミナル再起動。

Ruby, Railsをインストールする

続いてRuby、Railsをインストールしていきます。

Rubyをインストールする

$ brew link readline
$ rbenv install 1.9.3-p0
$ rbenv versions
  1.9.3-p0
$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [universal-darwin11.0]
$ rbenv global 1.9.3-p0
$ rbenv rehash
$ ruby -v
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.3.0]
$ which ruby 
/Users/あなた/.rbenv/shims/ruby

Railsをインストールする

$ gem update --system
$ gem update rake
$ brew install node
$ gem install rails --no-ri --no-rdoc
$ rails -v
Rails 3.2.3
$ which rails
/Users/あなた/.rbenv/shims/rails

Railsアプリ起動

$ rails new HelloRails
$ bundle
$ rails s
=> Booting WEBrick
=> Rails 3.2.3 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server

無事起動しました。

インストールはこれで完了です。

しばらくRailsから離れている間にずいぶんと機能が変わっていますね。肝心のAssets Pipeline機能を試すにはまだ遠いです。

2012年4月12日木曜日

curlコマンドでhttpヘッダを出す

curlコマンドに -i オプションをつけるとヘッダと一緒に出力されます。ちょっとした動作確認に。

$ curl -i http://localhost:4000
HTTP/1.1 200 OK
Content-Type: text/html; charset: UTF-8
Set-Cookie: sid=e17wm5Sqtag43RUC5RDlPAz4FTzJfUrTzAgLE0I6ADIszO0AufaDNrfXluWfBk7HkPaT1f1PZw54I7ND3gei7APEI37UaGiVSCNtMm87RZ1PVY1b9aJ9VT6lBCfzqiYA; path=/; expires=Thu, 26 Apr 2012 14:59:34 GMT
Connection: keep-alive
Transfer-Encoding: chunked

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Geddy App | This app uses Geddy.js</title>
    <meta name="description" content="">
    <meta name="author" content="">

(HTMLの文書)

2012年4月11日水曜日

bootstrapped-socket-express を使ってみた

bootstrapped-socket-express は、express, socket.io, bootstrapを組み合わせたシンプルなアプリの雛形です。テストに mocha が使えます。connect-assetを使ってcssやjqueryをまとめています。CoffeeScriptです。

インストールから起動まで。

$ npm install -g bootstrapped-socket-express
$ bootstrapped new sample_app
Success!
Next, you should:
    cd sample_app
    sudo npm install
And to start your app:
    node server.js
$ cd sample_app
$ npm install
$ node server.js
   info  - socket.io started
Listening on port 3000

起動したら、http://localhost:3000 にブラウザからアクセスしてみます。

bootstrapらしい画面が表示されました。

ちょっと構造を見ていきます。

.
├── app.coffee
├── assets
│   ├── css
│   │   ├── bootstrap-responsive.css
│   │   └── bootstrap.css
│   ├── img
│   │   ├── glyphicons-halflings-white.png
│   │   └── glyphicons-halflings.png
│   └── js
│       ├── bootstrap.js
│       ├── jquery.js
│       └── socket_handlers.coffee
├── node_modules/
├── package.json
├── public
│   └── favicon.ico
├── routes
│   └── index.coffee
├── server.js
├── test
│   └── test_sample.coffee
└── views
    ├── index.jade
    └── layout.jade

server.jsがエントリーポイントで、サーバ設定から起動まではapp.coffeeに書かれています。assets内にcss, img, jsがまとまっています。routes(ルータ)と views、test があります。modelやcontrollerはありません。

インストールされたパッケージを見ていきます。

$ npm ls
YOUR_APP_NAME@0.0.1 
├── coffee-script@1.2.0 
├─┬ connect-assets@2.1.9 
├─┬ express@2.5.9 
├─┬ jade@0.22.1 
├─┬ mocha@1.0.1 
├── should@0.6.1 
├─┬ socket.io@0.9.5 
└─┬ stylus@0.25.0 

基本のCoffeeScript、テストフレームワークのshouldとmocha。スタイルシートのstylus、socket.ioが見えます。テンプレートはjadeですね。connect-assets で Rails 3.1 の asset pipeline を実現しています。

app.coffeeを見ていきます。

express = require 'express'
stylus = require 'stylus'
routes = require './routes'
socketio = require 'socket.io'

app = express.createServer()
io = socketio.listen(app)

app.use express.logger {format: ':method :url :status :response-time ms'}
app.use require("connect-assets")()
app.set 'view engine', 'jade'
app.use express.static(__dirname + '/public')

# Routes
app.get '/', routes.index

# Socket.IO
io.sockets.on 'connection', (socket) ->
  socket.emit 'hello',
    hello: 'says server'

port = process.env.PORT or 3000
app.listen port, -> console.log "Listening on port " + port

express, stylus, socket.ioをrequireしています。ルータは routes にあります。テンプレートエンジンにJadeを指定しています。connect-assetsを指定しています。ExpressJSの書き方です。

routes/index.coffeeを見てみます。

exports.index = (req, res) -> res.render 'index'

ExpressJSの書き方です。

bootstrapped-socket-expressはフレームワークというよりは、アプリの雛形的なパッケージです。メジャーなパッケージである、ExpressJS、socket.io、Bootstrap、connect-assets、mochaをCoffeeSciprtで使うために組み合わせたパッケージです。ちょっとしたアプリを、シンプルにCoffeeScriptで始めたい場合にいいかもしれません。

2012年4月10日火曜日

Node.js「脱」初心者!CoffeeBoxでブログの作り方を学ぼう!

CoffeeBoxは、Node.js、CoffeeScript、MondoDbで作成されたシンプルなブログアプリです。

そこそこ本格的で「学べる」コードだと思いますので、インストールから触りだけ読んでみたいと思います。

UIもキレイです。

インストールして起動まで一気に。

$ git clone https://github.com/qiao/coffee-box
$ cd coffee-box/
$ npm install
$ mongod --dbpath ~/MongoDb (MongoDBを起動しておきます)
$ node index.js
coffee-box server listening on port 3000 in development mode


http://localhost:3000 にアクセスします。

Login画面。OpenIDを使えます。

新規投稿です。

投稿完了。

ダッシュボード。

コードを少し見てみます。

ファイル構成です。

index.js
server.coffee
lib
├── markdown.coffee
├── marked.js
├── require_dir.coffee
└── taglist.coffee
public/
├── 404.html
├── favicon.ico
└── images
    ├── CREDIT
    └── fabric_1.png
scripts/
└── populate.coffee
config/
├── config.coffee
├── routes.coffee
└── site.json
app
├── assets
│   ├── javascripts
│   │   ├── application.coffee
│   │   ├── bootstrap-tabs.js
│   │   ├── comments.coffee
│   │   ├── jquery.elastic.js
│   │   ├── jquery.js
│   │   ├── jquery.textarea.js
│   │   ├── preview.coffee
│   │   ├── session.coffee
│   │   └── site.coffee
│   └── stylesheets
│       ├── application.styl
│       ├── bootstrap.css
│       ├── comments.styl
│       ├── dashboard.styl
│       ├── posts.styl
│       ├── pygments.css
│       ├── session.styl
│       └── site.styl
├── controllers
│   ├── comments_controller.coffee
│   ├── dashboard_controller.coffee
│   ├── posts_controller.coffee
│   └── session_controller.coffee
├── helpers
│   ├── comments_helper.coffee
│   └── posts_helper.coffee
├── models
│   ├── comment.coffee
│   └── post.coffee
└── views
    ├── comments
    │   ├── _comment.jade
    │   ├── _comments.jade
    │   ├── _form.jade
    │   └── _spam.jade
    ├── dashboard
    │   ├── _comments.jade
    │   ├── _posts.jade
    │   └── index.jade
    ├── layouts
    │   ├── _footer.jade
    │   ├── _header.jade
    │   └── layout.jade
    ├── posts
    │   ├── _form.jade
    │   ├── edit.jade
    │   ├── index.jade
    │   ├── new.jade
    │   └── show.jade
    └── session
        └── new.jade

MVCにわかれています。ViewテンプレートにはJadeを使っています。スタイルシートはStylus。

次に依存パッケージを見ていきます。

coffee-box@0.0.6 /Users/inouetomoyuki/Projects/node/coffee-box
├── async@0.1.18 
├── coffee-script@1.2.0 
├─┬ connect-assets@2.1.9 
│ ├── connect-file-cache@0.2.4 
│ ├── mime@1.2.2 
│ ├─┬ snockets@1.3.4 
│ │ ├── dep-graph@1.0.1 
│ │ └── uglify-js@1.0.7 
│ └── underscore@1.1.7 
├─┬ express@2.5.8 
│ ├─┬ connect@1.8.6 
│ │ └── formidable@1.0.9 
│ ├── mime@1.2.4 
│ ├── mkdirp@0.3.0 
│ └── qs@0.4.2 
├── express-messages@0.0.2 
├── gravatar@1.0.6 
├─┬ jade@0.22.1 
│ ├── commander@0.5.2 
│ └── mkdirp@0.3.0 
├── moment@1.5.1 
├─┬ mongoose@2.5.13 
│ ├── hooks@0.2.0 
│ └─┬ mongodb@0.9.9-7 
│   └── bson@0.0.4 
├── openid@0.4.1 
├─┬ pygments@0.1.2 
│ └── underscore@1.3.1 
├─┬ rss@0.0.3 
│ ├── logging@2.0.16 
│ └── xml@0.0.7 
├─┬ stylus@0.25.0 
│ ├── cssom@0.2.3 
│ ├── debug@0.6.0 
│ └── mkdirp@0.3.1 
├── uglify-js@1.2.6 
└── validator@0.4.5 

Expressが使われています。MongoDBのODMにはMongooseです。エラー表示やステータス表示にexpress-message。connect-assetsで、Rails Asset PipelineっぽくCSSやらJSやらまとめているようです。

server.coffeeを見てみます。

express = require 'express'
app = module.exports = express.createServer()

require('./config/config') app 
require('./config/routes') app 

app.listen 3000
console.log "coffee-box server listening on port #{app.address().port} " +
  "in #{app.settings.env} mode"

Expressを使っています。ConfigとRouterがあるみたい。

ルータを見ていきます。

config/routes.coffee(一部)

module.exports = (app) ->

  # get controllers from app settings
  controllersGetter    = app.settings.controllersGetter
  PostsController      = controllersGetter.getPostsController     app
  CommentsController   = controllersGetter.getCommentsController  app
  SessionController    = controllersGetter.getSessionController   app
  DashboardController  = controllersGetter.getDashboardController app

  # middleware for finding all posts published as individual pages
  findPages = PostsController.findPages
  # middleware for requiring login
  requireLogin = SessionController.requireLogin

  app.get '/'                    , findPages                , PostsController.index

  app.get  '/posts.:format?'     , findPages                , PostsController.index
  app.get  POST_SHOW_PATTERN     , findPages                , PostsController.show
  app.get  '/posts/new.:format?' , requireLogin , findPages , PostsController.new
  app.get  POST_EDIT_PATTERN     , requireLogin , findPages , PostsController.edit
  app.post '/posts.:format?'     , requireLogin             , PostsController.create
  app.put  POST_SHOW_PATTERN     , requireLogin             , PostsController.update
  app.del  POST_SHOW_PATTERN     , requireLogin             , PostsController.destroy
  app.post '/posts/preview'                                 , PostsController.preview

Controllerを登録して、ルーティングを決めています。例えば app.get '/'だったら、PostControllerのindex関数にルーティングされていることがわかります。

Postコントローラを見ていきます。

post_controller.coffee(一部)

    index: (req, res, next) ->
      # check pagination param: /posts/?page=2
      pageNo = parseInt(req.query['page'], 10) or 1

      POSTS_PER_PAGE = 5
      Post.countPostPages POSTS_PER_PAGE, (err, totalPages) ->
        Post.getPostsOfPage pageNo, POSTS_PER_PAGE, (err, posts) ->
          return res.redirect '500' if err?
          res.render 'posts/index'
            posts:      posts
            pageNo:     pageNo
            totalPages: totalPages

Post.getPostsOfPage がモデルを呼び出しているところ。res.renderでViewのposts/index.jadeにデータを投げ込んでレンダリングしています。

Postモデルを見ていきます。

app/models/post.coffee

async    = require 'async'
mongoose = require 'mongoose'
Schema   = mongoose.Schema

{markdown} = require('../../lib/markdown')
{makeTagList} = require('../../lib/taglist')

{CommentSchema} = require('./comment')

PostSchema = new Schema
  title:
    type: String
    required: true
  content:
    type: String
  rawContent:
    type: String
  slug:
    type: String
    required: true
    unique: true
  comments:
    type: [CommentSchema]

(中略)

PostSchema.statics.getPostsOfPage = (pageNo, postsPerPage, callback) ->
  @countPostPages postsPerPage, (err, count) =>
    return callback err, null if err?
    query =
      public: true
      asPage: false
    options =
      skip:   (pageNo - 1) * postsPerPage
      limit:  postsPerPage
      sort:   [['createdAt', 'desc']]
    @find query, {}, options, callback

mongooseを使ってスキーマを作っています。getPostsOfPage メソッドで、MongoDbにクエリを投げています。

Postのindexビューを見ていきます。

app/views/posts/index.jade(一部)

// entry list
ul.unstyled#entry-list
  each post in posts
    li!= partial('show', { locals: { post: post } })

(略)

Postコントローラの、res.renderでPostモデルから取得したデータを postsに入れています。jadeでループさせて表示させています。個々のPostデータの表示には、パーシャルを使って show.jade で表示させています。

app/views/posts/show.jade

article.entry.post
  != messages()
  header.entry-header
    h2.entry-title
      a(href=postPath(post))= post.title
    .entry-meta
      .entry-day= postDay(post)
      .entry-month= postMonth(post)
  .entry-content
    != post.content 
        
  != partial('comments/comments', { post: post, comments: post.comments })

全体的な流れはこんな感じです。

CoffeeBoxのコードはMVCでの組み方がよくわかります。ブログではログインの方法やセッションの持たせ方、設定などの方法、Stylusでの組み方、Assetの使い方についても理解しやすいです。

まだ改善できるところもありますし、CoffeeBoxは、コールドリーディングにはちょうどいい素材かもしれません。これがすべてではありませんが、脱初心者を目指す方はぜひ。

2012年4月9日月曜日

HTMLをCoffeeKupに変換する「html2coffeekup」を試す

html2coffeekup は HTMLをcoffeekup 形式に変換するプラグインです。マイナーですがCoffeeKupテンプレート大好きな方には必須のツールです。

早速インストール。

$ npm install -g html2coffeekup

使い方は簡単。

$ html2coffeekup sample.html > sample.coffee

変換前

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>test</title>
</head>
<body>
  <h1>This is sample page</h1>
  <p>Hello, world!</p>
</body> 
</html>

変換後

doctype TODO
html ->
  head ->
    meta charset: 'utf-8'
    title 'test'
  body ->
    h1 'This is sample page'
    p 'Hello, world!'

これは便利かもしれません。

2012年4月8日日曜日

「EGit」でEclipseとGitHubを連携する

EGitは、バージョン管理システムGitをEclipseから使えるようにするプラグインです。

EGitでGitHubと連携してみます。ほとんどSSHの設定。。。

EGitのインストール

  1. [Help]>[Install New Software…]
  2. Work with: に http://download.eclipse.org/egit/updates と入力して[Add]ボタン
  3. [Eclipse Git Team Provider]を選択して[Next]ボタン
  4. [Finish]ボタンでダウンロードとインストール開始
  5. Eclipse再起動

GitHubのセットアップ

  1. GitHubをアカウント作成
  2. SSHの設定。今回はコマンドからも使いたいので、公式マニュアルを見ながら設定します。
$ cd ~/.ssh
$ mkdir key_backup
$ cp id_rsa* key_backup
$ rm id_rsa*
$ ssh-keygen -t rsa -C "GitHubに設定した自分のメールアドレス"
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/inouetomoyuki/.ssh/id_rsa): [ENTER]
Enter passphrase (empty for no passphrase): [任意のパスワード]
Enter same passphrase again: [任意のパスワード]
Your identification has been saved in /Users/inouetomoyuki/.ssh/id_rsa.
Your public key has been saved in /Users/inouetomoyuki/.ssh/id_rsa.pub.
The key fingerprint is:
XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX "メールアドレス"
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|                 |
|   Finger        |
|       Print     |
|                 |
|                 |
|                 |
+-----------------+

出力されたid_rsa.pubのテキストをコピーしてGitHubへ登録します。

設定できたかテストします。

$ ssh -T git@github.com
The authenticity of host 'github.com (207.97.227.239)' can't be established.
RSA key fingerprint is XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX 
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,207.97.227.239' (RSA) to the list of known hosts.
Identity added: /Users/inouetomoyuki/.ssh/id_rsa (/Users/inouetomoyuki/.ssh/id_rsa)
Hi tomoyukiinoue! You've successfully authenticated, but GitHub does not provide shell access.

パスワード入力画面が表示されたら、ssh-keygenで設定したパスワードを入力します。

ローカルのgitを設定します。

$ git config --global user.name "自分の名前"
$ git config --global user.email "自分のメールアドレス"
$ git config --global github.user (GitHubのアカウント名)
$ git config --global github.token (GitHubのAccount Settingsに書いてあるAPIトークン)

以上でSSHの設定完了です。

Eclipseで新規プロジェクト

  1. GitHubでレポジトリ作成。gitのアドレスをコピー。
  2. 新規プロジェクト作成
  3. [Team]>[Share Project…]
  4. [Git]を選択。
  5. [Team]>[Add to Version Control]。httpsがトラブル無し。
  6. binとgenフォルダを選択して[Team]>[Ignore]

CommitとPush

  1. [Team]>[Commit]
  2. [Push]

参考

EgitでGitHubにアクセスする

Eclipse Git プラグイン ~ インストールからコミット、履歴の比較まで

2012年4月5日木曜日

Canvasでネガポジ反転してみた

Canvasで画像を少しいじってみました。


<!DOCTYPE html>
<html>
    <head>
        <title>Canvas</title>
        <meta charset="utf-8">
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

        <script>
            $(document).ready(function() {
                var canvas = document.getElementById("myCanvas");
                var ctx = canvas.getContext("2d");

                var image = new Image();
    image.src = "sample.jpg";
    $(image).load(function() {
        ctx.drawImage(image, 0, 0);

        var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        var pixels = imageData.data;
        var numPixels = imageData.width * imageData.height;
        for (var i = 0; i < numPixels; i++) {
         pixels[i*4] = 255-pixels[i*4]; // Red
         pixels[i*4+1] = 255-pixels[i*4+1]; // Green
         pixels[i*4+2] = 255-pixels[i*4+2]; // Blue
     };
     ctx.clearRect(0, 0, canvas.width, canvas.height);  
     ctx.putImageData(imageData, 0, 0); 
    });

            });
        </script>
    </head>

    <body>
        <canvas id="myCanvas" width="500" height="500">

        </canvas>
    </body>
</html>

元画像

Canvasでネガポジ反転!

Canvasを使うとちょっとした画像処理ならできちゃうのですな。

2012年4月3日火曜日

Mac OS X Lion にNode.js 0.6.14をインストールする

Node.jsがv0.6.14になっていたので、インストールしてみます。

Node.jsのインストールには、nvmを使うとバージョンを切り替えたり、npm install 時に sudo が必要なくなったりど色々便利です。

$ git clone git://github.com/creationix/nvm.git ~/nvm
$ . ~/nvm/nvm.sh

ターミナルを開いた時に nvm.sh が実行されるように bash_profile を編集しておくと吉です。

source ~/.nvm/nvm.sh
nvm use v0.6.14
npm_dir=${NVM_PATH}_modules
export NODE_PATH=$npm_dir

source で再度読み込み。

$ source ~/.bash_profile
Now using node v0.6.14

Node.jsをインストールしてみます。

$ nvm install v0.6.14

(ダウンロード&インストール)

Now using node v0.6.14
/Users/inouetomoyuki/.nvm/v0.6.14/bin/npm
 
$ nvm ls
v0.4.12 v0.6.11 v0.6.12 v0.6.13 v0.6.14
current:  v0.6.14
$ node -v
v0.6.14

node -v でバージョンがv0.6.14にならない場合、ターミナルを再起動すると上手くいったりします。

2012年4月2日月曜日

ZombieとMochaでテストをはじめる

Zombieは、ブラウザをエミュレートできる軽量なテスティングフレームワークです。

Mochaと組み合わせると、わかりやすくテストを書くことができます。

$ npm install zombie mocha expect.js

Googleにアクセスしてタイトルが一致しているかテストを書いてみます。

Mochaを使いますので、test ディレクトリを作成し、その中にテスト用のファイルを作成します。

test/googleTest.coffee


expect = require 'expect.js'
Browser = require 'zombie'
browser = new Browser()

describe 'Googleのテスト', ->
  it 'google.comにアクセスできる?', (done) ->
    browser.visit 'http://www.google.com', ->
      expect(browser.text 'title').to.equal 'Google'
      done()

テストを実行してみます。

$ mocha -R spec


  Googleのテスト
    ✓ google.comにアクセスできる? (1093ms)


  ✔ 1 tests complete (1095ms)

googleのテストができました。

検索してみます。

expect = require 'expect.js'
Browser = require 'zombie'
browser = new Browser()

describe 'Googleのテスト', ->
  it 'google.comにアクセスできる?', (done) ->
    this.timeout 5000
    browser.visit 'http://www.google.com', ->
      browser
      .fill('q','Zombie')
      .pressButton 'Google 検索', () ->
          expect(browser.text 'title').to.equal 'Zombie - Google 検索'
          done()

fillでテキストを入力し、pressButtonでボタンを押しています。timeoutで5秒を指定しています。

$ mocha -R spec


  Googleのテスト
    ✓ google.comにアクセスできる? (2354ms)


  ✔ 1 tests complete (2355ms)

うまくテスト出来ました。ブラウザをエミュレートして画面のテストができそうです。