Executes scripts and provides a command line user interface with separate text fields for input and output. Executes EasyScript or JavaScript. Allows use of "short names" to replace full namespace pathnames of classes.

After the script is executed the result is converted to text and displayed in the output text field. The output is not displayed if the result is undefined or the script ends with a semicolon.

See also Customizing myPhysicsLab Software.

Getting Help

Type help in the Terminal input text area and press return to see the help message. Several useful Terminal commands are shown.

Perhaps the most useful command is vars which shows the list of variables that are available.

Summary: How Scripts Are Processed

Scripts entered into Terminal are transformed in these ways:

  • Scripts are split at semi-colons into separate lines. Each line is executed separately. (Semi-colons within braces are ignored).

  • EasyScript parser handles lines that it recognizes.

  • var at start of a line becomes a z variable property. For example var foo becomes app.z.foo.

  • Short-names are transformed to long-names. Example: DoubleRect becomes lab$util$DoubleRect. Also existing variables are transformed, for example foo becomes app.z.foo.

  • Javascript's eval function executes the resulting line.

Turning on verbose mode with terminal.setVerbose(true) shows these transformations as they happen.

Two Types of Scripts

Terminal can execute two types of scripts:

  1. JavaScript. The code is transformed so that short-names can be used.

  2. EasyScript: a very simple scripting language for setting Parameter values. See EasyScriptParser for syntax details.

These two types of script can be intermixed in a single script as long as they are separated by a semicolon. For example, here are both types of scripts in one line which could be entered in PendulumApp.

DAMPING=0.1; GRAVITY=9.8; ANGLE=2.5; bob.setFillStyle('red');

The first three commands are EasyScript commands that set Parameter values; the last is a JavaScript command.

In most applications EasyScriptParser is available in the variable easyScript, which you can use to execute EasyScript from within JavaScript. Here are examples that can be entered (as individual lines) in PendulumApp.

easyScript.parse('angle')

easyScript.parse('angle='+Math.PI/2)

easyScript.getParameter('gravity').getValue()

easyScript.getParameter('gravity').setValue(2.5)

Long Names

To make class names accessible for scripting in Terminal, we create a global variable for each class. For example

lab$util$DoubleRect

is the global variable for the DoubleRect class. This naming scheme is used to avoid potential conflicts with other global variables.

Short Names

To allow for shorter scripts, we define a variety of regular expressions in Terminal which convert short names to their proper long expanded form. This allows typing for example:

new DoubleRect(0,0,1,1)

which is automatically converted to

new lab$util$DoubleRect(0,0,1,1)

Applications will typically also make their key objects available with short-names. So instead of app.sim you can just type sim.

You can see this short-name to long-name conversion by using setVerbose:

> terminal.setVerbose(true)
> new Vector(2,3)
>> new lab$util$Vector(2,3)
Vector{x: 2, y: 3}

In verbose mode, the command is echoed a second time to show how it appears after expansion. The terminal prompt symbol >> is doubled to distinguish the expanded version.

Short-names are implemented by defining a set of regular expression replacement rules which are applied to the Terminal input string before it is executed.

Regular expression rules are registered with Terminal using addRegex. Then whenever a command is evaluated it is first expanded to the long form using expand.

stdRegex defines a standard set of regular expressions for expanding myPhysicsLab class names (like DoubleRect) and for expanding a few function shortcuts like methodsOf, propertiesOf and prettyPrint. An application can add more shortcuts via addRegex.

Variables and the 'z' Object

Scripts are executed with indirect eval under strict mode. Each script line is eval'd separately, and a new scope is created for each eval(). Any variables created only exist during that eval(), then they disappear.

To allow making variables that persist between lines and commands, the app provides an object named z where properties can be added. A script like var a = 1; a is translated to define a property on the z object, instead of a new global variable. It looks something like this:

> z.a = 1
1
> z.a
1

This z object is itself a property of the application object usually called app; z is initially an object with no properties. We define a short name regular expression so that referring to z is replaced by app.z when a script line is executed. Using setVerbose you would see the following:

> terminal.setVerbose(true)
> var a=1
>> app.z.a=1
1
> a
>> app.z.a
1

Declaring a Variable

To hide the usage of the z object, Terminal interprets the var, let and const keywords in a special way.

When Terminal sees the var or let keywords at the start of a command, it changes the script to use the z object and defines a new short-name. For example the command

> var foo = 3
3

is translated to

> app.z.foo = 3
3

and thereafter every reference to foo will be changed to app.z.foo in later commands. You can see this at work by using setVerbose:

> terminal.setVerbose(true)
> foo
>> app.z.foo
3

Line Splitting Affects How Scripts Are Processed

A script is executed by splitting it up into lines of code that are separated by semi-colons.

