Author Topic: Refreshing Variables  (Read 1087 times)

Castleberg

  • Newbie
  • *
  • Posts: 37
Refreshing Variables
« on: December 13, 2021, 12:21:38 PM »
btw, apologize for inconsistant code. below code / examples off the cuff, and not intended to be literal. (for example mixing C# with VA commands, etc. etc.). Intended to demonstrate the general problem....

I've run into a problem that has caused me to contrive a rather clumsy solution, and am wondering if there is a more direct and efficient method...

Problem :

I currently have a command with a long array of very complex variables. This command runs at startup, to set a myriad of profile variables.

For simplicity sake...

Lets say I have a variable with a story :

Story = {TXT:character1} and {TXT:character2} {TXT:verb1} up the {TXT:noun1} to {TXT:verb2} a pail of {TXT:material1}. {TXT:character1} {TXT:verb3} down and broke their {TXT:noun2}, and {TXT:character2} came {TXT:verb4} after.

sorry for the long example, I couldn't help myself but finish . . . OCD.

I would like to have a user choose the variables, and then print the response.

That is simple enough, however, the problem I am running into is that the variable definitions are very complicated, and in a very long definitional array, that is quite cumbersome to get to.

I am looking for a way to "refresh" the story definition, without having to Redefine it to update the variables.

That is, I am looking for something like :

user input var 1
user input var 2
user input var 3
...

Refresh(Story)
Console.WriteLine(Story);
NOT

user input var 1
user input var 2
user input var 3
...

Story = {TXT:character1} and {TXT:character2} {TXT:verb1} up the {TXT:noun1} to {TXT:verb2} a pail of {TXT:material1}. {TXT:character1} {TXT:verb3} down and broke their {TXT:noun2}, and {TXT:character2} came {TXT:verb4} after.

Console.WriteLine(Story);

Redeclaring the definition is absolutely out of the question, as it would be chaos. My current solution, while admittedly almost (if not more) cumbersome is to reference back to the definition command, passing an index, that then runs through a jump, to jump to the desired portion of the declaration file and rerun the original definition to update the variable (as apposed to having a second iteration of it floating around).

I.E.
command 1:

story1
user input var 1
user input var 2
user input var 3
...
jumpPoint = story1
run command 2, passing text story 1 (and wait until finishes)
Write to log ({TXT:story1})

command 2:
if jumpPoint is set
jump to {TXT:jumpPoint}
end

marker Story1
Story1
if jumpPoint is set
jumpPoint = not set
exit command
end

Ditto structure for...

Story2

Story3


While functional, this seems hardly ideal.
Is there a better way to approach this problem that I'm overlooking?

I've tried:
Redeclaring the variable to another, hoping it would "refresh" :
printStory = Story1

appending Story 1:
printStory = Story1 + " ".

Reassigning Story to itself to try to refesh the embedded variables:
Story1 = Story1   / Story1 = Story1 + "", etc.

Bottom line, as expected, the variables are resolved and saved in "Story1" at the time it is declared, and any reference to that variable does not carry the variables, which are now saved as text, thus the subsequent variable declarations are irrelevant unless Story1 is redefined. Which, as best I can tell, means either :

A) rerunning the orignal definition (my cumbersome strategy)
B) redefining it in another command (which largely negates the purpose of having a centralized declaration array in the first place)



Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4782
  • RTFM
Re: Refreshing Variables
« Reply #1 on: December 13, 2021, 12:32:32 PM »
Is there a reason you can't just escape the tokens in your "Story" variable, so that you essentially save a template, and have the token parser fill it out with whatever the variable values are at the point you're actually using it?

The "Write a Value to the Event Log" and the "Say Something with Text-To-Speech" action both parse tokens, so if you pass it the value of a variable that has tokens in it, the parser will also parse those

