5次元のカオス

南の島の学生がつらつらと日々を書き連ねます

Linuxコマンド健忘録

何回も忘れては調べ直してを繰り返してる気がするので、健忘録としてメモ.

随時、追加していけたらいいなあとか思ったり.

ワイルドカードの展開

$ mv test.{txt,md}

→ mv test.txt test.md というふうに展開される

find コマンドのワイルドカード展開

シェルはワイルドカードを展開してからスクリプトを実行する.

例えば下記の例.

カレントのディレクトリにあるtest.txtにマッチし、それが展開されたfindコマンドが実行される.

$ sudo find / -name *.txt
$ touch test.txt
$ sudo find / -name *.txt

これを抑制するためには、 -name オプションの文字列をシングルクォーテーションで囲む必要がある.

[技術][unix][未解決] スクリプトに渡す引数でワイルドカードが展開 - 読書子の日記 http://d.hatena.ne.jp/risingsun/20050217

diff, patchコマンドでファイルの変更を別のファイルへ適用する

$ diff -u 変更前のファイル 変更後のファイル > パッチファイル名

ファイルにpatchを当てる際にバックアップを作成する text1.origみたいな感じの拡張子を持ったファイルができる

su, su - の違い

環境変数を引き継ぐかどうかの違い. 通常は - をつけた方が良い.

環境変数を引き継がない場合は, 直接コマンドのパスを指定すれば良い.

ネットワーク系のコマンド

dig コマンド

dig コマンドは DNS の名前解決の状況確認やトラブルシューティングといったネームサーバーの管理用途に利用する。

例えば、 yahoo.co.jp のアドレスを DNS に問合せた結果。

$ dig yahoo.co.jp

; <<>> DiG 9.8.3-P1 <<>> yahoo.co.jp
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13182
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;yahoo.co.jp.           IN  A

;; ANSWER SECTION:
yahoo.co.jp.        159 IN  A   183.79.135.206
yahoo.co.jp.        159 IN  A   182.22.59.229

;; Query time: 9 msec
;; SERVER: 61.207.11.153#53(61.207.11.153)
;; WHEN: Mon Dec 14 01:55:51 2015
;; MSG SIZE  rcvd: 61

ルートサーバーを運用している組織は世界中で12組織あり、 VeriSign 社が二つのサーバを運用しているため、全部で13のサーバがルートサーバーとしてDNSに登録されてる。

Root Server Technical Operations Assn というサイトでルートサーバーのある場所と名称を確認できる。

ちなみに日本には WIDE プロジェクト が運用する M Root DNS Server があるらしい。

DNS を指定してアドレスを問い合わせるためには @ に続いて DNS サーバーを記述する。

$ dig @m.root-servers.net yahoo.co.jp

; <<>> DiG 9.8.3-P1 <<>> @m.root-servers.net yahoo.co.jp
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63865
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 13
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;yahoo.co.jp.           IN  A

;; AUTHORITY SECTION:
jp.         172800  IN  NS  d.dns.jp.
jp.         172800  IN  NS  e.dns.jp.
jp.         172800  IN  NS  f.dns.jp.
jp.         172800  IN  NS  c.dns.jp.
jp.         172800  IN  NS  b.dns.jp.
jp.         172800  IN  NS  a.dns.jp.
jp.         172800  IN  NS  g.dns.jp.

;; ADDITIONAL SECTION:
a.dns.jp.       172800  IN  A   203.119.1.1
b.dns.jp.       172800  IN  A   202.12.30.131
c.dns.jp.       172800  IN  A   156.154.100.5
d.dns.jp.       172800  IN  A   210.138.175.244
e.dns.jp.       172800  IN  A   192.50.43.53
f.dns.jp.       172800  IN  A   150.100.6.8
g.dns.jp.       172800  IN  A   203.119.40.1
a.dns.jp.       172800  IN  AAAA    2001:dc4::1
b.dns.jp.       172800  IN  AAAA    2001:dc2::1
c.dns.jp.       172800  IN  AAAA    2001:502:ad09::5
d.dns.jp.       172800  IN  AAAA    2001:240::53
e.dns.jp.       172800  IN  AAAA    2001:200:c000::35
f.dns.jp.       172800  IN  AAAA    2001:2f8:0:100::153

;; Query time: 30 msec
;; SERVER: 202.12.27.33#53(202.12.27.33)
;; WHEN: Tue Dec 15 02:01:15 2015
;; MSG SIZE  rcvd: 425

nslookup コマンド

dig コマンドと似たコマンドとして nslookup コマンドがある。

