A script is text document that contains a list of commands for a computer system. By recording the commands in a text document they can be replayed over and over again without having to be re-entered by hand. This is particularly useful when command entry is slow or limited, such as on a handheld.

pedit has powerful scripting facilities, but like many of its more powerful facilities the learning curve is pretty steep. The pedit manual includes around 43 pages of documention which give all the pScripting details, but they are a little intimidating.

This tutorial assumes general experience of using pedit, but no previous scripting or programming experience should be necessary.

The scripts in this tutorial have been tested with peditPro 7.15 but the pedit family are updated frequently.

Since users can customize pedit to use different escape characters I’ve followed the manual’s convention and used ESC to indicate the escape character. You will need to replace ESC in the example code by the escape character you have configured.

Entering Scripts

A pedit script, or pScript, consists of a script name followed by a list of pedit inputs. Invoking the script feeds the list of inputs to pedit as if they had been entered by the user.

pedit provides a single scriptPad; a separate edit area, similar to the magiPads. A menu option is provided for a scriptPad switcher, but at the moment only one scriptPad is supported. To go to the scriptPad do one of the following:

From a Memo:

  • Select scriptPad in|out from the Pad menu
  • Slide up from the [M] button
  • Enter ESC M

From the List View:

  • Select scriptPad... from the Navigate menu
  • Slide up from the [Recent] button
  • Enter ESC M

scriptPad is a special instance of magiPad and has the same menus and buttons. It can hold up to 32 Kbytes of pScripts.

Each pScript has the following structure:

{pScriptName::pScriptText}

The pScript is delimited by curly brackets.

pScriptName should be a unique name for the pScript. pedit can handle scripts with identical names but it is simpler to keep each unique.

The pScriptText - everything between the double colon and the closing curly bracket - is the list of inputs to pedit that will be replayed when the script is invoked. This can be up to 55 characters long. Any white space, that is spaces, tabs or linefeeds (marking the ends of a lines), are ignored and do not count towards that 55 characters.

pedit's scriptPad

pedit’s scriptPad

For example, suppose that you keep a daily journal in peditPro and that each day’s entry begins with the date in the format:

29-Dec-2004 Wednesday

But you find it tedious to enter the day name each day. Instead of entering ‘Wednesday’ it would be so much quicker to run a ‘we’ script. So you select scriptPad in|out from the menu and enter the following:

{we::Wednesday}

and then click on the [OK] button.

To run the script position the cursor where ‘Wednesday’ needs to be entered and do one of the following:

  • Select Script Memo... from the Rec menu
  • Slide down from the [Q] button
  • Type ESC &

pedit's scriptName dialog

pedit’s scriptName dialog

A ‘scriptName’ dialog will appear at the bottom of the screen. Enter we and click on [:D] to run the script. ‘Wednesday’ will be inserted at the cursor as a result of four stylus strokes instead of nine.

Any text in scriptPad outside of curly brackets is ignored, making it easy to add comments explaining what each script does. This may seem pointless for simple substitution scripts like ‘we’ but pScripting is addictive and you’ll be amazed by how soon you will be writing complex scripts that are not so easy to read and understand.

White Space

After using the ‘day name’ pScripts a few times you notice that you always have to enter a space after the year before calling the day name script. So why not update the script to put a space before the day name?

{we:: Wednesday}

But, as mentioned above, white space is ignored so the space character has no effect. In cases where white space does need to be entered three special commands allow white space characters to be sent to pedit:

  • /xs sends a space
  • /xt sends a tab
  • /xn sends a linefeed

So, updating your script to:

{we::/xsWednesday}

will have the desired effect, by explicitely feeding a space character to pedit before the day name.

Since white space is normally ignored it can be used to layout pScripts in a more readable manner, by placing each command on a different line. For example, it is easier to see what’s going on in our ‘we’ script when laid out as follows:

Script to insert 'Wednesday'
{we::
  /xs
  Wednesday
}

pedit Commands

As well as text and white space, a script can contain pedit commands that are played back to drive the editor when the script is invoked. Let’s assume that after using the ‘day name’ scripts for a few more days you suddenly realise that you always insert the date before calling one of the scripts. Why not get the script to insert the day too?

The pedit ESC 6 command inserts the date and time, so we can update the ‘we’ script as follows:

