3B2 Scripting
ArborX

Open the Documentation Legend

Summary

This chapter details the 3B2 scripting language, its uses and functionality.

Contents

1 Introduction

2 Overview

3 Types of Script

3.1 Internal Scripts - Text Stream

3.2 External String Number Scripts

3.2.1 Use of Strings

3.2.2 Changing the name of your user strings file

3.2.3 Converting internal scripts to external scripts

3.3 User Written Scripts - Extensions Scripts

3.3.1 Disclaimer

4 Document Start and Exit Scripts

4.1 Document Start-Up Scripts - Autoexec

4.2 Document Exit Scripts - Autoexit

4.3 Event Scripts - the automac command

5 Running/Executing Scripts

5.1 The trun macro

5.1.1 Passing Parameters

5.2 The run macro

5.3 Running a script within your document

5.4 Running a script as an external string

5.5 Running scripts from a key

5.6 Running scripts from a graphic

5.7 Running scripts from a dialogue box

5.8 Stopping a Script

5.8.1 Stopping a nested script

5.8.2 Suspending a script

6 Developing a Script

7 Script Components

7.1 Variables

7.1.1 Variables with macros

7.1.2 Loops - Jumps and Labels

7.1.3 Showstrings in Scripts

7.1.4 Using XPath in Scripts

7.1.5 Using Perl in Scripts

7.1.6 Communication with 3B2: Getvar Codes

7.1.7 Creating Lists

7.1.8 File Examiner

8 Debugging a Script

8.1 The trace command

8.2 The boxit command

8.3 Output to a log stream

8.4 The Script Bar

8.5 Modeless Dialogue

8.6 The debug macro

8.6.1 Development Assistant

8.7 Comments

8.7.1 Commenting a Script

8.7.2 Document and Tag Comments

8.7.3 Using comments to set script variables

9 Multiple Scripts/Chaining Scripts

10 Mini Scripts

11 Script Availability to Other Documents

12 Shelling Out to the Operating System

13 Cross-platform functionality

13.1 Mac functions not available on the PC

14 Useful System Files

15 Script Examples

15.1 Basic Script Example

15.2 Search and Replace Script Examples

15.3 Multi-function Concurrent Script Example

16 Miscellaneous Notes/Tips and Tricks

16.1 Turn Screen Display Off

16.2 Slow down scripts

16.3 Turning off ttundo

17 Further Information and References

17.1 Associated documentation

18 Subject Index

Introduction

This chapter describes 3B2 scripting features and provides practical examples of scripts and how you can use them. 3B2's dynamic scripting environment enables you to create automated publishing solutions that eliminate repetitive procedures that would otherwise have to be completed manually. 3B2 scripting can be used to create scripts to handle specific applications or perform specific tasks. Scripts can be programmed onto keys, started with a macro, or started automatically when a document is changed, opened or closed.

Internal scripting is possible because 3B2 is controlled by macros. 3B2’s enhanced macro language contains script features to make it more useful as a programming language, such as variables, looping, conditions, and interaction with 3B2 documents. Further useful scripts features are continually added to make 3B2’s scripting as comprehensive as possible.

Overview

3B2's macros provide a programming language that can be used to create sophisticated, flexible automated publishing solutions. They can be used as fast access codes to any of 3B2's functions. Every selection, keystroke, and even mouse movement generates internal macros. The next step after executing a sequence of macros is to include these macros in a script or macro file which can be run with a single command. A basic script consists of a sequence of macros.

As a sequence of consecutive instructions, scripts can be used as an interactive tool between users and 3B2 to control the appearance, behaviour and contents of documents. It is also possible to customise the 3B2 interface using scripts. Scripts test and store working environments and can set, change, transmit and display results.

3B2 internal scripting is an interpreted programming language and therefore does not have to be compiled. The core of the language is embedded in 3B2. Similarly, dates, time and the system environment are also embedded. 3B2's internal scripting language is similar to other programming and scripting languages, for example, there are instructions, queries, loops and operations with counters. However these similarities to other programming languages should in no way intimidate beginners or novices.

Creating a script is straightforward, making full use of 3B2's normal editing features. When writing a script you will need to know the appropriate macros to use. This knowledge is gained quickly with practice and experience of writing scripts. Absolute control of scripts requires good programming abilities and a logical, structured approach to problem solving. However it is important to be aware that there are many complexities involved in scripting which are not immediately obvious.

The full power of scripts is limited only by the imagination of the user, much like a programming language. For this reason, we recommend that anything more than simple projects should be undertaken by a competent programmer. However, there is no such limitation on the use of pre-written scripts. These can easily be started, and can be made to look like extensions to 3B2, for example modifying menus. 3B2 scripts can also contain 3B2 showstring syntax. In addition to 3B2's own internal scripting language, 3B2 also includes full support for XPath, Perl scripts and Perl mini scripts.

Types of Script

Scripts can be presented to 3B2 in two different ways:

3.1 

Internal Scripts - Text Stream

Internal scripts are set in a normal text stream within a 3B2 document and appended with the .sc tag extension.

You can for example create a script by entering the following in the macro bar:

 ttagmk "name_of_script.sc"
The closing double quote can be omitted from the above syntax, for example instead of ttagmk "name_of_script.sc" it is possible to write ttagmk "name_of_script.sc

By creating a script within your document, you will easily be able to develop and test the script. It also means that the file is portable because regardless of where the file is located, the script will always be inside your document. The problem with this method is that only the file containing the script will be able to use it.

User scripts are probably the most common type of script that you will use. The name of the script does not matter, however it is good idea to give a script a name that describes its function so that it is easily identifiable. For example, if a script loads text into a frame in your document, you could call your script 'load_text' User scripts are often launched when a document is opened by an autoexec. These scripts can then be chained together to create a series of scripts.

3.2 

External String Number Scripts

External String Number Scripts are scripts set into an external strings file, using a defined set of user string numbers. These are generally located in the 3B2 system directory and read into 3B2 on start-up.

If you create your script externally it will be more difficult to develop because of the need to regularly modify and save the script in a text editor such as Notepad and test the results in 3B2. This would result in having to restart 3B2. However, this can be avoided by using the loadstrs command.

One advantage however, is that the script will be truly global and can therefore be accessed by all 3B2 documents. It is more likely that you would develop the script in 3B2 then save it into an external file. In contrast to internal scripts, external string number scripts can not have a regular name, they must have a number.

3.2.1 

Use of Strings

3B2 string files contain all of 3B2’s language dependent strings and other user configurable strings. These strings define such things as 3B2’s menus and dialogue boxes.

By using defstr and addstr you can either define new strings or overwrite existing strings. These new strings can describe menus and dialogue boxes for use with your scripts.

Further dialogue string examples can be found in the sections on Dialogue boxes.

3.2.1.1 

The User Strings File

When you have developed a script you may decide that you wish to make it available to other documents. This can be done by putting the script in a user strings file. This file is usually called suser.3ad but another filename can be used by specifying its name on the 3B2 command line with the -u:filename option. See the 'shelp(lang).3ad' Arbortext APP system file for more command line parameter information.

For more information see Making Scripts available to other documents.

3.2.2 

Changing the name of your user strings file

You can specify an alternate name for user file(s) by using the command line option '-u: filename' in your 3B2 start-up file, startdos.3ad/ startwin.3ad etc. You will find the full list of command line options in the shelp.3ad file.

3.2.3 

Converting internal scripts to external scripts

When you have developed a script you may want to make it available to other documents, or even share it with other 3B2 users. Internal scripts are those defined within a document that exist within a 3B2 text stream, and are executed with the trun macro followed by a string containing the name of the text tag. They are accessible only by the document they are in.

External scripts are defined within one of 3B2's string files, exist within a numbered string and are executed with the trun macro followed by the string number. External scripts are accessible by any document. Converting an internal script to a form in which it can be added to your suser.3ad can be semi-automatic if you first save the text stream containing the script to a 3B2 text file. This is done using the tsave macro with a .3t extension to tell 3B2 to save a text file:

6 Append the file to your user strings file (suser.3ad) with an ASCII text editor.

8 Replace the fdt header with a string header. You will find that the $'s and <>'s are already correctly positioned. You should be aware of some small differences between fdt data and ts data:

