Comparing version 0.0.5 to 0.0.6
359
cdir.js
var tty = require('tty'); | ||
var rl = require('readline'); | ||
var fs = require('fs'); | ||
@@ -11,3 +12,8 @@ var jv = exports, stack = []; | ||
var displayed = 0; | ||
var copybuffer = 0; | ||
var searchmode = false; | ||
var searchbuffer = ''; | ||
var lastsearch = ''; | ||
var meta = [], map = [0]; | ||
@@ -18,3 +24,3 @@ | ||
var write = function write(s) { | ||
var write = function write (s) { | ||
process.stdout.write(s); | ||
@@ -24,15 +30,58 @@ } | ||
// | ||
// used for cut/copy/paste | ||
// | ||
Object.defineProperties(Object, { | ||
'extend': { | ||
'configurable': true, | ||
'enumerable': false, | ||
'value': function extend(a, b) { | ||
var extObj, witKeys = Object.keys(b); | ||
extObj = Object.keys(a).length ? Object.clone(a) : {}; | ||
witKeys.forEach(function (key) { | ||
Object.defineProperty( | ||
extObj, | ||
key, | ||
Object.getOwnPropertyDescriptor(b, key) | ||
); | ||
}); | ||
return extObj; | ||
}, | ||
'writable': true | ||
}, | ||
'clone': { | ||
'configurable': true, | ||
'enumerable': false, | ||
'value': function clone(obj) { | ||
return Object.extend({}, obj); | ||
}, | ||
'writable': true | ||
} | ||
}); | ||
// | ||
// move the cursor upward on the screen | ||
// | ||
var up = function up(i) { | ||
var up = function up (i, save) { | ||
var maxLineLen = process.stdout.getWindowSize()[0]/2; | ||
i = i || 1; | ||
if (i > 0) { | ||
while(i--) { | ||
write(ws(maxLineLen, true) + '\033[1A\r'); | ||
write(!save ? '\033[K\033[1A\r' : '\033[1A\r'); | ||
} | ||
} | ||
else { | ||
write('\033[1A\r'); | ||
}; | ||
var right = function right (i) { | ||
i = i || 1; | ||
if (i > 0) { | ||
while(i--) { | ||
write('\033[1C\r'); | ||
} | ||
} | ||
@@ -44,3 +93,3 @@ }; | ||
// | ||
var ws = function ws(i, multiplier) { | ||
var ws = function ws (i, multiplier) { | ||
@@ -59,3 +108,3 @@ var s = ''; | ||
var getType = function getType(o) { | ||
var getType = function getType (o) { | ||
@@ -88,4 +137,5 @@ if (typeof o === 'string' || typeof o === 'number' || | ||
var seed = -1; | ||
var constructMeta = function constructMeta(parentType, depth, node, itemPrefix, dontPreface) { | ||
var constructMeta = function constructMeta (parentType, depth, node, itemPrefix, dontPreface) { | ||
itemPrefix = itemPrefix || ''; | ||
@@ -148,5 +198,7 @@ | ||
var truncatedNode = '0'; | ||
var truncated = false; | ||
if (node.length > process.stdout.getWindowSize()[0] - extLen) { | ||
truncatedNode = '▸ ' + '\033[31m"' + node.substr(0, process.stdout.getWindowSize()[0]/2) + '..."\033[0m'; | ||
truncated = true; | ||
} | ||
@@ -163,8 +215,10 @@ else { | ||
depth: depth, | ||
node: node, | ||
index: seed | ||
}); | ||
addStrData(node); | ||
if (truncated === true) { | ||
addStrData(node); | ||
} | ||
break; | ||
@@ -183,2 +237,3 @@ case 'number': | ||
depth: depth, | ||
node: node, | ||
index: seed | ||
@@ -196,2 +251,3 @@ }); | ||
depth: depth, | ||
node: node, | ||
index: seed | ||
@@ -212,2 +268,3 @@ }); | ||
depth: depth, | ||
node: node, | ||
index: seed | ||
@@ -235,2 +292,3 @@ }); | ||
depth: depth, | ||
node: node, | ||
index: seed | ||
@@ -254,3 +312,3 @@ }); | ||
var renderMeta = function renderMeta() { | ||
var renderMeta = function renderMeta () { | ||
@@ -278,6 +336,216 @@ displayed = 0; | ||
var listener = function listener(chunk, key) { | ||
var toggle = function toggle (index) { | ||
if (key) { | ||
var start = selection; | ||
var stop = meta.length; | ||
var next = meta[index].depth+1; | ||
var started = false; | ||
if (meta[index].type === 'string' && | ||
(meta[index].description.indexOf('▸') === -1 && | ||
meta[index].description.indexOf('▾') === -1)) { | ||
return; | ||
} | ||
if (meta[index].expanded) { | ||
meta[index].description = meta[index].description.replace('▾', '▸'); | ||
meta[index].expanded = false; | ||
for (var i = index, l = stop; i < l; i++) { | ||
if (meta[i].depth >= next) { | ||
meta[i].displayed = false; | ||
// | ||
// if anything that was opened below this node shows that it was | ||
// expanded, change its icon so that it appears collapsed. | ||
// | ||
meta[i].description = meta[i].description.replace('▾', '▸'); | ||
meta[i].expanded = false; | ||
started = true; | ||
} | ||
else if (started && meta[i].depth < next) { | ||
break; | ||
} | ||
} | ||
} | ||
else { | ||
meta[index].description = meta[index].description.replace('▸', '▾'); | ||
meta[index].expanded = true; | ||
for (var i = index, l = stop; i < l; i++) { | ||
if (meta[i].depth === next) { | ||
meta[i].displayed = true; | ||
meta[i].expanded = false; | ||
started = true; | ||
} | ||
else if (started && meta[i].depth < next) { | ||
break; | ||
} | ||
} | ||
} | ||
map = []; | ||
for (var i = 0, l = meta.length; i < l; i++) { | ||
if (meta[i].displayed === true) { | ||
map.push(meta[i].index); | ||
} | ||
} | ||
up(displayed); | ||
renderMeta(); | ||
} | ||
var listener = function listener (chunk, key) { | ||
// | ||
// search mode stuff | ||
// | ||
if (chunk === '/') { | ||
searchmode = true; | ||
searchbuffer = ''; | ||
// | ||
// show the user a prompt, if they did a search, | ||
// include that before the prompt as the default. | ||
// | ||
if (lastsearch !== '') { | ||
process.stdout.write('(' + lastsearch + ') /'); | ||
} | ||
else { | ||
process.stdout.write('/'); | ||
} | ||
} | ||
else if (searchmode === true && typeof key !== 'undefined' && key.name === 'backspace') { | ||
// | ||
// dont delete more characters than the user has entered. | ||
// | ||
if (searchbuffer.length > 0) { | ||
searchbuffer = searchbuffer.slice(0, -1); | ||
write('\033[1D \033[1D'); | ||
} | ||
} | ||
else if (searchmode === true && typeof key !== 'undefined' && key.name === 'enter') { | ||
searchmode = false; | ||
// | ||
// if the user enters nothing, assume we want to repeat the last search. | ||
// | ||
if (searchbuffer === '') { | ||
searchbuffer = lastsearch; | ||
} | ||
else { | ||
// | ||
// start from the top if this is a unique search. | ||
// | ||
selection = 0; | ||
} | ||
// | ||
// clear the line | ||
// | ||
write('\r\033[K'); | ||
var regexp; | ||
var found = false; | ||
// | ||
// create a regular expression from the input. | ||
// if its a bad regexp, let the user know nicely. | ||
// | ||
try { | ||
regexp = new RegExp(searchbuffer); | ||
} | ||
catch(e) { | ||
write(e.message + '\r'); | ||
return; | ||
} | ||
for (var i = selection, l = meta.length; i < l; i++) { | ||
if (regexp.test(meta[i].description)) { | ||
// | ||
// we have a match now we need to unfold the appropriate nodes. | ||
// | ||
var currentDepth = meta[i].depth; | ||
var currentSelection = meta[i].index; | ||
var newSelection = 0; | ||
found = true; | ||
for (var j = i; j >= 0; j--) { | ||
if (meta[j].depth < currentDepth) { | ||
currentDepth--; | ||
if (meta[j].expanded === false) { | ||
toggle(j); | ||
} | ||
} | ||
} | ||
for (var i = 0, l = meta.length; i < l; i++) { | ||
if (meta[i].displayed === true) { | ||
newSelection++; | ||
} | ||
if (meta[i].index === currentSelection) { | ||
break; | ||
} | ||
} | ||
up(displayed); | ||
selection = newSelection; | ||
renderMeta(); | ||
break; | ||
} | ||
} | ||
if (!found) { | ||
write('Not found\r'); | ||
} | ||
// | ||
// save the last search even if its unsuccessful. | ||
// | ||
lastsearch = searchbuffer; | ||
// | ||
// reset the search buffer | ||
// | ||
searchbuffer = ''; | ||
// | ||
// discontinue listening to keypresses until we're | ||
// done searching. | ||
// | ||
return true; | ||
} | ||
else if (searchmode === true) { | ||
write(chunk); | ||
searchbuffer += chunk; | ||
} | ||
// | ||
// exploration mode stuff | ||
// | ||
if (key && searchmode === false) { | ||
var downAction = (key.name === 'tab' && !key.shift) || key.name === 'down'; | ||
@@ -316,62 +584,7 @@ var upAction = (key.shift && key.name === 'tab') || key.name === 'up'; | ||
var start = selection; | ||
var stop = meta.length; | ||
var next = meta[index].depth+1; | ||
var started = false; | ||
if (meta[index].type === 'string' && | ||
(meta[index].description.indexOf('▸') === -1 && | ||
meta[index].description.indexOf('▾') === -1)) { | ||
return; | ||
} | ||
if (meta[index].expanded) { | ||
meta[index].description = meta[index].description.replace('▾', '▸'); | ||
meta[index].expanded = false; | ||
for (var i = index, l = stop; i < l; i++) { | ||
if (meta[i].depth >= next) { | ||
meta[i].displayed = false; | ||
meta[i].expanded = false; | ||
started = true; | ||
} | ||
else if (started && meta[i].depth < next) { | ||
break; | ||
} | ||
} | ||
} | ||
else { | ||
meta[index].description = meta[index].description.replace('▸', '▾'); | ||
meta[index].expanded = true; | ||
for (var i = index, l = stop; i < l; i++) { | ||
if (meta[i].depth === next) { | ||
meta[i].displayed = true; | ||
meta[i].expanded = false; | ||
started = true; | ||
} | ||
else if (started && meta[i].depth < next) { | ||
break; | ||
} | ||
} | ||
} | ||
map = []; | ||
for (var i = 0, l = meta.length; i < l; i++) { | ||
if (meta[i].displayed === true) { | ||
map.push(meta[i].index); | ||
} | ||
} | ||
up(displayed); | ||
renderMeta(); | ||
index = map[selection-1]; | ||
toggle(index); | ||
} | ||
if (key.name === 'q' || (key.ctrl && key.name == 'c')) { | ||
if (key.name === 'q' || key.ctrl && key.name === 'q') { | ||
stdin.removeListener('keypress', listener); | ||
@@ -384,3 +597,3 @@ stdin.pause(); | ||
var dir = function dir(obj, options) { | ||
var dir = function dir (obj, options) { | ||
@@ -387,0 +600,0 @@ constructMeta(getType(obj), 0, obj); |
@@ -1,5 +0,2 @@ | ||
console.dir = require('../cdir'); | ||
var stuff = { | ||
{ | ||
"name" : "dir", | ||
@@ -80,4 +77,2 @@ "description" : "An interactive console.dir() for the terminal.", | ||
} | ||
}; | ||
console.dir(stuff); | ||
} |
@@ -9,6 +9,5 @@ { | ||
"json", | ||
"interacive", | ||
"prompt" | ||
], | ||
"version" : "0.0.5", | ||
"version" : "0.0.6", | ||
"author" : "Paolo Fragomeni <paolo@nodejisu.com>", | ||
@@ -15,0 +14,0 @@ "repository" : { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
107952
8
609