Script to insert ' Wednesday'
{we::
  ESC 6
  /xs
  Wednesday
}

Remember to replace ESC by whatever escape character you have configured in the General tab of the Preferences... dialog. On my machine the escape character is ‘;’ and so the script reads:

Script to insert ' Wednesday'
{we::
  ;6
  /xs
  Wednesday
}

Any pedit command accessible via the escape character can be issued in this way. For example the following script will hit [OK] to exit the current document, create a new one and insert the date for a new journal entry:

Script to start Wednesday Journal in new document
{nwe::
  ESC o
  ESC n
  ESC 6
  /xs
  Wednesday
}

ASCII Characters

One problem with the new version of the ‘we’ script that inserts the date, is that it also inserts the time, destroying the classical elegance of the journal title. We need to update the script to go back and delete the time before inserting the day name.

Like everything in pedit, there is at least 17 ways this can be achieved. One way is send backspace characters to pedit, to cause it to delete the eight characters of the time. We can leave the space between the date and time, saving the script from having to explicitely output it.

Control characters, such as cursor moves and backspaces, cannot be entered directly into the script - they will just edit the script itself. Instead any character can be entered into the script for replay to pedit by specifying its hexadecimal (base 16) ASCII code. The ASCII encoding is a standard for allocating numerical codes to the characters that can be handled by a computer.

To find the ASCII code for a character supported by pedit do the following:

  • Select ASCII Table... from the Ed+ menu
  • pedit will display the 256 ASCII characters it supports
  • Highlight a character and click on the [Q] button.
  • The pedit values... dialog will be displayed. Click on [Next].
  • The top line of the dialog will display the character details.
  • Click [.Cancel]

For the character ‘A’ the pedit values... dialog will display:

'A' = 0x0041 = 065

065 is A’s ASCII code in decimal.

Encoding details for 'A'

Encoding details for ‘A’

Ox means that the following number is in base 16. 0041 is the base 16 value for ‘A’ in Unicode, but the last two digits are the same as the code for ASCII. Note that base 16 needs 6 more digits than base ten, so in this context A..F are digits not letters!

So from the above we can see that entering /0x41 into a pScript will send an ‘A’ character to pedit. Like in /xs, the slash indicates that the next character indicates a command rather than the character itself.

Certain ASCII characters are interpreted by pedit as cursor movement commands, for example:

  • /0x08 means backspace
  • /0x0B means page up
  • /0x0C means page down
  • /0x1C means cursor left
  • /0x1D means cursor right
  • /0x1E means cursor up
  • /0x1F means cursor down

So issuing eight backspaces will remove the time from after the date:

Script to insert ' Wednesday'
{we::
  ESC 6
  /0x08 /0x08 /0x08 /0x08
  /0x08 /0x08 /0x08 /0x08
  Wednesday
}

55-Char Limit

In the first part of this tutorial it was mentioned that the pScriptText part of a pScript - that part that is replayed to pedit when the script is run - is limited to 55 characters.

This wasn’t entirely accurate. The Palm operating system maintains a 55 entry queue for text input to an application. When the user enters text via Graffiti or a keyboard the character codes are appended to the key-event queue at one end, and the application reads them from the other. The use of a queue means that characters are not lost if received from the user before the application is ready to read them. Up to 55 characters can be waiting in the queue for the application to handle them. This is why you can sometimes type ahead of pedit when it is updating the display, but the characters you enter are not lost.

pScripts make use of this key-event queue to feed commands and data into pedit. When the pScript is run it interprets the commands and writes the characters to the key-event queue. When the end of the script is reached, or the queue is full, control is passed to pedit which reads the key codes from the queue and processes them.

As you have probably realised multi-character commands in the pScript, such as /xs may result in only one character being added to the key-event queue. Let’s take a look at the last pScript we wrote and work out what it places in the key-event queue:

Script # Key-event Queue
{we::
; 1: ;
6 2: 6
/0x08 3: <Backspace>
/0x08 4: <Backspace>
/0x08 5: <Backspace>
/0x08 6: <Backspace>
/0x08 7: <Backspace>
/0x08 8: <Backspace>
/0x08 9: <Backspace>
/0x08 10: <Backspace>
W 11: W
e 12: e
d 13: d
n 14: n
e 15: e
s 16: s
d 17: d
a 18: a
y 19: y
}

