mirror of https://github.com/lukechilds/node.git
Browse Source
Now supports: - command options: .help, .break, .clear, .exit - local vars and global functions - ability to print 0, false and "" - when value is a function, prints [Function] - when object is circular, prints [Circular Object] instead of throwing an errorv0.7.4-release
RayMorgan
15 years ago
1 changed files with 156 additions and 18 deletions
@ -1,37 +1,175 @@ |
|||||
// A repl library that you can include in your own code to get a runtime
|
// A repl library that you can include in your own code to get a runtime
|
||||
// interface to your program. Just require("/repl.js").
|
// interface to your program. Just require("/repl.js").
|
||||
|
|
||||
|
puts("Type '.help' for options."); |
||||
|
|
||||
node.stdio.open(); |
node.stdio.open(); |
||||
|
node.stdio.addListener("data", readline); |
||||
|
|
||||
var buffered_cmd = ''; |
var buffered_cmd = ''; |
||||
var trimmer = /^\s*(.+)\s*$/m; |
var trimmer = /^\s*(.+)\s*$/m; |
||||
|
var scopedVar = /^\s*var\s*([_\w\$]+)(.*)$/m; |
||||
|
var scopeFunc = /^\s*function\s*([_\w\$]+)/; |
||||
|
|
||||
exports.prompt = "node> "; |
exports.prompt = "node> "; |
||||
|
exports.scope = {}; |
||||
function displayPrompt () { |
|
||||
print(buffered_cmd.length ? '... ' : exports.prompt); |
|
||||
} |
|
||||
|
|
||||
displayPrompt(); |
displayPrompt(); |
||||
|
|
||||
node.stdio.addListener("data", function (cmd) { |
|
||||
var matches = trimmer.exec(cmd); |
|
||||
|
|
||||
if (matches && matches.length == 2) { |
/** |
||||
cmd = matches[1]; |
* The main REPL function. This is called everytime the user enters |
||||
|
* data on the command line. |
||||
|
*/ |
||||
|
function readline (cmd) { |
||||
|
cmd = trimWhitespace(cmd); |
||||
|
|
||||
|
// Check to see if a REPL keyword was used. If it returns true,
|
||||
|
// display next prompt and return.
|
||||
|
if (parseREPLKeyword(cmd) === true) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// The catchall for errors
|
||||
|
try { |
||||
|
buffered_cmd += cmd; |
||||
|
// This try is for determining if the command is complete, or should
|
||||
|
// continue onto the next line.
|
||||
try { |
try { |
||||
buffered_cmd += cmd; |
buffered_cmd = convertToScope(buffered_cmd); |
||||
try { |
|
||||
puts(JSON.stringify(eval(buffered_cmd))); |
// Scope the readline with exports.scope to provide "local" vars
|
||||
buffered_cmd = ''; |
with (exports.scope) { |
||||
} catch (e) { |
var ret = eval(buffered_cmd); |
||||
if (!(e instanceof SyntaxError)) |
printValue(ret); |
||||
throw e; |
|
||||
} |
} |
||||
} catch (e) { |
|
||||
puts('caught an exception: ' + e); |
|
||||
buffered_cmd = ''; |
buffered_cmd = ''; |
||||
|
} catch (e) { |
||||
|
if (!(e instanceof SyntaxError)) |
||||
|
throw e; |
||||
} |
} |
||||
|
} catch (e) { |
||||
|
// On error: Print the error and clear the buffer
|
||||
|
puts('caught an exception: ' + e); |
||||
|
buffered_cmd = ''; |
||||
} |
} |
||||
|
|
||||
displayPrompt(); |
displayPrompt(); |
||||
}); |
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Used to display the prompt. |
||||
|
*/ |
||||
|
function displayPrompt () { |
||||
|
print(buffered_cmd.length ? '... ' : exports.prompt); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Used to parse and execute the Node REPL commands. |
||||
|
* |
||||
|
* @param {cmd} cmd The command entered to check |
||||
|
* @returns {Boolean} If true it means don't continue parsing the command |
||||
|
*/ |
||||
|
function parseREPLKeyword (cmd) { |
||||
|
switch (cmd) { |
||||
|
case ".break": |
||||
|
buffered_cmd = ''; |
||||
|
displayPrompt(); |
||||
|
return true; |
||||
|
case ".clear": |
||||
|
puts("Clearing Scope..."); |
||||
|
buffered_cmd = ''; |
||||
|
exports.scope = {}; |
||||
|
displayPrompt(); |
||||
|
return true; |
||||
|
case ".exit": |
||||
|
node.stdio.close(); |
||||
|
return true; |
||||
|
case ".help": |
||||
|
puts(".break\tSometimes you get stuck in a place you can't get out... This will get you out."); |
||||
|
puts(".clear\tBreak, and also clear the local scope."); |
||||
|
puts(".exit\tExit the prompt"); |
||||
|
puts(".help\tShow repl options"); |
||||
|
displayPrompt(); |
||||
|
return true; |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Trims Whitespace from a line. |
||||
|
* |
||||
|
* @param {String} cmd The string to trim the whitespace from |
||||
|
* @returns {String} The trimmed string |
||||
|
*/ |
||||
|
function trimWhitespace (cmd) { |
||||
|
var matches = trimmer.exec(cmd); |
||||
|
if (matches && matches.length == 2) { |
||||
|
return matches[1]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Converts commands that use var and function <name>() to use the |
||||
|
* local exports.scope when evaled. This provides a local scope |
||||
|
* on the REPL. |
||||
|
* |
||||
|
* @param {String} cmd The cmd to convert |
||||
|
* @returns {String} The converted command |
||||
|
*/ |
||||
|
function convertToScope (cmd) { |
||||
|
var matches; |
||||
|
|
||||
|
// Replaces: var foo = "bar"; with: exports.scope.foo = bar;
|
||||
|
matches = scopedVar.exec(cmd); |
||||
|
if (matches && matches.length == 3) { |
||||
|
return "exports.scope." + matches[1] + matches[2]; |
||||
|
} |
||||
|
|
||||
|
// Replaces: function foo() {}; with: foo = function foo() {};
|
||||
|
matches = scopeFunc.exec(buffered_cmd); |
||||
|
if (matches && matches.length == 2) { |
||||
|
return matches[1] + " = " + buffered_cmd; |
||||
|
} |
||||
|
|
||||
|
return cmd; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Echos the value of a value. Trys to print the value out |
||||
|
* in the best way possible given the different types. |
||||
|
* |
||||
|
* @param {Object} value The object to print out |
||||
|
*/ |
||||
|
function printValue (value) { |
||||
|
if (value === 0) { |
||||
|
puts("0"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (value === false) { |
||||
|
puts("false"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (value === "") { |
||||
|
puts('""'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (typeof(value) == "function") { |
||||
|
puts("[Function]"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
puts(JSON.stringify(value)); |
||||
|
} catch (e) { |
||||
|
if (e.message.search("circular")) |
||||
|
puts("[Circular Object]"); |
||||
|
else |
||||
|
throw e; |
||||
|
} |
||||
|
} |
||||
|
Loading…
Reference in new issue