Nasal library

From FlightGear wiki
Revision as of 13:12, 20 May 2015 by Www2 (talk | contribs) (→‎systime(): fix the epoch time from wrong date 1972/01/01 to correct date of 1970/01/01)
Jump to navigation Jump to search


This page documents the core library functions of FlightGear's built-in scripting language, Nasal. The relevant folders in Git are:

Note  Feel free to copy & paste the examples into your Nasal Console and execute them to see what they do.

Core library

This is the list of the basic core library functions that were in Nasal before its integration in to FlightGear. See also:

'"`UNIQ--syntaxhighlightinner-00000007-QINU`"'

core

This function appends, or adds, the given element(s) to the end of the vector given in the first argument. Returns the vector operated on.

vector
The vector to which the arguments will be appended.
element
An element to be added to the vector.

Examples

'"`UNIQ--syntaxhighlightinner-0000000B-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000000D-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000013-QINU`"'

core

This creates a new function object. A function in Nasal is three things: the actual code, a hash/namespace of local variables available to the function namespace, and the closure object of that namespace. These correspond to the three arguments respectively.

function
Function to evaluate.
locals
Hash containing values that will become the namespace (first closure) for the function.
outer_scope
Optional function which is bound to the next closure. This can be bound to yet another, making a linked list.

Example

'"`UNIQ--syntaxhighlightinner-00000017-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000001B-QINU`"'

core

Calls the given function with the given arguments and returns the result. This function is very useful as it allows much more control over function calls and catches any errors or die calls that would normally trigger run-time errors cancelling execution of the script otherwise.

func
Function to execute.
args
Vector containing arguments to give to the called function.
me
me reference for the function call (i.e., for method calls). If given, this will override any me value existing in the namespace (locals argument).
locals
A hash with key/value pairs that will be available to the called function, typically used as the namespace for the function to be called.
error
A vector to append errors to. If the called function generates an error, the error, place, and line will be written to this. These errors can be printed using debug.printerror() .

Examples

'"`UNIQ--syntaxhighlightinner-0000001F-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000021-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000027-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000002B-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000002F-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000033-QINU`"'

core

Returns a vector containing a record from the current call stack. The level numbering starts from the currently executing function (level 0). Level 1 (the default) is the caller of the current function, and so on. The result is a four-element vector containing a hash of local variables, the function object, the source, and the line number.

