Humanities Home page   Office of Digital Humanities
Back     BYU LiveCode Lessons Gateway

Digital Humanities & Technology 210

A New Way of Opening Stacks

Since we learned about file paths, external files, and the URL keyword in the last lesson, we can now introduce a new way of accessing remote stacks from anywhere on the internet. If you have LiveCode running, and you have a connection to the internet, you can open any stack on any web server, simply by referencing its URL. For instance, there is a stack called "TextLecture.rev" on this web server at the address:

http://livecode.byu.edu/textfind/TextLecture.rev
This stack contains many examples of the concepts being discussed in this reading. To open this stack in LiveCode, simply enter this command in the message box:
go to stack URL "http://livecode.byu.edu/textfind/TextLecture.rev"
LiveCode will find it on the internet and download it into memory on your computer. When you're finished with it you can simply close it, or you can choose to save the stack to your local disk.

For the remainder of the term you will often see references to example stacks in the readings. Any of those stack references can be accessed as described above.


Working With Text

Objectives

By the end of this reading you should know the following:

  1. Understand how the following text chunks are defined in LiveCode:
  2. Know how to refer to chunks of text in a LiveCode scripting statement.
  3. Understand the difference between the word and trueWord text chunks.
  4. Understand how to use a function in a LiveCode scripting statement.
  5. Remember the various ways to do boolean comparisons with text.
  6. Know how to do text string searches using the offset functions.
  7. Be aware of the find command and how to use it.
  8. Know how to use selection functions, click functions and mouse functions in a LiveCode Scripting statement.

The example stack for this section can be accessed at http://livecode.byu.edu/textfind/TextLecture.rev. To access it enter in the message box:

go to stack URL "http://livecode.byu.edu/textfind/TextLecture.rev"

Text Units

LiveCode recognizes some basic units of text: characters, words, lines, etc. While our human definition of these units can be a bit fuzzy, LiveCode defines these terms in a precise way:

Text Chunks

A chunk is LiveCode’s generic term for a substring of a longer text string; i.e., runs of text described by the units characters, words, lines, etc. You refer to chunks of text by specifying the sub-units as needed. For example, the statement

select trueWord 5 of line 3 of field "myField"

will highlight the fifth trueWord of the third line of the field.

LiveCode recognizes the ordinals first through tenth, which means that fourth word means the same as word 4 (i.e., they are functional equivalents, the former being slightly more readable).

Here are some other useful modifiers for referring to chunks:

You can specify a range of text using the to keyword. For example, word 5 to 7 or char 14 to 29. Note that you do not repeat "word" (e.g., you don't say word 5 to word 7 and you do not use an "s" in the character range (e.g., you don't say chars 14 to 29 but you do say char 14 to 29).

Text Functions

LiveCode provides some useful functions you can use to handle text

Offset Functions: Finding Text Inside of Longer Texts

Offset locates a pattern string in a larger string, for example:

put offset("crown",field "whatever") into myVar

where "crown" is the string you are looking for and field "whatever" is the container you are searching in.)

Note the following features of the offset function:

There are four other related offset functions:

These all work the same as offset, except instead of returning the number of characters from the beginning of the search container, they return the number of items, lines, words, or trueWords, respectively, from the beginning of the string to the first occurrence of the search string. These functions are extremely useful, for instance, for discovering what line in a container a certain word is found on. The offset functions are also the only way to search for strings in variables rather than fields.

Offset Functions: An Example

Here is an example of the use of the lineOffset function:

Problem: Find the first line where the word "red" appears in field "colors". Let's say the field "colors" contains the following:

  blue
  pink
  orange
  green
  red
  black
  yellow

The statement:

put lineOffset("red",fld "colors") into theLine

will return the value 5 to the variable theLine.

But what if you want to find just the whole word "red" in a field with the following contents:

  blue
  pink
  reddish orange
  orange
  green
  red
  black
  yellow

The statement above would match line 3 first instead of line 6. To force the lineOffset function to only match lines where the word "red" appears by itself, use the wholeMatches property:

  set the wholeMatches to true
  put lineOffset("red",fld "colors") into theLine

Now the result returned is 6, as desired, rather than 3. Keep in mind that the wholeMatches property only keeps its value for the duration of the current handler. When the handler ends, wholeMatches is set back to false. This property also works with the itemOffset and wordOffset functions in cases where you only want to find items or words that exactly match the search string.

Text Boolean Operators—Comparing Strings

There are several boolean operators that allow you to make true/false comparisons between strings or containers holding strings:

is in
is not in
contains
is among
is not among
begins with
ends with

The text boolean operators is in and contains allow you to test for a pattern in a text string. Both have the same purpose and they reflect the logic of English syntax. For example, the expressions:

if "bob" is in fld 1 then beep

and

if fld 1 contains "bob" then beep

say exactly the same thing. Case is ignored (it can be capitalized in the field and not capitalized in your script), but accents are not. Spaces and punctuation are not ignored, either. It handles empty in a predictable way: a field with anything at all in it does not contain empty.

The inverse of is in is the operator is not in.

The operators begins with and ends with are similar to the contains operator, except that they only report true is the string you're testing for comes at the very beginning or the very end of the string being checked.

put "My dog has fleas." into tRover
if tRover begins with "my dog" then -- this condition is true
put "Get me a ." into field "dog" end if if tRover ends with "fleas" then -- this condition is false because the sentence ends with a period--"...fleas." put "flea collar!" after field "dog" end if

