*RubyでScalaスクリプトをコンパイル補助するツールを作成する。 [#vd683dab]
#contents

*仕様 [#df26398e]
**ツール1 タイムスタンプスナップ機能 [#ac9ea477]
フォルダ内の.scalaファイルのタイプスタンプのスナップを取得する。
**ツール2 更新ファイル抽出機能 [#g2830135]
既存のタイムスタンプと現在のファイルのタイムスタンプを比較し更新されたファイルを取得しコンパイル可能なバッチファイルを生成する


*scalacc.batの例 [#n0b705be]
-説明 このバッチファイルはSCALAファイルをコンパイルする際、ライブラリを自動的に取り込んでからコンパイルする

BASEが2回出てきているが、どちらも自動的にJarファイルを読み込みたいフォルダである。下記の例のように追加したいフォルダの数だけ繰り返し記述するとよいでしょう。 
 @echo off
 setlocal ENABLEDELAYEDEXPANSION
 set CP=.
 set BASE=C:\scala\lib
 for %%f in (%BASE%\*) do set CP=!CP!;%%f
 set BASE=C:\scala\lib\user
 for %%f in (%BASE%\*) do set CP=!CP!;%%f
 SET SCALA_DOC_HOME="C:\scala\doc"
 ECHO %CP%
 scalac -classpath %CP% %1


*ツール1 タイムスタンプスナップ機能 [#la5cc9ff]

**rubyのディレクトリ関連の処理 [#q1973441]
***ディレクトリ中のファイル一覧を取得する [#ic08cdb2]
-コード例
 p Dir::entries("/home/take")
--結果
 [".", "..", "WorkbookScala.scala"]

***ワイルドカードにマッチしたファイル全てに処理を行う [#nda0b89a]
-コード例
 p Dir::entries("/home/take")
--結果
 [".", "..", "WorkbookScala.scala"]
---注意点
 フォルダの区切り文字は\ではなく、/を使うこと

***ファイルのタイムスタンプを取得する [#ud2674ec]
-例
 s = File.stat("c:/scala/user/src/WorkbookScala.scala")
 puts File.mtime(fname).strftime("%Y/%m/%d %H:%M:%S") # 最終更新時刻
-結果
 c:/scala/user/src/WorkbookScala.scala
 2009/12/05 22:16:11

***snap_timestamp.rb [#hffed54a]
 path=ARGV[0].gsub("\\","/")
 ext="scala"
 outfile="timestamp.txt"
 
 buffer = ""
 # **は再帰的検索。\0は複数パターンの区切り。.*は隠しファイル取得
 Dir.glob("#{path}/**/*\0#{path}/**/.*" + ext).each{|name|
    puts name
    buffer = buffer + name + "\n"
    
	s = File.stat(name)
	timestamp = File.mtime(fname).strftime("%Y/%m/%d %H:%M:%S") # 最終更新時刻
	puts timestamp
	buffer = buffer + timestamp + "\n"
	
 } 
 
 # タイムスタンプスナップを上書き更新します。
 file = File.open(path + "/" + outfile, "w");
 # 書き込む
 file.write(buffer);
 file.close
 

-使い方
   ruby c:\scala\bin\snap_timestamp.rb "c:\scala\user\src"
--指定したフォルダにtimestamp.txtが出力されファイルのタイムスタンプのスナップショットがとれます。

**snap_timestamp_diff.rb [#a7a5adf5]
更新したファイルを出力する
 #第一引数はフォルダ名
 path=ARGV[0].gsub("\\","/")
 ext=/.*\.scala$/
 outfile="timestamp.txt"
 
 current={}
 
 # **は再帰的検索。\0は複数パターンの区切り。.*は隠しファイル取得
 Dir.glob("#{path}/**/*\0#{path}/**/.*" ).each{|name|
	if ext =~ name
		s = File.stat(name)
		current.store(name,File.mtime(name).strftime("%Y/%m/%d %H:%M:%S"))
	end
 }
 
 # タイムスタンプ保存用ファイル読み込み
 before={}
 file = open(path+"/"+outfile)
 buffer = file.read().split("\n");
 file.close
 
 #2行を1つの配列にまとめた配列を作成
 newItem=""
 newItem = nil
 buffer.each{|line|
	if newItem == nil
		newItem=line
	else
		if ext =~ newItem
			before.store(newItem,line)
		end
		newItem = nil
 	end
 } 
 
 
 #タイムスタンプの比較 更新・新規追加したファイルを出力
 current.each{|filepath, timestamp|
	if timestamp != before.fetch(filepath)
		puts filepath
	end
 }
-使い方 snap_timestamp_diff.rb "c:\scala\user\src"


***備考 [#w8c99c3c]
 RubyをWindowsのDOSで動作させるとRubyからバッチファイルを動作させる際に使用する
 システムのShellが使用している
-ruby\lib\ruby\1.8\shell\command-processor.rb
 のPathの分割処理がバグっているというかcygwinしか想定していないので、
 使えません。
 動かしてもwindows版rubyにはfork関数が最初から実装されていないっぽい。
 つまり複数プロセスの同時実行には対応していない。


*Scala でコマンドの実行結果を文字列として取得 [#m4deff0b]
**「java -version」を実行する例 [#ddc5fad5]
 	Runtime r = Runtime.getRuntime();
	Process p = r.exec("java -version");

**複数の引数の指定方法 [#dfda1e31]
	Runtime r = Runtime.getRuntime();
	Process p = r.exec(new String[] {
		"C:\\Program Files\\Java\\j2re1.4.2_13\\bin\\java",
		"-version" });

**「echo zzz」を実行する例 [#sc8628a2]
	Runtime r = Runtime.getRuntime();
	Process p = r.exec("cmd /c echo zzz");
 //	Process p = r.exec(new String[]{ "cmd", "/c", "echo", "zzz" });


**環境変数の指定 [#jab4f667]
	String[] env = new String[2];
	env[0] = "TEST=サンプル";
	env[1] = "PATH=" + System.getProperty("java.library.path");

	Runtime r = Runtime.getRuntime();
	Process p = r.exec("cmd /c echo %TEST%", env);


***参考URL 外部プロセス起動 [#qeb4d144]
http://www.ne.jp/asahi/hishidama/home/tech/java/process.html#Runtime

*外部プロセスを実行し標準出力と標準エラーを取得する。 [#c01df620]
**Actorをつかってスレッドプログラムを置き換えてみる [#md939dcd]
上記で紹介した外部プロセス起動のスレッドを使ったコードはこちら
 import java.io.*;
 import java.util.*;

 /**
  * InputStreamを読み込むスレッド
  */
 public class InputStreamThread extends Thread {
 
	private BufferedReader br;
 
	private List<String> list = new ArrayList<String>();
 
	/** コンストラクター */
	public InputStreamThread(InputStream is) {
		br = new BufferedReader(new InputStreamReader(is));
	}
 
	/** コンストラクター */
	public InputStreamThread(InputStream is, String charset) {
		try {
			br = new BufferedReader(new InputStreamReader(is, charset));
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}
 
	@Override
	public void run() {
		for (;;) {
			try {
				String line = br.readLine();
				if (line == null) 	break;
				list.add(line);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
	}
 
	/** 文字列取得 */
	public List<String> getStringList() {
		return list;
	}
 }

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS