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

WaltBrown
Posts: 466
Joined: Mon May 11, 2009 9:12 pm

Whole word selection in field

Post by WaltBrown » Thu Jun 11, 2009 6:11 pm

Hi! I'm sure this has been asked but I couldn't find it in the forums.

I want to return the whole words when text is selected in a locked field. I have this in the field:

Code: Select all

on dragMove
   select the mouseText
end dragMove

on mouseUp
   answer the selectedText
end mouseUp
The user needs to be very careful to get the whole words this way. Has anyone seen a way to get the whole words if the user starts or ends in the middle of a word? I was wondering if there was a more elegant solution than:

Code: Select all

on mouseUp
   put word 2 of the selectedChunk into tStartChar
   put word 4 of the selectedChunk into tEndChar
   put "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'-" into tTestString
   
   // Move backward through the field to find the whole word start
   put false into tFoundStart
   repeat until tFoundStart = true
      put char tStartChar of field fText into tChar
      if tChar is not in tTestString then
         put true into tFoundStart
      else
         subtract 1 from tStartChar
      end if
   end repeat
   
   // Move forward through the field to find the whole word end
   put false into tFoundEnd
   repeat until tFoundEnd = true
      put char tEndChar of field fText into tChar
      if tChar is not in tTestString then
         put true into tFoundEnd
      else
         add 1 to tEndChar
      end if
   end repeat
   
   answer char tStartChar to tEndChar of field fText
end mouseUp
Thanks, Walt
Walt Brown
Omnis traductor traditor

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

Post by bn » Thu Jun 11, 2009 9:31 pm

Walt,

put this into the script of your field "ftext" (NoW is number of words)

Code: Select all

on mouseUp
    put field "ftext" into tText
    put the selectedchunk into tChunk
    put word 2 of tChunk into tCharNumberStart
    put word 4 of tChunk into tCharNumberEnd
    
    -- if the user includes a trailing ,.?! in the selection then Rev counts that as word
    if char tCharNumberStart of tText is in ".,?!" then add 1 to tCharNumberStart
    
    put the number of words of (char 1 to tCharNumberStart-1 of tText) into tNoWUntilSelection
    put the number of words of char tCharNumberStart to tCharNumberEnd of tText into tNoWSelection
    put the number of words of char 1 to tCharNumberEnd of tText into tNoWStartTextUntilEndSelection
     
    if tNoWSelection > 0  then 
        put word (tNoWStartTextUntilEndSelection - (tNoWSelection -1))  to tNoWStartTextUntilEndSelection of tText into ttheWords
    else 
        put empty into tTheWords
    end if
     
    -- somehow rev takes a trailing .?! , as part of the word
    if last char of tTheWords is in ".,?!" then delete last char of ttheWords
     
    put "tNoWUntilSelection" && tNoWUntilSelection & return & \
            "tNoWStartTextUntilEndSelection" && tNoWStartTextUntilEndSelection & return & \
            "tNoWSelection" && tNoWSelection & return & return & \
            "Words selected = " & return &   tTheWords into tDisplay
     
    answer tDisplay
end mouseUp
Your code works very well for me, but if you ask for an alternative then
this works also. But I just made this up as an exercise, I don't claim it to work flawlessly but in my limited testing it did. And I don't claim it to be 'better'/'faster' then yours. Just a little different approach.
please let me know how it works for you and if does what you want.
regards
Bernd

WaltBrown
Posts: 466
Joined: Mon May 11, 2009 9:12 pm

Post by WaltBrown » Fri Jun 12, 2009 3:52 am

Thanks, Bernd. I'll try yours too. I thought there might be an easier way.

On the regexp front, my automated version of this (for whole words, ie no human intervention) uses this (which I am currently experimenting with to simplify), which seems to work well in matchChunk for identifying whole words and ignoring partials, regardless of what adjacent byte codes exist:
(?i)([\s\r\n"&\(,-]+theWord[\s\x20\n\r!"&\)\x2C-\.:;\?]+)

For example, it will not find "and" in "hand" (since wholeMatches has no effect in matchChunk) or get confused if the word is preceded or followed by a control character or any punctuation. It's almost perfected :-).

I tried using the regexp \w word and \c control character classes but I could not get matchChunk to like them.
Walt Brown
Omnis traductor traditor

WaltBrown
Posts: 466
Joined: Mon May 11, 2009 9:12 pm

Post by WaltBrown » Fri Jun 12, 2009 4:05 am

Simplified:

Code: Select all

   // Move backward through the field to find the whole word start
   repeat until char tStartChar of field fText is not in tTestString
         subtract 1 from tStartChar
   end repeat
   
   // Move forward through the field to find the whole word end
   repeat until char tEndChar of field fText is not in tTestString
         add 1 to tEndChar
   end repeat
Walt Brown
Omnis traductor traditor

