Fetching contributors…
Cannot retrieve contributors at this time
210 lines (157 sloc) 9.74 KB
usage: jik [--help] <ast-selector> [<action>] <filename> [<filename>...]
search a javascript file or directory using the provided <ast-selector>
and execution <action> on each matching AST node.
if <filename> is a directory, that directory will be traversed and any
file ending with ".js" will be searched.
action must be valid javascript if present, surrounded by "{}". the following
objects and functions are available to you:
console - the console object.
$NODE - the current node.
$LINE - the line of the current node.
$FILE - the current filename.
$LAST - is the current node the last match in $FILE?
$COUNT - the number of times the action
has been called in the current file.
$POS - a macro for (!$COUNT ? $FILE + '\n' : '') + $LINE + ':'
parents([node,] selector) - returns the parent matching selector or an empty object.
pos(node) - returns an object with {line, col} attributes.
is([node,] selector) - returns whether or not the given node (or if
not given, $NODE) matches selector.
follow(file) - recurse into file.
require(module) - requires module.
$ctxt - an empty object that persists across different
jik file matches.
if not specified, the default action is '{print($POS, $NODE)}'.
ast-selectors
The AST selector language follows the same general rules as
CSS selectors. The following "tag" style selectors are available:
block if(x) {
 // also works with
 // for, do, while, etc
}
expr var x = 2, y = 3
y = x + 3
if(x + 1) {
...
ternary var y = x ? 1 : 2;
if if(x) {
} else {
}
if:first-child if(x) {
} else {
}
if > *:first-child + * if(x) {
} else {
}
if > *:first-child + * + * if(x) {
} else {
}
if > *:first-child + * + if if(x) {
} else if(...) {
}
break break;
break[label] break example;
continue continue;
continue[label] continue example;
with with(ex) {;
};
switch switch(ex) {;
};
return return;
return[argument] return anything;
return > * return anything;
while while(x) { }
do-while do { } while(x)
for for(var x; y; z) { }
for-in for(var k in o) { }
for-in[left] > *:first-child for(var k in o) { }
for-in[right] > *:first-child + * for(var k in o) { }
for-in > *:last-child for(var k in o) { }
variable-decl var x = 3, y = 2, z;
variable-decl[kind=const] const x = 3, y = 2, z;
variable-decl[kind=var] var x = 3, y = 2, z;
variable-decl[kind=let] let x = 3, y = 2, z;
variable var x = 3, y = 2, z;
variable[init] var x = 3, y = 2, z;
variable > id:first-child var x = 3, y = 2, z;
binary x + 2, x || y
binary[operator=\+] x + 2, x || y
assign x = y
assign[operator=\>\>\=] x = y
array y = [0, 1, 2]
object y = {a: 0, b: 1, c: 2}
object > * > :any(literal, id):first-child
y = {a: 0, b: 1, "c": 2}
object > * > :any(literal, id):first-child + *
y = {a: 0, b: 1, "c": 2}
function function() {}
function[id] function name() {}
sequence var x = 0, 1, 2 // x == 2
update ++x, y++
update[prefix] ++x, y++
unary void x, ~x, !x, delete x, typeof x
unary[operator=void] void x, ~x, !x, delete x, typeof x
call x(y, z)
call > *:first-child x(y, z)
call > *:first-child ~ * x(y, z)
new new Callee(arg, arg, arg)
new[callee] > *:first-child new Callee(arg, arg, arg)
new[callee] > *:first-child ~ * new Callee(arg, arg, arg)
lookup obj.x, obj["hello" + x]
lookup[computed] obj.x, obj["hello" + x]
lookup > * + expr obj.x, obj["hello" + x]
lookup > * + id obj.x, obj["hello" + x]
lookup > * + * obj.x, obj["hello" + x]
lookup > *:first-child obj.x, obj["hello" + x]
case switch(x) { case 3: arf; default: barf; }
case[test] switch(x) { case 3: arf; default: barf; }
throw throw
label example:
var x = 3;
try try {
} catch(err) {
}
try[handlers] try {
} catch(err) {
}
try[finalizer] try {
} finally {
}
try > catch try {
} catch(err) {
catch ... } catch(err) {
}
this this
id x, arf, $barf, x_y
literal 0, NaN, "hi", true, false, null, 3.2, /asdf/
The following operators are available:
parent-sel > direct-child-sel Selects only nodes who match
direct-child-sel and whose
direct parents match parent-sel.
parent-sel indirect-child-sel Selects nodes who match
indirect-child-sel and who
descend from any node matching
parent-sel.
child-sel + sibling-sel Selects nodes who match sibling-sel
and who are directly next to a node
that matches child-sel.
child-sel ~ sibling-sel Selects nodes who match sibling-sel
and who possess a prior sibling matching
child-sel.
complex selector-one, selector-two Selects nodes who match either the selector
to the left or the right of the comma.
[attr] attr is present on this node and is
truthy.
[attr=value] attr is present on this node and matches
value.
[attr$=value] attr is present on this node and ends with
value.
[attr^=value] attr is present on this node and begins with
value.
[attr*=value] attr is present on this node and contains value.
:first-child Node is the first child of its parent.
:last-child Node is the last child of its parent.
:empty Node has no children.
:root Node is the root of the tree.
:contains(text) The source code of node contains text.
:any(selector, selector) True if any selector matches node.