grasp - JavaScriptの構造を解析する検索/置換ツール
記法を習得しないといけないですが、その結果次第では開発が便利になりそうですよ。 正規表現を使うとプログラミングコードを一気に置き換えることができます。graspはそれをさらに柔軟に、そしてJavaScriptに特化させたソフトウェアになります。 grepや置換ツールの代替に使ってみると面白いかも知れません。使い方がこれまでにない感じですが、使いこなせば強力なツールになる可能性を秘めています。 インストールは簡単で、npmコマンドでできます。
$ npm install -g grasp
続いてヘルプ
$ grasp --help
Usage: grasp [option]... [selector] [file]...
Search (or --replace) for selector in file(s) or standard input.
For more help '--help more', '--help --option-name', '--help syntax'
Example: grasp --context 2 'if.test bi[op="< "]' file.js file2.js
Miscellaneous:
-h, --help display this help and exit '--help more' for more help info
-v, --version print version information and exit
-d, --debug output debug information
-x, --extensions [String] comma separated list of acceptable file extensions - default:
js
-r, --recursive recursively search directories
Replacement:
-R, --replace replacement::String replace each match with replacement, use `--help --replace`
for more info
-F, --replace-file file::String replace each match with contents of file
-t, --to Object | String write replaced output to file(s), `--help --to` for more info
-i, --in-place overwrite input files with replaced output
Selector interpretation:
-s, --squery use squery - selector query - css style selectors
-e, --equery use equery - example query - use code example with wildcards
-f, --file file::String obtain selector from file
Output control:
-m, --max-count n::Int stop after n matches
-n, --line-number print line number with output lines - default: true
-b, --col-number print column number with output lines
-H, --filename print the file name for each match (opposite: `--no-filename`)
-o, --only-matching show only the matching part of the line(s)
-q, --quiet, --silent suppress all normal output
-W, --files-without-match print only names of files containing no match
-w, --files-with-matches print only names of files containing matches
-c, --count print only a count of matches per file
-O, --color, --colour use color to highlight matches - default: true
-j, --json JSON output for matches
Context control:
-B, --before-context n::Int print n lines of leading context
-A, --after-context n::Int print n lines of trailing context
-C, --context n::Int print n lines of output context
-NUM::Int same as --context NUM
Version 0.1.0
<http://graspjs.com/>
では実際に使ってみます。例えばサンプルとして次のようなコードがあったとします。
$ cat a.js
function g(x) {
if (x && f(x)) { return [1, 2]; }
doSomething();
while(x < 2) {
if (xs.length && ys.length) {
return xs[x] + ys[x];
}
x++;
}
if (x == 3 && list[x]) {
return list;
}
}
まずif文を抽出します。Squeryという記法になります。
$ grasp 'if.test' a.js
2: if (x && f(x)) { return [1, 2; }]
5: if (xs.length && ys.length) {
10: if (x == 3 && list[x]) {
続いてreturn 〜の部分を抽出。
$ grasp -e 'return __' a.js
2: if (x && f(x)) { return [1, 2;] }
6: return xs[x + ys[x];]
11: return list;
さらにreturn ○○+○○という形の行を抽出。__で省略できる仕組みです。正規表現より分かりやすいかも知れませんね。
$ grasp -e 'return __+__' a.js
6: return xs[x + ys[x];]
そして置換の仕組みも用意されています。ここの文法が今ひとつ理解できていないのですが、変数の判定を置き換えたり、関数で覆ったりするのも容易にできるようです。
$ grasp bi --replace '{{.r}}+{{.l}}' a.js
function g(x) {
if (x && f(x)) { return [1, 2]; }
doSomething();
while(2+x) {
if (xs.length && ys.length) {
return ys[x]+xs[x];
}
x++;
}
if (3+x && list[x]) {
return list;
}
}
graspはJavaScriptの構造を認識した上で置換や検索を行うソフトウェアになります。汎用的な正規表現に比べるとJavaScriptに特化している分、より細かな検索や置換ができるようになっています。構造を認識していることもあって例えば、
if(〜){f(x)}
と一行で書かれている場合と、
if(〜){
f(x)
}
と三行で書かれている場合を正しく検索、置換できるということです。この辺りが正規表現とも相違点になるかも知れません。
graspはnode/JavaScript製、MIT Licenseのオープンソース・ソフトウェアです。