WaltBrown
Posts: 466
Joined: Mon May 11, 2009 9:12 pm

Post by WaltBrown » Fri Jun 12, 2009 4:09 am

Minor correction at the end since the repeats need their last iteration rolled back:

answer char tStartChar+1 to tEndChar-1 of field fText
Walt Brown
Omnis traductor traditor

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

Post by bn » Fri Jun 12, 2009 10:05 am

Walt,

regarding regular Expressions: I find them hard to construct and maintain. I for my part am avoiding them. In my coding they never seem to do what I want. If I find a working long/complicated regex I admire it...

For the whole words in the selection:
One advantage of letting Rev do the finding of the whole words is that in languages other than english you would have to adjust your

Code: Select all

put "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'-" into tTestString
for each language, or if you dont know what language your dealing with you would have to provide a complete list of the possible ascii characters, that can make up words.
In my example (supposing it works correctly) it would be easy to adjust, because you only test for the punctuation marks. This would probably hold true for unicode.

Maybe some of the experts here on the forum have some insights to share.
regards
Bernd

mtecedor
Posts: 68
Joined: Fri Sep 04, 2009 6:40 pm

Post by mtecedor » Sat Oct 17, 2009 11:01 pm

Hi,

I am trying to do something similar to what it was discussed in this topic. So I modified to fit my needs, but I still have one thing I cannot figure it out.

I want the user to be able to highlight chunks of text in a field (Text2). Then, I want these chunks to appear in another field (output). The selected chunks must appear in lines sorted in the order in which they appear in the original text, not in the order in which they were highlighted.

Everything works except when there is a change of paragraph. Then, some of the text appears at the beginning of the field (output). How can I tell revolution that it must obviate the space between paragraphs?


This is my code up until now:

on mouseUp
put hiliteCounter+1 into hiliteCounter
put word 2 of the selectedChunk into tStartChar
put word 4of the selectedChunk into tEndChar
put "1234567890.,¿!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'-" into tTestString

put false into tFoundStart
repeat until tFoundStart = true
put char tStartChar of field Text2 into tChar
if tChar is not in tTestString then
put true into tFoundStart
else
subtract 1 from tStartChar
end if
end repeat

put false into tFoundEnd
repeat until tFoundEnd = true
put char tEndChar of field Text2 into tChar
if tChar is not in tTestString then
put true into tFoundEnd
else
add 1 to tEndChar
end if
end repeat

set backgroundColor of char tStartChar+1 to tEndChar-1 of field "Text2" to yellow

put tStartChar+1 & " " & char tStartChar+1 to tEndChar-1 of field "Text2" into line hiliteCounter of hilitedList
sort hilitedList numeric
put hilitedList into field "output"
repeat with i = 1 to the number of lines in field "output"
delete word 1 of line i in field "output"
end repeat
end mouseUp



I tried adding something like

if char is " "
then add 1 to tStartChar

but it gives me an error message.

Any idea on how I can add that detail?

Thanks

Mark
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 5150
Joined: Thu Feb 23, 2006 9:24 pm
Contact:

Post by Mark » Sat Oct 17, 2009 11:34 pm

Hey guys, why do difficult if you can do it easy? The following script only works in locked fields whose traversalOn is true.

Code: Select all

on mouseUp
     put the selectedChunk into myChunk
     put (number of words of char 1 to (word 2 of myChunk) of me) into myFirstWord
     put (number of words of char 1 to (word 4 of myChunk) of me) into myLastWord
     put myFirstWord && myLastWord
     select word myFirstWord to myLastWord of me
     -- now you can do with the selectedText whatever you like
end mouseUp
Best regards,

Mark

P.S. On second thought, I now see that Bernd's script is a slightly more complex version of what I just posted. Now I wonder why it is a problem that some characters are selected as if they are part of a word...?
The biggest LiveCode group on Facebook: https://www.facebook.com/groups/livecode.developers
The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode

Mark
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 5150
Joined: Thu Feb 23, 2006 9:24 pm
Contact:

Post by Mark » Sat Oct 17, 2009 11:40 pm

mtecedor,

I expect that your problem is solved by replaced returns with spaces before processing the selected text.

Code: Select all

-- replace myVar with your own var
put the selectedText into myVar
replace cr with space in myVar
-- your script follows here
Best regards,

Mark
The biggest LiveCode group on Facebook: https://www.facebook.com/groups/livecode.developers
The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode

mtecedor
Posts: 68
Joined: Fri Sep 04, 2009 6:40 pm

Post by mtecedor » Tue Oct 20, 2009 2:26 am

Mark,

Thanks for the code, but it doesnt work exactly the way I want, becuase I would like to maintain the paragraphs in my "output field".

Right now, my code works perfectly if the user selects the end of one paragraph and the begining of the next one. Then, it messes everything up. It puts a cr and the begining of the second paragraph in the first line of my "output" field, when it should just keep it the way it appears in the original.

