Building a script statement

Anything beyond the basics in using the LiveCode language. Share your handlers, functions and magic here.

Moderators: Klaus, FourthWorld, heatherlaine, kevinmiller, robinmiller

Simon Knight
Posts: 635
Joined: Wed Nov 04, 2009 11:41 am
Location: Gunthorpe, North Lincs, UK

Building a script statement

Post by Simon Knight » Sun Feb 19, 2017 4:43 pm

I have a project that uses two near identical functions that I would like to merge into a single function. The two functions examine either the buttons or the fields on a card. The challenge is to merge the two functions into one and use a parameter to switch between fields and buttons. I don't want to use an if statement as this does not reduce the complexity in any way instead I wish to use the passed in value as part of a statement. In the non working code below the switch variable passed into the function is pType and I would like livecode to evaluate my lines as, for example

Code: Select all

put the long id of button 5 into tTemp or put the long id of field 5 into tTemp
I have read about the Value command but I am uncertain how to use it in the following example.

Code: Select all

Function LoopObjects  pType
          # pType is a string either "Field" or "Button"
          repeat with Counter = 1 to the number of pType of pLongIDCardOrGroup
               put cr & (the long name of pType counter) after tTemp
          end repeat  
     return avalue
end LoopObjects
Any thoughts?
Simon
best wishes
Skids

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7407
Joined: Wed May 06, 2009 2:28 pm
Location: New York, NY

Re: Building a script statement

Post by dunbarx » Sun Feb 19, 2017 5:39 pm

Hi.

I guess I understand what you want to do.

Does this help at all, perhaps in a button script somewhere:

Code: Select all

on mouseUp
   repeat with y = 1 to the number of controls
      if the long name of control y contains "button"  then add 1 to b
      else if the long name of control y contains  "field" then add 1 to f
   end repeat
   
   answer b && f
end mouseUp
Now if you see how this works, that is, how it examines everything and distinguishes fields and buttons among all possible controls, you might insert your own gadgetry, something like:

Code: Select all

on mouseUp
   repeat with y = 1 to the number of controls
      if the long name of control y contains "button"  then doButtonStuff
      else if the long name of control y contains  "field" then doFieldStuff
   end repeat
end mouseUp
Craig Newman

Simon Knight
Posts: 635
Joined: Wed Nov 04, 2009 11:41 am
Location: Gunthorpe, North Lincs, UK

Re: Building a script statement

Post by Simon Knight » Sun Feb 19, 2017 5:52 pm

Hi Craig,

I'm sorry but it is not quite what I was after. My actual functions are quite complex and one is the twin of the other except that one refers to buttons and the other to fields. So my aim was to merge the two functions into one and get rid of a load of code. So for example is it possible to get the line

Code: Select all

repeat with Counter = 1 to the number of pType of this card
to work with ptype being a variable? So that livecode sees

Code: Select all

repeat with Counter = 1 to the number of buttons of this card
or

Code: Select all

repeat with Counter = 1 to the number of fields of this card
depending on what is passed into the function in pType.
best wishes
Skids

dave.kilroy
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 858
Joined: Wed Jun 24, 2009 1:17 pm
Location: Plymouth, UK
Contact:

Re: Building a script statement

Post by dave.kilroy » Sun Feb 19, 2017 6:34 pm

Hi Simon, the following code functions and may give you enough to get you to where you want to go...

Code: Select all

on mouseUp
     put word 1 of the long name of control 1 into tType
     put LoopObjects(tType) 
end mouseUp

Function LoopObjects  pType
     repeat with Counter = 1 to the number of controls in the current card
          if word 1 of the long name of control Counter = pType then put cr & the long name of control counter after tTemp
     end repeat  
     return tTemp
end LoopObjects
"...this is not the code you are looking for..."

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7407
Joined: Wed May 06, 2009 2:28 pm
Location: New York, NY

Re: Building a script statement

Post by dunbarx » Sun Feb 19, 2017 7:08 pm

Simon.

What you are asking for cannot simply be that the type of control is placed in a variable, as Dave suggested, as opposed to being explicitly derived in a loop. This hardly simplifies or compacts anything at all.

Is it just a slight bit of compaction that you are looking for? Try this in a button, on a card that contains both fields and buttons and some other controls:

