続き書いた
下記で言及したFileList作ってみた
前置き
なんか、Grunt, Gulp界隈、「タスクランナー疲れ」みたいなポストがちらほらありますな。それに乗じて(笑)rakeを勧めている人なんかもいらっしゃいますが、
「Perl, Ruby, Python はどれかひとつ覚えときゃいい」
「ほほう。じゃ、Perl分かるからスキップでいっか」
と何気なくRuby, Pythonをスルーしてしまったおじさんには悲しいのだ。と言うわけで、タスクランナーなんて使わずに、ちょっとした便利関数をrequireして、
forever start -c coffee /path/to/tools/automake.coffee
でいいんじゃね?(もちろん、automake.coffeeがタスクランナーっちゅうか、自製生書き監視&タスク管理スクリプトだよ)
で、そういうことをしようとすると、その「ちょっとした便利関数」にrakeっぽいFileListとか、run(target, depedencyfiles, {watch: on}, func)みたいなのが欲しくなる。まあ、ちょろちょろと空き時間に書いてアップしようと思うが、それで良くないかい?
そのための最初の「ちょっとした便利関数」
とりあえず、FileList作るんなら、ワイルドカード欲しいよね。asterisk, globstar, question, bracket, braceが使えればそれで良いよね。変換ルールは下記
- 正規表現と被る表記全部
- エスケープしといた
- *
- [^/]* パス区切り以外の全ての0回以上繰り返し
- **
- .* パス区切りを含めた全ての0回以上繰り返し
- ?
- [^/] パス区切り以外の全て(1文字)
- {foo,bar}
- (foo|bar) 選択
- [a-z]
- [a-z] つーか、触ってない!
- 文末
- $ ワイルドカードの意味って、後方一致だよね
あれ? どこぞのシェルとかツールに採用されてる globstar「**」って、/path/**/hoge と書いたら /path/hoge にマッチすんの? するとしたらこれじゃ違うね。まあ、そこは突っ込みがあれば直す感じ。なんかシェルによって違うとかちらっと聞いたけどさ。
なんだかんだ言って直した方がよさげなので、/path/**/hoge と書いたら /path/hoge にマッチするようにした。
とゆーわけで、こいつだ。一般性が高いので、Javascript版も載せとくよ。
y_combi = (func) ->
return ((p) ->
return () ->
return func(p(p)).apply(this,arguments)
)((p) ->
return () ->
return func(p(p)).apply(this,arguments)
)
braces2parentheses = y_combi (func) ->
return (str) ->
dst = str
result = str.match(/^([^\{]*)\{([^\}]*)\}(.*)$/)
if result?
dst = result[1]+'('+result[2].split(',').join('|')+')'+func(result[3])
return dst
wildcard2regexstr = (str) ->
str = str.replace /\\/g,'\\\\'
str = str.replace /\+/g,'\\+'
str = str.replace /\./g,'\\.'
str = str.replace /\(/g,'\\('
str = str.replace /\)/g,'\\)'
str = str.replace /\^/g,'\\^'
str = str.replace /\$/g,'\\\$'
str = str.replace /\|/g,'\\|'
str = braces2parentheses str
str = str.replace /\?/g,'[^/]'
str = str.replace /<</g,'<<2'
str = str.replace /<<</g,'<<3'
str = str.replace /\/\*\*\//g,'(/.<<</|/)'
str = str.replace /\*/g,'[^/]+'
str = str.replace /<<</g,'*'
str = str.replace /<<2/g,'<<'
str = str.replace /<<3/g,'<<<'
str += '$'
wildcard2regex = (str) ->
return new RegExp(wildcard2regexstr str)
#test
testtext = "src/*.{js,coffee}"
console.log testtext
regexstr = wildcard2regexstr testtext
regex = new RegExp(regexstr)
console.log regexstr
こっちがJavascript版。
var y_combi = function(func) {
return (function(p) {
return function() {
return func(p(p)).apply(this, arguments);
};
})(function(p) {
return function() {
return func(p(p)).apply(this, arguments);
};
});
};
var braces2parentheses = y_combi(function(func) {
return function(str) {
var dst, result;
dst = str;
result = str.match(/^([^\{]*)\{([^\}]*)\}(.*)$/);
if (result != null) {
dst = result[1] + '(' + result[2].split(',').join('|') + ')' + func(result[3]);
}
return dst;
};
});
wildcard2regexstr = function(str) {
str = str.replace(/\\/g, '\\\\');
str = str.replace(/\+/g, '\\+');
str = str.replace(/\./g, '\\.');
str = str.replace(/\(/g, '\\(');
str = str.replace(/\)/g, '\\)');
str = str.replace(/\^/g, '\\^');
str = str.replace(/\$/g, '\\\$');
str = str.replace(/\|/g, '\\|');
str = braces2parentheses(str);
str = str.replace(/\?/g, '[^/]');
str = str.replace(/<</g, '<<2');
str = str.replace(/<<</g, '<<3');
str = str.replace(/\/\*\*\//g, '(/.<<</|/)');
str = str.replace(/\*/g, '[^/]+');
str = str.replace(/<<</g, '*');
str = str.replace(/<<2/g, '<<');
str = str.replace(/<<3/g, '<<<');
return str += '$';
};
var wildcard2regex = function(str) {
return new RegExp(wildcard2regexstr(str));
};
//test
var testtext = "src/*.{js,coffee}";
console.log(testtext);
var regexstr = wildcard2regexstr(testtext);
var regex = new RegExp(regexstr);
console.log(regexstr);