Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

[SugarCube 2.14] Dynamic variables in textbox?

Hello, I am currently writing a widget for a trading system and have run into a bit of an issue passing variables to a textbox within the widget.

My integer variables in the passage are _NumGeneral, _NumSurgery and _NumPharma and the widget is called with "General", "Surgery" or "Pharma" as $args[0].

Is it possible to write a generalized case within the widget for something like <<textbox "'_Num'+$args[0]" _Num+$args[0]>>, or will I need 3 separate widgets instead?

Comments

  • It should be possible, but you might be running into an issue with the way macros interpret expressions in their arguments. See SugarCube's documentation for an explanation:
    Passing an expression as an argument
    Passing the result of an expression as an argument is problematic for a couple of reasons: because the macro argument parser doesn't treat arguments as expressions by default and because it separates arguments with whitespace.

    Normally, those aren't issues as you should not need to use the result of an expression as an argument terribly often. To resolve instances where you do, however, you'll want to use either a temporary variable or a backtick expression.

    For example, the following will not work because the macro parser will think that you're passing five discrete arguments, rather than a single expression:
    <<link "Wake " + $friend + ".">> … <</link>>
    
    You could solve the problem by using a temporary variable to hold the result of the expression, then pass that to the macro. For example:
    <<set _text to "Wake " + $friend + ".">>\
    <<link _text>> … <</link>>
    
    A better solution, however, would be to use a backtick* expression (`…`), which is really just a special form of quoting available in macro arguments that causes the contents of the backticks to be evaluated and then yields the result as a singular argument. For example:
    <<link `"Wake " + $friend + "."`>> … <</link>>
    
    *A backtick is also known as a grave and is often paired with the tilde (~) on keyboards.

    Something like this might work (untested):
    <<textbox `"_Num" + $args[0]` `"_Num" + $args[1]`>>
    

    Alternatively you could change the way you're calling your widget to begin with (also untested):
    <<widget myWidget>>
    <<textbox $args[0] $args[1]>>
    <</widget>>
    
    <<myWidget _NumGeneral _NumSurgery>>
    
  • I tried both of those and method 1 doesn't work (SugarCube throws an error about missing sigils), but method 2 did with some adjustment since textbox seems to take a string for the first argument to convert into State.temporary["String] or State.variables["String"].
    <<widget myWidget>>
    <<textbox $args[0] $args[1]>>
    <</widget>>
    
    <<myWidget "_NumGeneral" _NumGeneral>>
    
  • edited March 2017
    To explain a bit. The following—a fleshed out version of Rokiyo's backtick expression example:
    <<widget "myWidget">>
    \<<textbox `"_Num" + $args[0]` `"_Num" + $args[1]`>>
    \<</widget>>
    
    Used thus:
    <<myWidget "General" "General">>
    
    Does not work because the backtick expression yields the unquoted variable name, allowing value substitution to happen.


    It needed to be something like:
    <<widget "myWidget">>
    \<<textbox `'"_Num' + $args[0] + '"'` `'_Num' + $args[1]`>>
    \<</widget>>
    
    Though, honestly, it would simply be easier to use the <<textbox>> macro directly at that point.

    The only way using a widget here becomes simpler is if it's doing other duties as well and/or you're only going to invoke it with a single argument. For example:
    <<widget "myWidget">>
    \<<textbox `'"_Num' + $args[0] + '"'` `'_Num' + $args[0]`>>
    \<</widget>>
    
    Usage:
    <<myWidget "General">>
    
  • AFAICT `'"_Num' + $args[0] + '"'` returns ""_NumGeneral"" when used with a string, and converting `'_Num' + $args[0]` to the value of the variable is definitely going to need something better than the eval(parse()) that I'm currently using.

    I'm actually using the widget to control a textbox and a pair of buy/sell links, so I'm not too worried about calling extra args, and thanks to both of you it works now, albeit in a messy way.
  • *sigh* That's what I get for posting while juggling a dozen other things and not testing my example. It should have been something like the following:
    <<widget "myWidget">>
    \<<textbox `'_Num' + $args[0]` `Scripting.evalTwineScript('_Num' + $args[0])`>>
    \<</widget>>
    
Sign In or Register to comment.