Main Help → GENerel Reference → Objects
Scripting objects are only used in internal scripts and correspond to internal classes or objects within the GEDitCOM II code. Objects are assigned to "object names." Details on using objects are in the following sections:
The rules for a valid object name are as follows:
Objects are used to target scripting commands, to pass as an argument to scripting commands, and to get or set the object's properties. Objects in these places can be just the object's name or can be an "object specifier" with the following format:
(object) = (root).(atom).(atom).(atom)...(atom)
where (object) is the result of the object specifier that starts with (root) for the initial object that can be:
#objref) that contains the object's name (i.e., a reference or pointer to the object). The variable can be an array variable and can include array index determined by an expression (e.g., #ref[#i])
The (root) is defined as the "current object" and it can optionally be followed by a period-delimited list of (atom)'s that provide cascading access to other objects. Any atom can be:
(atom) is set to that text.(atom) is set to value of the variable. Note that variables in (atom)'s can be array variables but cannot use expressions within the array index (i.e., #var[1] works but #var[#i] is not allowed; expressions in an array index are only allowed in the (root) element of the object specifier).
The (atom) defined by above two options is then evaluated as follows:
(atom) can extract an item from the list by number, ID, or name in that (atom).(atom) can extract a value from the dictionary by one of its attributes or one of it's keys in that (atom).(atom) can access any valid attribute of the current object (i.e., any "To-many object lists" or "To single objects" listed in the current object's attributes).(atom) needs to find a new current object that becomes basis to proceed to the next (atom) in the object specifier. If a new current object is not found or if options 1 or 2 find a string or number instead of an object, the object specifier has failed. The response to a failed specifier depends on how it is being used (see below).
The various uses of object specifies with examples an additional details are as follows:
(object).(command), but if (root) in that (object) references the initial object with a variable, the object specifier has to be prefaced with a caret '^'. For example:
gdoc.individuals.0.showAncestors ! No caret needed #var="indi" ^#var.listAncestors alist,5 ! Caret needed because starts with #varIf
(object) fails, no command can work so the script will exit with an error.
@objName = "(object)" (exception: if (object) is just an object name, it does not need to be quoted). A failed specifier will set objName to None object.ifDef (object) and ifNDef (object) will treat an failed specified as undefined and the script will continue in the appropriate branch of the conditional.
write "This object's property is "&@(object).(property)&return
(property) is any valid property of the specified object. When used in "@" expressions, the (root) is decoded like an (atom), which means array variables need explicit indices (i.e., #var[1] but not #var[#i]).
The use of object specifiers is available since 3.3/1.0 (robust options since 3.5/1.0). Prior versions could specify objects only by (root) or by (root).(atom) where (root) is a GC List or a list and (atom) extracts an item from that list by number, id, or name.
Object names can be assigned to objects using an "object assignment" command, which is distingushed from variable assignment commands by an at sign ('@') in front of the object name being assigned:
@objName = "(object)" @#ref = "(object)"
The first example provides a valid object name in objName. The second example provides object name by reference using in a variable starting in "#" that is equal to the variable name (e.g., #ref="objName"). The (object) is any object specifier (which must be quoted if has (atom)'s, i.e. contains periods). It can also be an expression that evaluates to a valid object specifier). Finally, the operator can only be "=" (other operators allowed when defining variables are not allowed).
Some example uses are:
@indi = "gdoc.individuals.5" ! quoted when more than one atom #ref = "fath" @#ref = "indi.father" ! object name assigned in a variable @newobj = indi ! just an object name
Once objName is set, it can then be used to target scripting commands, to pass as an argument to scripting commands, or to get or set the object's properties.
If the (object) is a failed object specifier, this assignment will not cause an error, but will instead assign the object to None type object. Code can check after the assignment to see if objName can be used:
@person = "gdoc.individuals.@I34@" ifDef person ! person with that ID exists and can use the object endif
The flexibility to not cause an error can make such assignments difficult to debug. For example, consider two object assignments for the father of an individual (in object indi):
@fath = "indi.father" @fath = "indi.farther" ifDef fath or ifDef fath ! code to work with father's record ! code to work with father's record endif endif
The one on the left is correct and will return father's record when the individual has a documented father and will return None object if not. The one of the right will always return None because the attribute name is misspelled as "farther". The script will continue but will never find a father until you fix the typo. To help debug such errors, any use of an invalid attributes in object specifiers will output a warning to the scripting panel, such as:
WARNING: 'farther' in 'indi.farther' is not valid attribute for INDIRecord objects
The script will continue, but you can check the panel for attribute typos that occurred will running the script.
Although warnings are generated for attribute typos, no warnings are generated for List index out of bounds or for a key not in a Dictionary (such invalid access will silently return a None object). This response can be used to check for valid list or dictionary access. For example:
@obj = "mylist.100" ifNDef obj ! code when index is out of bounds endif
This script will work without generating warnings.
One option to debug (or for a script that checks all errors) is to convert object assignments to get commands. For example:
@fath = "indi.farther" to indi.farther.get fath @obj = "mylist.100" to mylist.100.get obj
Because the object specifier is now finding an object for a command, it cannot continue if it has an errors (such as invalid attribute, index out of bounds, or key not in a dictionary). The options on the left will assign the object to None while the options on the right will stop the script with a error message due to an attribute typo or a list index out of bounds. In brief, object assignments are easier to write and continuing with errors is usually the preferred option. For debugging or for strict error checking, any assignment command can be converted to a get command.
The direct object assignment above is only available since 3.5/1.0. The alternative (for earlier versions but still supported) for assigning objects is to use scripting commands. The GetObject command:
GetObject objName,"(object)"
will set objName to the object in the the object specifier. Another alternative is the get command:
(object).get objName
Many internal scripts will work with GC Lists or Lists that contain objects. To access these objects or for other uses, you need to extract an item using obj.(extractor) where obj is object name for a list and (extractor) is one of the methods below to extract one element from the list.
You can access any list element by number or by a variable with a number:
@indi = "indis.4" #i=10 @indi = "indis.#i" or indis.4.get indi indis.#i.get indi
to get list elements at index 4 or 10 (lists are indexed starting from zero) and set object name indi to the extracted element. If the index is out of bounds for the list, the object assignment commands on top will return None while the get commands on the bottom will cause an error.
If the list is known to contain only GEDCOM Records, you can alternatively extract elements by record id:
@indi = "indis.@I378@" ! or indis.@I378@.get indi #id="@I5612@" @indi = "indis.#id" ifDef indi ! commands on this valid object endif
If no record with that record id is found, the object name (here indi) will be set to a None object. Such objects can be validated with ifDef or ifNDef conditionals before using them.
If the referenced list is known to contain GEDCOM Records, albums, or any object that has a "name" property, you can extract elements by their name using:
#name="Smith, John" @indi = "indis.#name" ifDef indi ! commands on this valid object endif
If a name has spaces, this name option has to go through a variable because spaces in names would cause the command to be interpreted incorrectly. The name of a record is the name as it appears in the index window for a column displayed using the "view" expression. The name of an album is as it appears in the index window (not including the number of records in the album). If the name matches more then one record or album, the first one found is returned. If no object with that name is found, the object name (here indi) will be set to a None object. Such objects can be validated with ifDef or ifNDef conditionals before using them.
If the list is known to contain GEDCOM Structures, you can access structure elements by tag name using
@sexline = "indi.structures.SEX" ifDef sexline write @sexline.contents endif
If no structure with that tag is found, the object name (here sexline) will be set to a None object. Such objects can be validated with ifDef or ifNDef conditionals before using them.
"#var") and variables used with those commands must being in "#".