I thought that a good way to learn more about Javascript would be to build some small tools for the machines I use at work. I've learned that Javascript on Windows machines come in at least 3 different flavors, Jscript hosted on the Windows Scripting Host, Jscript .NET compiled with the jsc compiler, and the Jscript running on Internet Explorer and Firefox. Not only that but doing things on Windows XP turns out to be slightly different than on Windows 7. Take for example embedding Jscript in a batch file so that I can call the tool from anywhere on the command line. What I found on StackOverflow was this cool calendar example:
REM Let's call this command "cal"
@set @junk=1 /*
@echo off
cscript //nologo //E:jscript %0 %*
goto :eof
*/
x = WScript.Arguments
Yr = x(0) ; Mo = x(1)
YS = "JanFebMarAprMayJunJulAugSepOctNovDec"
MN = Mo<1 || Mo>12 ? Mo : YS.substr(3*Mo-3, 3) // Month Name
WScript.echo(" ", Yr, " ", MN)
WScript.echo(" Mo Tu We Th Fr Sa Su")
WD = new Date(Yr, Mo-1, 1).getDay() ;
if (WD==0) WD = 7 // Week Day Number of 1st
LD = new Date(Yr, Mo, 0).getDate() // Last Day of month
Wk = "" ; for (D=1 ; D < WD ; D++) Wk += " "
for (D=1 ; D<=LD ; D++) {
Wk = Wk + " " + (D<10 ? "0"+D : D) ; WD++
if ((WD==8) || (D==LD)) { WScript.echo(Wk) ; WD = WD-7 ; Wk = "" }
}
WScript.echo(" ------ ")
Calling this script in Windows XP works, but it doesn't work on Windows 7. More Googling showed that for Windows 7, I need to change the batch script code to the following:
@if (@CodeSection == @Batch) @then
@echo off
cscript //nologo //E:jscript %~f0 %*
goto :eof
@end
Then the script will work and testing with "cal 2014 11" outputs:
2014 Nov
Mo Tu We Th Fr Sa Su
01 02
03 04 05 06 07 08 09
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
---------------------------------
Mo Tu We Th Fr Sa Su
01 02
03 04 05 06 07 08 09
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
---------------------------------
Another handy tool for Windows scripting would be a command line read-eval-print-loop similar to what Python and Lisp have. Jscript does not come with a REPL built in, but finding a basic example online was not hard. Here is the code that works good enough for my purposes.
@if (@CodeSection == @Batch) @then
@echo off
cscript //nologo //E:jscript %~f0 %*
goto :eof
@end
function hex(n) {
if (n >= 0) {
return n.toString(16);
} else {
n += 0x100000000;
return n.toString(16);
}
}
var scriptText;
var previousLine;
var line;
var result;
while(true) {
WScript.StdOut.Write("jscript> ");
if (WScript.StdIn.AtEndOfStream) {
WScript.Echo("Bye.");
break;
}
line = WScript.StdIn.ReadLine();
scriptText = line + "\n";
if (line === "") {
WScript.Echo(
"Enter two consecutive blank lines to terminate multi-line input.");
do {
if (WScript.StdIn.AtEndOfStream) {
break;
}
previousLine = line;
line = WScript.StdIn.ReadLine();
line += "\n";
scriptText += line;
} while(previousLine != "\n" || line != "\n");
}
try {
result = eval(scriptText);
} catch (error) {
WScript.Echo("0x" + hex(error.number) + " " + error.name + ": " +
error.message);
}
if (result) {
try {
WScript.Echo(result);
} catch (error) {
WScript.Echo("<<>>");
}
}
result = null;
}
@echo off
cscript //nologo //E:jscript %~f0 %*
goto :eof
@end
function hex(n) {
if (n >= 0) {
return n.toString(16);
} else {
n += 0x100000000;
return n.toString(16);
}
}
var scriptText;
var previousLine;
var line;
var result;
while(true) {
WScript.StdOut.Write("jscript> ");
if (WScript.StdIn.AtEndOfStream) {
WScript.Echo("Bye.");
break;
}
line = WScript.StdIn.ReadLine();
scriptText = line + "\n";
if (line === "") {
WScript.Echo(
"Enter two consecutive blank lines to terminate multi-line input.");
do {
if (WScript.StdIn.AtEndOfStream) {
break;
}
previousLine = line;
line = WScript.StdIn.ReadLine();
line += "\n";
scriptText += line;
} while(previousLine != "\n" || line != "\n");
}
try {
result = eval(scriptText);
} catch (error) {
WScript.Echo("0x" + hex(error.number) + " " + error.name + ": " +
error.message);
}
if (result) {
try {
WScript.Echo(result);
} catch (error) {
WScript.Echo("<<
}
}
result = null;
}
One application I have in mind for using Jscript at work is as a quick and small footprint command line calculator. In the past I have used Matlab, Google Sheets, the basic Windows calculator, and Excel. Most of these are overkill for what I need to do, and Windows calculator is too basic. Hard-coding the calculations into the command line sounds a lot more convenient for the things I need to do. Here is calculation I have been doing a lot recently on Google Sheets. It realigns the offset for the camera I am looking through to the desired coordinate system.
@if (@CodeSection == @Batch) @then
@echo off
cscript //nologo //E:jscript %~f0 %*
goto :eof
@end
// realign.bat
// Jovan Trujill
// Arizona State University
// 11/04/2014
//
// Usage: realign XActual YActual XDesired YDesired XOffset_Old YOffset_Old
// This command will return the alignment offset coordinates needed to correct
// camera positioning problems on the Cherry prober system.
//
var X_Actual = 0.0;
var Y_Actual = 0.0;
var X_Desired = 0.0;
var Y_Desired = 0.0;
var dX = 0.0;
var dY = 0.0;
var X_Offset_Old = 0.0;
var Y_Offset_Old = 0.0;
var X_Offset_New = 0.0;
var Y_Offset_New = 0.0;
var args = WScript.Arguments;
if (args.length != 6) {
WScript.echo("Usage: realign XActual YActual XDesired YDesired OldXOffset OldYOffset");
} else {
X_Actual = parseInt(args(0));
Y_Actual = parseInt(args(1));
X_Desired = parseInt(args(2));
Y_Desired = parseInt(args(3));
X_Offset_Old = parseInt(args(4));
Y_Offset_Old = parseInt(args(5));
dX = X_Desired - X_Actual;
dY = Y_Desired - Y_Actual;
X_Offset_New = X_Offset_Old - dX;
Y_Offset_New = Y_Offset_Old + dY;
WScript.echo("X_Actual Y_Actual");
WScript.echo(X_Actual + " " + Y_Actual);
WScript.echo("X_Desired Y_Desired");
WScript.echo(X_Desired + " " + Y_Desired);
WScript.echo("X_Old_Offset Y_Old_Offset");
WScript.echo(X_Offset_Old + " " + Y_Offset_Old);
WScript.echo("X_New_Offset Y_New_Offset");
WScript.echo(X_Offset_New + " " + Y_Offset_New);
}
@echo off
cscript //nologo //E:jscript %~f0 %*
goto :eof
@end
// realign.bat
// Jovan Trujill
// Arizona State University
// 11/04/2014
//
// Usage: realign XActual YActual XDesired YDesired XOffset_Old YOffset_Old
// This command will return the alignment offset coordinates needed to correct
// camera positioning problems on the Cherry prober system.
//
var X_Actual = 0.0;
var Y_Actual = 0.0;
var X_Desired = 0.0;
var Y_Desired = 0.0;
var dX = 0.0;
var dY = 0.0;
var X_Offset_Old = 0.0;
var Y_Offset_Old = 0.0;
var X_Offset_New = 0.0;
var Y_Offset_New = 0.0;
var args = WScript.Arguments;
if (args.length != 6) {
WScript.echo("Usage: realign XActual YActual XDesired YDesired OldXOffset OldYOffset");
} else {
X_Actual = parseInt(args(0));
Y_Actual = parseInt(args(1));
X_Desired = parseInt(args(2));
Y_Desired = parseInt(args(3));
X_Offset_Old = parseInt(args(4));
Y_Offset_Old = parseInt(args(5));
dX = X_Desired - X_Actual;
dY = Y_Desired - Y_Actual;
X_Offset_New = X_Offset_Old - dX;
Y_Offset_New = Y_Offset_Old + dY;
WScript.echo("X_Actual Y_Actual");
WScript.echo(X_Actual + " " + Y_Actual);
WScript.echo("X_Desired Y_Desired");
WScript.echo(X_Desired + " " + Y_Desired);
WScript.echo("X_Old_Offset Y_Old_Offset");
WScript.echo(X_Offset_Old + " " + Y_Offset_Old);
WScript.echo("X_New_Offset Y_New_Offset");
WScript.echo(X_Offset_New + " " + Y_Offset_New);
}
As the library of functions gets more complicated I will need to figure out a way to call JScript functions from other JScript programs. I think the most convenient way to do that will be:
/* include.js */
(function () {
var L = {/* library interface */};
L.hello = function () {return "greetings!";};
return L;
}).call();
And then the main function calls "include.js" like this:
var Fs = new ActiveXObject("Scripting.FileSystemObject");
var Lib = eval(Fs.OpenTextFile("include.js", 1).ReadAll());
WScript.echo(Lib.hello()); /* greetings! */
The example works but I have not tested it on anything more substantial.
No comments:
Post a Comment