Lifelines Emulation in GEDitCOM II and GEDitCOM using Internal Scripts

Introduction

Internal Scripting emulation of the Lifelines scripting language was done by developing a Lifelines.gcscpt module (included in this extension) that allows many Lifelines commands to work the same way in converted Internal Scripts. The Lifelines emulator was written to minimize the number of changes required to convert a Lifelines script to a Internal Script. Nevertheless, syntax differences between Lifelines scripting language and the Internal Scripting langauge mean that 100% emulation was not possible. The documentation below explains the steps needed to reconcile those difference to translate a Lifelines script into a Internal Script.

This extension comes with translations of selected Lifelines scripts and they appear in the "Scripts" section. The "Text Files" section has all Lifelines scripts as provided with a download using original names but with file's extension changed from "ll" to "txt". An underscore was inserted into the name of any script that has been translated. You can compare the Internal Scripting version to the original to see the translation process in action. The details below can enable translation of more scripts into Internal Scripts.

Documentation details aree:

Getting Started

Imagine you want to convert another Lifelines script originally called script.ll for use in the . The process starts with the following steps:

  1. Open the "LifelinesIS" extension in GEDitCOM Editor.
  2. Use the "New Script..." (or "S" icon in the tool bar) and create a script called newscript.gcscpt (i.e. pick any name and use Internal Scripting extension gcscpt).
  3. Expand the "Text Files" section and locate the original version, which will be called script.txt (i.e., extension "txt" instead of "ll"). Click on that file, copy all the text, and paste into the new newscript.gcscpt.
  4. To allow your new translation to be selected when running this extension, click on "menu choices" in the extension's "Properties." Click the "+" icon and set the key to newscript.gcscpt and the value to short text description of the script. Repeat for "menu choices SD" to make the script available in GEDitCOM too.
  5. When translation is finished, the follow steps make it official in this extension:

Once the above steps are completed, you are ready to start translating and testing. The process is explained in the next section. Note that developing Internals Script is best done by using GEDitCOM II and GEDitCOM Editor. Although you can develop Internal Scripts using GEDitCOM, the workflow is different and cumbersome. See the GEDitCOM Editor for workflow details.

Note the goal of this Lifelines emulator was to reproduce the language as much as possible. It was not written to maximize efficiency. If you find a converted Lifelines script to be useful, a logical next step would be to convert the logic of the script into a native Internal Script. The goal would be a script that can run without using the lifeline.gcscpt module.

Converting Lifelines Scripts

The remainder of this document gives details on converting Lifelines scripts to Internal Scripts for using the Lifelines.gcscpt module. The documentation sections are:

For ideas on more scripts to convert, you can refer to the original Lifelines scripts provided in the "Text Files" section of this extension. An on-line tutorial gives a specific example of converting a Lifelines script to the Internal Script.

Conversion Tasks

