Lua用LTSVパーサを書きました。

# GitHub リポジトリ

* [zaneli/lualtsv](https://github.com/zaneli/lualtsv)


…といってもLTSVのパース自体は大して難しくないので、環境設定から単体テスト、モジュール作成までの一連の流れを備忘として残しておく。

# Lua のインストール

Centos6.5には始めからLua 5.1.4が入っていたので(現時点の最新安定板は5.2.3のようだが)そのまま使うことにする。

```
> which lua
/usr/bin/lua

> lua -v
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
```

# 実装

[Ruby版パーサ](https://github.com/condor/ltsv)を参考に
文字列からテーブル(Luaの連想配列)を作る `ltsv.parse` 関数、
ファイルから読み込んでテーブルを作る `ltsv.load` 関数、
テーブルから文字列を作る `ltsv.dump` 関数を用意した。
どうも、文字列を分割するsplit関数的なものが標準には無いらしく、
`string.gmatch` 関数や `string.match` 関数を使って分割することにした。
`ltsv.dump` では一度テーブルを作り直してから `table.concat` してみたが、あまり効率良くない気がする…
もう少し良い書き方があるかな…。

# [LuaRocks](http://luarocks.org/) のインストール

ruby の gem のようなものらしい。
ユニットテストフレームワークの導入のため必要そうだったので入れる。

```
> curl -O http://luarocks.org/releases/luarocks-2.2.0.tar.gz
> tar zxf luarocks-2.2.0.tar.gz
> cd luarocks-2.2.0
> ./configure

Lua interpreter: /usr/bin/lua...
Lua version detected: 5.1
lua found in $PATH: /usr/bin
Checking Lua includes... lua.h not found (looked in /usr/include, /usr/include/lua/5.1, /usr/include/lua5.1)
You may want to use the flag --with-lua or --with-lua-include. See --help.

configure failed.
```

lua.h ヘッダファイルが無いため失敗してしまった。lua-develを先に入れる。

```
> sudo yum install lua-devel

Installed:
  lua-devel.x86_64 0:5.1.4-4.1.el6

> ./configure
> make build
> sudo make install

> which luarocks
/usr/local/bin/luarocks
```

# ユニットテスト

[busted](http://olivinelabs.com/busted/) を使ってみる。

```
> luarocks install --local busted

Error: Failed installing dependency: https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/ansicolors-1.0.2-3.src.rock - Failed unpacking rock file: /tmp/luarocks_luarocks-rock-ansicolors-1.0.2-3-8489/ansicolors-1.0.2-3.src.rock
```

ぬぬぬ…bustedが依存しているモジュールの ansicolors が見つからないと言われているのかな？
いや見つかったけどアンパックできないと言われているような…。
`--verbose`つけて再トライ。

```
> luarocks install --local --verbose busted

os.execute: 	cd '/tmp/luarocks_ansicolors-1.0.2-3-8776' && unzip -n '/tmp/luarocks_luarocks-rock-ansicolors-1.0.2-3-4292/ansicolors-1.0.2-3.src.rock'
sh: unzip: コマンドが見つかりません
```

…単に `unzip` コマンドが入ってないだけだった…。

```
> sudo yum install unzip

Installed:
  unzip.x86_64 0:6.0-1.el6

> luarocks install --local busted

Using https://rocks.moonscript.org/luafilesystem-1.6.2-2.src.rock... switching to 'build' mode
gcc -O2 -fPIC -I/usr/include -c src/lfs.c -o src/lfs.o
sh: gcc: コマンドが見つかりません

Error: Failed installing dependency: https://rocks.moonscript.org/penlight-1.3.1-1.src.rock - Failed installing dependency: https://rocks.moonscript.org/luafilesystem-1.6.2-2.src.rock - Build error: Failed compiling object src/lfs.o
```

ぬー、gcc入れて再トライ。

```
> sudo yum install gcc

Installed:
  gcc.x86_64 0:4.4.7-11.el6

Dependency Installed:
  cpp.x86_64 0:4.4.7-11.el6          glibc-devel.x86_64 0:2.12-1.149.el6_6.4          glibc-headers.x86_64 0:2.12-1.149.el6_6.4          kernel-headers.x86_64 0:2.6.32-504.3.3.el6

Dependency Updated:
  glibc.x86_64 0:2.12-1.149.el6_6.4              glibc-common.x86_64 0:2.12-1.149.el6_6.4              libgcc.x86_64 0:4.4.7-11.el6              libgomp.x86_64 0:4.4.7-11.el6

> luarocks install --local busted

busted 2.0.rc5-0 is now built and installed in /home/zaneli/.luarocks (license: MIT <http://opensource.org/licenses/MIT>)
```

やっとインストールできた！

テストコードは[この辺](http://thejacklawson.com/2012/09/lua-testing-with-busted-and-travis-ci/)を参考に書いてみる。

# CI
[Lua Testing with Busted and Travis-CI](http://thejacklawson.com/2012/09/lua-testing-with-busted-and-travis-ci/)を参考に .travis.yml を書く。
この記事では `language: erlang` に設定しているが、`language: bash` でも問題ないようだ。

# rockspec ファイルの作成

`luarocks` でインストールして使えれば便利かな、と思ったのでやってみたが、
これがいまいちよく分かっていない…。
とりあえず他のLuaリポジトリなど参照しながら見よう見まねでやってみた。

```
> luarocks --local install https://raw.githubusercontent.com/zaneli/lualtsv/master/lualtsv-0.0-1.rockspec
```

↑でGitHubからインストールされるようにできたようだが、インストール先が

* /usr/local/share/lua/5.1/lualtsv.lua
* /home/<ユーザー>/.luarocks/share/lua/5.1/lualtsv.lua (--local指定時)

で、Luaパスが通っているのが

```
> lua -e 'print(package.path)'
./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib64/lua/5.1/?/init.lua
```

なので、普通にLua対話環境を立ち上げてもインストールしたモジュールを見つけられない。

```
> require("lualtsv")
stdin:1: module 'lualtsv' not found:
	no field package.preload['lualtsv']
	no file './lualtsv.lua'
	no file '/usr/share/lua/5.1/lualtsv.lua'
	no file '/usr/share/lua/5.1/lualtsv/init.lua'
	no file '/usr/lib64/lua/5.1/lualtsv.lua'
	no file '/usr/lib64/lua/5.1/lualtsv/init.lua'
	no file './lualtsv.so'
	no file '/usr/lib64/lua/5.1/lualtsv.so'
	no file '/usr/lib64/lua/5.1/loadall.so'
stack traceback:
	[C]: in function 'require'
	stdin:1: in main chunk
	[C]: ?
>
```

仕方が無いのでLUA_PATHに追加する。

```
> lua -e 'print("export LUA_PATH=\"" .. package.path .. "\"")' >> ~/.zshrc
> echo 'export LUA_PATH="$HOME/.luarocks/share/lua/5.1/?.lua;$LUA_PATH"' >> ~/.zshrc
> source ~/.zshrc

> echo $LUA_PATH
/home/zaneli/.luarocks/share/lua/5.1/?.lua;./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib64/lua/5.1/?/init.lua
```

これで lualtsv を読み込めるようになった。
うーん…しかしこれは rockspec ファイルの書き方や luarocks コマンドの使い方を間違えているような気がしないでもない…。