One of the neat things you can do with the Rhino Javascript shell is take some piece of text manipulation or validation that’s been written for the web and use it in any shell script, or any editor that supports calling out to shell scripts.
For example, take this Javascript Code Beautifier written in Javascript. Useful as-is, but you have to
- Copy your code
- Switch to the browser
- Go to a website with the beautifier
- Paste the code in
- Click a button
- Select the code again
- Copy the code
- Switch back to your editor
- Paste the code back in the window
That’s nine distinct actions. Using Rhino and a text editor like BBEdit, you can reduce this to two distinct actions
- Select your code
- Invoke a Unix Filter
Taken for an individual case that’s not a big deal. Over a day of coding and debugging it’s a huge timesaver, as well as saving the mental energy of switching contexts from editor to browser and then back to editor.
Assuming you’ve installed the Rhino shell, just download this script and replace the following in the shebang line
/path/to/js.jar
with the full path to your js.jar file. The script will work with text streams or will treat the first argument as its input file.
cat ugly.js | beautify.js
beautify.js ugly.js
Together At Last
With a twist of irony for web old timers, Rhino exposes the entire Java API to Javascript. This is how I’m handling input streams. There is a major gotcha you’ll need to watch out for. Consider this stream handling code
importPackage(java.io);
//in is a reserved Javascript word, so we need to use [] for access
var readingIn = new BufferedReader(new InputStreamReader(java.lang.System["in"]));
var sInput = "";
var str = "";
while(str != null){
sInput += str;
str = readingIn.readLine();
}
The importPackage line is a convenience that lets us avoiding using a fully qualified package namespace. By importing java.io we can say
new BufferedReader
Instead of
new java.io.BufferedReader
The gotcha you’ll need to watch out for is Javascript’s reserved word policy. The following list of words are invalid in many Javascript contexts, including as a name in literal object notation and as a member name in dot notation.
abstract
boolean break byte
case catch char class const continue
debugger default delete do double
else enum export extends
false final finally float for function
goto
if implements import in instanceof int interface
long
native new null
package private protected public
return
short static super switch synchronized
this throw throws transient true try typeof
var volatile void
while with
You’ll notice the word [in] on that list. That means trying to use the following in your Rhino scripts will fail
java.lang.System.in
The Mozilla group also recommends not importing a package that uses these reserved words. Fortunately, you can still use these packages with Javascript’s subscript notation
java.lang.System["in"]
Remember, you’re not writing Java, you’re writing Javascript that has access to the Java API. Using Java in the context of a scripting language has the potential to expose both languages to a huge number of people who would otherwise never consider either language.
Whether this is a good thing or a bad thing is better left to history.