The section summarizes the process for converting a Lifelines script into an emulated Internal Script. Specific details on some conversion tasks are in the Lifelines Emulation Reference section. The conversion always starts with reorganizing high-level structures are follows:

  1. For the one main method, move it all to the end of the Internal Script, remove the proc main, remove its brackets ({}), and adjust indents (or automatically adjust indents later using GEDitCOM Editor's "Indent Commands" menu command, which works best when translation is farther along).
  2. Just before the main commands insert module initializer with the a name for the script:
    ll_init("name of script")
    
  3. To get the final results displayed in a window, put finish() command at the end of the main commands.
  4. Insert command to load the Lifelines.gcscpt module. It must be at the beginning of the script before any other commands.
    load Lifelines
    
  5. Change all Lifelines comments (/* a comment ... */) to Internal Scripting comments (! a comment ...) and an ! is needed on each line in mutliple line Lifelines comments. Some Lifelines scripts have long comments in the beginning and sometimes at the end with sample output. These sections can be deleted (they are always in the original file if needed).

Any Lifelines script converted to using these taks should now look like:

! Header comments (if retained)

! load module
Load Lifelines

! Subroutines
(original proc's and func's) 

! Preamble
ll_init("My translated script")

! Translated script
(original proc main statements)

! Final Output
finish()

! Final commands (if retained)

The rest of the convertion process deals with syntax and logic of the script. The following items list key tasks with links for more details in the Lifelines Emulation Reference section.

With luck, the conversion will be complete. Try running in and see what happens. The most likely errors are Internal Scripting syntax errors. Each time you run, the script will stop at the first error and print a brief (sometimes vague) reason. The error message will also indicate line in the script. Use "Go To Line..." menu command in GEDitCOM Editor to find that line. An error that says "In loaded subroutines" means the error was in the Lifelines.gcscpt module. It usually means you passed an invalid parameter to an module method.

Lifelines Emulation Reference

The following sections list all methods from the Lifelines manual, which is available in this extension in pdf form (control click and use "Back" to return to this documentation) or in a on-line translation). This reference does not define the behavior of the Lifelines functions (you can refer to the Lifelines documentation for that information). Instead, this reference lists all Lifelines methods, whether or not they are implemented, and whether or not they are identical or require some modification. Fully supported methods are in black; methods needing modification are in green, and methods not implemented are in red. The subsections are:

Value Types

Lifelines defines several types of values and any one can be assigned to a variable name. Internal Scripting has "variables" and "objects." Variables are anything that can be represented by a number or a string. Objects are eveything else. Internal Scripting has many types of objects. You can refer to GEDitCOM Editor help for listing of all possible object types:

LifelinesInternal ScriptingComments
INT Variable Internal scripting variables can be integers or floating point numbers
BOOL Variable A value of "0" or an empty string is treated as "false" in a conditional. All other values are "true"
STRING Variable Any text string (including numbers as strings)
LIST Object Internal Scripting "List" object
TABLE Object Internal Scripting "Dictionary" object
INDI Object Internal Scripting "Individual Record" object
FAM Object Internal Scripting "Family Record" object
SET Object Custom object implemented using the Lifelines.gcscpt module
NODE Object Internal Scripting "GEDCOM Record" or "GEDCOM Structure" object
EVENT Object Internal Scripting "GEDCOM Structure" object

In Lifelines, all types can be assigned to variable names. In contrast, Internal Script maintains different name spaces for variable names and object names. It is important that a scipt never uses the same name for a variable as a name used for an object.