So although the pScriptText is 51 characters long, it only appends 19 key codes to the key-event queue. The pedit manual lists the number of characters that each command or token adds to the queue.

Under some versions of the Palm operating system the size of the key-event queue can be increased with the /&setKeyQSize pFunction. However, this facility is no longer available under PalmOS 5+.

Immediate pFunctions

The last section mentioned a pFunction. pedit has numerous pFunctions that can be called from within pScripts to provide a wide variety of special services - everything from date handling to simulating Graffiti actions. Although we will cover numerous pFunctions in this tutorial series, we will only scratch the surface of the full range available. See the pedit manual for full detail.

pFunctions are all called with the following syntax:

/&pFuncName [pFuncParams]

where pFuncName is the name of the function and pFuncParams are a list of parameters (that may be empty).

As you will see from the pedit manual many of the functions have two or three versions. For example, the /&pscript[] function that is used to call another script has three versions:

  • /&pscript@[] - ‘immediate’ or ‘right now’ version
  • /&pscript[] - ‘runtime’ version
  • /&pscript$[] - ‘last action’ version

The versions only differ in at what point in the running of the script they are processed. In this section we will only consider the ‘immediate’ pFunctions.

When a script is being run pedit will process ‘immediate’ pFunctions at the point at which they appear in the script. Consider the following:

{test1::
   This /xs tests /xs how /xs
   /&script@ [@@test2@@]
   are /xs invoked.
}

{test2::
   pfunctions /xs
}

When test1 is invoked pedit processes the first line, adding each character of ‘This tests how ‘ to the key-event queue. It then processes the /&script@[] pFunction. This tells pedit to temporarily stop processing the current script and run the script named within the square brackets. In pScripts @@ is used as the delimiter for pStrings - they indicate the start and end of a lump of text that is to be considered as a single entity. In this case the pString is the name of the pScript to be run.

pedit runs the test2 pScript, which results in pFunctions being added to the key-event queue. When the test2 pScript finishes pedit goes back to where it left off in the previous pScript. So it then adds ‘are invoked.’ to the key-event queue.

At this point, the test1 pScript has finished and there are no other scripts being processed, so pedit starts work on processing the contents of the key-event queue. It reads each character that has been queued and inserts it into the text being edited. The result is:

This tests how pFunctions are invoked.

So how do we use this exciting new ability to call one pScript from another in the real world? Going back to our ‘day name’ script example, we had seven individual scripts:

{mo::
  ESC 6
  /0x08 /0x08 /0x08 /0x08
  /0x08 /0x08 /0x08 /0x08
  Monday
}

{tu::
  ESC 6
  /0x08 /0x08 /0x08 /0x08
  /0x08 /0x08 /0x08 /0x08
  Tuesday
}
...

We have the same piece of code to output the day, month and year repeated for each day of the week. This is inefficient for three reasons:

  • It is a waste of time entering the same code seven times. We want to enter it only once.
  • It is a waste of space to store the same piece of code seven times.
  • When we want to update the code (and we will) we want to change it just once in a single place.

The obvious solution is to move the code that outputs the day, month and year out into a separate pScript and call it from each of the day name pScripts. For example we can update the example to:

{date::
  ESC 6
  /0x08 /0x08 /0x08 /0x08
  /0x08 /0x08 /0x08 /0x08
}

{mo::
  /&script@ [@@date@@]
  Monday
}

{tu::
  /&script@ [@@date@@]
  Tuesday
}
...

This is much neater and efficient, especially when, leafing through the pedit manual, we discover that there are a series of /d, /L and /E tokens that output different parts of the date. These include:

  • /dD - which outputs the day of the month.
  • /Lm - which outputs a three letter abbreviation of the month in the local language set on the Palm.
  • /dY - which outputs the year as four digits.

So we can make our date pScript more efficient by rewriting it (just once) as:

{date::
  /dD-/Lm-/dY /xs
}

and the seven ‘day name’ pScripts do not need to be changed to take advantage of the new code.

Finally, you may have noticed while perusing the pedit manual section on /d and related tokens, that /LD adds the name of the current day to the key-event queue. This means that all our individual day name pScripts are redundant and that all we need is:

{ds::
  /dD-/Lm-/dY /xs /LD /xn
}

Note that we add a linefeed at the end so that user can start entering the diary text on the next line.