Added lines span and matches counting options #3

Open
wants to merge 2 commits into
from
View
@@ -15,6 +15,9 @@ program
.version('0.0.2')
.usage('[options] <query> [path ...]')
.option('-H, --hidden', 'search hidden files and directories')
+ .option('-s, --span <lines>', 'number of lines to span result')
@tj
tj Aug 25, 2011 Owner

this is for lines of context?

@stagas
stagas Aug 25, 2011

Yes, -s 1 would span 1 line above and 1 line below a line of match. It also highlights the line numbers that have matches, takes care not to repeat lines and puts some '...' to indicate distance. You need to try it to see it.

@tj
tj Aug 25, 2011 Owner

cool I'll read the rest and try it out :D

+ .option('-c, --count', 'count results next to line numbers')
+ .option('-0, --zero', 'start line counting at zero')
.parse(process.argv);
// no args
@@ -28,6 +31,7 @@ if (!program.args.length) {
var query = program.args.shift()
, paths = program.args
+ , span = +program.span
, pending = paths.length
, re = new RegExp('(' + query + ')', 'ig');
@@ -59,19 +63,64 @@ function search(path) {
var lines = [];
fs.readFile(path, 'utf8', function(err, str){
if (err) throw err;
- str.split('\n').forEach(function(line, i){
- if (!re.test(line)) return;
- lines.push([i, line]);
+ var docLines = str.split('\n');
+ var count = 0;
+ docLines.forEach(function(line, i){
+ var match = line.match(re);
+ if (!match) return;
+ for (var n = span; n > 0; n--) {
+ lines.push([i - n, docLines[i - n]]);
+ }
+ lines.push([ i, line, match.length]);
+ for (var n = 1; n <= span; n++) {
+ lines.push([i + n, docLines[i + n]]);
+ }
});
if (lines.length) {
- console.log('\n \033[36m%s\033[0m', path);
- lines.forEach(function(line){
+ var count = 0, space = ' ', linesUnique = {};
+ lines.forEach(function(line, index){
var i = line[0]
+ , matches = line[2]
, line = line[1];
- line = line.replace(re, '\033[37;43m$1\033[0;90m');
- console.log(' \033[90m%d: %s\033[0m', i, line);
+ if (linesUnique[i]) {
+ if (matches) linesUnique[i].matches = matches;
+ } else {
+ linesUnique[i] = {
+ i: i + (program.zero ? 0 : 1)
+ , matches: matches
+ , line: line
+ };
+ }
});
+ console.log('\n \033[36m%s\033[0m', path);
+ var last = 0;
+ Object.keys(linesUnique).forEach(function(ln){
+ var i = linesUnique[ln].i
+ , matches = linesUnique[ln].matches
+ , line = linesUnique[ln].line;
+ if ('undefined' === typeof line) return;
+ if (span && last + 1 != i && i != 0) {
+ console.log(new Array(20).join(' '), '...');
+ }
+ last = i;
+ line = line.replace(re, '\033[07;43m$1\033[0;90m');
+ if (matches) count += matches;
+ console.log(
+ '%s%s %s\033[90m: %s\033[0m'
+ , matches && '\033[37m' || '\033[90m'
+ , program.count && matches
+ ? ' \033[36m' + count + '\033[37m'
+ : span && space || ' '
+ , i, line
+ );
+ if (program.count)
+ space = new Array(2 + count.toString().length).join(' ');
+ });
+ if (span && linesUnique[last - 1].i < docLines.length - 1) {
+ console.log(new Array(20).join(' '), '...');
+ }
+ console.log('%s --- \033[33m%s\033[0;90m occurrences of \033[37m"%s"', space, count, query);
}
});
}