When writing Internal Scripts, variable names can start with a number sign (#) while objects names cannot. An good approach when writing Internal Scripts is to use a number sign for all variable names. By this approach, variable and object namnes are never in conflict. When transloating a Lifelines script, however, the original script's variables will not start with number signs. You could insert number signs in front of all INT, BOOL and STRING variables, but it is not necessary. Instead, you can use variable names as they defined in the original script, but you must be careful to not mix variable and object names. You should not, for example use a name for Internal Script variable in one part of the code and then reuse that same name in another part for an Internal Script object. The process is usually straight forward with one exception when passing objects to a subrourine.

(section index)

Expressions

All expression should be converted to Internal Scripting expressions, which are very similar to most programming languages. Most Lifelines functions used in expressions are supported for convenience. Expressions in an Internal Script can only combine variables, numbers, and strings. Numbers are combined by usually operators, String are concatenated using ampersands (&).

Expressions cannot use objects unless the entire expression is just the name of the object or a string expression that evaluates to the name of a object.

(section index)

Statements

Conditionals, loops, and procedure calls must all be converted to Internal Scripting syntax as explained above. Some additional statements also require minor changes:

LifelinesInternal ScriptingComments
include(string) See below
global(varb) Designate local variables instead (see Subroutines and Functions)
set(varb, expr) set("varb",expr)
setobj(obj,expr)
Or convert to Internal Scripting asignments; see below
continue() continue
break() break
return([expr]) return expr But a result returned from a subroutine has to read using result() after the subroutine is done (and before another subroutine is called).

include options

    The include(string) statement is not supported in this translation. It can be replaced by putting the other script into an Internal Scripting module in this extension (e.g., myModule.gcscpt) and then importing it with

Load myModule.gcscpt

and the Load command must be at the start of the script along with the Load Lifelines command. Such modules, however, can only contain Internal scripting subroutines and definitions.

set options

For set() to "set" a variable, the variable has to be passed by reference in an Internal Script, which means to put the variable's name in quotes. The variable is set to value of expr, which is any expression of variables that evaluates to a string or number. A common mistake when translating scripts it to forget to quote the variable. The script will not flag that as an error, but the script will not work because the variable will not be set.

    Note that emulation of the set() is just to make the translated script "look" like the original Lifelines script. If you are not concerned with looks, it is simpler to replace set() commands for variables with an Internal Script assignment command:

Lifelines:          set(varb,expr)
Emulation Method:   set("varb",expr)     ! quote varb
Assignment Method:  varb = expr          ! just use Internal Script assignment

    Because Internal Scripts have variables and objects, a separate command is needed to set objects. A setobj(obj,expr) sets obj to object name in expr (which is either just an object's name or an expression that evaluates to an object's name). A common method in Lifelines scripts to set an object is:

set(nextgen,parentset(thisgen))

or to set an object to result of a function. Because such subroutines in Internal Scripts cannot return an object and objects are set with setobj(), such commands must be changed. To make this easy, the Lifelines.gcscpt module adds an extra parameter to most functions like parentset(thisgen) to assign a new object. The above line from a Lifelines script could change to:

parentset(thisgen,nextgen)

Note that because Internal Scripts always pass objects by references, the first parameter need not be quoted (although it will still work if it is quoted). The second parameter in emulated functions is optional. If it is not used, the translation would need two lines — one to get the parent set and one to assign it to an object:

parentset(thisgen)
setobj(nextgen,result())

The subroutine will return a new object name and that name can be fetched with the return() expression and then used in a setobj() command (return() must be used before calling any other subroutine, because a new call would replace returned value with a new returned value).

    Note that emulation of the set() with setobj() for objects is just to make the translated script "look" like the original Lifelines script. If you are not concerned with looks, it is simpler to replace set() for objects with an Internal Script object assignment command:

Lifelines:          set(varb,expr)
Emulation Method:   setobj(varb,object)     ! replace expr with pre-calculated object
Assignment Method:  @varb = object          ! just use Internal Script object assignment

(section index)

Subroutines and Functions

Lifelines has procs and funcs. They are similar except funcs can return a value to be used inside an expression. In contrast, Internal Scripts have only subs. While they can return a value, they cannot be used in expressions. Translations of procs and funcs first changes their syntax and then may need one or more of the following changes:

(section index)

Arithmetic and Logic Functions

These Lifelines methods are mostly supported, but you can also convert to standard, simpler, and more powerful Internal Scripting expressions. The translations are:

LifelinesInternal ScriptingComments
INT add(x, y) Same or change to x + y
INT sub(x, y) Same or change to x - y
INT mul(x, y) Same or change to x * y
INT div(x, y) Same It is integer divide. Using x/y is floating point divide.
INT mod(x, y) Same
INT exp(x, y) Same or change to x^y
INT neg(x) Same or change to -x
VOID incr(x) VOID incr("x") or change to x += 1
VOID decr(x) VOID decr("x") or change to x -= 1
BOOL and(x, y) Not implemented Change to x && y
BOOL or(x, y) Not implemented Change to x || y
BOOL not(x) Not implemented Can replace if not(x) with Internal Scripting ifndef x
BOOL eq(x, y) Same or change to x = y
BOOL ne(x, y) Same or change to x != y
BOOL lt(x, y) Same or change to x < y
BOOL gt(x, y) Same or change to x > y
BOOL le(x, y) Same or change to x <= y
BOOL ge(x, y) Same or change to x >= y

(section index)

Person Functions

The following functions retrieve information about an individual. When the function needs an INDI, you pass a reference to a individual record.

LifelinesInternal ScriptingComments
STRING name(INDI [,BOOL]) Same The second parameter can be used, but it is ignored. A version of name() that uses the second parameter is in Lifelines.gcscpt but commented out. You can switch to that version if you want, but it is less efficient.
STRING fullname(INDI,BOOL,BOOL,INT) VOID fullname(INDI,BOOL,BOOL,INT) But result has to be read using result()
STRING surname(INDI) Same
STRING givens(INDI) Same
STRING trimname(INDI,INT) Same
EVENT birth(INDI) VOID birth(INDI[,EVENT]) Set EVENT to a person's event. If optional EVENT not provided, fetch event using result().
EVENT death(INDI) VOID death(INDI[,EVENT])
EVENT baptism(INDI) VOID baptism(INDI[,EVENT])
EVENT burial(INDI) VOID burial(INDI[,EVENT])
(not used) STRING birth(INDI) In an expression, this function inserts date for birth or death.
(not used) STRING death(INDI)
INDI father(INDI) VOID father(INDI[,FATH]) Set second parameter to a parent. If not provided, fetch parent using result().
INDI mother(INDI) VOID mother(INDI[,MOTH])
EVENT nextsib(INDI) Not implemented
EVENT prevsib(INDI) Not implemented
STRING sex(INDI) Same
BOOL male(INDI) Same 0 false, 1 true
BOOL female(INDI) Same 0 false, 1 true
STRING pn(INDI) VOID pn(INDI) Fetch pronoun from result() and added option to return "they/them" for individuals with unknown sex.
INT nspouses(INDI) Same
INT nfamilies(INDI) Same
FAM parents(INDI) VOID parents(INDI[,FAM]) Set second parameter to family. If not provided, fetch family using result().
STRING title(INDI) Same
STRING key(INDI|FAM[,BOOL]) Same The second parameter can be used, but it is ignored.
STRING soundex(INDI) STRING soundex(STRING) Input any STRING. To get soundex of a person use soundex(name(indi)).
NODE inode(INDI) Same or change to INDIINDI can be passed to any method expecting a NODE
NODE root(INDI)
INDI indi(STRING) VOID indi(STRING[,INDI]) Finds person by key (GEDCOM ID without '@' signs). If INDI provided it is set to the person's object. If not, fetch object using result().
INDI firstindi() VOID firstindi([INDI]) Set parameter to individual. If not provided, fetch individual using result().
INDI nextindi(INDI) Not implemented Loop through individuals in current sort order using forindi()
INDI previndi(INDI) Not implemented
spouses(indi,sp,fam,num) {
    statements
}
spouses(indi,spouselist)
repeatwith iter from spouselist
  spousesiter(iter,sp,fam,"num")
  statements
endrepeat
Note that num is quoted to pass by reference.
families(indi,fam,sp,num) {
    statements
}
families(indi,famlist)
repeatwith iter from famlist
  familiesiter(iter,fam,sp,"num")
  statements
endrepeat
Note that num is quoted to pass by reference. and that sp object will be None object if that family does not have a spouse
forindi(indi,num) {
    statements
}
forindi(indilist)
repeatwith iter from indilist
  forindiiter(iter,indi,"num")
  statements
endrepeat
Note that num is quoted to pass by reference.

(section index)

Family Functions

The following functions retrieve information about a family. When the function needs an FAM, you pass a reference to a family record.

LifelinesInternal ScriptingComments
EVENT marriage(FAM) VOID marriage(FAM[,EVENT]) Set second parameter to output object. If optional parameter not provided, fetch it using result().
INDI husband(FAM) VOID husband(FAM[,INDI])
INDI wife(FAM) VOID wife(FAM[,INI])
INT nchildren(FAM) Same
INDI firstchild(FAM) VOID firstchild(FAM[,INDI])
INDI lastchild(FAM) VOID laastchild(FAM[,INDI])
STRING key(INDI|FAM[,BOOL]) Same The second parameter can be used, but it is ignored.
NODE fnode(FAM) Same or change to FAMFAM can be passed to any method expecting a NODE
NODE root(FAM)
FAM fam(STRING) VOID fam(STRING[,FAM]) Finds family by key (GEDCOM ID without '@' signs). If FAM provided it is set to the family's object. If not, fetch object using result().
INDI firstfam() VOID firstfam([FAM]) Set parameter to family. If not provided, fetch family using result().
INDI nextfam(INDI) Not implemented Loop through individuals in current sort order using forfam()
INDI prevfam(INDI) Not implemented
children(fam,indi,num) {
    statements
}
children(fam,chillist)
repeatwith iter from chillist
  childreniter(iter,indi,"num")
  statements
endrepeat
Note that num is quoted to pass by reference.
forfam(fam,num) {
    statements
}
forfam(famlist)
repeatwith iter from famlist
  forfamiter(iter,fam,"num")
  statements
endrepeat
Note that num is quoted to pass by reference.

(section index)

List Functions

Lists are handled using Internal Scripting lists, which means you can make use of all the Internal Scripting options for lists (see details in GEDitCOM Editor help). The Lifelines options are supported as follows:

LifelinesInternal ScriptingComments
VOID list(LIST_V) Same
BOOL empty(LIST) Same 1 if empty, 0 if not
INT length(LIST) INT lengthlist(LIST) Name changed because length is reserved by Internal Scripts.
VOID enqueue(LIST,ANY) Same
ANY dequeue(LIST) VOID dequeue(LIST,ANY) ANY is object name or quoted variable name (and is not optional)
VOID requeue(LIST,ANY) Same
VOID push(LIST,ANY) Same
ANY pop(LIST) VOID pop(LIST,ANY) ANY is object name or quoted variable name (and is not optional)
VOID setel(LIST,INT,ANY) Same
ANY getel(LIST,INT)
VOID getel(LIST,INT,"ANY")
ifndef ANY then ANY=0
Move ANY to third argument and quote if a variable. Invalid ANY sets ANY undefined while Lifelines returns 0. Second line only needed if list might be empty.
forlist(alist,val,num) {
    statements
}
forlist(alist,listlist)
repeatwith iter from listlist
  forlistiter(iter,objval,"val","num")
  statements
endrepeat
If objval is defined (check with ifdef objval, the item is an object, but if not defined, the item is variable set equal to val Note that val and num are quoted to pass by reference.

(section index)

Table Functions

Tables are handled using Internal Scripting dictionaries, which means you can make use of all the Internal Scripting options for dictionaries (see details in GEDitCOM Editor help). The Lifelines methods are implemented as follows:

LifelinesInternal ScriptingComments
VOID table(TABLE_V) Same
VOID insert(TABLE,STRING,ANY) VOID insert(TABLE,STRING,"ANY") Pass ANY by reference (object name or quoted variable name)
ANY lookup(TABLE,STRING) VOID lookup(TABLE,STRING,ANY) ANY is object name or quoted variable name (and is not optional)

(section index)

GEDCOM Node Functions

Lifelines nodes are equivalent to structures. In addition, record objects can be used wherever a NODE is expected and it will be treated as the root or level 0 node for that record (a record's tag is its record type).

LifelinesInternal ScriptingComments
STRING xref(NODE) Not implemented
STRING tag(NODE) Same
STRING value(NODE) Same Does not work for INDI or FAM records
NODE parent(NODE) VOID parent(NODE[,NODEV]) If optional NODEV provided it is set, otherwise fetch it using result().
NODE child(NODE) VOID child(NODE[,NODEV])
NODE sibling(NODE) VOID sibling(NODE[,NODEV])
NODE savenode(NODE) Not implemented
fornodes(node,nodev) {
    statements
}
fornodes(node,nodelist)
repeatwith nodev from nodelist
  statements
endrepeat
traverse(node,nodev,lev) {
    statements
}
traverse(node,nodelist)
repeatwith iter from nodelist
  traverseiter(iter,nodev,"lev")
  statements
endrepeat
Note that lev is quoted to pass by reference.

(section index)

Event and Date Functions

In an Internal Script, an EVENT is a structure and can be used directly in any NODE function. Options in Lifelines are supported as follows:

LifelinesInternal ScriptingComments
STRING date(EVENT) Same
STRING place(EVENT) Same
STRING year(EVENT) Same
STRING long(EVENT) Same
STRING short(EVENT) Same
EVENT gettoday() STRING gettoday() Returns today's date as STRING instead of EVENT with that date.
VOID dayformat(EVENT) Same except 0 is same as 2
VOID monthformat(EVENT) Same except 0 is same as 2, 5 is same as 3, and 6 is same as 4
VOID dateformat(EVENT) Same
STRING stddate(EVENT) VOID stddate(EVENT[,"STRING"]) Sets variable in quoted second argument to the date. If omitted fetch the date using result(). Also allows EVENT to be date STRING.

(section index)

Value Extraction Functions

LifelinesInternal ScriptingComments
VOID extractdate(NODE,INV_V,INV_V,INV_V) VOID extractdate(NODE,"INV_V","INV_V","INV_V") Variables by reference (quoted)
VOID extractnames(NODE,LIST_V,INV_V,INV_V) VOID extractnames(NODE,LIST_V,"INV_V","INV_V")
VOID extractplaces(NODE,LIST_V,INV_V) VOID extractplaces(NODE,LIST_V,"INV_V")
VOID extracttokens(STRING,LIST_V,INV_V,STRING) VOID extracttokens(STRING,LIST_V,"INV_V",STRING)

(section index)

User Interaction Functions

LifelinesInternal ScriptingComments
VOID getindi(INDI_V[,STRING]) Same If record is selected, return it, otherwise a dialog box to pick record of appropriate type; script exits if user cancels the selection
VOID getindimsg(INDI_V,STRING) Same
VOID getfam(FAM_V[,STRING]) Same
VOID getfammsg(FAM_V,STRING) Same
VOID getindiset(SEV_V[,STRING]) Not implemented
VOID getint(INT_V [,STRING]) VOID getint("INT_V" [,STRING]) Pass variable by reference (i.e., quoted); script exits if user cancel's the entry
VOID getstr(STRING_V[,STRING]) VOID getstr("STRING_V"[,STRING])
VOID getstrmsg(STRING_V,STRING) VOID getstrmsg("STRING_V",STRING)
INDI choosechild(INDI|FAM) VOID choosechild(INDI|FAM[,INDI|FAM]) Return choice in INDI or FAM; if not provided, fetch choice from result(). Returns None if no choice made.
FAM choosefam(INDI) VOID choosefam(INDI[,FAM])
INDI chooseindi(SET) VOID chooseindi(SET[,INDI])
INDI choosespouse(INDI) VOID choosespouse(INDI[,INDI])
SET choosesubset(SET) Not implemented
INT menuchoose(LIST [,STRING]) VOID menuchoose(LIST [,"INT",STRING]) Return choice in INT (quote to pass by reference); if not provided, fetch choice from result()

(section index)

String Functions

Internal Scripting has many methods for working with strings. The Lifelines methods are implemented as follows (some just for convenience):

LifelinesInternal ScriptingComments
STRING lower(STRING) Same
STRING upper(STRING) Same
STRING capitalize(STRING) Same
STRING trim(STRING, INT) STRING trunc(STRING, INT) Name change because trim is reserved in Internal Scripts.
STRING rjustify(STRING, INT) Same
STRING save(STRING) Same Just returns the string; no need to copy
STRING strsave(STRING) Same
STRING concat(STRING [,STRING]+) Same Except changed to maximum of 6 arguments
STRING strconcat(STRING [,STRING]+) Same
INT strlen(STRING) Same
STRING substring(STRING, INT, INT) Same
INT index(STRING, STRING, INT) Same Always returns index to first occurence; INT is optional and is ignored
STRING d(INT) Same
STRING card(INT) Same
STRING ord(INT) Same
STRING alpha(INT) Same
STRING roman(INT) Same
STRING strsoundex(STRING) Same
INT strtoint(STRING) Same Causes error if STRING not a number
INT atoi(STRING) Same
INT strcmp(STRING, STRING) Not implemented Use Internal Scripting string conditional expressions
BOOL eqstr(STRING, STRING) Not implemented
BOOL nestr(STRING, STRING) Not implemented

(section index)

Output Mode Functions

In Lifelines scripts, elements that are not function calls are sent to the output. This method has to be modified in this emulator. The functions are listed here; details on translating scripts are below the table.

LifelinesInternal ScriptingComments
VOID linemode() Same Must move to before calling ll_init() and cannot change modes within the translated script.
VOID pagemode(INT, INT) Same
VOID col(INT) Same line mode will start new line if INT is before current column number but page will mode will move to that column on current row.
VOID row(INT) Same Page mode moves to requested row while line mode inserts input number of new lines
VOID pos(INT, INT) Same Page mode moves to position; line mode inserts new lines and then moves to provided column.
VOID pageout() Same
STRING INT STRING INT ...
out STRING INT ...
cout INT STRING INT ...
Lines with alternating strings and column numbers prefaced with out if starts with a STRING (or only has a STRING) or with cout if starts with a column number
STRING nl() Same Used within an out line it is same as return character.
STRING sp() Same
STRING qt() Same
VOID newfile(STRING,BOOL) Same STRING can be full path to save report to file instead of open in window; if empty user prompted for save file (see below)
STRING outfile() Same File set by calling newfile() or "window" if report will go to a window.
VOID copyfile(STRING) Not implemented
VOID print(STRING[,STRING]*) VOID print(STRING[,FRACTION]) See below

Line Mode

The line mode is the default mode. In this mode Lines of Lifelines scripts that are not other commands are output to the report. The translation must comnbine text elements into a single string and then preface the line with out. For example, a line such as:

"ANCESTORS OF -- " upper(name(i)) "    (" key(i) ") " nl() nl()

should be converted to

out "ANCESTORS OF -- "&upper(name(i))&"    ("&key(i)&") "&nl()&nl()

which combines the strings (with &'s) and inserts out() at the start of the line (note: the nl() can optionally be changed to return)

Some Lifeline scripts in line mode output text separated by col() to move to column number before the next block of text. This style is translated as follows: if the line starts in col(), start the line with cout and combine any text sections into single text blocks. For example change:

col(12) name(child) col(63) "(RN=" key(child) ")"

to

cout col(12) name(child) col(63) "(RN="&key(child)&")"

Note that ampersands (&) were used in the last text block to make it a single STRING. If the line starts with a text block, start the command with out and combine text sections into single blocks:

name(child) col(63) "(RN=" key(child) ")"

to

out name(child) col(63) "(RN="&key(child)&")"

In summary, text blocks and col() must alternate and then use cout if the line starts in col() or cout if if it starts with text.

Page Mode

Page mode buffers pages before adding them to a report, which allows output to jump around a page. A common option is to move to position and then output some text. For example, this Lifelines script outputs some text at a position on a page with:

pos(4,10)
"  FULL NAME:   " name(i) col(46) "(" key(i) ")" nl() nl()

This is translated similar to line mode to:

pos(4,10)
out "  FULL NAME:   "&name(i)) col(46) "("&key(i)&")"
nl()
nl()

The text blocks are combined when needed (with ampersands &) and text blocks can be separated by col() commands. In page mode for Internal Scripts, nl() or return are converted to spaces. If you really want a new line, use nl() on a line by itself. A report that is outputting consecutive lines, however, need not use explicit nl() commands because a new line will automatically be started when a requested col() within an out line is before the current column position in the report. Note that col() on a line by itself will move that column on current row and never cause a new line.

An enhancement of page mode in Internal Scripts is that if any col() within an out line is changed to -col(), the previous text will be right justified in the space up to that column. This option only applies when using page mode.

Script Output

By default, script output is sent to a report window with fixed-width font. To direct to a file instead of a report, use an newfile(STRING,INT) command anytime before the final finish() command. The STRING parameter can be a full POSIX path to the desired output file. If it is empty, the user is prompted to pick a file. If user cancels option to pick a file, the report will revert to opening in a report window.

Any output displayed in a report window can also by ouuput to a file later using the "File→Export→Report to Text File" menu command in .

Pinting Messages

The print command in Lifelines sends messages to standard output. It appears scripts use this to indicate a script is working (such as printing a period) or various other information that is not part of the report. In the command is changed to have a single STRING argument (to translate one that uses multiple STRING's, concatenate them into a single string with ampersands ("&"). The optional second argument is estimate of the fraction of calculations that are completed. It is converted to a percentage and displayed in the scripting panel.

Note that the scripting panel disappears when the script is done. If you want the panel to remain open, such as if the printed messages are useful, include a write " " command in the script. This command also writes to the scripting panel, but also tells the panel to remain open after the script is done.

(section index)

Person Set Functions and GEDCOM Extraction

These functions are implemented with custom Lifelines.gcscpt modulue methods with list objected passed to each method:

LifelinesInternal ScriptingComments
VOID indiset(SET_V) Same
SET addtoset(SET,INDI,ANY) VOID addtoset(SET,INDI,ANY) Does not return SET
SET deletefromset(SET,INDI,BOOL) Same BOOL is 0 for false, ašnything else for true
INT lengthset(SET) Same
SET union(SET,SET) VOID union(SET,SET[,SET]) The new set is returned in the third SET; if omitted, first SET is changed to be the new set
SET intersect(SET, SET) VOID intersect(SET,SET[,SET])
SET difference(SET, SET) VOID difference(SET,SET[,SET])
SET parentset(SET) VOID parentset(SET[,SET]) The new set is set to the second SET parameter; if omitted, fetch new set object using result()
SET childset(SET) VOID childset(SET[,SET])
SET spouseset(SET) VOID spouseset(SET[,SET])
SET siblingset(SET) VOID siblingset(SET[,SET])
SET ancestorset(SET) VOID ancestorset(SET[,SET]) The new set is set to the second SET parameter; if omitted, fetch new set object using result()
SET descendentset(SET) SET descendentset(SET[,SET])
SET descendantset(SET) SET descendantset(SET[,SET])
SET uniqueset(SET) Same Unique individuals but no sorting; call a sort afterwards if needed
VOID namesort(SET) Same
VOID keysort(SET) Same
VOID valuesort(SET) Same
VOID genindiset(STRING,SET) Not implemented
VOID gengedcom(SET) Not implemented
forindiset(b,i,v,n)
forindiset(b,blist)
repeatwith iter from blist
  forindisetiter(iter,i,"v","n")
  statements
endrepeat
Note that v and n are quoted to pass by reference.

(section index)

Record Update Functions

This Lifelines emulation does not support editing of the data. You can however, use other script-editing methods to make changes to the data in a script.

LifelinesInternal ScriptingComments
NODE createnode(STRING, STRING) Not implemented
VOID addnode(NODE, NODE, NODE) Not implemented
VOID deletenode(NODE) Not implemented

(section index)

Record Linking Functions

LifelinesInternal ScriptingComments
BOOLEAN reference(STRING) Not Implemented Sending invalid reference to next two just returns None object
NODE dereference(STRING) VOID dereference(STRING,NODE) STRING is GEDCOM id with '@' signs and NODE is set to record with that id or None object if not found
NODE getrecord(STRING) VOID getrecord(STRING,NOID)

(section index)

Miscellaneous Functions

LifelinesInternal ScriptingComments
VOID lock(INDI|FAM) Not implemented
VOID unlock(INDI|FAM) Not implemented
STRING database() Same Name of document
STRING version() Same version number
(not used) STRING application() GEDitCOM II or GEDitCOM application being used
VOID system(STRING) Not implemented

(section index)