プログラミングHaskellでHaskellことはじめ


あらすじ

やりたいことがあるのだけど、調べていたらHaskellでやってみました系の記事が多い気がしたので読めるようになりたい!

参考

※ とても良書だと思うのだけど、超初心者が挑むには早すぎたので、以下の簡単なライブラリを使用してみた後は「すごいHaskell」にいったん移行しました。

(本の中の記述が数学記号で書かれているのが予想外にキツい。記号の意味はわかるんだけど、 Haskellでの書き方が わからないので脳内で数学記号をHaskellに戻して…をやっていると全く進まなかった…。一周目はまず無心で写経しないとダメなタイプ)

インストール

Haskell入門 5ステップ - HaskellWiki によると、HaskellはGHCかHugsのどちらかで行けるよう。

ただし、Hugsはもうメンテナンスされていないみたい。

Hugs

Downloading Hugs からDL。Windows版は.exeなのでそのままインストール。

GHC

The Glasgow Haskell Compiler からDL。これもWindows版は.exeがあるのでそのままインストールできる。

※ これよりもHaskellPlatformも入れた方が良いらしい。オールインワン的な?

Downloadページには Bundled packages and cabal-install と書かれている。cabalとは


Cabal is a system for building and packaging Haskell libraries and programs.


パッケージを作る…とかはまだ必要ないと思うけど。The Haskell Cabal からDLできるのだが、setupファイルが.hsで、Haskellファイルのようなので、Haskellを入れてからsetupする感じか。まだいらない。

ghciのコマンド

コロンから始まるいろいろなコマンドでファイルをロードしたり、ghciを終了したりできる。まずは脱出できるように。

変数

小文字から始まればよいみたい。意外なのはシングルクォーテーションが使えること。まじか。

test.hsとして、関数をこう定義する。

double x' = x' + x'

ghciから呼ぶ。

Prelude> :load test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> double 13
26

呼べる!

Hello World

以下ghcとghciを使ってやっていく。

インストールが完了したらコマンドプロンプトを起動し、 ghci と入力。

> ghci
GHCi, version 7.6.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude>

とりあえずよくわからないが、Hello World

Prelude> "Hello World"
"Hello World"
Prelude> putStrLn "Hello World"
Hello World

ファイルに記述してコンパイルして実行させる事もできる。 hello.hs ファイルを作って以下のように記述する。

main = putStrLn "Hello World"

コンパイル。

$ c -o hello hello.hs
[1 of 1] Compiling Main ( hello.hs, hello.o )
Linking hello.exe ...

成功したらhello.exeというファイルができているので実行してみる。

$ hello.exe
Hello World

階数を求める

fac.hs として以下のようなファイルを作る。

fac n = if n == 0 then 1 else n * fac (n-1)

なんか、右辺はなんとなく読めるな。

$ ghci
GHCi, version 7.6.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :load fac.hs
[1 of 1] Compiling Main ( fac.hs, interpreted )
Ok, modules loaded: Main.
*Main> fac 2
2
*Main> fac 3
6
*Main> fac 4
24
*Main> fac 42
1405006117752879898543142606244511569936384000000000

標準ライブラリを使う

head

リストの先頭を取得。

Prelude> head [2,4,5]
2
Prelude> head [4,2,5]
4

tail

リストから先頭の要素を取り除く。

Prelude> tail [1,2,3,4]
[2,3,4]
Prelude> tail [2,3,1,4]
[3,1,4]

!! n

リストのn番目の要素を取得。

Prelude> [1,2,3,4,5] !! 2
3
Prelude> [1,2,3,4,5] !! 7
*** Exception: Prelude.(!!): index too large

take n

リストの先頭からn個の要素を取得する。多く指定してもよい。

Prelude> take 1 [1,2,3,4,5]
[1]
Prelude> take 4 [1,2,3,4,5]
[1,2,3,4]
Prelude> take 9 [1,2,3,4,5]
[1,2,3,4,5]