If you open a 3B2 document (.3d file) in an external text editor, you will notice the fdt data. fdt is a form of data that 3B2 recognises in order to process a document. It includes dollar $ signs at the start of each line and angle brackets <> at each new paragraph. To convert an internal 3B2 file to an external strings file you must remove the fdt data. This can be achieved using a search and replace routine. It is also necessary to add the string info, i.e. "ts","350". It is then possible to add your script as a strings file to suser.3ad. If any of your script lines are very long (more than 70-80 characters) then the fdt data may contain \ characters at the end of lines to help preserve end of line spaces. These are ignored by the fdt reader but not by the string reader and must be removed. Move any end-of-line spaces to the beginning of the next line after the $.

The last line will end with a \ character. Delete this character and replace it with the <> characters.

Avoid using characters saved as &...; sequences within a script. These include tabs, ampersands, angle brackets and other codes below ASCII 32, for example special line breaks and column or page breaks, but not the normal line break, this gets output as <>). If they cannot be avoided, translate the &...; sequence back to the correct ASCII character in the strings file (usually by pressing  Alt  followed by the number sequence in an ASCII text editor).

The conversion process is best illustrated by example. Suppose that the text stream 'xedit' contained the following script:

 defstr 390,"Hello\n" 1
 addstr 390,"World\n" 2
 addstr 390,"%1e[Continue]"wdb 390 3

The tsave "xedit.3t" macro would have converted this to a file called xedit.3t. The file would contain the following lines:

 fdt "xedit",0,"" 1
 defstr 390,"Hello\n"<> 2
 addstr 390,"World\n"<> 3
 addstr 390,"%1e[Continue]"<> 4
 wdb 390\ 5

Following the above guidelines, the header line can be changed to a string header, and the last line removed to leave:

 "ts","350" 1
 defstr 390,"Hello\n"<> 2
 addstr 390,"World\n"<> 3
 addstr 390,"%1e[Continue]"<> 4
 wdb 390<> 5

This is now in the right form for the user strings file. To start the script, the macro would now be trun 350 (instead of trun "xedit"). You should also be aware that, in this particular example, scripts which simply use defstr and addstr to define what appears in a dialogue box or menu (but actually do nothing else) could be translated more severely, so that the string in your user file would simply hold the dialogue box or menu definition, for example:

 "ts", "350"Hello World %1e[Continue]

or:

 "ts", "350Hello<>World<>%1e[Continue]
The above example would just be a dialogue box definition. It would be called using wdb (wmn would call for a menu), but trying to run it with trun is likely to crash 3B2.

3.3 

User Written Scripts - Extensions Scripts

A number of user-written scripts, many of them with comment lines, are included in the sscr.3ad or scrwin.3ad files supplied with MS-DOS, Windows and Mac versions of 3B2. We recommend that you examine these carefully in an ASCII editor to see how they work.

These files are no longer shipped with 3B2 version 8 and beyond.

3.3.1 

Disclaimer

The sscr.3ad or scrwin.3ad files contain scripts written by users of 3B2 to perform a variety of functions. Advent Publishing Systems is pleased to make these available with 3B2 but cannot accept any responsibility for their reliability or otherwise support the features provided using scripts.

Please note that all strings from these files are loaded automatically if the file exists in your 3B2 program directory.Most of these Extensions scripts have been edited by Advent to minimize memory usage by reusing variables where possible and use variable names in the form ^_z_..^_a_ This makes them more daunting, at first sight, than the scripts a user might write. Using variable names in the form ^_z_..^_a_ also helps avoid possible conflicts with the variable names chosen by the user.

As you become familiar with 3B2's scripting language you will build up a library of useful routines which can be re-used in other projects.

To see scripts that are already set-up in 3B2 open the sscrwin.3ad file.

The range of user string numbers available to the user is detailed in the table below:

Strings

Use

Strings 350 - 399

Reserved USER strings (in suser.3ad)

Strings 1500 - 1599

Reserved USER strings (in suser2.3ad)

Strings 1600 - 1699

Reserved USER strings (in suser3.3ad)

The range of numbers not available to the user is:

Strings

Use

Strings 345 - 349

Reserved for Advent temporary strings

Strings 400 - 699

Reserved HELP boxes (in shuk.3ad)

Strings 700 - 899

Reserved for Advent strings (in this file)

Strings 900 - 999

Reserved for implementation specific scripts (in sscr.3ad - see table below)

Strings 1000 - 1099

Reserved for MAIN MENU strings (in this file)

Strings 1100 - 1199

Reserved for Advent strings (in this file) (Strings 1155 to 1169 for 3B2 SGML v3 message strings in ssgmlukf.3ad)

Strings 1200 - 1299

Reserved for SGML strings (in ssgmluk.3ad)

Strings 1300 - 1499

Reserved for Advent strings (in this file)

Strings 1700 - 1799

Reserved for CONTEXT MENU strings (in this file)

Strings 1800 - 1899

Reserved for Advent temporary strings

Below is a list of scripts in the strings file stuk.3ad

Strings

Use

String 320

Search and replace script. (All variables in this string start with: ^_sr_*).

String 336

Builds URI from script variables that were filled in from dialogue box 818. (Used variables: ^_x_ and ^_str_336_*. Additionally the script uses the variables from string 818).

String 1147

Mini-script to display showstring counters in units. (All variables in this string start with: ^_str_1147_*).

String 1148

Mini-script to display under/overmatter. (All variables in this string start with: ^_str_1148_*).

String 1150

Script called from eprint macro. (All variables in this string start with: ^_eprint_*).

String 1185

Script to run the Showstring Analysis. (Used variables: ^_c_ and ^_t_).

String 1194

Tag Rename search/replace script. (Used variables: ^_ttagren(0), ^_ttagren(1) and ^_ttagren(2)).

Version specific information7.68a  String 1385

Stream Editor – Modeless dialogue box. (Arrays: ^_te_type(), ^_te_tname(), ^_te_tl(), ^_te_otl(), ^_te_link(),^_te_t(), ^_te_s() and ^_te_r(). Scalars: ^_te_pos, ^_te_stretch, ^_te_nsname, ^_te_nstype and ^dummy. Note that ^_te_nstype and ^_te_nsname are also used in string 1386).

Version specific information7.72a  String 1398

Format Log Navigation – Modeless dialogue box. (Scalars: ^_db1398_s).

Document Start and Exit Scripts

4.1 

Document Start-Up Scripts - Autoexec

Any 3B2 document can have a start-up script known as an autoexec (auto-execute). An autoexec runs automatically when the document is opened, unless otherwise specified in the Open document dialogue box.

Because this is a special type of start-up script the name of this script must be 'autoexec'. If you rename the script it will not work.

An autoexec can be used to set-up documents, for example graphic preferences and file specific key assignments or to provide specific special features. The start-up script is simply a text stream called autoexec with the file extension .sc

Below is an example of an autoexec:

 *101136 tft 1
 *101137 tfo 2
 getvar 12501 "pathname" "filename" 3
 run "^pathname^filename.3m^ 4

The following is a description of the above syntax line by line:

1
Assigns the tftext command to the  F1  key using the * command.
2
Assigns the tfo command to the  F2  key using the * command.
3
Uses the getvar command to get the current file name.
4
Runs the macro file with the same file path and prefix as the current file with the suffix .3m added. The .3m extension indicates that this is a file that contains a list of macros.
When developing and testing a script, be aware that whenever you revert (see trevert) a file the autoexec will run automatically. If this situation occurs it is advisable to close the file and then open the file with the Run autoexec: □ option de-selected in the Open Document dialogue box.

4.2 

Document Exit Scripts - Autoexit

In the same way that an autoexec is launched when a file is opened, the autoexit script will be run automatically when a file is closed enabling various actions to take place before a file is truly closed. One such use could be to save the values of the variables within a file.

Because this is a special type of exit script the name of this script must be autoexit. If you rename the script it will not work when closing the document.

By default, the autoexec script will be run when a file is closed. The autoexec script will still run if the document is closed without any changes having been made or if changes are abandoned either by selecting Abandon from the Close Document dialogue box or entering:

 wcl "a"