$  nslookup yahoo.co.jp
Server:     61.207.11.153
Address:    61.207.11.153#53

Non-authoritative answer:
Name:   yahoo.co.jp
Address: 183.79.135.206
Name:   yahoo.co.jp
Address: 182.22.59.229

2つのコマンドの違いについては @IT:DNS Tips:digコマンドとnslookupコマンドの違いとは を見る限りだと、DNS の挙動を見たいときは dig コマンド、 純粋に IP アドレスとの ドメイン名の対応を見たい時は nslookup コマンドはというように見える。

word2vecに関する勉強会に参加してきました

概要

2015/4/10にサイバーエージェントのアドテクスタジオ主催で行われた「ディープラーニングチュートリアル 応用編:言葉の『意味』表現〜word2vec〜」に参加してきました.

講師としてDanushka Bollegala教授(英リバプール大准教授)を招いて行われたこの講演会では,近年注目を集めているword2vecについて勉強することができました.

興味本位で遊びに行って大丈夫かな...?と心配していたのですが,講師の方が言葉を噛み砕いて丁寧にお話してくれたこともあってなんとかついていくことができました.

最近、東京に引っ越してきたためこういった勉強会への参加することに緊張していたのですが、楽しく勉強することができてよかったです.

講演資料は以下のサイトで公開されております.

ディープラーニングチュートリアル 応用編

以下,勉強会でのメモです.(間違えているところもあるかもしれません)

word2vec とは?

「Word2Vec」は,米グーグルの研究者であるトマス・ミコロフ氏らが提案した手法であり,いくつかの問題について従来のアルゴリズムよりも飛躍的な精度向上を可能にした自然言語処理の手法.

Word2Vecは,その名前の表す通り,単語をベクトル化して表現するする定量化手法である.例えば日本人が日常的に使う語彙数は数万から数十万といわれるが,Word2Vecでは各単語を200次元くらいの空間内におけるベクトルとして表現する.

mecab - 米googleの研究者が開発したWord2Vecで自然言語処理(独自データ) - Qiita より

単語の意味とは?

この講演中は自然言語処理の最小単位「単語」(特に1単語)にする.

有名な「単語」に関する仮説:単語自身には意味はなく,周辺に現れる言葉によって意味を持つ

問題:Xは持ち歩くことが可能で相手と通信ができてネットも見れて便利だ

X にはどんなワードが入るか? → iPhone

もしXが初めて見る単語だったとしても,Xの周辺を読み取ることで意味を知ることは出来る.

これは X自身には意味は無い = 周りの意味で決まる ということに等しい.

※ X自身に意味があったら,周りをみても予測することができない

それは本当のこと?

辞書は単語の意味を定義している.

  • 辞書も他の単語との関係を述べているに過ぎない?

膨大なコーパスがあれば,周辺単語を集めてくる.

コーパス = 自然言語の文章を構造化し大規模に集積したもの.

意味表現を作るアプローチ

分布的な方法 (古典的)

「林檎」という単語の意味表現を作る

林檎 という成分を考える

  • S1 = 林檎は赤い
  • S2 = 赤いリンゴは美味しい
  • S3 = 青森県は林檎の生産地として有名である

→ 共起の表現で林檎を作ることができる.

林檎とは?:赤い・美味しい・青森で生産される という意味で表現できる

同様に「みかん」の意味表現を作ると,林檎とみかんの意味的な類似度を調べることができる.

Jaccard係数 = 林檎 AND みかん / 林檎 OR みかん

Jaccard係数 = 2要素の共通要素の割合を0~1の間で示す.

ナマの共起頻度を信頼できるかの実験

2つのワードがどれくらい共起しているかを見るためにGoogle検索を使う.

  • Googleのヒット件数
    • (car, automobile) = 200,000,000
    • (car, apple) = 373,000,000

→ 共起が大きすぎると問題が起こるため,なんらかの重み付けが必要となってくる

そこで,共起頻度の重み付けを行う手法が提案されている.

重み付けの手法

以下のように手法がたくさんある(30個以上)ため,どの手法が適しているかはケースバイケース

  • 点情報量(pointwise mutual information)
  • 正点情報量(PPMI)
  • 移動点情報量(SPMI)

ゼロ共起による問題

大きなコーパスを持っていたとしても共起しない単語というものが出てくる.

  • 単語xとyが共起しない原因を考察する
    • そもそも関連性がない
    • たまたまデータがない

→ どちらの理由で共起が置きないのかを判定することができない

共起行列に0が並ぶと相関が0に近づいてしまう.

そこで,共起行列から0を削除するための次元削減 / 低次元射影という手法が提案されている.