level
Optional integer specifying the stack level to return a result from. Defaults to 1 (the caller of the currently executing function.

Examples

'"`UNIQ--syntaxhighlightinner-00000037-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000039-QINU`"'

This is a real example taken from $FG_ROOT/Nasal/canvas/MapStructure.nas. r(); (highlighted) returns a hash with the key/value pairs as per its arguments. For example, something like this is returned: { name: "<name>", vis: 1, zindex: nil }.

'"`UNIQ--syntaxhighlightinner-0000003F-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000043-QINU`"'

core

Returns a character as per the single argument. Extended ASCII is supported (see http://www.asciitable.com/ for a list of supported characters), although this may vary between different systems. For a list of the most commonly used characters, see http://en.wikipedia.org/wiki/ASCII#ASCII_printable_code_chart (Dec column). The following table lists supported control characters, along with their equivalent control characters in Nasal strings.

Note  In Nasal, only strings enclosed with double-quotes ("string") supports control chracters. Strings in single quotes ('string') do not.
Code Name Equivalent to
10 Newline This is a link to a Wikipedia article \n
9 Horizontal tab This is a link to a Wikipedia article \t
13 Carriage return This is a link to a Wikipedia article \r
code
Integer character code for the desired glyph.

Examples

'"`UNIQ--syntaxhighlightinner-00000047-QINU`"'

This example displays all of the characters in a list, in the format Code n = >char<, n being the index, and char being the character.

'"`UNIQ--syntaxhighlightinner-00000049-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000004F-QINU`"'

core

Returns the hash table containing the lexical namespace of the given function. The level numbering start with level 0 being the namespace of func.

func
Function to evaluate.
level
Optional integer specifying the scope level. Defaults to 0 (the namespace of func).

Example

'"`UNIQ--syntaxhighlightinner-00000053-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000057-QINU`"'

core

Compares two strings, returning -1 if a is less than b, 0 if they are identical and 1 if a is greater than b.

a
First string argument for comparison.
b
Second string argument for comparison.

Examples

'"`UNIQ--syntaxhighlightinner-0000005B-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000005D-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000063-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000067-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000006B-QINU`"'

core

Compiles the specified code string and returns a function object bound to the current lexical context. If there is an error, the function dies, with the argument to die being filename.

code
String containing Nasal code to be compiled.
filename
Optional string used for error messages/logging. Defaults to <compile>

Examples

'"`UNIQ--syntaxhighlightinner-0000006F-QINU`"'

compile is very convenient to support Nasal loaded from other files. For instance, PropertyList XML files (such as GUI dialogs) may contain embedded Nasal sections that need to be parsed, processed and compiled. For an example of how to do this, save the below XML code as $FG_ROOT/gui/dialogs/test.xml.

<?xml version="1.0"?>

<PropertyList>

<nasal><![CDATA[
print("You have FlightGear v", getprop("/sim/version/flightgear"));
]]></nasal>

</PropertyList>

Now, start FlightGear and execute this code in the Nasal Console.

'"`UNIQ--syntaxhighlightinner-00000071-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000079-QINU`"'

core

Returns 1 (True) if the hash contains the specified key, or 0 (False) if not.

hash
The hash to search in.
key
The scalar to be searched for, contained as a key in the hash.

Examples

'"`UNIQ--syntaxhighlightinner-0000007D-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000007F-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000085-QINU`"'

core

Deletes the key from the hash if it exists. Operationally, this is identical to setting the hash value specified by the key to nil, but this variant potentially frees storage by deleting the reference to the key and by shrinking the hash. Returns the hash that has been operated on.

hash
The hash from which to delete the key.
key
The scalar to be deleted, contained as a key in the hash.

Example

'"`UNIQ--syntaxhighlightinner-00000089-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000008D-QINU`"'

core

Terminates execution and unwinds the stack. The place and the line will be added to the error. This invokes the same internal exception handler used for internal runtime errors. Use this to signal fatal errors, or to implement exception handling. The error thrown (including internal runtime errors) can be caught with call .

error
String describing the error.
Note This parameter is technically optional, but it is highly recommended to use it.

Example

'"`UNIQ--syntaxhighlightinner-00000091-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000095-QINU`"'

core

Finds and returns the index of the first occurrence of the string needle in the string haystack, or -1 if no such occurrence was found.

needle
String to search for.
haystack
String to search in.

Examples

'"`UNIQ--syntaxhighlightinner-00000099-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000009B-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000A1-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000A5-QINU`"'

core

Returns a string containing either a descriptive name of a ghost (a raw C/C++ object), or a unique id (the pointer to the C/C++ naGhostType instance) if no name has been set. Ghost is an acronym that stands for Garbage-collected Handle to OutSide Thingy.

ghost
Ghost to return a description for.
'"`UNIQ--syntaxhighlightinner-000000A9-QINU`"'

core

Returns a string containing information on the type and ID of the object provided in the single argument. The information is returned in the form of type:id, where type is the type of object, and id is the ID.

object
Can be either of a string, a vector, a hash, a code, a function, or a ghost.

Example

'"`UNIQ--syntaxhighlightinner-000000AD-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000B1-QINU`"'

core

Returns the integer part of the numeric value of the single argument, or nil if none exists.

number
Number or string with just a number in it to return an integer from.

Examples

'"`UNIQ--syntaxhighlightinner-000000B5-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000B7-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000BD-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000C1-QINU`"'

core

Returns a vector containing the list of keys found in the single hash argument.

hash
The hash to return the keys from.

Example

'"`UNIQ--syntaxhighlightinner-000000C5-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000C9-QINU`"'

core — Version added: FG 2.12.0+

Returns a substring of string, starting from the left.

string
String to return part of.
length
Integer specifying the length of the substring to return.

Example

'"`UNIQ--syntaxhighlightinner-000000CD-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000D1-QINU`"'

core

Returns the numerical value of the single striing argument, or nil if none exists.

number
String with just a number in it to return a number from.

Examples

'"`UNIQ--syntaxhighlightinner-000000D5-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000D7-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000DD-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000E1-QINU`"'

core

Removes and returns the last element of the single vector argument, or nil if the vector is empty.

vector
Vector to remove an element from.

Examples

'"`UNIQ--syntaxhighlightinner-000000E5-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000E7-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000ED-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000F1-QINU`"'

core — Version added: FG 2.12.0+

Returns a substring of string, starting from the right.

string
String to return part of.
length
Integer specifying the length of the substring to return.

Example

'"`UNIQ--syntaxhighlightinner-000000F5-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000F9-QINU`"'

core

Sets the size of a vector. The first argument specifies a vector, the second a number representing the desired size of that vector. If the vector is currently larger than the specified size, it is truncated. If it is smaller, it is padded with nil entries. Returns the vector operated upon.

vector
The vector to be operated on.
size
The desired size of the vector in number of entries.

Examples

'"`UNIQ--syntaxhighlightinner-000000FD-QINU`"'
'"`UNIQ--syntaxhighlightinner-000000FF-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000105-QINU`"'

core

Returns the size of the single argument. For strings, this is the length in bytes. For vectors, this is the number of elements. For hashes, it is the number of key/value pairs. If the arguent is nil or a number, this error will be thrown: object has no size().

object
Object to find the size of. Must be a string, a vector or a hash.

Examples

'"`UNIQ--syntaxhighlightinner-00000109-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000010B-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000111-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000115-QINU`"'

core

Returns a vector containing the elements in the input vector sorted in according to the rule given by function. Implemented with the ANSI C qsort() , sort() is stable. This means that if the rules in the first example are used, equal elements in the output vector will appear in the same relative order as they do in the input. It is run in a loop, so function is run several times.

vector
Input vector to sort.
function
Function according to which the elements will be sorted by. It should take two arguments and should return one of 1, 0, or -1.
Return value Meaning
less than 0 first argument should go before second argument
0 first argument equals second argument
greater than 0 first argument should go after second argument

Examples

This example sorts elements from greatest to smallest.

'"`UNIQ--syntaxhighlightinner-00000119-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000011B-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000121-QINU`"'

core

Splits the input string into a vector of substrings bounded by occurrences of the delimiter substring.

delimiter
String that will split the substrings in the returned vector.
string
String to split up.

Examples

'"`UNIQ--syntaxhighlightinner-00000125-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000127-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000012D-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000131-QINU`"'

core

Creates and returns a string formatted using ANSI C vsnprintf() [1]. Below is a table of supported format specifiers.

%[flags][width][.precision]specifier
Flags
Flag Output
+ Forces to precede the result with a plus or minus sign (+ or -) even for positive numbers. By default, only negative numbers are preceded with a - sign.
space Prefixes non-signed numbers with a space.
- Left-align the output of this placeholder (the default is to right-align the output) when the width option is specified.
0 Use 0 instead of spaces to pad a field when the width option is specified.
# Used with o, x or X specifiers the value is preceded with 0, 0x or 0X respectively for values different than zero. Used with e, E and f, it forces the written output to contain a decimal point even if no digits would follow. By default, if no digits follow, no decimal point is written. Used with g or G the result is the same as with e or E but trailing zeros are not removed.
Width
Integer specifying the minimum number of characters to be returned.
Precision
Integer preceded by a dot specifying the number of decimal places to be written.
Specifiers
Specifier Output
d, i Signed decimal number.
% Percent (%) character.
c A single character assigned to a character code, the code given in an integer argument. See http://www.asciitable.com/ for a list of supported characters and their codes.
o Unsigned integer as an octal number.
u Unsigned decimal integer.
x, X Unsigned integer as a hexadecimal number. If x is used, any letters in the number are lowercase, while X gives uppercase.
e, E Double value in scientific notation (i.e., [-]ddd.ddde[+/-]ddd), with an exponent being denoted by e or E depending on whether an upper or lowercase is used respectively.
f Floating-point number, in fixed decimal notation, by default with 6 decimal places.
F Appears to be supported [2], but doesn't work.
g, G Double in either normal or exponential notation, whichever is more appropriate for its magnitude. g uses lower-case letters, G uses upper-case letters. This type differs slightly from fixed-point notation in that insignificant zeroes to the right of the decimal point are not included. Also, the decimal point is not included on whole numbers.
format
String specifying the format. Can be used with or without a format specifiers. See below for examples.
arg
Argument specifying a value to replace a format placeholder (such as %d) in the format string. Not required if there are no format specifiers.

Examples

'"`UNIQ--syntaxhighlightinner-00000137-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000139-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000013F-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000143-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000147-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000014B-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000014F-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000153-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000157-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000015B-QINU`"'

core

Tests the string values of the two arguments for equality. This function is needed because the == operator (see Nasal Operators) tests for numeric equality first. If either or both the arguments are not strings, 0 (False) will be returned. Returns either 0 (False) or 1 (True).

Note  This function is rarely required in typical code.
a
First argument for testing equality.
b
Second argument for testing equality.

Examples

'"`UNIQ--syntaxhighlightinner-0000015F-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000161-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000167-QINU`"'

core

Similar the subvec , but operates on strings. Computes and returns a substring. The first argument specifies a string, the second is the index of the start of a substring, the optional third argument specifies a length (the default is to return the rest of the string from the start).

string
String to return a substring from.
start
Integer specifying the start of a substring.
length
Optional argument specifying the length of the substring. Defaults to the end of the string.

Examples

'"`UNIQ--syntaxhighlightinner-0000016B-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000016D-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000173-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000177-QINU`"'

core

Returns a sub-range of a vector. The first argument specifies a vector, the second a starting index, and the optional third argument indicates a length (the default is to the end of the vector).

vector
The vector to take the sub-vector from.
start
The starting point of the sub-vetor within the given vector.
length
Optional argument specifying the length of the sub-vector, from the starting point.

Examples

'"`UNIQ--syntaxhighlightinner-0000017B-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000017D-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000183-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000187-QINU`"'

core

Returns a string indicating the whether the object is nil, a scalar (number or string), a vector, a hash, a function, or a ghost.

object
Object to return the type of.

Examples

'"`UNIQ--syntaxhighlightinner-0000018B-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000018D-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000193-QINU`"'
'"`UNIQ--syntaxhighlightinner-00000197-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000019B-QINU`"'
'"`UNIQ--syntaxhighlightinner-0000019F-QINU`"'

Extension functions

cmdarg()

cmdarg() is a mechanism to pass arguments to a nasal script (wrapped in properties) instead of "normal" function parameters. Note that cmdarg() should be primarily used in Nasal code embedded in XML files and should be considered depreciated otherwise (see [4]).

cmdarg() will keep working in (joystick) XML-bindings and on the top-level of embedded Nasal scripts (i.e. dialog and animation XML files).

As such, the cmdarg() function is primarily used for listener callbacks declared in XML markup, cmdarg() returns the listened-to property as props.Node object, so you can use it with all its methods (see $FG_ROOT/Nasal/props.nas) for example:

print(cmdarg().getPath(), " has been changed to ", cmdarg().getValue())

The cmdarg() function avoids that you have to type the exact same path twice (once here and once in the setlistener() command) and it makes clear that this is the listened to property. Also, you can use all the nice props.Node methods on cmdarg() directly:

setlistener("/gear/launchbar/state", func {
    if (cmdarg().getValue() == "Engaged")
        setprop("/sim/messages/copilot", "Engaged!");
}, 1, 0);

Use of cmdarg() outside of XML-bindings won't cause an error, but (still) return the last cmdarg() property. This just won't be the listened-to property anymore, but whatever the last legitimate cmdarg() user set. Most of the time it will be the property root of a joystick binding.

Don't make any assumptions and use cmdarg() only in one of these cases:

  • binding: returns root of this binding's property branch. Needed for accessing an axis' value: cmdarg().getNode("setting").getValue()
  • dialog xml files: returns root of that file's property branch in memory. This can be used to let embedded Nasal change the dialog (e.g. clear and build lists) before the final layout is decided
  • animation xml files: returns root of this model's place in /ai/models/ when used as AI/MP model. Examples: /ai/models/multiplayer[3], /ai/models/tanker[1], etc.[3]
  • AI aircraft XML files
  • remotely invoking Nasal code by setting properties using the built-in telnet daemon (RPC)[4][5].

In all cases, the cmdarg() call must not be delayed until later using settimer() or setlistener(). Because later it'll again return some unrelated property!

fgcommand()

Runs an internal "fgcommand", see Bindings for a full list of available items (since they are most often used in bindings for input devices). The first argument is the name of the command (e.g. "property-interpolate") and the second is a props.Node object or its ghost which is the "argument" to the fgcommand. (This ensures that fgcommands are universal since props.Node/SGPropertyNode objects can really be accessed from anywhere in FlightGear.) Each fgcommand returns 1 if it succeeded or 0 if it failed.

The profiling related fgcommands profiler-start and profiler-stop are documented at Built-in Profiler.

addcommand()

Add a fgcommand which can be used like a regular fgcommand (global scope, etc.). First argument is the name, second is the function to run. Note that this fgcommand will always return true! Inside the callback/function one can use either cmdarg() to retrieve the arguments or use the first argument passed to the function (since they will be the same).

removecommand()

As you can guess, there's also a removecommand() function which will remove any command – even those implemented in C++! As such it can be very dangerous and remove core functionality, so use with caution.

print()

Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.

print("Just", " a ", "test");

logprint()

Similar, but the first argument is reserved for number specifying the priority (i.e. matching a sgDebugPriority object: 1 for bulk, 2 for debug, 3 for info, and 4 for warn). Also see printlog() in globals.nas: it does essentially the same but with named levels ("bulk", etc.). (The latter relies on print(), however, and does not make use of the sophistication of sglog in dealing with source file and line number.)

getprop()

Returns the node value for a given path, or nil if the node doesn't exist or hasn't been initialized to a value yet.

getprop(<path> [, <path>, [...]]);

Several arguments will be added together to produce a path, with numeric arguments specifying indexes (as of FlightGear 3.1), so

getprop("canvas/by-index", "texture", 1, "name");

is the same as:

getprop("canvas/by-index/texture[1]/name");

Example:

print("The frame rate is ", getprop("/sim/frame-rate"), " FPS");
for (var i=0; i < 10; i += 1) {
    print("View ", i, "'s name is: ", getprop("/sim/view", i, "name"));
}

setprop()

Sets a property value for a given node path string. Returns 1 on success or 0 if the property could not be set (i.e. was read-only).

setprop(<path> [, <path>, [...]], <value>);

All arguments but the last are concatenated to a path string, like getprop() above. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.

Examples:

setprop("/sim/current-view/view-number", 2);
setprop("/controls", "engines/engine[0]", "reverser", 1);

Erasing a property from the property tree: a property that has been created, for example through setprop() has to be erased using the props namespace helper, like this:

props.globals.getNode("foo/bar").remove(); 		# take out the complete node
props.globals.getNode("foo").removeChild("bar"); 	# take out a certain child node

interpolate()

Give the value from a value or a source node to a destination node in given time.

interpolate(<path>, <value>, <time> [, <value2>, <time2> [, ...]]);

Examples:

interpolate("controls/switches/nav-lights-pos", 1, 0.25); # After 25ms, nav-lights-pos = 1
interpolate("controls/gear/brake-left-pos", getprop("controls/gear/brake-left"), 1); # After 1s, brake-left-pos = brake-left

To interpolate with a constant speed, use the formula time = distance/speed.

# Apply the brakes at 20%/second
var p = "controls/gear/brake-left";
var current = getprop(p);
var dist = 1-current;
if (dist) interpolate(p, 1, dist/.2);

setlistener()

settimer()

CautionImproper use of the settimer() API may cause resource leaks.

This typically is caused by the low-level nature of such code, requiring manual tracking of listeners and timers and manual reset and re-init handling.

It is instead recommended that you use the maketimer() API. Alternatively a wrapping helper class can be used to handle low-level APIs, which is the recommended way to support multiple FlightGear versions.

Runs a function after a given simulation time (default) or real time in seconds.

settimer(<function>, <time> [, <realtime=0>]);

The first argument is a function object (ie, "func { ... }"). Note that this is different from a function call (ie, "func ( ... )"). If you don't understand what this means, just remember to always enclose the first argument in any call to settimer with the word "func" and braces "{ }", and it will always work.

The second argument is a delay time. After this amount of time the function will be executed. For instance, if you want to print the words "My result" in five seconds, use this code:

settimer ( func { print ( "My result"); }, 5);

Inside the braces of the func object you can put any valid Nasal code, including a function call. In fact, if you want to call a function with certain values as arguments, the way to do it is to turn it into a function object by enclosing it with a func{}, for example:

myarg1="My favorite string";
myarg2=432;
settimer ( func { myfunction ( myarg1, myarg2); }, 25);

The third argument is optional and defaults to 0, which lets the time argument be interpreted as "seconds simulation time". In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.

# simulation time example
var copilot_annoyed = func { setprop("/sim/messages/copilot", "Stop it! Immediately!") }
settimer(copilot_annoyed, 10);
# real time example
var popdown = func ( tipArg ) { 
    fgcommand("dialog-close", tipArg); 
}

var selfStatusPopupTip = func (label, delay = 10, override = nil) {	
    var tmpl = props.Node.new({
            name : "PopTipSelf", modal : 0, layout : "hbox",
            y: 140,
            text : { label : label, padding : 6 }
    });
    if (override != nil) tmpl.setValues(override);

    popdown(tipArgSelf);
    fgcommand("dialog-new", tmpl);
    fgcommand("dialog-show", tipArgSelf);

    currTimerSelf += 1;
    var thisTimerSelf = currTimerSelf;

    # Final argument 1 is a flag to use "real" time, not simulated time
    settimer(func { if(currTimerSelf == thisTimerSelf) { popdown(tipArgSelf) } }, delay, 1);
}

More information about using the settimer function to create loops.

maketimer() (2.11+)

As of 2.11, there is a new API for making a timer that allows more control over what happens in a timer – as opposed to setting one and forgetting about it.

var timer = maketimer(<interval>, <function>)
var timer = maketimer(<interval>, <self>, <function>)
timer.start()
timer.stop()
timer.restart(<interval>)
timer.singleShot [read/write]
timer.isRunning [read-only]
# create timer with 1 second interval
var timer = maketimer(1.0, func { 
 print('timer called'); 
 }
);
# start the timer (with 1 second inverval)
timer.start();
# restart timer with 4 second interval
timer.restart(4);

# fire one single time in 6 seconds
timer.singleShot = 1;
timer.restart(6);
var Tooltip = {
  new: func
  {
    var m = {
      parents: [Tooltip]
    }
    m._hideTimer = maketimer(1.0, m, Tooltip._hideTimeout);
    m._hideTimer.singleShot = 1;

   return m;
  },
  run: func
  {
    if( !me._hideTimer.isRunning )
      me._hideTimer.start();
  }
  _hideTimeout: func
  {
    print('_hideTimeout');
  }
};

geodinfo()

Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot or the scenery tile is not loaded.

var lat = getprop("/position/latitude-deg");
var lon = getprop("/position/longitude-deg");
var info = geodinfo(lat, lon);

if (info != nil) {
    print("the terrain under the aircraft is at elevation ", info[0], " m");
    if (info[1] != nil)
        print("and it is ", info[1].solid ? "solid ground" : "covered by water");
}

A full data set looks like this:

debug.dump(geodinfo(lat, lon));

# outputs
[ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,
solid : 0,  names : [ "Lake", "Pond", "Reservoir", "Stream", "Canal" ], friction_factor : 1, 
rolling_friction : 1.5 } ]

Note that geodinfo is a *very* CPU intensive operation, particularly in FG 2.4.0 and earlier, so use sparingly (forum discussion here).

airportinfo()

Function for retrieval of airport/runway information. Usage:

var apt = airportinfo("KHAF");   # get info about KHAF
var apt = airportinfo(lat, lon); # get info about apt closest to lat/lon
var apt = airportinfo();         # get info about apt closest to aircraft

The command debug.dump(airportinfo("KHAF")) outputs this:

{ lon : -122.4962626410256, lat : 37.51343502564102, has_metar : 0,
  runways : { 12 : { stopway2 : 0, threshold1 : 232.5624,
  lon : -122.5010889999999, lat : 37.513831, stopway1 : 0, width : 45.72,
  threshold2 : 232.5624, heading : 138.1199999999999, length : 1523.0856 } },
  elevation : 20.42159999999999, id : "KHAF", name : "Half Moon Bay" }

That is: a hash with elements lat/lon/elev/id/name/has_metar for the airport, and a hash with runways, each of which consists of lat/lon/length/width/heading/threshold[12]/stopway[12]. Only one side of each runway is listed -- the other can easily be deduced.

Positioned Object Queries

Several functions exist to query the navigation database of 'positioned' objects, i.e items with a defined location in the simulation world. (These objects all inherit from FGPositioned internally). The functions return either one, or a vector, of wrapped Nasal objects. These are efficient, but unlike a hash they cannot simply be debug.dump() to view all their members and methods, many of which are computed in a lazy fashion (i.e. on demand).

When the query functions take a position, the default value is the current aircraft location. An alternative location can be supplied by passing two number (lat, lon), a Geo.Coord object, or any positioned object or waypoint retrieved from another query.

findAirportsWithinRange()
Find all airports within a specified range (in NM) of the current position or explicit position
findAirportsByICAO()
Find airports matching a complete or partial ICAO code. In particular this can search for all airports starting with a two or three letter prefix.
navinfo()
Return a list of navaids near a location by type and ident. Type should be 'fix', 'vor', 'ndb', 'dme'
findNavaidsWithinRange()
Search for navaids within a particular range (in NM), optionally limited by type. This provides a 'find the closest ILS' function
findNavaidByFrequency()
find the closest navaid (of a particular type) matching an exact frequency
findNavaidsByFrequency()
find all the navaids matching a particular frequency and optional type, sorted by distance from the search location.

All positioned objects returned by the above methods have the following members:

id
Identifier - ICAO code for airports, published ident for navaids and fixes
lon
degrees longitude
lat
degrees latitude

Depending on type, the following members are also available:

name
the full name of the airport or navaid if one is defined
elevation
the ASL elevation of the object in feet

For navaids, the following members are available:

frequency
the navaid frequency in kHz
type
the navaid type as a string: vor, dme, loc, ils, ndb
course
the degrees course associated with the navaid, for localiser and ILS stations

history() (3.1+)

Function to expose flight history as aircraft.history()

var hist = aircraft.history();

# get history of aircraft position/orientation collapsing
# nodes with a distance smaller than the given minimum
# edge legth
debug.dump( hist.pathForHistory(<minimum-edge-length-meter>) );


flightplan()

Function to retrieve the active flight-plan object, or load a flight plan from a file path.

Usage:

var fp = flightplan();
var fp = flightplan('/some/path/to/a/flightplan.xml');

In advance of converting the Map and NavDisplay to use the Canvas, James has improved the "flightplan()" extension function of the Nasal scripting interpreter to expose the full route-path vector for each flight plan leg as a vector on the leg.


var fp = flightplan();
for (var i=0; i<fp.getPlanSize(); i += 1)
{
  var leg = fp.getWP(i);
  debug.dump(leg.path());
}

systime()

Returns epoch time (time since 1970/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.

#benchmarking example:
var start = systime();
how_fast_am_I(123);
var end = systime();
print("took ", end - start, " seconds");

carttogeod()

Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.

var geod = carttogeod(-2737504, -4264101, 3862172);
print("lat=", geod[0], " lon=", geod[1], " alt=", geod[2]);

# outputs
lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776

geodtocart()

Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.

var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)
print("x=", cart[0], " y=", cart[1], " z=", cart[2]);

# outputs
x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495

parsexml()

This function is an interface to the built-in Expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XML file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).