E.G.
Code: [Select]
Set text [Story] to '|{TXT:character1} and |{TXT:character2} |{TXT:verb1} up the |{TXT:noun1} to |{TXT:verb2} a pail of |{TXT:material1}. |{TXT:character1} |{TXT:verb3} dow...
Set text [character1] to 'Bob'
Set text [character2] to 'Jedediah'
...
Write [Blue] '{TXT:Story}' to log

(if you want to use examples, concise is preferred...)

Castleberg

  • Newbie
  • *
  • Posts: 37
Re: Refreshing Variables
« Reply #2 on: December 13, 2021, 02:25:34 PM »
I'm not sure if this would work for my purposes directly, as the variable will be sent to the clipboard via an inline function directly.. (I'm using this in conjunction with our discussions regarding richText.

Although, your point is well taken.

I suppose, by the same logic, I could have an inline function parse the tokens, send it back to VA, which can populate the story, and then send it out via the normal variable to clipboard inline function? That is, have an inline function function as write to log would.

i.e.
Set text [story] to '|{TXT:character1} and |{TXT:character2}...
Run Inline function : which removes "|", and setting the result to VA variable "storyRefresh"

then

Set richText to storyReady
Run Inline function : Which copies that to clipboard

Somewhat confusingly, and for context, if you recall our prior discussion, the inline function run to generate the variable text itself was . . . (I am citing it here, as I feel it would throw a wrench/complication in the proposed solution)

Code: [Select]
string openingBraceSubstitute = ((char)2).ToString();