次元削減の説明は, 大まかな説明をすると,0じゃない部分を0でない値で埋める とのこと.

林檎,みかんの中で共起が0となっているものを削除する

以下のように手法はたくさんあるが,主にやっていることは0の数を減らすということ.

  • 特異値分解(SVD)
  • 主成分分析(PCA)
  • 非負行列分解(NMF)

共起の幅を決める必要があったり,単語距離によって重みをつけるなど工夫が色々ある.

分散的な意味表現を作るアプローチ

単語xをコーパス中でその周辺に現れる全ての単語の共起頻度分布を持って表す.

ディープラーニング/表現学習 ブームで最近人気になってきた

ディープラーニング = 学習アルゴリズムがデータの中から有効な特徴量を探してくる

分散表現な方法(近代的)

クラスタ分割などの局所的な表現:ある点のデータを示すとき,周辺の近傍を調べる

分散表現の表現:ある点のデータを示す時,その点を分割するように線を引くイメージ

f:id:pxp_ss:20150418213337p:plain

→ いくつかの線(次元)を引くだけで分割するので,少ない次元数で表現が可能

→ 分割する線(次元)によって全ての単語を同じ次元で対比できる

分散表現を学習する

分散表現では,各単語xの意味表現がD次元のベクトルで表されると仮定する.

そのベクトルの要素の値をコーパスから学習する.

xの意味表現ベクトルv(x)を使って,コーパス中でxの周辺に出現する単語cを予測できるか学習する.

word2vec

  • Word2vecは単語の分散意味表現を学習するためのツールアルゴリズムではない)
    • skip-gram
    • continuous bag of words

→ 2つのアルゴリズムでなりたっている.今回はskip-gramだけ説明.

skip-gramモデル

1つの単語に対して2個のベクトルが割り当てられていると仮定

「私は味噌汁とご飯を頂いた」 → 「私 / は / 味噌汁 / と / ご飯 / を / 頂いた」(意味解析をする前準備として形態素解析を行う)

味噌汁の周辺でご飯が出現するかどうかを予測する問題を考える.

日本人は味噌汁という単語が出たら,ご飯を連想したりする.

→ これをコンピュータでやりたいというもの.

では,このスコアをどうやって計算するか.

1. 味噌汁のベクトルとご飯のベクトルを内積で定義する:score(x, c) = v(x)T u(c)

内積は+∞⇔-∞の範囲を取られるため,正規化する必要がある

2. 全ての文脈単語c'に関するスコアで割ることで計算できる:(log-bilinear model:LBL)

このようなモデルを対数双線型という

双線型とは?:f(ax + b, y) = af(x, y) + f(b, y) パラメータ1つを変動,ソレ以外は固定すること

連続単語集合モデル(CBOW)

周辺の単語を全てを使って,対象単語を予測する.

分膜の前後いくつかの単語に限定して対象単語を予測する.

(順序は無視,)

表現能力は高いがskip-gramよりも若干精度が悪い.

高速化のための工夫が必要?

負例サンプリング(アンダーサンプリング?)

コーパス中のいくつかの単語だけ正規化する方法

負例 = 元々の単語に存在していなかったもの

階層的ソフトマックス

単語の出現の代わりに意味クラスの出現を使うことで語彙の大きさを減らす.

単語を階層的に表現することで比較する単語の数を減らす.

(関係ない(近似しない)意味クラスの階層は無視すれば良い)

ツリーの作り方自体は手法は色々ある:ハフマン木などが有名(それぞれの単語にバイナリの値を振る)

※ よく出現する奴は短いバイナリになる

学習した意味表現の評価

意味表現はベクトルなので「目で見ても分からない」

→ なんらかのタスクに応用してその性能向上度合いで評価する必要がある

こういうふうに評価することを間接的評価という.

関節的評価の手法

  • 意味的類似性による評価:人間がつけたスコアとアルゴリズムが出したスコア間の相関を計測する
  • アナロジー問題:cos類似度などを使って最大の類似度を持つ単語を答えとして返す

Global Vector Prediction(GloVe)

  • skip-gram と CBOWは一文単位でコーパスを処理し意味表現を学習していく

CBOWやskip-gramは1文単位での共起を調べていたが,コーパス全体で共起を探索する?

※ 負の共起を使っていないのが問題?(ご飯と味噌汁というような「正」の共起しか利用していない)

質疑応答

Q.d次元のベクトルはどうやって求まるのか?

dを横軸,性能を縦軸で評価する論文などがある

→ ある次元からは飽和するみたいなものが分かったりする

