Whole word selection in field

Got a LiveCode personal license? Are you a beginner, hobbyist or educator that's new to LiveCode? This forum is the place to go for help getting started. Welcome!

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller

Regulae
Posts: 136
Joined: Tue Oct 20, 2009 6:05 am

Whole-word selection in unlocked field

Post by Regulae » Wed Oct 28, 2009 6:53 am

Though this does not address all the issues raised in earlier posts, the following may be of interest to some. Placed in the script of an unlocked, user editable field, it enables whole-word selection with a shift key override. In this example, leading and trailing punctuation is removed, with special treatment of brackets and quotes. It looks lengthy because of the comments, which explain some of the strategy used.

Code: Select all

on mouseEnter
    global quoteChar, specialChar, exclusionList

/* load non-keyboard characters into variables for use as "markers". */

    put numToChar(18) into quoteChar
    put numToChar(19) into specialChar

/* nominate the punctuation to be removed from front/back of whole-word selection, adding the special "quote marker" to the list .*/

    put "( ) , . : ; ? ! / " into exclusionList
    put quoteChar after exclusionList
    pass mouseEnter
end mouseEnter


on selectionChanged
    global quoteChar, specialChar, exclusionList
    if the selection is not empty then

/* if user holds down shift key during selection, whole-word selection is bypassed, they get exactly what they select */

        if the shiftKey is down then
            pass selectionChanged
        end if

/* to speed manipulation, the contents of the field is loaded into a variable */

        put me into textStore

/* given the RevTalk definition of "word", the quote characters are substituted with another character. Again for speed, we replace to only just beyond the actual selection. */

        replace quote with quoteChar in char 1 to ((word 4 of the selectedChunk) + 100) in textStore
        put (the number of words in char 1 to (word 2 of the selectedChunk) of textStore) into firstWordNum
        put (the number of words in char 1 to (word 4 of the selectedChunk) of textStore) into lastWordNum

/* having found the number of the first and last word included in the whole selection, we use this to find the first and last characters. We load a variable for the purpose, keeping textStore intact for further use. */

        put textStore into tempTextStore
        put specialChar into the last char of word lastWordNum of tempTextStore
        put offset(specialChar, tempTextStore)  into lastCharNum
        put specialChar into char 1 of word firstWordNum of tempTextStore
        put offset(specialChar, tempTextStore) into firstCharNum
        put char firstCharNum to lastCharNum of textStore into wholeWordSelection

/* note: wholeWordSelection is the actual text the handler has identified for inclusion in the new selection. Next step: remove leading/trailing punctuation by adjusting the char number range to be finally selected */

        if char 1 of wholeWordSelection is in exclusionList then
            put (firstCharNum + 1) into firstCharNum
        end if
        if the last char of wholeWordSelection is in exclusionList then
            put (lastCharNum - 1) into lastCharNum
        end if

 /* if the user actually selects a leading bracket,  and if the last char in wholeWordSelection is a closing bracket, the brackets are restored to the selection range, otherwise, just the words inside are selected. */

        if char 1 of the selectedText = "(" then
            if the last char in wholeWordSelection = ")" then
                put (firstCharNum - 1) into firstCharNum
                put (lastCharNum + 1) into lastCharNum
            end if
        end if

/* similar to brackets, note that because "selectedText" is from the original text, it still includes quote characters, rather than the special quoteChar used in this handler. */

        if char 1 of the selectedText = quote then
            if the last char in wholeWordSelection = quoteChar then
                put (firstCharNum - 1) into firstCharNum
                put (lastCharNum + 1) into lastCharNum
            end if
        end if

/* the whole-word selection, based on the conditions above, is selected */

        select char firstCharNum to lastCharNum in me
    end if
    pass selectionChanged
end selectionChanged
A particularly useful step is going from the word range to be selected, to a chunk expression in terms of characters. quoteChar and specialChar are non-keyboard ASCII characters, which thus (ideally) won’t already be present in the text. The specialChar is inserted into the last char of word lastWordNum, and "offset" used to find the lastCharNum. Then the specialChar is inserted into the first char of word firstWordNum, and firstCharNum determined. The lastCharNum is identified before firstCharNum because "offset" starts from the beginning of the container, and if we did firstCharNum first, finding lastCharNum would be a little more involved (we would have to use an offset with a "skip", and then add the first offset (firstCharNum) to the second (from firstCharNum to the second specialChar) to determine lastCharNum.

By determining the whole word selection as a range of char numbers, it is relatively easy to make the selection more "intelligent", removing unwanted leading and trailing punctuation. If the user selects the leading bracket/quote and continues to select across to the word containing the trailing bracket/quote, the brackets/quotes are included in the final selection. Otherwise, only the text inside the brackets/quotes is selected. Further refinements are possible- in logical/mathematical applications, the selection can be constrained so that the correct number of brackets is automatically selected i.e. the user can't accidentally make a selection including an odd number of brackets. The selection handler can be adjusted for specialised text, for example conveniently selecting RevTalk code. The example above illustrates the basic idea, however. Further conditions can be added to cover special cases, for example when a sentence is in quotes, and thus ends with a full stop/quote combination.

Some effort has been made to keep things fairly fast e.g. loading key variables once on mouseEnter, processing the text in a variable, limiting the extent of "replace", use of “offsetâ€

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4171
Joined: Sun Jan 07, 2007 9:12 pm

Post by bn » Wed Oct 28, 2009 2:15 pm

Regulae,
thanks for posting this very clear script. It went right into my "Scripter's Scrapbook"
regards
Bernd

Post Reply