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.revThis 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.
By the end of this reading you should know the following:
offset
functions.find
command and how to use it.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"
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:
trueWord
chunk defines the “actual words” in a sentence, and more closely matches what we usually mean by the term “word”. (This chunk type first appeared in LiveCode version 7; having become necessary because of the greatly expanded support for Unicode in that version. Unicode is the standard system for representing text of all the world’s languages.)A chunk is LiveCodes 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:
the middle word of "red yellow green mauve"
is "green")put any line of field "myField" into tRandomLine
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
and you do not use an "s" in the character range (e.g., you don't say word 5 to word 7
but you do say chars 14 to 29char 14 to 29
).
LiveCode provides some useful functions you can use to handle text
put the length of line 12 of field "whatever"
). Note: "the" is required before length in this construct.the number of lines in field "whatever"
or the number of words of field "whatever"
in this construct. The prepositions in
and of
are completely interchangable in this context. The abbreviation num
is a valid synonym for this function.
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:
itemOffset()
()lineOffset()
()wordOffset()
()trueWordOffset()
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.
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.
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."
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).
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.
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.
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 are a set of functions similar to found and selected functions. They return information from clicks on a locked text field:
trueWord
definition of “word” (where words are defined more “naturally” according to language) rather than the word
definition (where words are delimited by spaces and returns).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.
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.
trueWord
definition of “word” (where words are defined more “naturally” according to language) rather than the word
definition (where words are delimited by spaces and returns).Note that the mouseControl
, mouseLoc
, mouseH
, mouseV
and mouseColor
functions return information about all locations and objects, not just about fields.