Each execution of a line (via indirect eval) has it's own temporary scope where any created variables, functions, or classes go. That scope disappears as soon as the execution finishes.

Only lines that are at the "top level" are split by semi-colons; any semi-colons within braces or parenthesis (or inside of strings) are ignored. Braces turn off line splitting.

For example: this script creates a class and does a test within braces, but the class and variable disappear after execution. The value 7 is printed if you paste this entire script into Terminal input, but a and myClass are no longer defined.

{ class myClass {
myField=7;
constructor() {}
}
var a = new myClass();
println(a.myField) }

To make things within braces persistent, assign them to something defined beforehand.

var a;
{ class myClass {
myField=7;
constructor() {}
}
a = new myClass(); };
a.myField

To make a class (or function) persistent, assign it to a variable.

var myClass = class { myField=7; constructor() {} };
var a = new myClass();
a.myField

The Result Variable

The result of the last Terminal script is stored in a variable named result. Here is an example Terminal session:

> 2+2
4
> result*2
8
> result*2
16

Note that eval has an argument called output which if set to false prevents result from being updated. When output==false, then result is is defined for commands in the same string, but that version of result is temporary and independent of the permanent result variable.

The terminal Variable

Some features (such as the result variable) require that the name terminal is defined and resolves to the Terminal object.

In most applications this is accomplished by using addRegex something like this:

terminal.addRegex('terminal', 'app');

where app is the global variable containing the application. The purpose of the regex is to replace the word terminal with app.terminal which is a valid JavaScript reference.

(In unit tests of Terminal, we temporarily define a global variable named terminal.)

Cautions About Newline Character

When you paste a script into the Terminal text input field, be aware that newlines are replaced by spaces. For a multi-line script this can cause errors. To prevent problems:

  • Use explicit semicolons instead of relying on JavaScript's policy about optional semicolons.

  • Use slash-star style comments instead of double-slash style comments (which are terminated by a newline).

  • If for some reason you really need a newline in the script, use \u000A or \x0A. These are replaced with the newline character before the script is evaluated.

  • Put the multi-line script in a start-up HTML page. You can then call Terminal.eval() directly on a string that you create, and that string can include newline characters.

The tab character also cannot be input directly to the Terminal input field, because the browser interprets that to mean "move to the next field". You can use \u0009 or \x09 which are replaced by a tab character before the script is evaluated.

URL Query Script

A Terminal script can be embedded into a URL query string which will be executed when the page is loaded. This provides a convenient way to remember or share a customized simulation with someone else.

The script follows a question mark in the URL, so it is called a 'query script' or 'query URL'. Here is an example:

https://www.myphysicslab.com/pendulum/pendulum-en.html?DRIVE_AMPLITUDE=0;
DAMPING=0.1;GRAVITY=9.8;ANGLE=2.5;ANGLE_VELOCITY=0;

The URL Query Script is executed at startup by calling parseURL. Most myPhysicsLab applications do this.

Some websites will only accept user-supplied URLs that follow the strict guidelines of URL percent-encoding. Therefore we must substitute in the URL:

  • %20 for space
  • %22 for "
  • %3C for <
  • %3E for >
  • %5C for \

See this character encoding chart to learn which other characters must be percent-encoded. You can use {@link encodeURIComponent} which is a more stringent version of doing the character encoding; it percent-encodes other symbols such as:

  • %27 for '
  • %28 for (
  • %29 for )
  • %3B for ;

Here is an example of a URL query script using JavaScript in an application:

https://www.myphysicslab.com/pendulum/double-pendulum-en.html?
simRun.pause();simRun.reset();sim.setGravity(5.0);statusView.getDisplayList()
.add(energyGraph);statusView.getDisplayList().add(displayClock);
var%20va=sim.getVarsList();va.setValue(0,0.15545);va.setValue(1,-0.33548);
va.setValue(2,-2.30681);va.setValue(3,2.68179);sim.saveInitialState();
simRun.resume();layout.showTerminal(true);

Try this link which contains the above code; you should also see the code in the Terminal output area.

Here is an interactive tool for trying out URL Encode/Decode. Note however that tool replaces a space with a + which instead should be replaced by %20.

Many websites and programming tools require that the URL be fully encoded with the more stringent version.

Session History

The session history feature recalls previous input lines; these are accessed using the up/down arrow keys. Command-K clears the output area.

Constructors

  • Parameters

    • term_input: null | HTMLInputElement

      A text input field where user can enter a script to evaluate, or null.

    • term_output: null | HTMLTextAreaElement

      A multi-line textarea where results are shown, or null

    Returns Terminal

Properties

afterErrorFn: (() => void)

