Referencing the current note and setting one of its properties in a function

I am creating a stamp that I would like to search the text of a note for a specific string and, if it finds that string, stores the return value in one of the note’s properties.

I have created this function.

function findTitlePosition(encounterText) {
	var position = encounterText.find("Title:");
	return position;

}

Which I’m calling from this stamp code.

set MySelection to selected note;
MySelection.Title = FindTitlePosition($Text);
  • I came up with this stamp code by searching aTbRef 10, but the code I wrote is not working
  • I have also search this forum without finding an answer to my two questions

I have two specific questions:

  1. How do I programmatically refer to the currently selected note?
  2. How do I programmatically set the value of one of the properties of the currently selected note?

A more general question - Is there any other reference out there besides aTbRef 10 and this forum that will help people like myself interested in programming Tinderbox, starting with a simple “Hello World” and moving gradually on to more complex automation or programming tasks?

Note: I have recently upgraded to Tinderbox v10.0.1.

set MySelection to selected note;
MySelection.Title = FindTitlePosition($Text);

This is AppleScript. Use AppleScript in Tinderbox only in two situations:

  1. In the very rare situation where it’s the only way to do something
  2. When most of the work involves controlling other applications

The best starting point is Tinderbox Help, and especially the Agents tutorial in the Help menu. The Tinderbox Way might also help.

Could you give us a concrete example of the task you’re doing? I almost understand, but not quite. I think it will turn out to be quite easy.

@eastgate - Thanks for the timely reply. Here are some more details of what I’m trying to do.

I have this JSON-ish text that I cut & paste into a note (not the complete text).

{
    Title: "InterceptingCattleRustlers",
    CenterDate: 290,
    IntroText: "There's some shouting coming from the northeast gate; you hurry in that direction to see what's happening. It doesn't sound good. A rider gallops up from the gate area, directly towards you.%%\"Arthur! It's the Saxons! They've taken a bunch of cattle from Kaye's people!\" %%This is your opportunity to show the merits of Kaye's dike-building. If you move fast, you might be able to catch the cattle-rustlers at one of gaps in the dike system. 
...
}

I have the following properties in my note.

What I am trying to do is find the Title text (“InterceptingCattleRustlers”) and put it in the Title property for later use (ideally, I would have this code in a stamp).

In a nutshell, that’s it (thanks to everyone on the 9/29 Tinderbox meetup for links and advice).

Okay, based on what I heard in the 9/29 meetup and some reading of the documentation, this code in a stamp:

$Text.contains("Title:(.+)");
$Title = $1;

Will search the note text for "Title: "

{
    Title: "InterceptingCattleRustlers",
    CenterDate: 290,
    IntroText: "There's some shouting coming from the northeast gate; you hurry in that direction to see what's happening. It doesn't sound good. A rider gallops up from the gate area, directly towards you.%%\"Arthur! It's the Saxons! They've taken a bunch of cattle from Kaye's people!\" %%This is your opportunity to show the merits of Kaye's dike-building. If you move fast, you might be able to catch the cattle-rustlers at one of gaps in the dike system. 
...
}

And populate the Title property with the title text after the colon.

Before running the stamp on the note.

After running the stamp on the note.

There’s some text massaging I need to do to get rid of the quotes and comma but I’m sure I can figure that out with the suggestion and help I received.

Thanks again everyone!

One way to do this with the streaming interface might be:

$MyString.skipTo("Title:").captureTo(",","Name"); 
$Name=$Name.replace('"',"");

The second line gets rid of the quotation marks.

Thanks @eastgate.

This:

$Text.skipTo("Title:").captureTo(",","Title");
$Title = $Title.replace('"',"");

Is much more succinct than this:

$Text.contains("Title:(.+)");
$Title = $1;
$Title = $Title.replace('"',"");
$Title = $Title.replace(",","");

This is going to speed up things tremendously.

1 Like

The origin of the stream parsing, IIRC, was parsing the plain text of on an email where there is a certainty about the presence/order key fields of interest. but whict if you know (or supsect) certain markers like title: are present but the ordering o fields might vary?

No problem as String.pargraphsList() , i.e. $Text.paragraphList() gives us a List-type object we can iterate with List.each() such that each $Text paragraph can be individualy parsed with Stream parsing. Tada!

@mwra @eastgate - If I have this Option text that consists of 1-3 options, do you have any suggestions as to the best way to parse it into attributes?