Code: Select all

on mouseUp
   repeat with y = 1 to the number of controls
      if the long name of control y contains "button"  or the long name of control y contains  "field"\
      then doStuff (the long name of control y)
   end repeat
end mouseUp

on doStuff tControlType
   if tControlType contains "button" then 
   set the backColor of tControlType to any item of "red,yellow,green,blue,orange"
   else
    do "put random(9999) into" && tControlType
   end if
end doStuff
Do you know why you have to use a "do" construction to make this work?

Craig

[-hh]
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 2262
Joined: Thu Feb 28, 2013 11:52 pm
Location: Göttingen, DE

Re: Building a script statement

Post by [-hh] » Sun Feb 19, 2017 11:57 pm

Here a slightly different solution:
You could try to "generalize" your work _within_ the loop, leaving the enumerating of the loop "concrete".

Code: Select all

function dojob obj -- param obj is the long id of a field or button
  put (the long name of obj) & cr after tTemp
  put (the backcolor of obj) & cr after tTemp
  ...
  return tTemp
end dojob

function loopObjects pType
  if pType is "field" then
    repeat with i = 1 to the number of fields of pLongIDCardOrGroup
      put dojob(the long id of field i of pLongIDCardOrGroup) after tReturn
    end repeat
  else
    repeat with i = 1 to the number of buttons of pLongIDCardOrGroup
      put dojob(the long id of button i of pLongIDCardOrGroup) after tReturn
    end repeat
  end if
  return tReturn
end loopObjects
shiftLock happens

Simon Knight
Posts: 635
Joined: Wed Nov 04, 2009 11:41 am
Location: Gunthorpe, North Lincs, UK

Re: Building a script statement

Post by Simon Knight » Mon Feb 20, 2017 8:14 am

Hi, thanks for all your replies and the confirmation that it is not possible to use a variable in the way I hoped. I have included a copy of one of my functions which I accept needs refactoring with some of the ideas given above; specifically extracting the type of control, button or field from the long name of the control.

Craig, you ask if I understand why the "Do" is needed ? My answer is maybe! I believe that the do statement means treat all that follows as an expression that needs evaluating before it is then executed:

Code: Select all

 put "field " & quote & "debug" & quote into tControl
   -- put random(9999) into tControl  -- no error raised  if only line but causes error to be raised on next line
     do "put random(9999) into" && tControl  -- this works
Have I understood ?

An example of the rather complex dedicated function which I shall rewrite later today.....

Code: Select all

Function GetButtonScripts pLongIDCardOrGroup, pStackName, pCardName, pGroupName
     # Function that extracts the scripts from the buttons on the stack/card/group passed in.
     put empty into tText
     if pStackName is  empty then
          return False
     else
          Put "***! Stack:" & pStackName into tHeader
     end if
     
     if pCardName is empty then
          return False
     else
          Put ":Card:" & pCardName after tHeader
     end if
     
     # Either dealing with buttons on a card or within a group (on a card)
     
     if pGroupName is empty then
          # process the buttons on the card ignore those in groups
          put the number of buttons of pLongIDCardOrGroup into tItemCount
          repeat with btnCounter = 1 to the number of buttons of pLongIDCardOrGroup
               put the long name of button (btncounter) of pLongIDCardOrGroup into tTemp
               if the long id of button btncounter of pLongIDCardOrGroup contains "group" then
                    -- ignore
               else
                    put tHeader & ":Button:" & (the short name of button btncounter of pLongIDCardOrGroup) into tButtonHeader
                    put (the script of button btncounter of pLongIDCardOrGroup) into tButtonScript
                    # Only save an entry if the button has a script
                    if tButtonScript is not empty then put tButtonHeader & cr & tButtonScript & cr after tText
               end if
          end repeat  
     else
          # process the button in the group, ignore those on the card
          Put ":Group:" & pGroupName after tHeader
          repeat with btnCounter = 1 to the number of buttons of pLongIDCardOrGroup
               if the long id of button btncounter of pLongIDCardOrGroup contains "group" then
                    put tHeader & ":Button:" & (the short name of button btncounter of pLongIDCardOrGroup) into tButtonHeader
                    put (the script of button btncounter of pLongIDCardOrGroup) into tButtonScript
                    # Only save an entry if the button has a script
                    if tButtonScript is not empty then put tButtonHeader & cr & tButtonScript & cr after tText
               end if
          end repeat 
     end if
     return tText
     