drop n

先頭からn個の要素を削除する。多く指定してもよい。

Prelude> drop 1 [1,2,3,4,5]
[2,3,4,5]
Prelude> drop 3 [1,2,3,4,5]
[4,5]
Prelude> drop 9 [1,2,3,4,5]
[]

length

要素のサイズを取得する。

Prelude> length [1,2]
2
Prelude> length [1,2,3,4,5]
5

sum

リストの要素の和を返す。

Prelude> sum [1,2,3,4]
10

product

リストの要素の積を返す。

Prelude> product [8,8]
64

++

リストの連結を行う。

Prelude> [1,2,3] ++ [1,2,3]
[1,2,3,1,2,3]

reverse

リストの要素を逆転させる。

Prelude> reverse [1,2,3,4,5]
[5,4,3,2,1]

‘div’

divはできなかった。 くくるのはシングルクォーテーションじゃなくてバッククォートだった!

Prelude> 2 'div' 1

<interactive>:25:3:
Syntax error on 'div'
Perhaps you intended to use -XTemplateHaskell


練習問題

2章の練習問題にあったリストの最後を取得する。

*Main> head (reverse [1,2,3,4,5])
5

2012年KPT

今年学んだこと


  • Ruby

    • Jekyll

      • ブログをGitHub Pagesに移そうかなーと目論み、色々運用法などを試行錯誤

      • それに伴い、Markdown書式も勉強



    • Selenium

      • Seleniumスクリプトを書いてみた

        • 社内の勤怠管理システム(Web)に毎日毎日毎日手動で時刻をポチポチ入れてると体調が崩れそうになるので、時刻を取得してぶっこむ!(使い方がアレかもしれない……)







  • Git

    • git-svnを実践に投入してみた



  • Jenkins


Keep


  • 引き続きGitを使う

    • さしあたり、もう少しsvnプロジェクトをgit-svnで使っていく



  • Jenkinsは「CIに使わなければならない」という(思い込みの)呪縛から解き放たれたということで、ドンドン使っていく

    • Redmineに登録されている不具合チケットをぶっこぬいて社内標準の不具合管理表に流し込む作業や、プロジェクトでやり取りしてるメールの添付ファイルだけをぶっこぬいて共有サーバの「受領ファイル」フォルダに突っ込む作業や上述のSeleniumスクリプトを毎日動かす程度に使い倒している

    • あとはAntの実行にも



  • 去年のTryに挙げていたブログ月一更新は達成できた


  • Advent Calendarは二年連続二回目の投稿

Problem


  • Objective-C復習

    • 一時期必要に迫られたので、少し本で勉強しイケるようになった……と思ったのに、数ヶ月ブランクがあくとまったく読めなくなっていた



  • gemを作れるようになれなかった

    • 去年のTryの残件を引き続き



  • 社内スクリプトの汎用化→GitHubへ

    • これも去年のTry



  • DropboxEvernoteAPIをもう少し使えるようになる

Try


  • 新しい言語を学ぶ

    • 候補はHaskell

      • 今、自分がやりたいことを実現している記事がWeb上に多い言語→見ても何しているのかさっぱりわからん……

      • なので、学びはじめる





  • TDDやるやる詐欺からの脱却

    • TDDBCに参加し、ちょっとずつ書くように意識はできるようになったのでもう少し



  • Advent Calendar以外でも何か発表したい!(去年と同じ)

  • 友達をつくる

    • 社内にGitとかJekyllとかの話が出来る人がおらんのよ



来年もがんばろう。

メモ化を知った

この投稿はRuby Advent Calendar 2012の16日目の記事としてQiitaに投稿したものです。

はじめに

あんまりRuby関係ないんですが、一応、The RSpec Bookを読んでいて知ったのがきっかけなので…。

あらすじ

The RSpec Book のletの解説には以下のように記述されています。

   describe "テストコードはてきとう" do
let(:test) { "TEST" }
it "test let" do
test.should == "TEST"
end
end