Option: [
      {
        OptionText: "\"Are you afraid of Saxons, Siarl?\" I sneer.",
        DeltaPBad_Good: -0.03,
        DeltaAsabiyyah: 0.0,
        DeltaPTimid_Dominant: 0.03,
        DeltaWisdom: 0.0,
        Reaction: [
          {
            ReactionText: "Siarl looks down, abashed.",
            ConsequenceText: "KillingCattleRustlers"
          },
        ]
      },
      {
        OptionText: "\"That just means we'll have more Saxons to kill.\" I counter.",
        DeltaPBad_Good: 0.01,
        DeltaAsabiyyah: 0.0,
        DeltaPTimid_Dominant: 0.03,
        DeltaWisdom: 0.0,
        Reaction: [
          {
            ReactionText: "Siarl doesn't seem much encouraged, but the other troopers chuckle.",
            ConsequenceText: "KillingCattleRustlers"
          },
        ]
      },
      {
        OptionText: "\"Don't worry, Siarl; they won't have time to form an organized defensive line.\"",
        DeltaPBad_Good: 0.03,
        DeltaAsabiyyah: 0.0,
        DeltaPTimid_Dominant: 0.01,
        DeltaWisdom: 0.0,
        Reaction: [
          {
            ReactionText: "Siarl nods. \"I'm ready!\"",
            ConsequenceText: "KillingCattleRustlers"
          },
        ]
      },
    ]

I’m thinking that a good first step would be to get each option’s key/value pairs into a single attribute and parse it from there.

Option1 attribute

      {
        OptionText: "\"Are you afraid of Saxons, Siarl?\" I sneer.",
        DeltaPBad_Good: -0.03,
        DeltaAsabiyyah: 0.0,
        DeltaPTimid_Dominant: 0.03,
        DeltaWisdom: 0.0,
        Reaction: [
          {
            ReactionText: "Siarl looks down, abashed.",
            ConsequenceText: "KillingCattleRustlers"
          },
        ]
      }

Option2 attribute

      {
        OptionText: "\"That just means we'll have more Saxons to kill.\" I counter.",
        DeltaPBad_Good: 0.01,
        DeltaAsabiyyah: 0.0,
        DeltaPTimid_Dominant: 0.03,
        DeltaWisdom: 0.0,
        Reaction: [
          {
            ReactionText: "Siarl doesn't seem much encouraged, but the other troopers chuckle.",
            ConsequenceText: "KillingCattleRustlers"
          },
        ]
      }

Option3 attribute

      {
        OptionText: "\"Don't worry, Siarl; they won't have time to form an organized defensive line.\"",
        DeltaPBad_Good: 0.03,
        DeltaAsabiyyah: 0.0,
        DeltaPTimid_Dominant: 0.01,
        DeltaWisdom: 0.0,
        Reaction: [
          {
            ReactionText: "Siarl nods. \"I'm ready!\"",
            ConsequenceText: "KillingCattleRustlers"
          },
        ]
      }

The high-level plan would be to create child notes from the Option1, Option2, Option3 attributes, with each new note having its own attributes populated from the original text (the screenshot below is just an example, it doesn’t match the text above).

I’d seen (via email) and drafted a reply you the above before it got deleted, but I think your hunch about ingesting the source JSON as separate options makes sense if you want to use stream parsing as then there is only one instance of a ‘field’, e.g. OptionText or DeltaPBad_Good etc., per note.

Whereas OptionText likely most obviously goes to $Text, if you’d like to retain the current note’s $Text for the source JSON code then you could use a user String-type attribute, e.g. $OptionText. For other source fields/keys, if the key name meets Tinderbox attribute naming conventions you might was well re-use the keys as it helps mentally when mapping between systems. If you are using user attributes to store strings and displaying them as Displayed Attributes but they are too long to read on one line, be aware that the line height—see row height-can be altered.

†. For instance, you might want the option to use AutoFentch (via a suitavbly scoped call) to re-call the option’s JSON from the original source. In that case a String-type user attribute $OptionText might make sense. If the JSON key make valid

1 Like

@mwra - Thanks for the suggestion. I have restored my original post for context (I deleted it because I wanted to see if I could figure it out for myself before posting).

1 Like

An approach/aspect that might seem counterintuitive from a coding perspective is to figure out first where eveything will end up. Why? I helps figure out how many Tinderbox tools/operators are needed en route. IOW, if using Stream .captureTo(attr) to match a string and store that in s String type attribute, job done. If the matched string is actually a list of things, etc., it might need further processing. Although you can add variables as you need them, etc., it can help to understand clearly the end outcome of the process. Indeed, it can help to ‘manually’ populate an example end item so that you’re a comparison ‘correct’ example to check your first try/tries at parsing/importing data.

Further benisons of mocking up the end state is that even assuming the ingest is correct (in terms of source), is the result actually what you ant. For instance, you might realise you need to addition fields inot the export template of the source app. Or, as happens, in figuring out how to use the resulting data in Tinderbox for the next task at hand you realise there is a different better way to approach the problem. this saves time on the fine detail of code you then throw away.

Of course, any Tinderbox coding is still practice in the foibles of action/export code, but it is more satisfying if it gets you to, or closer to, where you want to go with needing extra post-processing.