Q.スキップグラムの飛ばし方はタスク依存なのか?

タスク依存.文を超えるものはできない.

ストップワード:よく出る単語(が/は/と:助詞など)は除外する.

離れた距離の単語には重み付けとして離れた距離の逆数で割ったりする.

Q.今回の勉強会はディープラーニングの領域?

今回の目的は予測問題を解くこと.

今回は2つの問題の内積で説明したが,これをNN法みたいなものに入れ替えても構わない.

問題はデータ量が多くなるときにどうするのか?というところだった.

ディープラーニングとの関係は特徴を学習できれば良い.今回の講演は単語の特徴を意味学習した.

参考資料

研修合宿を振り返る

4/4 ~ 4/6の2日間 静岡の某所で合宿研修に参加しました。

研修の内容自体は主に会社のことに関するプレゼン大会のような感じだったのですが、すごく大きな学びがあったのでこの2日間で得られた学びを文字に起こしてみることにしました.

プレゼンに関する反省

イデア出しをする中で僕は自分たちの班には大きく3つの問題を感じていました.

  • イデア出しする中で、会話が止まることが多い
  • フィードバックを貰えないアイデアがあった(0点のアイデアの時)
  • イデアベースの話の多さ

1. アイデア出しをする中で会話が止まることが多い

これは最後の振り返りの際に担当のメンターにも言われたのだけれど「個々の実力が足りない」っていうのをかなり感じた.

自分たちのチームには 圧倒的なカリスマ みたいな人がいなかったっていうのもあってアイデアを生みやすくするための取り組みをやれば良かったと反省した.

会話が止まると雰囲気が暗くなる → アイデアに自信が持てなくなる → アイデアが煮詰まる

という負の循環に陥っていたように思える.

2. フィードバックを貰えないアイデアがあった

自分たちのチームは2度もフィードバックをもらわないアイデアがあり、かなりもったいないことをしました.

これは1.の問題にも関連するけど、時間内にアイデアを固めることができなかったことが原因.

1つの1つのアイデアに対して時間をかけすぎたり、こだわりを捨てきれずに長い間悩み続けたためにアイデアを固める頃には時間が足りなくなっていた.

僕は本当に良いアイデアというのは当たり前過ぎて誰も気付かない/見落としているものなのかな?というふうに考えています.

もっと自信を持って「これに決めましょう」と言い切ることや、「面白い/面白くない」ともっと自分の意見をはっきり言えれば良かった.

「面白い/ 面白くない」とシンプルに言い切るだけでいいのに、自信がないから「~だから面白い/ ~だから面白くない」みたいな理由を誰にも聞かれてないのに話したりしてたように思う.

3. アイデアベースの話の多さ

なぜこのテーマでプレゼンをするのかという認識にズレがあったような気がします.

問題が設定された背景や課題をもう少し深く考察し、全員で共有する部分が甘かった.

背景の設定 → 既にある取り組み → カバーできていない人はどんな人/モノか → 手法

学生の頃、研究をするために徹底的に叩き込まれた論理的な指向がこの研修では全くできなかった。

そのために、アイデアベースの話が多くなる(アイデアを話すときにターゲットやこのアイデアの狙いについて話す)ということが起こり、アイデアの説明をする時間が多くなってしまったように思う.

研修を通しての学び

心理的な意味での成長

長い間、南の島でのんびり生活していたから、「内定者バイトとかできないし、会社のことはまだ全然分からないよ〜」ってゆるい気持ちでいたけど、これに危機感を覚えるようになった.

ビジネスコースの人と話していて「このアプリのDL数は~で、売上を~円だしていて」みたいなのをきちんと把握していたり、企業が細かく分かれているにも関わらず、それぞれの企業動向や所属する人なんかをきちんと分かっているのがすごいなって感じる.

この人のブログ, 755はチェックするべきみたいなのをもっと知りたいですね.

(特に焦っているわけではないけれど)

技術者が技術を好きなのは当たり前だけど、使いどころのある技術を身に付けたい。

僕は経営とかには全く興味はないと今まで会社の動向なんかを軽視しているところはあったけど(たまにIRを眺めるぐらい)、もっとちゃんと会社のことを理解し、意味のある技術を身に付けたい。

施策の打ち出し方

ビジネスコースの人から以下のスキームを教わりました.

現状 → 課題 → ターゲット → 訴求 → 施策

自分たちのチームは、これを守ることには気をつけていて施策を打つ前提は綺麗に立てられていたと思う。

(点数はパッとしなかったけど)