メソッドが最初に呼び出されたときに戻り値がキャッシュされ、それ以降、同じスコープ内でメソッドが呼び出されるたびにキャッシュされた値が返されることを意味します。


これをメモ化というそうです。で、メモ化って?

一番簡単なメモ化

調べてみると、だいたいフィボナッチ数を求める例が多い。なのでn番目のフィボナッチ数を求めるメソッドを書いてみる。

普通に書いた場合

def f(n)
if n <= 1 then
n
else
f(n-1) + f(n-2)
end
end

実行していくと、己のPCスペックではf(30) = 832040 くらいからマシンがもたついてきた。

これを メモ化 してみる。

メモ化した場合

# こっちは変わらず
def f(n)
if n <= 1 then
n
else
f(n-1) + f(n-2)
end
end
def f_memo(n)
@cache ||= []
@cache[n] ||= f(n)
end

実行すると、最初の一発目は同じくらい遅いんだけど、一回実行すればキャッシュとして @cache に格納されるので二回目以降はバク速で求められる。

||= とは

上の例の @cache[n] ||= f(n)@cache[n] = @cache[n] || f(n) と同義。@cache[n]が真ならば@cache[n]を返す。偽ならnのフィボナッチ数を求める。 @cache[n]が真ならば、f(n)は評価しない、実行しない 。だから早い。

||=の例。

irb(main):001:0> a          # 未定義の時はエラー
NameError: undefined local variable or method `a' for main:Object
from (irb):1
from C:/rubies/Ruby-193-p0/bin/irb:12:in `<main>'
irb(main):002:0> a ||= 500 # a || 500 a は偽なので500
=> 500
irb(main):003:0> a
=> 500
irb(main):004:0> b = 0
=> 0
irb(main):005:0> b
=> 0
irb(main):006:0> b ||= 500 # b || 500 b は真なので0のまま
=> 0
irb(main):007:0> b
=> 0

…って所まで調べて、初めてのRubyを読み返してみたらバッチリ書いてあるし!!

初期化イディオム として紹介されていました。。。

git-svnインストールからgit svn dcommit完了までの手順

あらすじ

CentOSのインストール時に入れたGitにはgit-svnが入っていない(?)ので、一から入れようとしたが、ネットに繋がっていない環境だと結構依存とかがめんどくさかったのでメモ。

環境


  • CentOS 6.2

  • Git 1.7.1

    • git は入っているが、git svnは実行できない



$ git svn 
git: 'svn' is not a git command. See 'git --help'.


  • svn 1.6.11 (r934486)

  • ネットにつながっていないぼっち環境

yumとかで入れられると一発っぽいんだけどなー。

手順

まずは、git-svnのrpmをDLしてくる。

インストールしたいPCに持ってきて、rpmコマンド。 perl(SVN::Core) と、 perl(Term:ReadKey) がないと言われる。

# rpm -ivh git-svn-1.7.1-2.el6_0.1.noarch.rpm
警告: git-svn-1.7.1-2.el6_0.1.noarch.rpm: ヘッダ V3 RSA/SHA256 Signature, key ID c105b9de: NOKEY
エラー: 依存性の欠如:
perl(SVN::Core) は git-svn-1.7.1-2.el6_0.1.noarch に必要とされています
perl(Term::ReadKey) は git-svn-1.7.1-2.el6_0.1.noarch に必要とされています

perl(SVN::Core)

SVN::Coreは subversion-perl というパッケージから入れられるよう。

subversion-perlをDLしてインストール。

# rpm -ivh subversion-perl-1.6.11-7.el6.i686.rpm
警告: subversion-perl-1.6.11-7.el6.i686.rpm: ヘッダ V3 RSA/SHA1 Signature, key ID c105b9de: NOKEY
エラー: 依存性の欠如:
subversion = 1.6.11-7.el6 は subversion-perl-1.6.11-7.el6.i686 に必要と されています

あれ?Subversion入ってるのに見つけられてない?Subversionを入れ直してみる?

