Programming/JavaScript/JSSh/Command line
From Skypher
|
▼Main Page |
|
A simple command line version of JSSh exists: You can enter commands, which will be executed when you press ENTER. The result will be displayed in a useful format - see JS/visualize(). Pressing ENTER without entering a command terminates JSSh.
The code
The below file, JSSh.cmd, is chimera code, which is both a valid batch file as well as a JavaScript. You can run it from the command line, in which case it will be run as a batch file. The batch file does nothing more than load the javaScript using CSCRIPT.EXE. The JavaScript contains the main loop that asks for imput and executes it.
@if (!@_jscript) == (!@_jscript) (ECHO OFF) else BAT PART OF FILE STARTS HERE
CSCRIPT /Nologo /e:jscript "%~f0" %0 %*
GOTO :EOF
@end // JAVASCRIPT PART OF FILE STARTS HERE
function visualize(xValue, sPadding, iDepth) {
if (typeof(sPadding) !== "string") sPadding = "";
if (typeof(iDepth) !== "number") iDepth = 2;
switch (typeof(xValue)) {
case "undefined": return "undefined";
case "boolean": return xValue.toString();
case "string":
return "\"" +
xValue.replace(/[\0-\x1F\"\\\x7F-\xA0\u0100-\uFFFF]/g, function (sChar) {
switch (sChar) {
case "\b": return "\\b";
case "\t": return "\\t";
case "\n": return "\\n";
case "\f": return "\\f";
case "\r": return "\\r";
case "\\": return "\\\\";
case "\"": return "\\\"";
}
var iChar = sChar.charCodeAt(0);
if (iChar < 0x10) return "\\x0" + iChar.toString(16);
if (iChar < 0x100) return "\\x" + iChar.toString(16);
if (iChar < 0x1000) return "\\u0" + iChar.toString(16);
return "\\u" + i.toString(16);
return c;
}) +
"\"";
case "number":
// Inifinity, NaN, floats, small integers and negative numbers
// are displayed as is:
if (
!isFinite(xValue) || isNaN(xValue) ||
xValue != parseInt(xValue) || xValue < 10
) {
return xValue.toString();
}
// Otherwise we'll display as a decimal and hexadecimal number:
return xValue.toString() + " (0x" + xValue.toString(16).toUpperCase() + ")";
case "function":
var sFunction = xValue.toString();
if (iDepth == 2) return sFunction.replace(/\r?\n/g, "$&" + sPadding);
else return sFunction.replace(/\{[\s\S]*$/, "{ ... }");
case "object":
if (xValue == null) return "null";
var sConstructor = null;
try { sConstructor = xValue.constructor.toString(); }
catch (e) { return "object unknown"; }
var sHeader = "Unknown{", sFooter = "}";
var oName = sConstructor.match(/^\r?\n?function (\w+)\([\s\S]*$/);
if (oName) switch (oName[1]) {
case "Boolean": return "Boolean(" + visualize(xValue.valueOf(), sPadding, iDepth) + ")";
case "Date": return "Date(" + visualize(xValue.toString(), sPadding, iDepth) + ")";
case "Number": return "Number(" + visualize(xValue.valueOf(), sPadding, iDepth) + ")";
case "String": return "String(" + visualize(xValue.valueOf(), sPadding, iDepth) + ")";
case "RegExp":
var sFlags = "";
if (xValue.global) sFlags += "g";
if (xValue.ignoreCase) sFlags += "i";
if (xValue.multiline) sFlags += "m";
return "RegExp(/" + xValue.source + "/" + sFlags + ")";
case "Array":
sHeader = "Array [", sFooter = "]";
break;
default:
sHeader = "Object " + oName[1] + " {";
} else try {
oName = xValue.toString().match(/^\[(?:object )?(.*)\]$/);
if (oName) sHeader = "Object [" + oName[1] + "] {";
} catch (e) { }
if (iDepth == 0) return sHeader + " ... " + sFooter;
var asValues = [];
try {
for (var i in xValue) {
// Integers are displayed as numbers, anything else as a string
var sIndex = parseInt(i).toString() == i ?
i:
visualize(i);
// A child object that is the same as its parent is displayed as "=> self",
// Anything else is "visualized":
var sValue = xValue[i] === xValue ?
"=> self":
visualize(xValue[i], sPadding + " ", iDepth - 1);
asValues.push(sPadding + " " + sIndex + ": " + sValue);
}
} catch (e) {
return "object unknown";
}
return sHeader + "\r\n" +
asValues.join("\r\n") + "\r\n" +
sPadding + sFooter;
default:
try { return typeof(xValue) + " " + new String(xValue); }
catch(e) { return "unknown"; }
}
}
var goFSO = new ActiveXObject("Scripting.FileSystemObject");
var goWSS = new ActiveXObject("WScript.Shell");
var goENV = goWSS.environment("PROCESS");
WScript.stdOut.writeLine("JavaScript Shell (CScript) build 080818 by Berend-Jan \"SkyLined\" Wever");
WScript.stdOut.writeLine("Global objects:");
WScript.stdOut.writeLine(" goFSO = new ActiveXObject(\"Scripting.FileSystemObject\")");
WScript.stdOut.writeLine(" goWSS = new ActiveXObject(\"WScript.Shell\")");
WScript.stdOut.writeLine(" goENV = goWSS.environment(\"PROCESS\")");
WScript.stdOut.writeLine("");
WScript.stdOut.writeLine("Enter commands or type \"quit\" or \"exit\" to quit:");
while (1) {
WScript.stdOut.write("JSSh>");
var sInput = WScript.stdIn.readLine();
if (sInput.match(/^\s*$/)) {
do {
sInput += WScript.stdIn.readLine() + "\r\n";
} while (!sInput.match(/\r\n\r\n$/));
}
if (sInput == "quit" || sInput == "exit") WScript.quit();
var xResult;
try {
new Function(sInput);
} catch (e) {
WScript.stdOut.writeLine("Parse error: " + visualize(e));
continue;
}
try {
xResult = eval(sInput);
} catch (e) {
WScript.stdOut.writeLine("Exception thrown: " + visualize(e));
continue;
}
WScript.stdOut.writeLine(visualize(xResult));
}
Example usage
C:\Windows\system32>jssh
JavaScript Shell (CScript) build 080818 by Berend-Jan "SkyLined" Wever
Global objects:
goFSO = new ActiveXObject("Scripting.FileSystemObject")
goWSS = new ActiveXObject("WScript.Shell")
goENV = goWSS.environment("PROCESS")
Enter commands or type "quit" or "exit" to quit:
JSSh>1+1
number: 2
JSSh>WScript.stdOut.writeLine("hello, world!");
hello, world!
undefined: undefined
JSSh>Math.random();
number: 0.47396005286261244
JSSh>cause an exception
Exception: Expected ';'
JSSh>quit
C:\Windows\system32>
