forked from unconed/TermKit
/
grep.js
158 lines (130 loc) · 3.57 KB
/
grep.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
var view = require('view/view'),
reader = require('shell/reader'),
parseArgs = require('misc').parseArgs;
exports.main = function (tokens, pipes, exit, environment) {
var out = new view.bridge(pipes.viewOut);
var args = parseArgs(tokens),
options = args.options;
var negative = options.v,
matchKeys = options.k;
if (!args.values.length) {
out.print("Usage: grep [-v] [-k] <pattern> [file] ...");
exit(false);
}
var pattern = args.values.shift(),
files = args.values;
if (files.length) {
// TODO file grep
out.print("File grep unsupported.");
return exit(false);
}
else {
var json, tail = '';
// In-place grepper
function grep(object, value, force) {
var i;
if (object.constructor == String || object.constructor == Number) {
// Match strings.
return ((!matchKeys || force) && (negative ^ !!(''+object).match(value))) ? object : null;
}
if (object.constructor == Array) {
// Keep only non-null items after grep.
object = object.map(function (key) {
return grep(key, value);
}).filter(function (x) { return x !== null; });
// Prune empties.
return object.length ? object : null;
}
var out = {};
for (i in object) {
var item;
if (matchKeys) {
// Pass keys through grep.
item = (grep(i, value, true) !== null) ? object[i] : null
}
else {
// Pass values through grep.
item = grep(object[i], value);
}
// Keep non-null items.
if (item !== null) {
out[i] = item;
}
}
// Prune empties.
if (JSON.stringify(out) == '{}') {
return null;
}
return out;
}
// Buffered mime reader handler.
var handler = {
/**
* Pipe open, headers found.
*/
begin: function (headers) {
var type = headers.get('Content-Type');
buffered = false;
switch (type) {
default:
case 'text/plain':
json = false;
break;
case 'application/json':
buffered = json = true;
break;
}
// Remove content-length, output rest.
headers.set('Content-Length', null);
pipes.dataOut.write(headers.generate());
return buffered;
},
/**
* Pipe data.
*/
data: function (data) {
if (json) {
// Process whole json object (buffered).
data = JSON.parse(data.toString('utf-8'));
}
else {
// Process line by line (unbuffered chunks).
data = (tail + data).toString('utf-8').split("\n");
tail = data.pop();
}
// Filter values recursively.
data = grep(data, pattern);
if (json) {
// Serialize
data = JSON.stringify(data);
}
else {
// Join lines.
data = data.join("\n");
}
// Pipe out.
pipes.dataOut.write(data);
},
/**
* Pipe closed.
*/
end: function (exit) {
if (tail) {
// Last dangling line.
data = grep([tail], pattern);
if (data !== null) {
pipes.dataOut.write(data);
}
}
// Quit.
exit();
},
};
// Stdin grep.
var pipe = new reader.reader(pipes.dataIn,
function () { return handler; },
function () {
exit(true);
});
}
};