To close a file without running the autoexit script, add the following parameter to the wcl macro:

 wcl "s", 1

The autoexit script will not run if the wcl command is cancelled from the Close Document dialogue box.

Below is an example of an autoexit that saves the variables within file. The example assumes that the following variable assignments have taken place:

^var_day=21

^var_month=03

^var_date=02

Note that the above variables have a prefix of 'var'. This is recommended to avoid clashes with 3B2's internal variables, for example day, month, date.
 savevars "c:\Temp\saved_variables","var_*" 1
 tprint 2

The following is a description of the above syntax line by line:

1
Uses the macro savevars to save the variables. The first parameter specifies the filename and the second specifies the variables to save using a wildcard pattern for variable names. The * matches all the remaining characters of the variable name.
2
Invokes the Print dialogue box.

Alternatively you could also save the variables in a document within an autoexec. This enables the variables to be used when the file is re-opened later. As an example, the following syntax will save all variables at the top of an existing autoexec:

savevars "{1}autoexec","*"

For more information see savevars

4.3 

Event Scripts - the automac command

It is also possible to run scripts when certain events occur. This can be achieved with the automac command.

The automac command enables a script to be run automatically when the assigned expression changes.

For more information see automac

Running/Executing Scripts

5.1 

The trun macro

The trun macro controls the running of scripts. It can be used to start and stop both types of script (stream and string), either manually by the user by being entered in the macro bar, or automatically from within a script. For example, the following syntax would run the script called 'my_script':

 trun "my_script

Besides the basic running of 3B2 scripts, the trun macro provides other functionality to the scripting environment such as re-running previous scripts if run concurrently in the document. In previous versions of 3B2 nesting of scripts was limited to up to 10 levels. There is now no limit to the number of scripts that can be nested.

For more information see trun

The trun command can also slow down the 3B2 script processor. For more information see the Tips and Tricks section at the end of this chapter.

5.1.1 

Passing Parameters

The second parameter of the trun macro, if present, is a string enclosed in double quotes. Each line in a script can refer to the parameter by including the syntax %b or %s.

When the script is processed, %b will be replaced by the parameter itself, and %s will be replaced by both the parameter and the double quotes which surround it. Each line of a script can have no more than one replacement item. The example script shown below takes two variable parameters:

Sc script1 - 10(23)c

@hello %b#13@hello %s

When this "script1" is run using the following:

 trun "script1","World"

The output will be:

hello World

hello "World"

Passing parameters can be a useful feature; they provide flexibility, as one script can be made to fit many different requirements. This is particularly true if you have written a large number of scripts and have started running out of user-definable strings. In this case, you can often concatenate related scripts, and access them by giving each one an option number.

5.2 

The run macro

It is important to be aware of the differences between the trun and run commands. The run macro runs a list of macros. The run macro is used to run a macro file which has been saved to disc as an ASCII text stream (using the tsavetxt macro) or a control file that has a series of variables defined. Unlike scripts, a macro file cannot contain another trun macro unless it is at the end of all the other macros.

A macro file differs from the scripts included in a strings file in that there is no string header and each line is presented without a leading $ or ending < > apart from these differences, a macro file can not access script features such as loops and jumps and is restricted to the macro commands you can enter in the macro bar.

Despite these limitations, macro files can be very useful. It is possible, for example, to run a macro file from a document start-up script (autoexec) to load tags from a master template document or update text with information from a database. Macro files are easier to write than scripts, and are worthwhile if you find yourself repeating sequences of complex macros.

5.3 

Running a script within your document

Use the trun command followed by the name of your script in double quotes, for example:

 trun "name of script"

5.4 

Running a script as an external string

Use the trun command followed by the string number of your script for example:

 trun 350

5.5 

Running scripts from a key

Sequences of macros of up to 255 characters can be assigned to a single key stroke. You cannot use the Scripts Extension Macros in this way, although user-written scripts can still be run with a single keystroke by simply assigning the relevant trun macro to the key, the following example assigns trun "my_script" to the F1 key.:

 *101136 trun"my_script"

For further information see *, # and trun

5.6 

Running scripts from a graphic

Macros and scripts can also be run by clicking on a 3B2 object graphic. This makes it possible to program intelligent documents or to use 3B2 as a hypertext authoring tool.

Below is an example of a script that assigns a script to a graphic:

Draw a graphic object.

Create a script called "my_script" that you want to execute when clicking on the graphic. As a simple example this could just contain a boxit

Then create the following script to assign your script to the graphic:

 tgsel -1 1
 tgtext "my_script" 2
 tgtpos -1 3
1
Selects the graphic object.
2
Assigns the text stream "my_script"
3
Changes the position of the text assigned to a object graphic so that the text is not shown above the graphic.

After running the script above, click on the graphic object and the script "my_script" will be executed.

For further information see tgsel, tgtext, tgtpos.

5.7 

Running scripts from a dialogue box

You create a dialogue box by using script syntax. Similarly, it is possible to initiate a script through a dialogue box. For more information see the Dialogue Boxes chapter.

5.8 

Stopping a Script

Scripts are stopped with the trun 0 command. This leaves no scripts running and is therefore the way to exit all scripts immediately.

5.8.1 

Stopping a nested script

A trun -1 command allows scripts to be run and stopped from within other scripts depending if certain conditions are met. For more information see Conditional Tests

The macro shown below exits 2 scripts and returns to 2 levels back (if any), otherwise it will terminate. Because the first parameter is a number less than 0 the script backs-up the given number of nesting levels.

trun -2

For more information see trun

5.8.2 

Suspending a script

Scripts can be suspended until certain condition(s) are met. To suspend a script you use the trun command, for example, trun +1 suspend scripts until any raw keycode is received from the keyboard.

To continue with any suspended scripts trun +0 could be assigned to a key to restart a script without waiting for any other conditions. This can be used if an external script has been running and 3B2 now needs to continue.

For more information see trun

5.8.2.1 

Suspending a script for a set amount of time

The example below suspends a script for 5 seconds. In this example the getvar code 21022 is used. This is the number of seconds since the 1st Jan 1970 determined by 3B2 (as an alternative you could use any other of the 3B2 getvars that record a fixed point in time).

The expression (v21022+5) says what is the result of this getvar value plus five. Because the getvar 21022 is in seconds, the +5 is determined to be a value in seconds.

The macro below therefore takes the value of the getvar as its reference point in time. It then waits until the expression is true then adds (pauses) five seconds and then continues with the script:

 trun +21022,^(v21022+5)^

If a new script is started when another is suspended the suspension will temporarily be lifted while the new nested script is running. As soon as the new script terminates, the suspended script will again be current, but will remain suspended.

Developing a Script

The diagram below illustrates the main stages and options when developing a script and making it available across your system or to other users.

It is usually best to start the development cycle from within a 3B2 document, since this provides a way of testing your work as you develop the script.

Script Components

The following section contains descriptions of the commands and operators you will come across in the construction of scripts. There are also practical examples of how to use the script components and where to find further relevant details.

7.1 

Variables

The following sections describe variables and variable use in scripts. In 3B2, variables are named areas of memory used to store a sequence of characters. A variable is used to hold a specific piece of information needed by your script. Variable names are indicated by text preceded with a ^ for example below is a variable called var:

^var

You can use 3B2's macro and script system to manipulate and make use of variables in numerous ways, using variable operators. See ^

Make your variable names meaningful.
From version 3B2 7 variable names are now case sensitive.

For more information see the topic Variables.

7.1.1 

Variables with macros

One of the main uses for variables is to output a value as a macro parameter. This is done by including the variable name on a macro line and appending a ^ character to the end of the line. When 3B2's macro processor receives a macro line ending with ^ it scans the whole line looking for valid variable names (with a preceding ^) and replaces them with the contents of the variable. The resulting line is then executed as a normal macro and parameter combination.

There is no limit to the number of replacements on a line, or to the number of times an individual variable content is replaced, but the total length of the resulting line must not exceed 242 characters.

7.1.1.1 

Arrays

Version specific information4.52a  Variables can now have up to 2000 array elements. The elements can be indexed with any range of numbers (including negative) provided the range is no wider than 2000. Elements are created when they are first assigned a value. The array will grow automatically when a new element is assigned, provided the maximum number of elements would not be exceeded (in which case the assignment would be ignored).