end GetButtonScripts
Thanks

Simon K
best wishes
Skids

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7407
Joined: Wed May 06, 2009 2:28 pm
Location: New York, NY

Re: Building a script statement

Post by dunbarx » Tue Feb 21, 2017 6:53 pm

Simon.

You have "done" it correctly.

But among the several example approaches offered, I am still not sure why you still say that the variable cannot be, er "variable", in that it can reference, albeit with a little kluging, any control class, and hold that specific class within itself while you make it do actual work for you.

The "do" construction is what allows that, to evaluate twice, so that the "implicate" control reference is extracted "from within" the actual "working" line of code.

Oy. So many quotes.

Craig

Simon Knight
Posts: 635
Joined: Wed Nov 04, 2009 11:41 am
Location: Gunthorpe, North Lincs, UK

Re: Building a script statement

Post by Simon Knight » Wed Feb 22, 2017 8:03 am

I am still not sure why you still say that the variable cannot be, er "variable",
Because I was wrong! excuses excuses...... late at night mind set........ need coffee etc etc

Thanks again for all the help,

best wishes

Simon K
best wishes
Skids

Simon Knight
Posts: 635
Joined: Wed Nov 04, 2009 11:41 am
Location: Gunthorpe, North Lincs, UK

Re: Building a script statement

Post by Simon Knight » Wed Feb 22, 2017 8:33 am

Here is the function I ended up with :

Code: Select all

 Function GetControlScripts pLongIDCardOrGroup, pStackName, pCardName, pGroupName
    # Function that extracts the scripts from the buttons on the stack/card/group passed in.
    put empty into tText
    if pStackName is  empty then
        return False
    else
        Put "***! Stack:" & pStackName into tHeader
    end if
    
    if pCardName is empty then
        return False
    else
        Put ":Card:" & pCardName after tHeader
    end if
    
    # Either dealing with buttons on a card or within a group (on a card), pGroupName is used as the switch var
    
    if pGroupName is empty then
        #  processing the controls on the card - ignore any with group in their long name/id
        repeat with Counter = 1 to the number of controls of pLongIDCardOrGroup
            put the long id of control counter of pLongIDCardOrGroup into tLongID
            if  tLongID contains "group" then
                next repeat
            end if
            # tLongID refers to a control on the card and not in a group
            If   tLongID contains "field" Or tLongID contains "button" then
                put ":" & the first word of tLongID & ":"  into tType  -- field or button
                put  tType & (the short name of control  counter of pLongIDCardOrGroup) into tHeaderSuffix
                put (the script of control counter of pLongIDCardOrGroup) into tScript
                # Only save an entry if the control has a script
                if tScript is not empty then put tHeader & tHeaderSuffix & cr & tScript & cr after tText  -- one line if
            end if
        end repeat  
    else
        # process the button in the group, ignore those on the card
        Put ":Group:" & pGroupName after tHeader
        repeat with Counter = 1 to the number of controls of pLongIDCardOrGroup
            put the long id of control counter of pLongIDCardOrGroup into tLongID
            If   tLongID contains "field" Or tLongID contains "button" then
                put ":" & the first word of tLongID & ":"  into tType  -- field or button
                if tLongID contains "group" then
                    put tType & (the short name of control counter of pLongIDCardOrGroup) into tHeaderSuffix
                    put (the script of control counter of pLongIDCardOrGroup) into tScript
                    # Only save an entry if the button has a script
                    if tScript is not empty then put tHeader & tHeaderSuffix & cr & tScript & cr after tText -- one line if
                end if  -- contains group
            end if -- contains either field or button
        end repeat   -- loop through all the controls on the card
    end if  -- Check if working with controls on the card or the group
    return tText
    
end GetControlScripts
Thanks yet again
best wishes
Skids

Thierry
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 821
Joined: Wed Nov 22, 2006 3:42 pm
Location: France
Contact:

Re: Building a script statement

Post by Thierry » Wed Feb 22, 2017 11:20 am

Hi Simon,