後から見返すと、高得点をとれたチームと同じアイデアを出していたりしたりしたこともあって方向性は間違ってなかったんだって思った.

感想

研修すごく良いですね。

全然楽じゃないし、毎日毎日遅くまでガッツリやるから疲れるけど、この2年間1人でコツコツ頑張る!みたいなのが多かったからそれに比べるととても良いです。

自分の殻に閉じこもることが多かったり、たまに外に出てみてもレベルの高い人の多さに自分は才能が無いんじゃないかと絶望したこともあったけど、この会社に入ってそれがちょっとずつ改善されつつある気がする。

同期のポジティブさだったり貪欲さだったりになにかしら影響を受けているんだろうと思います。

まだ1週間しか経ってないけど、性格は大分ポジティブなってきているね。

まだ人と話すときは緊張するし、実力の無さも痛感してるっていう現状に変化はないんだけど、なんとなく頑張り方がポジティブになってきたっていうのかな?

(学生の頃もがむしゃらにやってたけど、ネガティブな頑張り方をしてた気がするんだよね)

そういう意味では、この会社に入って良かったと思います。

同期のみんな、合宿を支えてくれた皆様 2日間の研修合宿お疲れ様でした!

ありがとうございました。

チームもすごく会話しやすいメンバーで良かった...

同期のみんなの意外な一面も見られたり、ホントに毎日良い刺激を貰ってる!

明日からの研修も頑張りましょう!

社会人になりました

7年間通い続けた学校を卒業し、心機一転ついに社会人となりました。

アウトプットする癖を常々付けたいと思っていましたが忙しい日々が続くと更新が滞ってしまいます。

過去の残骸

そんな中、入社式の中で最初に聞いた言葉が、「応援される人は発信量が多い」ということでした。

自分自身の経験の中でもこれは確立された理論であり、頑張っていることは素直にアピールするべきだなと思っています。

そこで再び、ブログを再開してみることにしました。

(もしかしたら、移転するかもしれないけど...)

入社式で得られた学び

社長謝辞より、「勝負どころを見極め努力する」という言葉を頂きました。

人生は長いマラソンのようなもので頑張ることは誰にもできるけど、いつまでも全力疾走することはできないため勝負所を見つけることが大切とのことでした。

また人材開発本部長からは「視点を高く持つこと」という言葉を頂きました。

目標があれば軸がブレにくくなるため、成功への近道となるそうです。

僕は、目標を設定すること自体を忘れてしまったり、なにかに打ち込んでいるうちに最初の目的と変化していたりといったことが多々あります。

大きすぎる目標や周囲との差によって生まれた焦りがそうさせるのかなあ...と話を聞きながら自分の人生を振り返っていました。

自分自身の目標

そんな自分の目標は、 技術で尖ったエンジニアになる に決めました。

これは自分自身が生涯をかけて叶えたい目標です。

僕は技術が大好きです。

技術の使い所を誰よりも熟知し、良いプロダクトをを作る一角を担えるような人材として

成長していきたいと思いました。

(この会社新しいもの好きは多いけどそれに流されない視点がほしい)

しかし、これは中長期的な目標であるため、これを実現するために実現可能な手の届く範囲の目標を細かく打ち立てていかないといけないわけですが、そういうのはどうやって考えていったらいいかなあ...

自分のエンジニアとしてのキャリアプランはまだまだ甘いところがあるので

まずは色々な人と関わり、常に目標が1~2個 用意されているといった状態を作り出せるようにしたいです。

(タスクを細かく分割するのに似てるかも)

最後に

研修を担当してくださった方々や研修で一緒になった皆には本当に感謝しています。

ありがとうございました。

これから、一緒にこの会社を盛り上げていければと思います。

よろしくお願いします。

Swiftはじめました

Swiftはじめました

先日、内定先の会社で研修会を行った際に、「次回の研修ではSwiftを使った開発を行ってもらうつもりです」

というお話をされたことをきっかけに、Swiftをはじめてみることにしました。

以下、環境構築からSwiftを動かしてみるまで。

Hello, World的なものを動かすまでの手順を自分への健忘録としてメモ。

環境構築

AppleのデベロッパーサイトからiOS 8 beta 2を選択します.

f:id:pxp_ss:20140702154937p:plain

下の方にスクロールしていくと、Download Xcodeという項目があるので、ダウンロードします.

f:id:pxp_ss:20140702154949p:plain

Downloadされたxcode_6_beta.dmgを解凍し、Applicationフォルダへ移動すればインストール完了です。

既存のxcodeとは別にインストールされるため、安心してインストールしても良いと思います。

プロジェクトの作成