A variable's array index is simply a bracketed expression appended to the variable name:

 ^test(3)=three 1
 ^test(8)=eight 2

The above example would create a 6 element array with elements numbered 3 to 8. Elements 4 to 7 would be blank.

 ^test(2000)=big number

This assignment would be ignored because it would require the array to grow to 2001 elements, more than the maximum. The array does not change at all (only elements 0 to 8 are allocated).

When an indexed variable is saved with savevars then all allocated elements are saved.

If you need to re-use a variable with a different element range or need to ensure that the variable is re-allocated from scratch then use the freevars macro.

7.1.1.2 

Expressions

Version specific information4.51a  3B2 (post version 4.51a) allows arithmetic expressions in place of any script variable. Enabling variable manipulation with a greatly simplified syntax, used extensively in scripts and various other functions, such as automac

Syntax ^(expression)

Expressions can contain combinations of constants, variables, getvars, operators, brackets, and in the case of showstrings expressions can contain counters, for example:

 ^(20+10) 1
 ^(^num1*2) 2
 ^(^wid*(^ht+1)) 3
 ^(v21020) 4
 ^(v^getnum)(v(^val1+1)/10000) 5
 ^(v21020/v01021) 6
 ^(a+b*10+d) 7

This last example is only applicable to showstrings as it contains references to showstring counters.

For more information see showstring and Regular Expressions

There are several places in 3B2 where variables can be used, all of which allow this syntax, for example:

7.1.1.3 

Variable operators

 ^num=^(^num2*^num3) 1
 ^sum=^(^num1+^num2+^num3) 2
 ^average=^((^num1+^num2+^num3)/3) 3
4
The value of ^num equals ^num2 times ^num3.
6
The value of ^sum equals ^num1 plus ^num2 plus ^num3.
8
The value of ^average equals ^num1 plus ^num2 plus ^num3 divided by 3.

7.1.1.4 

Variables in a macro replacement

 @The result is ^(^num1+^num2) units 1
 ^tpgoto ^(v01535-1)^ 2
4
The example above inserts the text and the result of ^num1 plus ^num2
6
Go to the penultimate page using the tpgoto command and the getvar for the last page minus 1.

7.1.1.5 

Variables within script conditions

 ?+^(^val1+^val2+^val3) @expression is positive 1
 ?+^(value),^(10) @value is more than 10 2
 ?=^(20),^(^val1-^val2) @expressions are equal 3
4
If the value of ^val1 plus ^val2 plus ^val3 are positive then output text.
6
If ^value is greater than 10 then output the text.
8
If the result ^val1 minus ^val2 is 20 then output text.

This enhancement to conditional tests allows comparisons to be treated as numeric by using an expression for one or both of the arguments:

 ?+^(expr1),^(expr2) - true if expr1 is bigger 1
 ?-^(expr1),^(expr2) - true if expr1 is smaller 2

When a variable is used in an expression then the variable itself can contain an expression in brackets:

 ^sum=(^val1+^val2+^val3) 1
 ^average=^(^sum/3) 2

As there is no ^ after the = sign, ^sum is not evaluated until it is included in the expression for ^average.

7.1.1.6 

Saving Variables

Variables only retain their values until 3B2 is shut down. Variables that need to be preserved until the next time 3B2 is started can be saved in a file, and re-read the next time they are needed. The macro used to save variables is savevars

7.1.1.7 

Clearing/ Freeing Variables

If you need to clear variables use the macro freevars. The freevars command frees 3B2 script variables that match a wildcard pattern. If you are not sure of the name of the variables that you want to clear you could use the wildcard functionality which can, for example, clear all variables that begin with 'var':

freevars "var*"

7.1.1.8 

Setting Variables - Initialise Fields

It is possible to set the variables in your script to a particular value. This is useful, for example, if there is a loop in your script and you wish to reset the values of your variables each time. This means that when the script is run, the variable fields are either reset to empty or set to a default value.

It is possible to initialise the variable fields, so that each time a script is run, the fields are either reset to empty or set to a default value. This is particularly useful when, for example, you have generated a dialogue box from your script that a user will enter their details into. In this case you would want the details entered to be cleared each time. You can either set the variables at the a start of a script or make another new script specifically to initialise the variable fields, for example:

Sc initialise_fields - 1(105)c

^fname=
^sname=
^title=
^age=
^date=

7.1.1.9 

Function Variables

Function variables are an addition to the variable syntax, that enables you to call functions by name, for example:

^[funcname parameter(s)]

This new syntax can be used anywhere that a regular 3B2 variable can be used, such as in show strings, in scripts, in expressions, etc.

For more information on Function Variables see the Variables chapter and individual function documentation such as var.

7.1.2 

Loops - Jumps and Labels

It is often necessary to re-execute certain sections of a script. 3B2 provides support for this with label and jump macros.

A label is any valid name preceded by a : (colon) character. The label must appear on a line of its own. Labels are used as targets for one of 3B2's jump macros.