string richText = VA.GetText("richText");
if (!String.IsNullOrEmpty(richText))
{
Clipboard.SetText
(
richText.Replace("\\{", openingBraceSubstitute)
.Replace("{", "|{")
.Replace("\\}", "}")
.Replace("\r\n", "{NEWLINE}")
.Replace(openingBraceSubstitute, "{")
);

That works well, and is allowing my tokens to function. My only issue now is "updating" the tokens.

It would seem, if I understand you correctly, your suggesting adding an escape, "|" to the token, which would prevent it from being updated on declaration, at which point I would "write to log" whenever I wanted to update it, correct?

But, that seems to negate purpose of us adding the openingBraceSubstitute (STX) placeholder in the first place... correct?


If you need more context (Skip if not) this is my current work flow....

WordPad :
{TXT:Character1} and {TXT:Character2} went to the mall

Run command : Clipboard to Literal :
Code: [Select]
Execute precompiled Inline Function: 'C:\Program Files\VoiceAttack\Apps\Inline Functions\Rich Text Clipboard to Variable.dll', wait until execution finishes
Execute precompiled Inline Function: 'C:\Program Files\VoiceAttack\Apps\Inline Functions\Rich Text Literal with Token.dll', wait until execution finishes

Which runs two inline functions. The first, "Rich Text Clipboard to Variable" being :

Code: [Select]
using System;
using System.Text;
using System.Windows.Forms;

public class VAInline
{
public void main()
{
if (Clipboard.ContainsText(TextDataFormat.Rtf))
{
VA.SetText("richText", Clipboard.GetText(TextDataFormat.Rtf));
}
else
{
VA.SetText("richText", Clipboard.GetText());
VA.WriteToLog("No Rich Text Format data in clipboard; copied as regular text", "yellow");
}
}
}

and the second, "Rich Text Literal with Token" being :

Code: [Select]
using System;
using System.IO;
using System.Text;
using System.Windows.Forms;



public class VAInline
{
public void main()
{
string openingBraceSubstitute = ((char)2).ToString();

string richText = VA.GetText("richText");
if (!String.IsNullOrEmpty(richText))
{
Clipboard.SetText
(
richText.Replace("\\{", openingBraceSubstitute)
.Replace("{", "|{")
.Replace("\\}", "}")
.Replace("\r\n", "{NEWLINE}")
.Replace(openingBraceSubstitute, "{")
);
}
else
{
VA.WriteToLog("No text to paste", "red");
}
}
}
/*  */

which gives me a clipboard value of :

Code: [Select]
|{\rtf1\ansi\ansicpg1252\deff0\nouicompat|{\fonttbl|{\f0\fnil\fcharset0 Calibri;}}{NEWLINE}|{\*\generator Riched20 10.0.19041}\viewkind4\uc1 {NEWLINE}\pard\sa200\sl276\slmult1\f0\fs22\lang9{TXT:Character1} \b and\b0  {TXT:Character2} \ul went\ulnone  to the \i mall\i0\par{NEWLINE}\par{NEWLINE}}{NEWLINE}
which is manually placed into the "set text value to" field.

I am then wanting to populate that variable.

To test my current version, vs the proposed solution, I placed 2 variations of the above into variables as follows :

Current Version:
Set text [story] to '|{\rtf1\ansi\ansicpg1252\deff0\nouicompat|{\fonttbl|{\f0\fnil\fcharset0 Calibri;}}{NEWLINE}|{\*\generator Riched20 10.0.19041}\viewkind4\uc1 {NEWLINE}\pard\sa200\sl276\slmult1\f0\fs22\lang9{TXT:Character1} \b and\b0 {TXT:Character2} \ul went\ulnone  to the \i mall\i0\par{NEWLINE}\par{NEWLINE}}{NEWLINE}'

With proposed escapes:
Set text [story2] to '|{\rtf1\ansi\ansicpg1252\deff0\nouicompat|{\fonttbl|{\f0\fnil\fcharset0 Calibri;}}{NEWLINE}|{\*\generator Riched20 10.0.19041}\viewkind4\uc1 {NEWLINE}\pard\sa200\sl276\slmult1\f0\fs22\lang9|{TXT:Character1} \b and\b0 |{TXT:Character2} \ul went\ulnone  to the \i mall\i0\par{NEWLINE}\par{NEWLINE}}{NEWLINE}'

and executed the following :
Code: [Select]
Set text [Character1] to [Not Set]
Set text [Character2] to [Not Set]
Set text [story] to '|{\rtf1\ansi\ansicpg1252\deff0\nouicompat|{\fonttbl|{\f0\fnil\fcharset0 Calibri;}}{NEWLINE}|{\*\generator Riched20 10.0.19041}\viewkind4\uc1 {NEWLINE}\...
Set text [story2] to '|{\rtf1\ansi\ansicpg1252\deff0\nouicompat|{\fonttbl|{\f0\fnil\fcharset0 Calibri;}}{NEWLINE}|{\*\generator Riched20 10.0.19041}\viewkind4\uc1 {NEWLINE}...
Set text [Character1] to 'Bill'
Set text [Character2] to 'Ted'
Set text [richText] to [story]
Execute precompiled Inline Function: 'C:\Program Files\VoiceAttack\Apps\Inline Functions\Rich Text Variable to Clipboard.dll', wait until execution finishes

Press Left Ctrl+V keys and hold for 0.05 seconds and release

Set text [richText] to [story2]
Execute precompiled Inline Function: 'C:\Program Files\VoiceAttack\Apps\Inline Functions\Rich Text Variable to Clipboard.dll', wait until execution finishes

Press Left Ctrl+V keys and hold for 0.05 seconds and release

with the output being :
Code: [Select]
Not set and Not set went to the mall
TXT:Character1 andTXT:Character2 went to the mall

 :-\

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4782
  • RTFM
Re: Refreshing Variables
« Reply #3 on: December 13, 2021, 02:49:29 PM »
If you're sticking with manually copying blocks of Rich Text, you can modify the inline function to escape the markup twice, but the tokens only once.

E.G. instead of turning "{markup \{text\}}" into "|{markup {text}}", turn it into "||{markup |{text}}", then store that in a template variable.

That will result in the literal text stored in the template variable being "|{markup {text}}", as the token parser removes one escape character each time it runs.

This allows you to either set another variable to the value of the template variable, using a token in the "Text" field, so the token parser actually runs, or to use the ParseTokens() method in an inline function (E.G. right before copying the data into the clipboard), to replace the tokens with the values of the referenced variables