The operators is among and is not among allow you to check for the presence of text strings by looking at specific text chunk types. For example, referring to the color list example above, if I wanted to know whether one of the lines contained exactly the string "red" I could use:

  if "red" is among the lines of field "colors" then
   <do stuff>
 end if

This would only be true if one of the lines of field "colors" held exactly the word "red", with nothing else on the line.

You can also use is [not] among with the chunk types words and items. The expression:

"hello" is among the items of field "stuff"

  would return true if field "stuff" contained this text:

there,are,many,words,hello,here

  but would return false if field "stuff" contained this text:

 there,are,hello world,also,here 

The negative expression:

"world" is not among the words of field "otherstuff" 

  would return true if field "otherstuff" contained the text "many wordly pleasures";

  but would return false if field "otherstuff" contained "The pleasures of the world beckon."

Find Command

An example stack for the find command, selection functions and click functions sections can be viewed by entering in the message box:

go stack URL "http://livecode.byu.edu/textfind/FindLecture.rev"

In most cases the offset functions described above provide all the search capability you need. However, there may be some cases when you need to specify very exacting search requirements, such as the need to search for two words in some text that are not adjacent to each other. In these cases you may want to look at the find command. The find command is a formal LiveCode command used to locate a certain string or strings in the fields within a stack. This is the basic syntax:

find [form] <textToBeFound> [in field]

where

[form] is any of the form words described below.
<textToBeFound> is any expression that evaluates to a string.
[in field] a specfic field optionally specified in which the search will be confined.

When the command is executed, LiveCode places a box around the first instance of the string that it locates. It keeps track of latest find, and subsequent finds continue from most recent. Otherwise it begins with the first field on the current card. The command follows a certain hierarchy as it searches: first, grouped fields in order; second, non-grouped fields in order; then on to subsequent cards.

As stated earlier the search can be confined to a specific field. When no field is specified, LiveCode finds the first occurrence in search order. With a field specified, then the search is confined to that field alone. If not found and the field is part of a group, then it continues searching that field on subsequent cards.

The form find empty clears the current find operation, meaning a subsequent search will begin all over again in the search hierarchy, rather than beginning from the most recently found text. Consequently, the box drawn around the text found is removed.

There are five forms of the find command:

Find uses a complex technique to speed searching through large amounts of data. However, its behavior with the different forms may seem somewhat peculiar when the search text consists of more than one word (i.e., it contains a space). With normal, chars, and word, LiveCode breaks the search into words and performs a subordinate search as necessary: It looks for first word and then looks for the second word within same scope. That is, if a field is specified, they must be in the same field; otherwise they can be present on the same card for the search to be successful. Note: the found word rectangle is placed only around the first word. The other two forms (string and whole) do not break this way (but also do not take full advantage of search speed).

Found Functions

The find command, if successful, results in a box being drawn around the text found. This is done to give a visual indication of where the found text is on the card. Often we also want access in a script to the chunk of text that was found. Several functions exist to achieve that end:

If the search is not successful (i.e., the text was not found), then not found is returned in the result function.

The Select Command and Selection Functions

While a specific text string may be located using the find command or the offset functions, it is not automatically selected, the way it must be, for example, before you can cut or copy the found text. In order for that to happen, you must use the select command. With the select command you can select text using any of the text chunk expressions that we have looked at in this lesson. Here is the basic format:

  select text chunk of field field name

So, for example:

  select char 5 to 10 of field "sourceFld" 

This command selects a chunk of text the same as if you clicked in the field and dragged the mouse across the text. You can then do cut, copy, or paste operations, or change text attributes, etc. You can use the select command on any field, even a locked one, as long as the field’s traversalOn property is true (indicated by the "Focusable" checkbox in the field property inspector.) Of course, only operations that don't affect the field’s content, such as "copy", can be performed on locked fields.

Once text is selected, there are five functions you can use to get information about the selected chunk of text. They are similar to the found functions:

Note that for all of these functions, the is required.

More about select

To select the entire contents of a field, you might be tempted to use the simple:

  select field "whatever"

However, this form of the command will select, not the text in the field, but the field object itself, just as if you had clicked on it with the edit tool (e.g., to edit its properties). To select the text within the field you must use the text property of the field:

  select the text of field "whatever"

You can also use select before or select after to control exactly where the insert cursor is placed in the text.

select before word 3 of field "whatever"

In practice, the selection functions can be used in conjunction with the found and offset functions to find, highlight, and copy a string or unit:

  find "hello"
  select the foundChunk
  put the selectedText into thisVariable

Finally, what if, after selecting text in a field (or even selecting the field itself), you just want to clear all selections? You can do that with a simple, if not intuitive, command:

  select empty

Click Functions

Click functions are a set of functions similar to found and selected functions. They return information from clicks on a locked text field:

The values, of course, vary depending upon what is clicked. Note that some of the functions are empty in special cases: clicking on a space, clicking at the end of a line, clicking in an empty field, etc.

Mouse Functions

There is one more set of functions that return information about text and objects the mouse pointer is over. They closely parallel the selected and click functions. Unlike the click functions, the mouse functions can get this information regardless of whether the field is locked or unlocked.


Note that the mouseControl, mouseLoc, mouseH, mouseV and mouseColor functions return information about all locations and objects, not just about fields.