A jump macro is any valid name with corresponding label, preceded by a '{' or a '}' (curly brackets) characters. The '{' specifies to jump backwards and the '}' specifies to jump forwards. A jump macro must appear on a line of its own, unless it is part of a condition. If the target label is not specified or found, the script is terminated. Below is an example of a script with a loop:

 :loop_back_to_me 1
 ^myname=Advent 2
 @^myname^ 3
 {loop_back_to_me 4
7
Defines the loop label.
9
Populate the variable 'myname' with 'Advent'
11
Insert the variable 'myname' into the test stream.
13
Defines the 'loop_back_to_me' jump.

See ?, :, {, }

7.1.3 

Showstrings in Scripts

It is possible to use showstring syntax in scripts. Although showstrings deal mainly with formatting issues, while scripts are mainly concerned with automation, there are reasons why you would want to use showstrings inside a script such as passing certain special characters to a variable.

For more information on Showstrings see the Showstrings chapter.

7.1.3.1 

Showstring Variable Interpreter

Sc script - 1(29)c

^"strm0"=text_^number
trf:wdr

4
Inserts the word 'text' followed by the value of a variable to the text stream "stream0".
6
Refreshes and Redraws the screen

When the script is run, the result 'text_^number' should now appear. However, the value of ^number will not be interpreted. Instead the stream literally contains a ^ followed by the word 'number'. This is because if a ^ does not appear immediately after the = (equals sign) 3B2 assumes that you are setting a literal value and will no longer attempt to interpret any variables.

To solve this problem, modify the script using the showstring variable interpreter. This resolves all the variables. So, if the script is modified so that it looks like the following:

Sc script - 1(33)c

^number=1
^"strm0"=^?"text_$^number"
trf:wdr

The ? signifies the switch to showstring mode. The ^ will allow the variables to be resolved. The $ needs to be placed before the variable as this is how a variable is displayed within a showstring. A pair of double quotes must also surround whatever is being passed to the stream (or variable).

When the script is run 'text_1' will be output.

7.1.3.2 

Difficult Characters to Pass to a Variable

An example of a difficult character to pass to a variable is a hard return. This is because a return usually places the next piece of information on a new line within a script. In the example below several special characters are passed into variables:

Sc script - 1(33)c

^var1?$10#
^var2?$9#
^var3?$32#
@^var1^
@var1 contains a ^var1^
@^var1^
@var2 contains a ^var2^
@^var1^
@var3 contains a ^var3^
@^var1^

When the above script is run you will see the content of each variable. In this case ^var1 is a hard return ($10#), variable ^var2 is a tab ($9#) and variable ^var3 is a space ($32#).

For more information on special characters see Character Access in 3B2 - Entering Special Characters in the User Reference Manual

7.1.3.3 

Checking the Status of a tag

There are occasions when it is useful to know if a tag exists or not. Using showstrings it possible to use the following syntax:

@xbody

This will then return a value of 1 if the 'body' tag exists, and 0 if there is no such tag. These values can be stored within a counter enabling you to test the counter, for example:

Sc script - 1(33)c

^exists?="@xbody"x(1)$x(1)
@does body exist = ^exists^
?=^exists,1 boxit "the tag body DOES exist"
?=^exists,0 boxit "the tag body DOES NOT exist"
trf:wdr

When the script is run the following will happen:

1
Checks if the tag body exists and stores the value (0 for negative, 1 for positive) in a counter. This value is passed into the variable exists. (The ? indicates this is a showstring function).
2
Output the text 'does body exist' = the value of the variable exists. (0 for negative, 1 for positive).
3
If the body tag does exist, a value of 1is returned and the boxit will display the text "the tag body DOES exist".
4
If the body tag does not exist, value of 0 is returned and the boxit will display the text "the tag body DOES NOT exist".
5
Refresh and re-draw the screen.
Using counters in a script is not the usual method. Normally counters are applied to a stream. In this case however the stream is the script. They would not effect another counter of the same name that has been used in your document.

7.1.3.4 

Conditional Tests

The testing of variables is key to a script. 3B2's script extension has a condition tester so that macros can be executed if the condition is met, for example conditional test can be use to test counters or exit loops. There are many different types of conditional test, using variable and string comparisons as well as utilising verify strings etc.

Below is a basic syntax example of a conditional test:

?=^(^var),^(3) tend

The above example tests if var=3. If yes, the tend macro will be executed. (The tend macro moves to the end of the current text stream).

See the ? command, for information and examples on conditional operators.

For more information see Showstrings

7.1.4 

Using XPath in Scripts

It is possible to use XPath together with 3B2 syntax in scripts to locate and format XML documents. By using XPath in unison with 3B2, you can manipulate a document and create simple solutions to otherwise complex problems.

7.1.4.1 

How to call XPath in a script

To call XPath in a script use the following syntax:

^!"expression"

The 'expression' can be any valid XPath expression. The XPath expression belongs between quotes.

The following working example of XPath syntax inside a 3B2 script outputs the name of the parent node to the text stream 'name':

^"name"=^!"name(parent ::node())"

In scripts you can use either absolute or relative location paths in your XPath expression. You can select the stream you want by prefixing the location path with the stream name and a hash # symbol. The following example will count all the Chapter descendants of the 3B2 XML stream called 'stream':

^chapter=^!"count(stream#//Chapter)"

However, the following example does exactly the same thing by moving the cursor to the top of the stream using the ttop command and counting the Chapter descendants from there:

 ttop "stream^chapter=^!"count(//Chapter)"

For more information see the XPath in 3B2 chapter.

7.1.5 

Using Perl in Scripts

It is possible to use Perl together with 3B2 syntax in scripts to further manipulate data.

7.1.5.1 

How to call Perl in Scripts

The perl macro enables Perl to be called directly, outside of any script context. The macro passes everything from the first non-space to the end of the macro line to the embedded Perl interpreter for evaluation.

For more information see the Perl in 3B2 chapter.

7.1.6 

Communication with 3B2: Getvar Codes

Scripts often require information about a user's set-up and document settings, for example, the size of the screen, colour settings and zoom level, current font selections, etc. The getvar macro allows you to extract information from 3B2 about the user's set-up or the state of the current document.

3B2 output commands can be used to display system or document values to the screen or to a variable. For example, to get the document path name or width of a selected frame. The macro wmnx 800 will produce the getvars menu in accordance to the version you are running. Alternatively, getvars can be accessed through the menu [Text/Showstring/3B2 variable (getvar)]

An example of a getvar is when selecting a block of text you can use the current cursor position system variable (21522) to select all text from the start of the text stream to the cursor position.

 getvar 11520, "cur_txt":getvar 21522,"cur_pos" 1
 "^cur_txt",^cur_pos,0^ 2

See also System Variables and getvar

7.1.7 

Creating Lists

The tflist macro gives a script access to a list of files in a directory given a path and wildcard filename. The macro comes in two forms. The first form takes a string parameter which specifies a wildcard filename (including path). It instructs 3B2 to prepare and sort a list of files which match the specified wildcard. It also fills in some predefined variables with various parts of the name of the first file in the sorted list.

The second form takes no parameters and is called repeatedly to fill in the variables with the name of the next file in the list. When the list is exhausted, the variables are emptied (made blank).

The variables that are automatically filled in on each call are as follows:

The variations available are:

tflist will output the path, name and extension

tflistp will output the path only

tflistn will output the name only

tfliste will output the extension only

As an example, suppose this file is the next in the list:

C:\3D\SAMPLE.3D then the tflist macro would set-up these variables:

 ^tflist=C:\3D\SAMPLE.3D 1
 ^tflistp=C:\3D\ 2
 ^tflistn=SAMPLE 3
 ^tfliste=.3D 4

The macro tflist can also be used as a general purpose list getter. The macro takes an optional numerical parameter in front of the string parameter to specify which type of list is required. If the parameter is 0 or not specified then the macro behaves exactly as described in the previous section.

Other values are as follows:

tflist 1,"..." Get a list of document tags

tflist 2,"..." Get an original name

tflist 3,"..." Get a list of fonts

tflist 4,"..." Get a list of 3B2 tokens

tflist 5,"..." Gets a list of all current 3B2 variables

tflist 6,"..." Get a sub-directory list

tflist 7,"..." Get a list of all available printers

tflist 8,"..." Get a list of used fonts

For more information see tflist

7.1.8 

File Examiner

The tfread macro provides the facility to examine a set of variables that have been stored with a document or saved entity (tag) so that decisions can be made about the file, for example whether to open it.

The set of variables to be stored are placed in the file's document comment (in a comment stream for the case of a saved entity) as a sequence of ^var_name=value operators. The tfread macro takes a filename as one of its parameters. It works by opening the file and finding the document comment (or first tag comment) and adding all lines that begin with ^ to the current macro queue, causing all the variables to be set to the stored values.

The tfread macro is most useful when combined with the tflist macro. Each file could be examined in turn to find a particular set of criteria before a file is opened. It is worth noting that if the correct comment type is not found or if it contains no variables then nothing happens. This means that all existing variables will remain unchanged. It is therefore a good idea to set all variables of interest to a known value (usually blank) before calling tfread. It will then be much easier to detect that the file did not contain the required variables.

For more information see tfread

Debugging a Script

Sometimes it is necessary to examine a script that is not working as you intended in development. There are various different methods of locating errors in scripts. The following section describes how to make this process as simple as possible.

8.1 

The trace command

Debugging your script can be assisted by use of the trace macro which enables you to process scripts line by line. It is then possible to change commands as and when necessary. Problem areas can be enclosed within a trace sequence and traced until you locate the problem.

For more information see trace

8.2 

The boxit command

The boxit command is an internal or debugging macro that is used to test elements. This provides a useful way of displaying the value of a particular variable or string on screen, rather than in the text with the insert macro. See @

The macro boxit calls standard 3B2 dialogue box code. Instead of displaying a dialogue box, however, boxit simply displays the individual elements of the dialogue box without their surrounding border.

Note that if you boxit a blank variable you will not see anything. You must enclose variables in quotes or parentheses.

For more information see boxit

8.3 

Output to a log stream

Instead of using the boxit macro, you may instead choose to output the results of each stage of your script to a separate text stream. This can act as a log file that keeps a record of whether each stage of the script was successful. If you wanted to output the contents of a variable to a text stream you could for example include the following lines of syntax in your script:

 ^var=10 1
 ttagmk "tx1.tx" 2
 "tx1 3
 @^var^ 4
 tsavetxt "tx1","c:/Temp/contents_of_var.txt",0 5
1
Specifies that the variable var is ten.
2
Creates the text stream "tx1"
3
Go to the top of text stream "tx1"
4
Outputs the contents of the variable var. See also ^.
5
Saves the text stream "tx1" as a text file called contents_of_var using the tsavetxt command.

8.4 

The Script Bar

There is a script information toolbar that displays information about nested and running scripts.

To enable the Script bar:

— Select script_bar under the drop down lists under the Name: field in the Toolbars dialogue box.

Alternatively, enable the script_bar using the toolbars macro as shown below:

 toolbars "script_bar",4

Below is a description of the information displayed on this toolbar:

— The other boxes provide a view of the callstack of the top ten running scripts.

If you want to keep your new toolbars for subsequent 3B2 runs, remember to use the tprefs macro to save your preferences.

For more information on toolbars and editing toolbars see toolbars and tooledit

8.5 

Modeless Dialogue

It is possible to use a modeless dialogue box as a debugging tool for scripts. Modeless dialogue boxes are interactive, so it is therefore possible to make a modeless dialogue box into a watch dialogue that displays information on the progress of a script, for example if you were loading a file into 3B2 you could use a modeless dialogue to display information on the progress and status of the file being loaded.

For more information on modeless dialogue boxes see the Dialogue Boxes chapter.

8.6 

The debug macro

The debug command is used extensively in the development of 3B2.

It is possible to use debug to debug scripts. The debug macro enables you to write information about a script to an error log. The error log is the serrlog.3at in the 3B2 system directory. Every time 3B2 processes a step in a 3B2 script, the debug command will output the information in its debug log. To view the information in the serrlog.3at file, open the file in a text editor such as Notepad. For more information see debug

8.6.1 

Development Assistant

The development assistant is a set of handy tools to aid template development and access to system information in 3B2. It is a library plug-in that can be installed from the 3B2 CD or downloaded from the support downloads site support.3B2.com.

8.7 

Comments

8.7.1 

Commenting a Script

Adding comments to a script is recommended so that you will know what each piece of the script is doing when you return to the script after a period of time. Comments are represented as pink text and also help others understand what your script is trying to achieve.

There are two ways of inserting comments in a script:

 <!This is a comment>

A <! comment instructs 3B2 to ignore everything from the <! up until the next hard return or the next closing chevron >

 ' This is a comment

A ' (single quote) comment instructs 3B2 to ignore everything from the ' to the end of the line.

Blank lines are also a useful way of separating segments of your script, making it easier to read. Remember that too many comments in a script has a negative effect, making your script harder to read and understand. It is important to strike a balance in this respect.

8.7.2 

Document and Tag Comments

It is also possible to add document and tag comments:

— Tag comments are added with the tcom macro.

When the tag is saved (with tsave), the comment stream is automatically saved with it. If comment streams are to be created externally, for example, by an editor program, or a database, then they must be the first tag in the document (this saves unnecessary searching of long documents). For example, it is best to create a file using 3B2 and then examine the resulting ASCII file.

8.7.3 

Using comments to set script variables

Comments can also be used to make information about a document or tag available to other documents or users. In this case the comment should take the form of one or more variable definitions beginning with a ^ character. These variables can then be examined from within a script by the tfread macro and evaluated.

The tfread command reads document or entity comments from another document. The comment to be read should take the form of a set of variable definitions, which begin with a ^ character. These are then used to set the values of script variables.

For more information see tfread

Multiple Scripts/Chaining Scripts

3B2 scripts can be nested. In other words, a script can start another script, which can then start its own script. There is no limit to the number of nested scripts. It is also possible to use jumps and labels to run the scripts that you want to test. This enables you to jump to a specific section of the script and only run the specified section.

The problem with having one main script is that it is difficult to manage. Trying to debug a large script is very difficult in comparison to debugging smaller scripts. Split your scripts into modules. It is then possible to run each individual module, and when they are all working correctly, you can chain them together.

The primary advantage of splitting one big script into separate scripts is that you can run different sections of it at a time. Having separate scripts makes it easier to test your script as well as making it easier for yourself and others to understand and follow. This in turn means that it is easier to re-use scripts.

When you have successfully created the individual scripts, you will need to chain these together, in the sequence that they should be executed by placing a trun command in the scripts at the end of each sub-routine script.

Note that scripts do not run concurrently, but work rather like separate subroutines in that any script can return to the one that started it.

10 

Mini Scripts

Mini scripts are scripts you can refer to within a tag to allow string manipulation that is not possible with showstrings. Mini scripts are not executed using the trun command but are instead referenced from within your document tags with the following showstring syntax:

<?show $^"*myminiscript">

This means that there are limitations in some aspects to what you can include in them, for example macros and temporary variables will not function.

A simple mini script example would be to crop characters from a variable. In the example below the mini script removes the file extension from a raster graphic name defined by an attribute tag in the text stream and then inserts the result as the name for an anchor reference:

Tx Text: 0(00)c

…<graphic id=picture1-1.tiff>…

Rf graphic: 0(00)c

<?show "^pic_name"$^id#^>
<?show $^[mini mini_1]>
<?show $60#?"$^pic_name^",0$62#>

The following is a description of the above syntax line by line:

1
Shows the contents of the attribute id to a variable called ^pic_name.
2
Process the mini script 'mini_1' (below).
3
Show the resulting ^pic_name variable content to the anchor reference command.
The example above uses the vunction variable method for calling a miniscript, see mini

Sc mini_1: 0(00)c

^pic_name]6..[

The above syntax removes the last five characters, (or, in other words crop from the 6th character from the left).

The resulting ^pic_name variable will now just contain 'picture1-1'.

11 

Script Availability to Other Documents

Scripts which do not use the Script Extension Macros, such as labels, jumps and conditions, can be saved with the tsavetxt command as an ASCII text file and run as a simple macro file using the run macro. It is recommended that you gives these macro files the extension .3m.

Short sequences of macros of not more than 255 characters can be assigned to a single keystroke or the right-hand mouse button using the * macro and saved using the tks command.

Scripts which do use the Script Extension Macros can be put in your user strings file, (usually suser.3ad, suser1.3ad, suser2.3ad). If you have not written any scripts, you will not have a suser.3ad file and will have to create it using any ASCII text editor.

The structure of the suser.3ad file is identical to that of the standard stuk.3ad file supplied with 3B2. Each string begins with a header, followed by the contents of the string on one or more lines, each line beginning with a $ symbol, which is not counted as part of the string. The string ends on the first line that does not begin with $. This is usually a blank line. Line breaks are represented by the characters <>, usually at the end of a line. The <> sequence can also appear within a line, when it will still be interpreted as a line break.

Line breaks are illustrated below:

 $This line has a line break<> 1
 $ This is on one line <> 2
 This is really on the next line <> 3
 $There is no line end here. 4

Strings files can also contain comment lines that begin with a ' (single quote) character. A complete string, with the menu it would produce is shown below:

 'A menu string 1
 "ts","350" 2
 $My Menu<> 3
 $Zoom|wzm<> 4
 $Redraw|wdr<> 5
 $Reformat page|trf:wdr<> 6

For more information see the Dialogue boxes.

1
A comment.
2
String header.
3
Menu definition.

When 3B2 is started, the user strings file is read after stuk.3ad, shuk.3ad and sscr.3ad. It can therefore be used to override any strings in those files simply by re-using the same string number. This is preferable to changing a string in its own file. It will be more difficult to revert to a standard system in case of problems, and will also save you having to duplicate changes when you upgrade 3B2. However, you should still check any strings you have changed to ensure they are still compatible with the upgrade; for example, extra options may have been added to a menu which when overridden by your old string will not appear, or some functions provided by your own scripts may now be available as a new feature.

The startup.3ad macro file is read after suser.3ad. This means that you can include defstr and addstr macros in the startup.3ad file in order to append your own menus to existing 3B2 menus defined in stuk.3ad.

The example below shows a basic startup.3ad macro file, in which a user-defined menu from string 350 in suser.3ad is added to:

 speed 10000 1
 curblink 0,0 2
 addstr 61,350 3
19
Uses the speed macro to configure 3B2 to the speed of your system.
21
Uses the curblink macro to set the cursor blink rate in tenths of a second.
23
Uses the addstr command to add a user-defined menu from string 350 in suser.3ad to string no.61.

12 

Shelling Out to the Operating System

It is possible for a script to operate outside of the 3B2 environment.

The following macro will 'shellout' to 'DOS' and allow you to use 'DOS' commands, for example moving, renaming and creating folders.

The above example will take you completely out of the 3B2 environment and you will not automatically 'bounce back'.
 !

The macro below is the option that is most commonly used. It will 'shell out' and 'bounce back' allowing a script to keep running.

 !!

The following is an example of shelling out to a mail-to with an e-mail addressed to [email protected]

!!start "" "mailto:[email protected]"

The following is an example of shelling out to a website, in this case documentation.3b2.com

!!start "" "http://documentation.3b2.com"

For more information see !

13 

Cross-platform functionality

This manual is designed to support all versions of 3B2. Script developers will usually wish to provide for a measure of cross-platform compatibility and, on the whole, this is rarely a problem when writing for platforms. (other than the Mac pre 3B2 version 7 as is no longer supported.

A small number of macros available on the PC are not available or work differently on the Mac (pre version 7), and vice versa. The rules for defining dialogue boxes and menus may also vary slightly. These differences do not, however, affect the overall functionality of scripts. Essentially, if it can be done on one platform, it can be done on the other.

The stuk.3ad file supplied with 3B2 is shared between each version. Strings which are not suitable for certain platforms special string headers restricting their availability. The illustration below shows the platform variations in string no.5 from the stuk.3ad file:

 '**** clip file(s) path+name 1
 "ts","5" 2
 #if UNIX 3
 $./3d/clip 4
 #elseif OCX 5
 ${@}3d/clip 6
 #else 7
 $/3d/clip 8
 #endif 9

13.1 

Mac functions not available on the PC

Dialogue boxes on the Mac can include radio buttons, conforming to the Mac interface. If you want to make a script available to both PC and Mac you should specify radio buttons (field_type: r> regardless of which platform you are using.

The Mac can call a Save dialogue box. If you want to make a script available to both PC and Mac you should specify (selector: !?4!). On the Mac this invokes the Save dialogue box. On the PC it will simply invoke the directory picker (selector: !?5!).

Post 3B2 version 6.05 the Mac OS supported was discontinued.

14 

Useful System Files

The following files are useful when developing scripts:

File

Description

stuk.3ad

3B2 menus and dialogue boxes in ASCII format

suser.3ad, suser1.3ad, suser2.3ad

If the stuk.3ad is changed, save it as suser.3ad as this will not be overwritten when a new release of 3B2 is loaded. See Changing the name of your user scripts file

shelp.3ad

3B2 arguments and definitions

startwin.3ad

Start-up preferences, for example keyboard layout

sscrwin.3ad

File for point of reference - user scripts, for example, trun 900

15 

Script Examples

Without detailed descriptions or comments in your script it can be very time consuming to decipher exactly what it is doing, as with the examples in the sscr.3ad or sscrwin.3ad files.

The following scripts are commented line by line to give you an overview of general script structure and some insight to how each component works.

It contains the elements talked about this manual and even if your script is designed for an entirely different task, the following examples should prove a good reference for syntax examples.

15.1 

Basic Script Example

This simple script inserts text and a processing instruction at the current cursor position and then invokes the Print dialogue box. After the script there is a line by line description:

 tf "Times-b" 1
 @Hello World! 2
 tf "arial-i" 3
 #13 4
 @How's it going? 5
 tprint 6
1
Defines the typeface as Times Bold.
2
Inserts the text 'Hello World!' at the current cursor position.
3
Changes the typeface to Arial Italic.
4
Insert a hard return.
5
Inserts the text 'How's it going?'
6
Invokes the Print dialogue box.

15.2 

Search and Replace Script Examples

This script example contains multiple search and replace routines. It also makes use of regular expressions within the search and replace routines to enable more complex and exact search and replace options.

For more information see / and Regular Expressions

The script is in three separate strings, with line by line description after each section:

 /<stuff id="things">([a-z]*)<\47\stuff>/<otherstuff>\\1<\47\otherstuff>/ctgr
1
The first / searches for the tag <stuff id="things">. The regular expression ([a-z]*) looks for any characters from a to z up until the closing </stuff> tag 0 or more times.
2
The second / replaces the stuff tags with the otherstuff tags while leaving all the information between the tags unchanged using the \\1 syntax.
The end tag (</stuff>) has to be entered into the script as <\47\stuff>, this is due to the special character / (forward slash) being part of a search string. \47\ is the ASCII value for the forward slash character. This is then replaced with the tag <otherstuff> while keeping everything the same up until replacing the end tag with </otherstuff>

Another example of a regular expression in a search and replace routine is when you want to replace <stuff=x,x> to <things="x","x"> where the x are numeric values that can change:

 /<stuff=([0-9]+),([0-9]+)>/<things="\\1","\\2">/tgcr
 :loop 1
 /<this_tag>/<that_tag>/c1 2
 getvar 21526,"found_this_tag" 3
 ?=^(^found_thistag),^(0)}exit 4
 /<\47\this_tag>/<\47\that_tag>/c1 5
 {loop 6
 :exit 7
1
Specifies the loop label.
2
Search for <this_tag> and replace with <that_tag>
3
Populate the variable ^found_thistag with the number from the search and replace results (Either 1 for positive or 0 for nothing).
4
Test if the last search and replace found anything, i.e. if the variable ^found_thistag contains the value 0 then jump to the exit label.
5
Search for </this_tag> and replace with </that_tag>
6
Jump to the loop label and repeat the process.
7
The exit label.
 tsavetxt "^curr_strm","C:\myfolder\^curr_strm.xml",1^ 1
 tend "log 2
 @^curr_strm^ 3
 @.xml 4
 #13 5
1
Save the current text stream named in the variable curr_strm out to an external .xml file in the location C:\myfolder\
2
Go to the end of the stream called log.
3
Insert the text stream name, in this case the value of the variable curr_strm.
4
Add .xml to the end of the stream name.
5
Insert a hard return

15.3 

Multi-function Concurrent Script Example

The following script has been designed to cut sections of text between user designated tags, and paste it into individually named text streams assigned to anchored frames, while only placing two frames to a page.

This script was originally designed, primarily with tables or figure captions in mind. In this case using <table> as the start tag and </table> as the end tag. The script appears as it would in the suser.3ad file.

The script is in five separate strings, '350' to '354' with line by line description after each section.

Each of the separate strings are summarised below:

350
Invokes the Setup dialogue box, where the start and end tags are specified, along with the naming requirements for the text stream(s), Anchor name(s) and the position for the frames to be placed on the page. The position of the frame placement can be set automatically, using the current position of the main underlay frame on the template, retrieved using the appropriate getvar code. If this is to be used on various templates you must therefore ensure that they will comply with your script, i.e. same underlay name etc. Alternatively if no co-ordinates are specified, the positioning of your frames can be done when formatting your document.
351
Invokes a menu that displays the quantity of start and end tags in the text stream. As it stands this script will not work correctly without corresponding pairs of tags to extract from.
352
First stage of the extraction, make the frames and assign the text stream anchor name and frame gap, while placing only two frames per page utilising string '354'.
353
Second stage, cut and paste text into corresponding streams.
354
This will simply page down and reset the variables, when run from string '352'.

The screenshot below shows the resulting dialogue box from string '350':

 "ts","350" 1
 $^depth?15<> 2
 $^width?0<> 3
 $^down?0<> 4
 $^across?0<> 5
 $^extstrt?<> 6
 $^extend?<> 7
 $^asigntxtnm?<> 8
 $^asignanchnm?<> 9
 $defstr 390,"|Extract on tags of your choice\n"<> 10
 $addstr 390,"Frame values and denomination:\n"<> 11
 $addstr 390,"Frame width {^width%1..10s\n"<> 12
 $addstr 390,"Frame position down ^down%1..10s\n"<> 13
 $addstr 390,"Frame position across {^across%1..10s\n"<> 14
 $addstr 390,"-\n"<> 15
 $addstr 390,"Extract start tag {^extstrt%1..20s\n"<> 16
 $addstr 390,"Extract end tag {^extend%1..20s\n"<> 17
 $addstr 390,"Text strm name (for example: Fig? Tab?){^asigntxtnm%1..20s\n"<> 18
 $addstr 390,"Anchor names (for example: F? or T?){^asignanchnm%1..20s\n"<> 19
 $addstr 390,"-\n"<> 20
 $addstr 390,"|%2..1e [Continue] [Stop] \n"<> 21
 $wdb 390<> 22
 $?^wdb,^1) trun 0<> 23
 $trun 351<> 24
1
Defines this section as string number '350'
2-9
Re-sets variables, the ^depth variable being the default frame depth.
10
Defines the header string for the dialogue box, see defstr and addstr.
12-14
Define field(s) in the dialogue box where the value of the ^width, ^down and ^across variables can be assigned from the dialogue box.
16-17
As lines 12-14 assigning the contents of ^extstrt (start tag) and ^extend (end tag) variables. Note the end tag (</table>) has to be entered into the dialogue box as <\47\table>, this is due to the special character being part of a search string, \47\ being the ASCII value for the forward slash character.
18-19
As above assigning the contents of ^asigntxtnm (text stream name) and ^asignanchnm (anchor name), to be followed by the current extraction number ^no_find in string '352'.
20
Defines a grooved line across the dialogue box.
21
Defines the 'Continue' and 'Stop' radio buttons, returning a value of either '2' or '1' respectively to the ^wdb variable.
22
Must always be set, as it tells 3B2 to invoke the relevant dialogue box string number. See wdb
23
Tests if ^wdb equals 1 (i.e 'Stop' was pressed), if so stop the script.
24
If 'continue' was pressed, trun the next stage.
 "ts","351"$/^extstrt/ctgi^<> 1
 $getvar 21526,"no_strt"<> 2
 $/^extend/ctgi^<> 3
 $getvar 21526, "no_end"<> 4
 $defstr 390,"|CAUTION \n"<> 5
 $addstr 390,"Ensure you are in the txt strm you want to extract \n"<> 6
 $addstr 390,"from and only continue if equal numbers of tags\n"<> 7
 $addstr 390,"-\n"<> 8
 $addstr 390,"^extstrt%1..15t}tags ?{^no_strt%1..5t\n"<> 9
 $addstr 390,"^extend%1..15t}tags ?{^no_end%1..5t\n" <> 10
 $addstr 390,"-\n"<> 11
 addstr 390,"If run accidentally key 'esc' trun 0\n"<> 12
 $addstr 390,"abandon changes and re-start\n"<> 13
 $addstr 390,"-\n"<> 14
 $addstr 390,"|%2..1e [Continue[ [Stop[ \n"<> 15
 $wdb 390<> 16
 $??^wdb,^(1) trun 0 17
 $trun 352<> 18

The screenshot below shows the resulting menu from string '351':

2-3
Search for the contents of the ^exstrt variable (start tag), defined in the previous dialogue box, using search options: by character 'c', from the top 't', global 'g' and ignore case 'i'. Then show the result of this find to the ^no_strt variable, using the getvar code 'v21526' (last search and replace number, find count). See /
4-5
As above with the ^extend variable.
10-11
Displays the contents of the 'tag name' variables assigned in the dialogue box, and the number of occurrences in this text stream, i.e. the ^no_strt and ^no_end variables above.
12-19
Additional text lines in menu, exit buttons and conditions as in previous.
 "ts","352" 1
 $^no_find?0<> 2
 $tpgoto +1<> 3
 $getvar 11520,"strm"<> 4
 $ttop "^strm"^<> 5
 $^no_find=^no_strt<> 6
 $^pg?0<> 7
 $:loop<> 8
 $?^(^pg),^(2) trun 354<> 9
 $^pg+1<> 10
 $^down+^(^depth+1)<> 11
 $?^(^no_find){exit<> 12
 $tfmk ^across,^down,^width,^depth^<> 13
 $tfgap 1,1,1.5,1.5<> 14
 $tfanchor "^asignanchnm^no_find"^<> 15
 $tft "^asigntxtnm^no_find"^<> 16
 $^no_find--<> 17
 $}loop<> 18
 :exit<> 19
 $trun 353<> 20
2
Re-set the variable ^no_find to 0.
3
Page down once.
4
Set the name of the text stream the cursor is currently in to the ^strm variable.
5
Go to the top of ^strm.
6
Set the variable ^no_find to the same value of ^no_strt from the previous script, (alternatively another search could be set).
8
The 'loop' label.
9
If the ^pg variable is '2' (two frames have been made), then trun string '354' which will page down for the next placement and reset the ^down variable so the position will be the same on each page. The ^pg variable can only have the value of '2' once the script has returned to the 'loop' label twice. As above the label, it is re-set to '0' and below this line it is incremented by '1'. Note string '354' is ended with trun -1 therefore it will return one level back, to this script.
10
Increment the ^pg variable by '1'
11
Add the value of ^depth variable plus '1' to the ^down variable so the frames are not overlapping when placed.
12
If ^no_find is '0' (no start tags where found), goto the exit label.
13
Make a frame using the values defined in the dialogue box.
14
Set the frame gap. (Dependent on the document preferences measurement settings unless otherwise defined).
15
Set the Anchor name for the frame using the contents of ^asignanchnm defined in the dialogue box and the current value of ^no_find.
16
Make a new text stream using the same process as above.
17
Decrement the value of ^no_find for the next frame assignments, as the way the script is designed means it will extract and place the text in reverse order. Until document formatting occurs with anchors in the text, to place the frames with there corresponding reference. See trefanc
18
Jump back to the corresponding label 'loop'.
20
trun the next stage
 "ts","353" 1
 $^ext?0<> 2
 $^found?0<> 3
 $:loop<> 4
 $ttop "^strm"^<> 5
 $^ext++<> 6
 $/^extstrt/tcsi^<> 7
 $getvar 21526,"found"<> 8
 $/^extend/cei^<> 9
 $?+^(^found),^(0)tcut<> 10
 $"^asigntxtnm^ext^<> 11
 $?^(^found),(0){exit<> 12
 $tpaste<> 13
 $}loop<> 14
 $:exit<> 15
 trf<> 16
 $wdr<> 17
 $trun 0<> 18
2-3
Re-set the variables to 0.
4
The 'loop' label.
6
Increment the ^ext variable by 2, so the cut text is pasted into the correct stream, used on line 11.
7-8
Search for the start tag, this time including the 's' (select) search option and show the result to the ^found variable.
9
Search for the end tag. (Now selected from the last search up to this).
10
If found is greater than '0' cut the selected text. Without this test, the tcut macro will cut one character off the beginning of the stream.
11
Edit the text stream defined by the contents of, ^asigntxtnm and ^ext variables.
12
If ^found is '0' jump to the 'exit' label.
13
Paste the text, using tpaste
14
Jump back to the 'loop' label.
15
The 'exit' label.
16
Reformat page using the trf command (this and the line below can be combined to simplify you script i.e. trf:wdr
17
Redraw the page with the wdr command.
18
Stop the script using trun 0
 "ts","354" 1
 $^down?0<> 2
 $tpgoto+1<> 3
 $^pg?0<> 4
 $trun -1 5
2
Re-set the ^down variable to 0.
3
Page down once.
4
Re-set the ^pg variable.
5
Return one level to the previous script.

See also Dialogue Box chapter.

16 

Miscellaneous Notes/Tips and Tricks

16.1 

Turn Screen Display Off

When you run a script you will notice how the screen flickers as the document formats. This marginally increases the time it takes for a script to run. If it is necessary to reduce the time it takes for a script to run to this extent, simply use the draw command to turn 3B2's screen redraw off.

16.2 

Slow down scripts

Occasionally 3B2 runs a script too quickly for itself to keep up with. If you find that the script is not working properly at any one point, it may need to be paused. You need to insert a trun +10 command which will suspend a script until 3B2 is truly idle. This will cause 3B2 to pause until it has executed all the macros in the pending macro queue.

For more information see Suspending a Script

16.3 

Turning off ttundo

The macro ttundo specifies that a given text stream should record undo information of the latest changes that were made to the document, prior to saving.

If you turn ttundo off while running a script, (i.e specifying ttundo 0 at the start of your script), 3B2 will not record the changes that are made to your document so that they can be undone. As a result your script will run faster.

Another useful aspect to the ttundo macro is that it is stream independent, so it only affects the text stream for which it is specified. This means that ttundo 0 can be specified only for your script and not the main text stream in your document so that undo changes for the main document are still possible.

17 

Further Information and References

17.1 

Associated documentation

—  tflist

—  run

—  !

— 'Codex scriptorium' documentation from the support downloads site support.3B2.com.

18 

Subject Index

Subject index only applicable to the PDF version.

Document created on 01-Jan-2002, last reviewed on 06-Sep-2005 (revision 6)