# rpm -ivh subversion-1.6.11-7.el6.i686.rpm
警告: subversion-1.6.11-7.el6.i686.rpm: ヘッダ V3 RSA/SHA1 Signature, key ID c105b9de: NOKEY
準備中... ########################################### [100%]
ファイル /usr/bin/svnserve (パッケージ subversion-1.6.11-7.el6.i686 から) は、パッケージ subversion-1.6.11-2.el6_1.4.i686 からのファイルと競合しています。


やっぱインストール済み…1.6.11-2.el614…だと…。このrelease番号?ってsvn –versionじゃ確認できないの?

# svn --version
svn, バージョン 1.6.11 (r934486)
コンパイル日時: Sep 27 2011, 14:59:40

Copyright (C) 2000-2009 CollabNet.
Subversion is open source software, see http://subversion.tigris.org/
This product includes software developed by CollabNet (http://www.Collab.Net/).

以下のリポジトリアクセス (RA) モジュールが利用できます:

* ra_neon : Neon を利用して WebDAV (DeltaV) プロトコルでリポジトリにアクセスするモジュール。
- 'http' スキームを操作します
- 'https' スキームを操作します
* ra_svn : svn ネットワークプロトコルを使ってリポジトリにアクセスするモジュール 。
- Cyrus SASL 認証を併用
- 'svn' スキームを操作します
* ra_local : ローカルディスク上のリポジトリにアクセスするモジュール。
- 'file' スキームを操作します


色々探して、とりあえず1.6.11-2.el614のsubversion-perlを見つけた。

再チャレンジ。

# rpm -ivh subversion-perl-1.6.11-2.el6_1.4.i686.rpm
警告: subversion-perl-1.6.11-2.el6_1.4.i686.rpm: ヘッダ V4 DSA/SHA1 Signature, key ID 192a7d7d: NOKEY
準備中... ########################################### [100%]
1:subversion-perl ########################################### [100%]

入ったー。で、依存は一個消えた。

# rpm -ivh git-svn-1.7.1-2.el6_0.1.noarch.rpm
警告: git-svn-1.7.1-2.el6_0.1.noarch.rpm: ヘッダ V3 RSA/SHA256 Signature, key ID c105b9de: NOKEY
エラー: 依存性の欠如:
perl(Term::ReadKey) は git-svn-1.7.1-2.el6_0.1.noarch に必要とされています

perl(Term::ReadKey)

特にバージョンの指定がないんだけど、とりあえず後ろ(el6)は合わせてみた。elってRHELのELなのかな…?

[root@tpc6102 share]# rpm -ivh perl-TermReadKey-2.30-13.el6.i686.rpm
警告: perl-TermReadKey-2.30-13.el6.i686.rpm: ヘッダ V3 RSA/SHA1 Signature, key ID c105b9de: NOKEY
準備中... ########################################### [100%]
1:perl-TermReadKey ########################################### [100%]

いった!

で、git-svnも入った!

動作確認

コミットしようとしたらエラーが。

$ git svn dcommit
Committing to svn://xxxxxxx/repo/trunk ...
Authentication realm: <svn://xxxxxxx:3690> xxxxxxxx-...

(gnome-ssh-askpass:20438): Gtk-WARNING **: cannot open display:
Use of uninitialized value $password in substitution (s///) at /usr/libexec/git-core/git-svn line 3979.
error: git-svn died of signal 11


GUILinuxをインストールしている場合、 gnome-ssh-askpass を使ってパスワード認証をかますようにパスが通っており、今はtelnetなどでつないでいる(=認証画面出したいのに画面ない)のが問題みたい。

確かにいる。

$ echo $SSH_ASKPASS
/usr/libexec/openssh/gnome-ssh-askpass

これを空にしてやればよい。

$ unset SSH_ASKPASS
$ echo $SSH_ASKPASS

で、dcommit!

$ git svn dcommit
Committing to svn://xxxxxxxx/repo/trunk ...
Authentication realm: <svn://xxxxxxxx:3690> xxxxxxxxxxx.....
Password for 'kk_Ataka':

パスワード認証もOK。

M       memo/test.txt


コミットされた!

はてなダイアリーのエントリをJekyllへ移行する


あらすじ

はてなダイアリーからJekylに移行したいんだけど、完全に移行し切るには過去の遺産(はてなダイアリーのエントリ)も移したいよ。

はてなのエントリ取得

何はなくともエントリをエクスポートしてこない事には始まらない。管理画面から データ管理 => インポート/エクスポート => はてなの日記データ形式 をDL。

はてな => Jekyll

どうやるか

はてなのエントリをJekyllで見るためには、恐らく2通りの方法がある。


  1. はてなエントリをMarkdown記法に変換して、Jekyllに突っ込む

  2. はてなエントリから記事を作れるようにJekyllにパーサを突っ込む

さて…。

てっく煮ブログさんのJekyll

俺の最強ブログ システムが火を噴くぜ - てっく煮ブログ

自分がどうすればいいのかなーと悩んでいる時、ものすごくタイムリーに移行なされており(タイムリーでした)、かつ自分のやりたい事(はてなエントリの移行など)を全てプラグインなどで実現されていたためすぐにGitHubを見に行きました。

nitoyon/tech.nitoyon.com ・ GitHub

$ git clone https://github.com/nitoyon/tech.nitoyon.com.git

ぐ…中身は結構複雑。

ソースを見る前にローカルで動くか見せてもらおうっと。

$ vi Gemfile

gem 'jekyll'
gem 'hparser'
gem 'sass'
gem 'RedCloth'
gem 'rdiscount'


これで bundle exec jekyll --server で行けるかと思ったけど、なんか色々ないって言われる。

どうやらまだgemが最新版になっていないらしい(gemからJekyllを持ってくると、多分 JEKYLL_HOME/lib/jekyll/tags/post_url.rbがないとか言われる)ので、GitHubから最新版を持ってくる。

$ git clone git://github.com/mojombo/jekyll.git # fa8400ab61cb8df176f9fb2ec52d85f93c7418a7より新しければ大丈夫そう
$ git clone git://github.com/hotchpotch/hparser.git # 4fbeefc8becc45ed18bf374bec9a2d862db473d5より以下同文

Jekyllとhparserはこれに置き換え。これで実行すると…おお、自分のローカルでてっく煮ブログが…!

なんとなく動かして、どうなっているか色々見てみる。

コンバート

それでは、いよいよはてなのエントリ.xmlをhogehoge.htn * n個 のファイルにコンバートする。以下の作業は全て上記のてっく煮さんのブログをcloneした中を間借りして行なっている。己のリポジトリで行なってもできる。


  • Gemfileに nokogiri を追加する

$ vi Gemfile

gem 'nokogiri' # コンバート用



  • _scripts/ 直下に _posts_caches ディレクトリを作る

  • bundle exec ruby convert_hatena_to_jekyll_posts.rb HATENA_ID はてなのエントリ.xml を実行!

  • ……が、途中で止まる。どうやらUrl先のtitleを探しに行くとき、対象が404だった場合例外を吐くらしい


対象のコンテンツが 404 になっている場合には例外が出てスクリプトが停止します。
その場合は _caches/url_title.json に手動でエントリを追加する、元のエントリを
修正する、などして回避してください。


との事なので、止まっては修正止まっては修正。最後まで行くと、hogehoge.htnの山が_posts下に築かれる。

※ これをskipがなくなるまでやる(スーパーpreの中の文頭にアスタリスクがあるとダメみたい(Gitのグラフなどダメだった))

……が。あれ? はてなダイアリーの記事のタグが複数あってもhogehoge.htnにコンバートされると先頭の1個しか指定してくれていない?

parse_dayメソッドをいじってみる…。

    unless m = title.match(/^\*([^*]+)\*(\[.*\])(.*)/)

     tags[0].gsub!("][", ",")
tags[0].gsub!("[", "")
tags[0].gsub!("]", "")
tags = tags.join(",")
tags.gsub!(",", ", ")

content = {
"layout" => "post",
"title" => name_ja,
"description" => "",
"catecory" => "",
"tags" => tags + "]",
"old_url" => "http://d.hatena.ne.jp/#{hatena_id}/#{old_url}",
}.to_yaml

content.gsub!("tags: ", "tags: [")

content = content + "---\n" + convert_text(text, hatena_id)


これで、やりたいことができた……。

が、yamlの扱い方がよくわからん。hogehoge.htnファイルのtagsとして tags: [aaa, bbb, ccc] って出力したかったんだけど、配列の記述のまま "[aaa, bbb, ccc]" to_yamlすると hogehoge.htn内で ! ' [aaa, bbb, ccc] ' こう出力されてしまったので力技でうまくいくように。

まあ一回しか変換しないしいっか……。

これではてなダイアリーの全ての記事がhogehoge.htnとして _posts ディレクトリに生成された。

あとはこれを己のJekyllの _posts に放り込み、コンバートは完了。

起動/変換

最後にJekyllでhogehoge.htnファイルを静的ファイルに変換する。てっく煮さんのpluginがいくつかないと正常に変換されず、途中で止まるかも。

(要確認)とりあえず _plugins 下にこんだけあれば動いた。ここははてなダイアリーで使っている記法による?amazonを使ってなければamazon.rbはいらないかもしれない。

converters
┣ hatena.rb
┣ ext
┃┗ post_to_liquid_raw.rb
┣ filters
┃┣ json_filter.rb
┃┣ locale_filter.rb
┃┗ simplify_rss_description.rb
┗ tags
┣ amazon.rb
┣ post_link.rb
┣ tweet.rb
┣ twitter.rb
┗ youtube.rb

プロジェクトのGemfileでは Jekyllhparser をGutHubから最新のものを持ってくればそれで良いかな。(そのうちgemでも取れるようになると思うが)あと albino じゃなくて pygments.rb を使うようにする。

自分用TODO


  • おかしい

    • 2009-10-19-1255949562.htn

    • 2011-05-01-1304204171.htn

    • 2011-10-08-1318068887.htn

    • 2011-11-27-1322329546.htn

    • 2011-11-28-1322482230.htn

    • 2011-12-16-1324086694.htn



Jekyll(Liquid)で記事の目次を出力するプラグインを作ってみた


あらすじ

Jekyllのプラグイン作成の練習。エントリから見出しを抽出して目次を出力してみたい。

参考サイト

ソース

まだできてない事


  • 記事中に h1 (#) タグがあるとうまく生成されない

    • 記事タイトルが h1 (#) なので、 h2 (##) 以下の見出しを集めてくるようにしている



  • 目次から記事へのリンク

    • Markdownでは ## <a name="section"> hoge と記載すればnameを振ってくれるようだけど、めんどいので自動で振ってほしい

    • むしろ今はaタグを入れているとレイアウトが崩れる

      • …あれ? 別の環境でやったら hタグに section , section-1 , section-2 … って連番が振られてる!? なんで!





作り方

最小単位はこうなるみたい。(何もしないプラグイン)

module Jekyll
class SampleTag < Liquid::Tag
def initialize(tag_name, xxx, tokens)
super
end

def render(context)
end
end
end

Liquid::Template.register_tag('sample', Jekyll::SampleTag)


これでMarkdown中に {% sample hogehoge fuga %} と書くと、initializeメソッドの tag_name にsample、 xxx にhogehoge fuga、 tokens に本文が渡される。

という事でタグにつけた引数や本文を使う場合はinitializeで確保しとく。

renderメソッドでreturnした文字列がそのままページに出力される。

※ 新しくタグを作ったときは、Jekyllを再起動しないと Unknown tag が出続ける。


  • 己のJekyll下の _pluginstree_list.rb を突っ込む

  • html(postするMarkdownファイルでもいいし、テンプレートのhtmlでもいい)のどこかに {% tree %} を埋め込む

  • $ jekyll --server 実行後localhost:4000にアクセス

これで文中の見出しが目次としてかき集められる。ただし、GitHub Pagesを使っている場合はソースをそのままpushするだけではダメで、対策が必要っぽい。

bundle execを省略したいのでバッチを作った(Windows版)

あらすじ

Bundler、非常によいツールなんだけど、bundle exec がめんどい。

ググってみたところ gemset を使う方法 rvmのgemsetを使ってbundlerと賢く付き合う方法 - Hello, world! - s21g と、 bundler-exec.sh というツールを使う bundle exec を省略する - おもしろWEBサービス開発日記 方法があるみたい。

Windowsでこれを実現したいんだけど、gemsetはちょっと大げさな気がするので、bundler-exec.shを参考にバッチファイルを作成できないかな。

参考サイト

調査

ソースを読む限り、やっている処理は


  1. ruby とか rspec とかbundle exec hogehogeしたいコマンドにaliasをはる(rubyならbundler-exec.sh rubyとなるように)

  2. bundle コマンドが使えるのか探してみる。使えない場合はそのままコマンドを実行する

  3. bundle が使える場合、今いるパスに Gemfile ファイルがあるのか調べる。ない場合は一つ階層を上がってまた Gemfile があるか探す

  4. 上記をを繰り返す。 Gemfile がない場合はそのままコマンドを実行する

  5. Gemfile があった場合、 bundle exec を付加してコマンドを実行する

という感じになっている。

ソース

で、作ってみた。

gosyujin/bundler-exec-bat

使い方

aliasをはる

コマンドプロンプトの場合にはaliasがないようなので、マクロ定義ファイルを作成し、それを起動時に読むようにバッチファイルを作る。または起動オプションを変更する必要があるらしい。(レジストリに登録などでもいい)

定義ファイルは以下のように記述する。とりあえずruby, rspec, herokuを使えるように。必要なコマンドは適宜このファイルに追加する事になる。

heroku=bundler-exec heroku $*
rspec=bundler-exec rspec $*
ruby=bundler-exec ruby $*

定義ファイルを読み込む場合は

> doskey /macrofile=MACRO_FILE

alias(マクロ)を確認するには

> doskey /macros

それ以降

それ以降の処理は bundler-exec.bat に記述している。

バッチファイルをがっつり書く機会もあまりなかったので、結構試行錯誤。(pwdをWindowsで実現させるには? コマンドの実行結果を変数に格納するには? while文ないの? 等々)

とりあえず、動く版を作る事ができた。一応、Documents and Settings下でも実行できたのでパスにスペースが入っていても大丈夫そう。

これをパスが通っているところに放り込み、下記のようなfizzbuzzディレクトリで実行してみる。

C:\fizzbuzz
┣.bundle
┣Gemfile
┣Gemfile.lock
┣fizzbuzz.rb
┣autotest/
┣spec/
┗vendor/
┗bundle
┗ruby
┗1.9.1
┗…

まずは普通に。

$ ruby fizzbuzz.rb 3
bundler is found: bundle exec ruby fizzbuzz.rb 3
Fizz

ちょっと下の階層から実行しても、無事にGemfileを探してbundle exec。

$ cd autotest\
$ ruby ../fizzbuzz.rb 5
bundler is found: bundle exec ruby ../fizzbuzz.rb 5
Buzz

Gemfileを消して Ruby コマンド実行。

$ ls
autotest/ fizzbuzz.rb* spec/
$ ruby fizzbuzz.rb 15
bundler is NOT found or Gemfile is NOT found: ruby fizzbuzz.rb 15
FizzBuzz

ちゃんと bundle exec なしで実行できた!

残件


  • なんか重い

結構力技でやってるから…? またはテストしてるPCがヘボいから?