var ret = parsexml(<path> [, <start-elem> [, <end-elem> [, <data> [, <pi> ]]]]);

<start-elem>  ... called for every starting tag with two arguments: the tag name, and an attribute hash
<end-elem>    ... called for every ending tag with one argument: the tag name
<data>        ... called for every piece of data with one argument: the data string
<pi>          ... called for every "processing information" with two args: target and data string

<ret>         ... the return value is nil on error, and the <path> otherwise

Example:

var start = func(name, attr) {
    print("starting tag ", name);
    foreach (var a; keys(attr))
        print("\twith attribute ", a, "=", attr[a]);
}
var end = func(name) { print("ending tag ", name) }
var data = func(data) { print("data=", data) }
var pi = func(target, data) { print("processing instruction: target=", target, " data=", data) }
parsexml("/tmp/foo.xml", start, end, data, pi);

resolvepath()

SimGear features its own path resolving framework that takes a relative path and returns an absolute path, checking from base directories such as $FG_ROOT, $FG_HOME, $FG_AIRCRAFT, and the current aircraft directory (/sim/aircraft-dir). This function in Nasal takes a path string and returns the absolute path or an empty string if the path couldn't be resolved.

Example:

var guess_path = func(path...) {
    var path_concat = string.join(path, "/");
    var file_path = resolvepath(path_concat);
    if (file_path == "") die("Path not found: "~path_concat);
    return file_path;
}