Here is a variation of your latest script.
Take or Drop whatever you want.

Regards,

Thierry

Code: Select all

Function controlScripts pLongIDCardOrGroup, pStackName, pCardName, pGroupName
   # extracts scripts from  buttons on the stack/card/group passed in.
   local tHeader, tText
   local ignoreInGroup, listOfControls, theScript
   
   if pStackName is  empty then  return false
   if pCardName is empty then  return false
   
   put (pGroupName is empty)  into ignoreInGroup
   put "***! Stack:" & pStackName & ":Card:" & pCardName into  tHeader
   
   # get list of all control
   repeat with Nc = 1 to the number of controls of pLongIDCardOrGroup
      put the long id of control Nc of pLongIDCardOrGroup &cr after listOfControls
   end repeat
   
   # keep only buttons and fields
   filter listOfControls with regex pattern "^(button|field)"
   
   #  keep  controls in OR not in a group
   if ignoreInGroup then filter listOfControls without  "*group*"
   else  filter listOfControls with  "*of group*"
   
   repeat for each line aControl in listOfControls
      put the script of aControl into theScript
      if theScript is empty then next repeat
      if ignoreInGroup then get tHeader & ":"
      else  get tHeader & ":Group:" & pGroupName & ":"
      put IT & word 1 of aControl & ":" & the short name of aControl &cr after tText
      put theScript & cr after tText
   end repeat
   
   return tText
end controlScripts
Thierry Douez
- Senior computer scientist
- Conseil, dévelopement et support en Français
https://sunny-tdz.com
https://sunny-tdz.com/livecode/externals

Simon Knight
Posts: 635
Joined: Wed Nov 04, 2009 11:41 am
Location: Gunthorpe, North Lincs, UK

Re: Building a script statement

Post by Simon Knight » Thu Feb 23, 2017 10:03 am

Hi Thierry,

Thank you for your refactored version of my script. In it you have used constructs that I did not know were allowed e.g.

Code: Select all

put (pGroupName is empty)  into ignoreInGroup
and your use of the filter command to reduce the list size is very elegant. My only concern is the use of the single line if statements :

Code: Select all

if theScript is empty then next repeat
      if ignoreInGroup then get tHeader & ":"
      else  get tHeader & ":Group:" & pGroupName & ":"
again I was not aware that the else statement could be used in this way also I am so use to expecting an if to be finished with an end if that your lines seem strange and alien.

I have learned a lot - thanks,

best wishes

Simon K
best wishes
Skids

Thierry
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 821
Joined: Wed Nov 22, 2006 3:42 pm
Location: France
Contact:

Re: Building a script statement

Post by Thierry » Thu Feb 23, 2017 10:21 am

Simon Knight wrote:Hi Thierry,
I have learned a lot - thanks,
best wishes
Hi Simon,

You're welcome.

Reading other's code from time to time
is a good exercise to open our mind....

and after that, we do what we like :)

If you feel the "end if" is missing, than add it and here you go....

Good luck with your project,

Thierry
Thierry Douez
- Senior computer scientist
- Conseil, dévelopement et support en Français
https://sunny-tdz.com
https://sunny-tdz.com/livecode/externals

Klaus
Posts: 12205
Joined: Sat Apr 08, 2006 8:41 am
Location: Germany
Contact:

Re: Building a script statement

Post by Klaus » Thu Feb 23, 2017 3:37 pm

Hi Simon,

short note:
Do not use IT (get xyz...) unless really neccessary!
IT wil change when you least exspect IT! :D


Best

Klaus

Thierry
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 821
Joined: Wed Nov 22, 2006 3:42 pm
Location: France
Contact:

Re: Building a script statement

Post by Thierry » Thu Feb 23, 2017 5:10 pm

Klaus wrote: short note:
Do not use IT (get xyz...) unless really neccessary!
IT wil change when you least exspect IT!
another short note:
Learn when IT will change and how to use IT and then you're free...

I'm using IT quite a lot since many years on numerous professional projects
without any trouble and I love IT :)

Best,

Thierry
Thierry Douez
- Senior computer scientist
- Conseil, dévelopement et support en Français
https://sunny-tdz.com
https://sunny-tdz.com/livecode/externals

Post Reply

Return to “Talking LiveCode”