|
@ -46,6 +46,7 @@ exports.writer = util.inspect; |
|
|
function REPLServer(prompt, stream) { |
|
|
function REPLServer(prompt, stream) { |
|
|
var self = this; |
|
|
var self = this; |
|
|
if (!context) resetContext(); |
|
|
if (!context) resetContext(); |
|
|
|
|
|
if (!exports.repl) exports.repl = this; |
|
|
self.context = context; |
|
|
self.context = context; |
|
|
self.buffered_cmd = ''; |
|
|
self.buffered_cmd = ''; |
|
|
|
|
|
|
|
@ -56,6 +57,9 @@ function REPLServer(prompt, stream) { |
|
|
return self.complete(text); |
|
|
return self.complete(text); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
this.commands = {}; |
|
|
|
|
|
defineDefaultCommands(this); |
|
|
|
|
|
|
|
|
if (rli.enabled && !disableColors) { |
|
|
if (rli.enabled && !disableColors) { |
|
|
// Turn on ANSI coloring.
|
|
|
// Turn on ANSI coloring.
|
|
|
exports.writer = function(obj, showHidden, depth) { |
|
|
exports.writer = function(obj, showHidden, depth) { |
|
@ -86,7 +90,12 @@ function REPLServer(prompt, stream) { |
|
|
|
|
|
|
|
|
// Check to see if a REPL keyword was used. If it returns true,
|
|
|
// Check to see if a REPL keyword was used. If it returns true,
|
|
|
// display next prompt and return.
|
|
|
// display next prompt and return.
|
|
|
if (self.parseREPLKeyword(cmd) === true) return; |
|
|
if (cmd && cmd.charAt(0) === '.') { |
|
|
|
|
|
var matches = cmd.match(/^(\.[^\s]+)\s*(.*)$/); |
|
|
|
|
|
var keyword = matches && matches[1]; |
|
|
|
|
|
var rest = matches && matches[2]; |
|
|
|
|
|
if (self.parseREPLKeyword(keyword, rest) === true) return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// The catchall for errors
|
|
|
// The catchall for errors
|
|
|
try { |
|
|
try { |
|
@ -185,7 +194,7 @@ REPLServer.prototype.complete = function (line) { |
|
|
var match = null; |
|
|
var match = null; |
|
|
match = line.match(/^\s*(\.\w*)$/); |
|
|
match = line.match(/^\s*(\.\w*)$/); |
|
|
if (match) { |
|
|
if (match) { |
|
|
completionGroups.push(['.break', '.clear', '.exit', '.help']); |
|
|
completionGroups.push(Object.keys(this.commands)); |
|
|
completeOn = match[1]; |
|
|
completeOn = match[1]; |
|
|
if (match[1].length > 1) { |
|
|
if (match[1].length > 1) { |
|
|
filter = match[1]; |
|
|
filter = match[1]; |
|
@ -397,34 +406,63 @@ REPLServer.prototype.complete = function (line) { |
|
|
* @returns {Boolean} If true it means don't continue parsing the command |
|
|
* @returns {Boolean} If true it means don't continue parsing the command |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
|
|
|
REPLServer.prototype.parseREPLKeyword = function (cmd) { |
|
|
REPLServer.prototype.parseREPLKeyword = function (keyword, rest) { |
|
|
var self = this; |
|
|
var cmd = this.commands[keyword]; |
|
|
|
|
|
if (cmd) { |
|
|
switch (cmd) { |
|
|
cmd.action.call(this, rest); |
|
|
case ".break": |
|
|
|
|
|
// TODO remove me after 0.3.x
|
|
|
|
|
|
self.buffered_cmd = ''; |
|
|
|
|
|
self.displayPrompt(); |
|
|
|
|
|
return true; |
|
|
|
|
|
case ".clear": |
|
|
|
|
|
self.stream.write("Clearing context...\n"); |
|
|
|
|
|
self.buffered_cmd = ''; |
|
|
|
|
|
resetContext(); |
|
|
|
|
|
self.displayPrompt(); |
|
|
|
|
|
return true; |
|
|
|
|
|
case ".exit": |
|
|
|
|
|
self.stream.destroy(); |
|
|
|
|
|
return true; |
|
|
|
|
|
case ".help": |
|
|
|
|
|
self.stream.write(".clear\tBreak, and also clear the local context.\n"); |
|
|
|
|
|
self.stream.write(".exit\tExit the prompt\n"); |
|
|
|
|
|
self.stream.write(".help\tShow repl options\n"); |
|
|
|
|
|
self.displayPrompt(); |
|
|
|
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
return false; |
|
|
return false; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
REPLServer.prototype.defineCommand = function(keyword, cmd) { |
|
|
|
|
|
if (typeof cmd === 'function') cmd = {action: cmd}; |
|
|
|
|
|
else if (typeof cmd.action !== 'function') { |
|
|
|
|
|
throw new Error('bad argument, action must be a function'); |
|
|
|
|
|
} |
|
|
|
|
|
this.commands['.' + keyword] = cmd; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
function defineDefaultCommands(repl) { |
|
|
|
|
|
// TODO remove me after 0.3.x
|
|
|
|
|
|
repl.defineCommand('break', { |
|
|
|
|
|
help: 'Sometimes you get stuck, this gets you out', |
|
|
|
|
|
action: function() { |
|
|
|
|
|
this.buffered_cmd = ''; |
|
|
|
|
|
this.displayPrompt(); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
repl.defineCommand('clear', { |
|
|
|
|
|
help: 'Break, and also clear the local context', |
|
|
|
|
|
action: function() { |
|
|
|
|
|
this.stream.write("Clearing context...\n"); |
|
|
|
|
|
this.buffered_cmd = ''; |
|
|
|
|
|
resetContext(); |
|
|
|
|
|
this.displayPrompt(); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
repl.defineCommand('exit', { |
|
|
|
|
|
help: 'Exit the repl', |
|
|
|
|
|
action: function() { |
|
|
|
|
|
this.stream.destroy(); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
repl.defineCommand('help', { |
|
|
|
|
|
help: 'Show repl options', |
|
|
|
|
|
action: function() { |
|
|
|
|
|
var self = this; |
|
|
|
|
|
Object.keys(this.commands).sort().forEach(function(name) { |
|
|
|
|
|
var cmd = self.commands[name]; |
|
|
|
|
|
self.stream.write(name + "\t" + (cmd.help || '') + "\n"); |
|
|
|
|
|
}); |
|
|
|
|
|
this.displayPrompt(); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
function trimWhitespace (cmd) { |
|
|
function trimWhitespace (cmd) { |
|
|
var trimmer = /^\s*(.+)\s*$/m, |
|
|
var trimmer = /^\s*(.+)\s*$/m, |
|
|
matches = trimmer.exec(cmd); |
|
|
matches = trimmer.exec(cmd); |
|
|