Xcode 6 beta を起動します。

とりあえず、触ってみようということでCreate a new Xcode projectを選択

f:id:pxp_ss:20140702154945p:plain

LanguageにSwiftを選択することを忘れないようにしましょう。

f:id:pxp_ss:20140702154941p:plain

xcode全体がフラットな感じのデザインに洗練されたように思います。

objective-cの時と同様に、適当なラベルを設置した後にViewDidLoad内に

ラベルを変更する処理と、デバッグエリア上にHello, Swiftを表示するプログラムを書いてみました。

f:id:pxp_ss:20140702154955p:plain

とりあえず、今回はここまで。

環境が整ったので色々と試して見つつ、なにか作ることができればと思います。

参考

grunt.jsを使ってcoffee-scriptでの開発を便利にしたい

前回の記事から引き続いてgrunt.jsを使ってcoffee-scriptで便利に開発するためのgruntfileを組み立てていきたいと思います.

一応 github上に公開してみたので、色々とフィードバックを頂けると幸いです.

seka/myGrant-repo

以前からgruntをやりたいとは思ってはいたのですがインターンに参加していたり就職活動でバタバタしていたこともありなかなか時間を割くことが出来なくて辛かった...

自動化は学習コストは高い気がするけど一度書くと使い回しがきくのが良い感じですね.

今回はcoffee-scriptに関するタスクの自動化のみですが、色々なところで開発の話を聞いているとgrunt.jsを使った開発はもはや必須と言っても過言ではないと思ったので、もっと色々と試行錯誤してみたいと思います.

以下、健忘録としてメモ.

開発環境

各環境のバージョンは下記の通り.

grunt-cli : v0.1.13
"grunt : "^0.4.4"
"grunt-contrib-uglify" : "^0.4.0"
"grunt-contrib-coffee" : "^0.10.1"
"grunt-contrib-requirejs" : "^0.4.3"
"grunt-contrib-copy" : "^0.5.0"

これまでの僕の開発

とあるプロジェクトのファイル管理

$ tree 
.
|____ javascripts
| |____app.coffee
| |____app.js
| |____app.map
| |____HtmlTemplateClass.coffee
| |____HtmlTemplateClass.js
| |____HtmlTemplateClass.map
| |____InitCodeMirror.coffee
| |____InitCodeMirror.js
| |____InitCodeMirror.map
| |____main.coffee
| |____main.js
| |____main.map
| |____SubmitCodeClass.coffee
| |____SubmitCodeClass.js
| |____SubmitCodeClass.map
| |____SwitchResultWindowClass.coffee
| |____SwitchResultWindowClass.js
| |____SwitchResultWindowClass.map

→ お恥ずかしい話ですがjavascriptファイルとcoffeeスクリプトが混在した状態で放置されています.

※ source mapはjavascript実行時に起きたエラーをcoffee-script用のどの部分に対応するか示すためのファイルです