Function to execute after an error in a script occurs, but only for scripts that are not "user input". Typical use is to do "show terminal" on the Layout, so the user can see the error there.

Type declaration

    • (): void
    • Function to execute after an error in a script occurs, but only for scripts that are not "user input". Typical use is to do "show terminal" on the Layout, so the user can see the error there.

      Returns void

afterEvalFn_?: (() => void) = undefined

Function to execute after a script is executed.

Type declaration

    • (): void
    • Function to execute after a script is executed.

      Returns void

changeFn_?: ((e) => void) = undefined

change event handler, saved for removing listener.

Type declaration

    • (e): void
    • change event handler, saved for removing listener.

      Parameters

      • e: Event

      Returns void

error: string

Holds the error message from last eval()

evalCalls_: number = 0

Number of simultaneous calls to eval() for detecting recursion

hasAlerted_: boolean = false

Whether the alertOnce function has happened.

histIndex_: number = -1

index of item last recalled from session history array; or -1 otherwise.

history_: string[] = []

session history of scripts entered.

keyDownFn_: ((e) => void)

keydown event handler, saved for removing listener.

Type declaration

    • (e): void
    • keydown event handler, saved for removing listener.

      Parameters

      • e: Event

      Returns void

prompt_: string = '> '

The prompt to show before each user-input command.

regexs_: regexPair[] = []

Set of regular expressions to apply to each script to replace short names with full expanded name. For example, DoubleRect is the short name that expands to myphysicslab.lab.util.DoubleRect.

result: any = undefined

Contains results of last script. Can be referred to in Terminal as result.

resultStack_: any[] = []

Contains saved results when eval is being called recursively.

term_input_: null | HTMLInputElement

terminal input, usually a text input field.

term_output_: null | HTMLTextAreaElement

terminal output, usually a textarea

vars_: string = ''

The variables available to the user. Names separated by | symbol.

verbose_: boolean = false

Whether to print the expanded or unexpanded script. Seeing the expanded script is useful for debugging, or for understanding how Terminal works.

z: object = {}

An object that scripts can store properties into. See The z Object. Note that an app might specify it's own z object, which would shorten the long name to be app.z.foo instead of app.terminal.z.foo.