Any idea why this is happening?

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

Post by bn » Tue Oct 20, 2009 4:12 pm

Marta,

I modified your script to do what I --think-- what it should do:a user works on a text and can hilight words or parts of the text he wants. He can do so repeatedly and hilite stuff further up from where he hilighted before. You want this in a output list, one hilited selection on one line in the order it was in the text.
For speed I work mostly in variablesl, because accessing fields slows things down. If you click in the field with the optionkey (altkey) down it clears the counter etc. It is marked in the script.

Code: Select all

local hiliteCounter, hilitedList
on mouseUp 
   -- this is for debugging to reset the counter and the list and the hilites
   -- you can take this out
   if the optionkey is down then
      set the backgroundcolor of char 1 to -1 of me to ""
      put 0 into hiliteCounter
      put "" into hilitedList
      put "" into field "output"
      exit mouseUp
   end if
   put hiliteCounter+1 into hiliteCounter 
   put word 2 of the selectedChunk into tStartChar 
   put word 4of the selectedChunk into tEndChar 
   put tStartChar && tEndChar
   
   -- if the user clicks before the first word it selects the whole text
   if  tEndChar = 0 then exit mouseUp
   
   put "1234567890.,¿!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'-" into tTestString 
   put field "text2" into tTest
   
   put false into tFoundStart 
   repeat until tFoundStart = true 
      put char tStartChar of tTest into tChar 
      if tChar is not in tTestString then 
         put true into tFoundStart 
      else 
         subtract 1 from tStartChar 
      end if 
   end repeat 
   
   put false into tFoundEnd 
   repeat until tFoundEnd = true 
      put char tEndChar of tTest into tChar 
      if tChar is not in tTestString then 
         put true into tFoundEnd 
      else 
         add 1 to tEndChar 
      end if 
   end repeat 
   
   set backgroundColor of char tStartChar+1 to tEndChar-1 of field "Text2" to yellow 
   put char tStartChar+1 to tEndChar-1 of tTest into tReplaceReturns
   replace return with space in tReplaceReturns
   replace space & space with space in tReplaceReturns
   
   put tStartChar+1 & " " & tReplaceReturns into line hiliteCounter of hilitedList
   sort hilitedList numeric
   -- we leave the hilitedList alone and work on a copy of it
   put hilitedList into tListToClean
   repeat with i = 1 to the number of lines of tListToClean
      delete word 1 of line i of tListToClean
   end repeat
   filter tListToClean without empty
   put tListToClean into field "output"
end mouseUp 
try this and let us know.
regards
bernd

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

Post by bn » Tue Oct 20, 2009 5:46 pm

Marta,
if you want to retain paragraphs in the output field then say so. The way it is now returns (which mark paragraphs) are taken out. That was the reason your original script did not work. You can not put things in "lines" and put a paragraph into that line, which will add a line.
If you want the paragraphs let me know.
regards
Bernd

mtecedor
Posts: 68
Joined: Fri Sep 04, 2009 6:40 pm

Post by mtecedor » Tue Oct 20, 2009 6:41 pm

Bernd,

Thanks a lot for the code, it works pretty well, except that of course I dont have pragraphs in my output field. I looked in the user guide and in the dictionary for something related to that, but i havent found anything.

I also tried inserting a line if the original text contains return but it didn't work.

I would really appreciate it if you could give me a hand.

Marta

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

Post by bn » Tue Oct 20, 2009 6:47 pm

Marta,
replace the bottom part.

Code: Select all

set backgroundColor of char tStartChar+1 to tEndChar-1 of field "Text2" to yellow 
   
   put char tStartChar+1 to tEndChar-1 of tTest into tReplaceReturns
   
   -- take returns out so it won't break the lines of the hilitedList
   replace return with "|" in tReplaceReturns
   
   put tStartChar+1 & " " & tReplaceReturns into line hiliteCounter of hilitedList
   sort hilitedList numeric
   put hilitedList into field 3
   -- we leave the hilitedList alone and work on a copy of it
   put hilitedList into tListToClean
   repeat with i = 1 to the number of lines of tListToClean
      delete word 1 of line i of tListToClean
   end repeat
   -- remove empty lines
   filter tListToClean without empty
   -- put the returns back in
   replace "|" with return in tListToClean
   
   put tListToClean into field "output"
end mouseUp 
it inserts a 'pipe' or | instead of a return in the hilitedlist. This is than turned back into a return in the tListToClean
regards
Bernd

I noticed I had included a line of code that puts the selected chars into the message box, you might want to delete the line

Code: Select all

put tStartChar && tEndChar

mtecedor
Posts: 68
Joined: Fri Sep 04, 2009 6:40 pm

Post by mtecedor » Wed Oct 21, 2009 3:30 pm

Thanks Bernd, that helped a lot

Post Reply