※ 今にして見るとファイル名も見せられたもんじゃな(ry

.

.

.

なぜこのような状態になったかというと、普段の開発環境がvimなのですがcoffee-scriptをwriteする際に下記コマンドが走るようにしていました.

.vimrc

"  coffee scriptをwriteすると.jsと.mapを書き出す
autocmd BufWritePost *.coffee silent CoffeeMake! -cb -m | cwindow | redraw!

そのため、coffee-scriptと同じフォルダ内にjsファイルとmapファイルが生成されることにより前述のようなカオスなファイル管理が生まれてしまうことになりました.

自分一人だけが見るプロジェクトではなく、githubなどのような複数の人が見るようなプロジェクトにおいてjavascriptとcoffee-scriptのファイルが混在しているのは、見栄え上よろしくないとの指摘を多数の方から頂き、どうしたものかと考えていました.

grunt.jsを使ってcoffee-scriptでの開発を便利にする

そこでタイトルにあるようにgrunt.jsを使ってcoffee-scriptでの開発を便利にしたいと考えました.

そこで、下記の手順を自動化できないかと考えました.

1. coffee-scriptを自動コンパイルし、javascriptsフォルダへ (coffee-scriptとjavascriptのフォルダをきちんと分ける)
2. javascriptsフォルダ内のjavascriptを1つのファイルとして結合する(ファイル連結)
3. 1つになったjavascriptファイルに対して最適化・圧縮をかける

それらをまとめたものをgithubで公開してみることにしました.

seka/myGrant-repo

色々とフィードバックが頂けると嬉しいなと思っています.

意外とコレだ!っていうものが見つからなかったので、自分で色々と試しつつ作ってみることにしたのですがなかなか使いまわすことができそうなので良いなと思ってます.

少しはcoffee力ついたかなあ....

htmlやcss周りについても色々書いていければと思っています.

参考

grunt.jsについて勉強してみた

先日のことですが、とあるゲーム開発会社に訪問しコードレビューしてもらいました.

その際に、「coffeescriptをpublic内に置いておくのはあまり良くない。grunt.jsとか使ってみたら?」というアドバイスを受け、

gruntとはなんぞやと勉強してみました.

最近の開発って自動化が必須ツールとなっているような気がします.

学習コストは高い気がするのですが、すごく便利なので使いこなしていけるといいなあ...

以下、自分への健忘録としてメモ.

※ 基本的な流れはドットインストールです.

grunt.jsとは?

公式サイトより
The less work you have to do 

Grunt.jsはnode.jsを利用したタスクの自動化のためのツールらしいです.(都合の良い部分を拝借して超訳

  • 公式サイト:gruntjs.com
  • 知識(列挙していますがお試しなのであまり必要ないです)
    • node.js
    • javascript
    • フロントエンド周りの知識
    • less
    • unixコマンド

記事を書いた時の情報

grunt-cli : v0.1.13
grunt     : v0.4.3
node.js   : v0.10.25

環境構築

npmを使ってgruntコマンドのインストールを行います.

$ npm install -g grunt-cli

プラグインなども同様の手順でインストールすることができます.

$ npm install grunt --save-dev ~

※ save-devをつけることで開発環境と本環境を切り分けることができます.

package.jsonの作成

node.jsを使ってWebサイトを作ることを想定します.

テスト用のフォルダを作成

$ mkdir mysite
$ cd mysite/

プロジェクトへgruntをインストールする

$ npm init
$ npm install grunt --save-dev
$ cat package.json

→ grunt:"~0.4.2"が追加されていることが確認できます.

package.jsonを書くことでアプリを譲渡した際に、コマンド1つで環境を構築することができます.

$ npm install

Gruntfileの作成

Gruntfileは自動化するタスクをコードにしたものです.

プロジェクト内のルートディレクトリに存在し、 同階層にpckage.jsonファイルがあります.

coffee スクリプトを使って記述していきます.

$ touch Gruntfile.coffee または touch Gruntfile.js

Gruntfileにはプロジェクトの設定やプラグインのロード、自動化するタスクを記述していきます.

プラグインの探し方

公式サイト:plgins

contribという名前が付いているものはgruntが公式にチェックしているプラグインとなっています.

プラグインを導入してみる

試しにlessをcssコンパイルするプラグインを導入していきます.

プラグインの導入

$ npm install grunt-contrib-less --save-dev

Gruntfileへの記述

Json形式で(), {}がすごく多くなってしまうのでcoffeeスクリプトで書いて手抜きしm(ry

lessファイルは適当に作る感じです.

Gruntfile.coffee

module.exports = (grunt) ->
    # プロジェクトの設定
    grunt.initConfig
        less :
            build :
                src : "src/style1.less"       # 対象フォルダ
                dest : "build/styles.css"    # コンパイル先のフォルダ

  # プラグインのロード
  grunt.loadNpmTasks('grunt-contrib-less')

  #  デフォルトのタスクを指定
  grunt.registerTask('default', 'less');

gruntの実行

Gruntfile.coffee と同改装で下記コマンドを実行.

$ grunt

エラーの無いことを確認して次に進みます.

カスタムタスクを実行する

一般的な書式

less :
    build1 :
        設定1
    build2 :
        設定2
    buildN :
        設定N

デフォルトタスク以外にも個別でタスクを設定することもできる.

# tasks1のbuild1を実行するように書きなおす
# grunt.registerTask('default', 'less')
grunt.registerTask("build1", "less:build1")

実行は下記のコマンドで行う.

$ grunt build1

→ tasksに登録したものを個別実行される

タスクのターゲット指定の方法

コンパクト形式とファイルオブジェクト形式という2つの書き方がある.

コンパクト形式

less :
    build :
        src : "src/style1.less"      # 対象フォルダ
        dest : "build/styles.css"    # コンパイル先のフォルダ
    build2 :
        src: ['src/style1.css', 'src/style2.css']
        dest: "build/styles2.css"

ファイルオブジェクト形式

less :
  build :
     files :
        "build/style1.less" : "src/styles.css"    # コンパイル先のフォルダ : 対象フォルダ

ファイルオブジェクト形式では1対多のファイル対応をさせることができる

"build/styles.css" : ["src/style1.less", "src/style2.less"]

※ * を使えばコンパクト形式でも複数ファイルに対応することはできるがファイル名の指定などができない?

※ 公式サイト gruntjs.com/configuring-tasks に書き方が指示されている.

optionsの書き方

全てのタスクに共通したオプションとあるタスクにだけオプションを適用する2つの書き方がある.

grunt-contrib-lessのcompressオプションを使って実験.

全部のタスクに共通させる

task :
    options :
        compress: true
    target1 :
        src : "src/style1.less"
        dest : "build/styles.css"
    build2 :
        src: ['src/style1.css', 'src/style2.css']
        dest: "build/styles2.css"

あるタスクにだけ適用したい

targetの中に記述することでそのタスクにのみオプションを適用できる.

 task :
     target1:
         options:
             compress: true
         src : "src/style1.less"
         dest : "build/styles.css"
     target2 :
         src : "src/style1.less"
         dest : "build/styles.css"

コメントに関するオプション

圧縮された時に、コメントを消してほしくない(ライセンスとかコピーライターcommentに!をつける.

/*! comment */g

他のプラグインを使ってみる

プラグインをいくつか導入し、試しに使ってみます.

grunt-contrib-csslint

css の妥当性をチェックするプラグイン.

導入

$ npm install grunt-contrib-csslint --save-dev

使用例

Gruntfile.coffee

module.exports = (grunt) ->
    grunt.initConfig
        csslint :
            check :
                src: "<%= less.build.dest %>" # 変数を展開させることも可能

    grunt.loadNpmTasks('grunt-contrib-less')

    grunt.registerTask("default", "csslint"]);

grunt-contrib-cssmin

css圧縮するためのプラグイン.

導入

$ npm install grunt-contrib-cssmin --save-dev

gruntのtemplate変数でコメントに日付けを挿入するなどのことができる.

"/*! <%= grunt.template.today("yyyy-mm-dd") %> */"

他の変数を展開させることも可能

"<%= css.minify.src %>""

使用例

Gruntfile.coffee

module.exports = (grunt) ->
    grunt.initConfig
        cssmin :
            options :
                banner : "/*! <%= grunt.template.today("yyyy-mm-dd") %> */"
            minify :
                src : "build/styles.css"

    grunt.loadNpmTasks('grunt-contrib-cssmin')

    grunt.registerTask("default", "cssmin"]);

grunt-contrib-watch

ファイルの変更を監視し、自動でgruntを実行してくれるプラグイン

プラグインの導入

$ npm install grunt-contrib-watch

使用例

Gruntfile.coffee

module.exports = (grunt) ->
    grunt.initConfig
        watch :
            files: "src/*.less"
            tasks: ["less". "csslint", "cssmin". "watch"]
        less :
            build :
                src : "src/style1.less"
                dest : "build/styles.css"
        csslint :
            check :
                src: "<%= less.build.dest %>"
        cssmin :
            options :
                banner : "/*! <%= grunt.template.today("yyyy-mm-dd") %> */"
            minify :
                src : "build/styles.css"

    grunt.loadNpmTasks('grunt-contrib-less')
    grunt.loadNpmTasks('grunt-contrib-csslint')
    grunt.loadNpmTasks('grunt-contrib-cssmin')
    grunt.loadNpmTasks('grunt-contrib-watch')


    grunt.registerTask("default", ""watch"");

→ 指定したlessファイルに変更があったときに自動でgruntを実行する

※ watchを止めるには ctrl - cで止める

livereloadオプション

ファイルを監視し、変更があった場合にブラウザをリロードするためのプラグイン.

grunt-contrib-connect

擬似的にサーバを起動するためのプラグイン.

optiondでホスト名とポートを指定するとそこにアクセスできるようになる.

(Apacheを動かしているようなイメージ)

ちなみにconnectはNode.jsで広く使われているシンプルなWeb serverである.

導入

$ npm install grunt-contrib-connect

使用例

Gruntfile.coffee

module.exports = (grunt) ->
    grunt.initConfig
        connect : 
            server : 
                options :
                    port: 8080;
                    hostname; "192.168.33.1"
                    livereload: 35729


    grunt.loadNpmTasks('grunt-contrib-connect')

    grunt.registerTask("default", "connect"]);

livereloadオプション

ファイルを監視し、変更があった場合はブラウザをリロードするためのオプション.

オプションをつけるとlivereload.jsを自動作成してくれるため、それを編集中のhtmlから読み込む形になる.

index.htmlに下記のスクリプトを追加

<script src="http://192.168.33.76:35729/livereload.js">

※ 35729がデフォルトのポートとなっている

参考