Methods

  • Adds a regular expression rule for transforming scripts before they are executed.

    One usage is to prepend the namespace to fully qualify a short name. For example, to transform DoubleRect into myphysicslab.lab.util.DoubleRect

    terminal.addRegex('DoubleRect', `myphysicslab.lab.util.');
    

    Another usage is to make properties of an object available as a single short name. For example to transform rod or bob into app.rod or app.bob

    terminal.addRegex('rod|bob', 'app.');
    

    The regular expression rule is added to the end of the list of regex's to execute, unless opt_prepend is true.

    Parameters

    • names: string

      set of names separated by | symbol

    • prefix: string

      the string to prepend to each occurence of the names

    • Optional opt_addToVars: boolean

      if true, then the set of names is added to the set of defined names returned by vars; default is true

    • Optional opt_prepend: boolean

      if true, then the regex rule is added to the front of the list of regex's to execute; default is false

    Returns boolean

    whether the regex rule was added (returns false if the regex rule already exists)

  • Adds a regular expression rule for transforming scripts before they are executed.

    Parameters

    • regex: RegExp

      the RegExp to find

    • replace: string

      the replacement expression

    • Optional opt_prepend: boolean

      if true, then the regex rule is added to the front of the list of regex's to execute; default is false

    Returns boolean

    whether the regex rule was added (returns false if the regex rule already exists)

  • Adds to the set of defined names returned by vars

    Parameters

    • name: string

      string to add to white list

    Returns void

  • Shows an alert with the given message, but only the first time it is called. This prevents infinite loop of alerts. An example where that can happen is if an error occurs during a blur or focus event, which can then repeat after the user dismisses the alert which causes further blur/focus events.

    Parameters

    • msg: string

      the message to show

    Returns void

  • Returns command scripts in current Terminal output text area, as array of strings. Commands are any line in the output text area that start with > . Each script is also trimmed of leading or trailing whitespace.

    Returns string[]

    array of command strings in current Terminal output

  • Remove connections to other objects to facilitate garbage collection.

    Returns void

  • Executes the given script and returns the result.

    When output is true: updates the result variable, prints the result in the output text area, scrolls the output so the most recent text is visible, clears the input text area, remembers the script in the session history.

    When output is false: the result variable is updated for successive scripts (separated by a semicolon) in the same script line, but after the script is finished executing the result variable is unchanged. The output text area and session history array are unchanged.

    The output=false option allows for evaluating scripts that define a variable, for example in FunctionVariable. The FunctionVariable script can be executed frequently without modifying the result seen by the user in Terminal.

    The script is split into pieces separated by top-level semicolons (top-level means they are not enclosed by braces). Each fragment is first offered to the Parser installed with setParser. If the Parser does not recognize the fragment, then the fragment is expanded expand before being executed using JavaScript eval.

    Error handling: when showAlert is false we avoid throwing an error and only print the error to the output text area where the user will presumably see it. When showAlert is true we show an alert with the error message.

    eval() never throws an error because the error message would be lost in that process. Because of CORS policy (Cross-origin Resource Sharing) browsers only report the message "Script error." Therefore we instead show an alert to the user here with the error text. This can happen for example on start-up if a script in the HTML file is being eval'd.

    In unit tests, you can pass showAlert = false and examine the resulting error with getError.

    Parameters

    • script: string

      a fragment of JavaScript to be executed

    • output: boolean = true

      whether to print the result to the output text area and add the script to session history; default is true

    • showAlert: boolean = true

      whether to show an alert with error message when an error occurs in the script; default is true

    Returns any

    the result of executing the script

  • Returns the given Javascript script expanded by the various regular expression rules which were registered with addRegex. The expanded script has short names like DoubleRect expanded to have full path name like lab$util$DoubleRect. Doesn't expand words inside of quoted strings or regular expressions.

    Parameters

    • script: string

      a Javascript script to be executed

    Returns string

    the script expanded by registered regular expressions

  • Returns the error message from the last eval call, or empty string if no error occurred.

    Returns string

  • Called when a key has been pressed. Implements the meta-K command to clear the output area, and the up/down arrow keys to scroll through session history.

    Parameters

    • e: Event

      the event that caused this callback to fire

    Returns void

  • Returns true if the given regexPair is already on the list of regex's to execute.

    Parameters

    Returns boolean

    true if q is already on the list of regex's to execute.

  • This callback fires when the textbox 'changes' (usually from focus lost).

    Parameters

    • _evt: Event

      the event that caused this callback to fire

    Returns void

  • Parses and executes the query portion of the current URL (the portion of the URL after a question mark) as a script. See URL Query Script.

    Before executing the query script, this calls Parser.saveStart to save the current settings.

    Returns boolean

    returns true if there was a URL query script

  • Print the given text to the Terminal output text area, followed by a newline.

    Parameters

    • text: string

      the text to print to the Terminal output text area

    Returns void

  • Removes the var or let at front of a script (if any) and adds regexp which mimics that JavaScript var statement. This helps make Terminal scripts more JavaScript-like, by hiding usage of the z object. For example, if the script is

    var foo = 3;
    

    this will return just foo = 3; and add a regexp that replaces foo by z.foo.

    Parameters

    • script: string

      a Javascript script to be executed

    Returns string

    the script with the var removed

  • Sets the function to execute after evaluating the user input. Typically used to update a display such as a SimView or DisplayGraph.

    Parameters

    • Optional afterEvalFn: (() => void)

      function to execute after evaluating the user input; can be undefined to turn off this feature

        • (): void
        • Returns void

    Returns void

  • Sets the prompt symbol shown before each command.

    Parameters

    • prompt: string

      the prompt symbol to show before each command

    Returns void

  • Specifies whether to show the expanded command in the Terminal output text area. In verbose mode, the command is echoed a second time to show how it appears after expansion. The terminal prompt symbol is doubled to distinguish the expanded version.

    Parameters

    • expand: boolean

      true means show expanded names in the Terminal output

    Returns void

  • Finds the section of text up to first top-level semicolon (top-level means not enclosed in curly braces). Ignores semicolons in quotes or regular expression. Note however that top-level double-slash comments end at a new-line not semicolon.

    Parameters

    • text: string

      The text to be split up.

    Returns string[]

    array with two elements: array[0] = the section up to and including the first top-level semicolon; array[1] = the remaining text.

  • Returns names of the variables that have been defined using addRegex. This is used as a "help" command for the user to know what variables are available.

    Returns string[]

    names of defined variables, in alphabetic order

  • This is a more stringent version of encodeURIComponent which adheres to RFC 3986 which reserves characters !'()*. Some websites (such as reddit) will not accept a user supplied URL that contains those characters.

    Parameters

    • str: string

      the string to encode

    Returns string

    the encoded string

  • Adds the standard set of regular expression rules to the given Terminal instance. These regular expression rules replace short names with the full expression that is valid JavaScript for referring to the object. This defines short names for many classes and also utility functions like prettyPrint, methodsOf, println and propertiesOf.

    Parameters

    • terminal: Terminal

      the Terminal instance to which the regexp's will be added

    Returns void

  • Returns string identifying current version of myPhysicsLab software.

    Returns string

    version information

Generated using TypeDoc