HTTP module (2.99+)

Get remote data using the HTTP.

http.load()

Load resource identified by its URL into memory.

var request = http.load(<url>);
http.load("http://example.com/test.txt")
    .done(func(r) print("Got response: " ~ r.response));

http.save()

Save resource to a local file.

var request = http.save(<url>, <file_path>);
http.save("http://example.com/test.png", getprop('/sim/fg-home') ~ '/cache/test.png')
    .fail(func print("Download failed!"))
    .done(func(r) print("Finished request with status: " ~ r.status ~ " " ~ r.reason))
    .always(func print("Request complete (fail or success)"));

rand()

Return a random number as generated by sg_random.

srand()

Seed the random number generator based upon the current time. Returns 0.

md5() (3.1+)

Get the md5 hash of a string.

var hash = md5(<str>);

abort()

Wrapper for the C++ library abort() function – i.e. it just aborts the process without regard to what's happening. For exiting (gracefully) from FlightGear use the fgcommand "exit" instead.

References
  1. fg/simgear/source/next:simgear/nasal/lib.c, line 308. Retrieved February 2015.
  2. fg/simgear/source/next:simgear/nasal/lib.c, line 389. Retrieved February 2015.
  3. Melchior Franz (8 December 2007). multiplayer generic properties.
  4. Melchior Franz (2 January 2006). Calling FG functions via network interface.
  5. Melchior Franz (7 January 2006). Calling FG functions via network interface.