Getting text of children in a note

I’m trying something that I think I have done in a simple way in the past… but forgot how to do it!

I would like to have as text in a note the text of it’s children.

$Text=collect(children,$text);

In the action field of a prototype should do it, no? But it doesn’t work. What I’m missing?

thanks in advance!

Roberto

You are really close! Attributes are case-sensitive, so you’d want to use $Text instead of $text in your action code.

How are you by the way? How’s the script writing going?

1 Like

Thanks, Michael. I was laughing alone, how could I forget it? But then I correct it and… it’s not working.

Maybe I can do something to find what is preventing the action code to work?

I’m fine, writing a new script and, as usual, evolving my template for it.

Here go, try this. Note, I added in a .replace to get linked breaks between the children text.


TBX L - CollectChildrenText.tbx (91.0 KB)

It’s working. thanks!

And your addition is great. But I can’t make it work. I still get a “;” between the texts of each note in the parent note.

Another question. If I want to gather all the texts in a hierarchy of notes, I should replace “children” by descendants, no?

If you are using the code as in @satikusala’s TBX’s “Collect Children” stamp:

$Text=collect(children,$Text).replace(";","\n");

Without being able to see the code causing your mistake, the likely cause is you omitting the .replace() step.

In the demo file above, we have 3 notes with respective Text: " Note 4 Text.“, “Note 2 Text.”, and Note 3 Text.”.
Using a stamp like below on Note:

$Text=collect(children,$Text);

creates $Text of:

Note 4 Text.;Note 2 Text.;Note 3 Text.

Why? Because collect() returns a list of value as List-type data. Lists and Set data are essentially a String but with a semi-colon between each list item. Thus if $MyList contains values “A”, “B” and “C”, it is stored as the string A;B;C.

Sure enough when we pass the output of collect() to $Text, is is like doing an action:

$MyList = collect(children,$Text);
$Text = $MyList;

This forces Tinderbox to ask, what do I do with List data? As it is essentially a string, $Text now holds the literal stored string content of the list.

The point of the format("formatString") us to tell Tinderbox, give me the list with the list delimiters (the semicolons) replaced by the characters in the formatString argument. The most common list-to-string choices are ", " for a coma+space list, e.g. “A, B, C” or “\n” where each item becomes a separate line/paragraph as in:

A
B
C

It is the latter one (.format("\n") that I think you want, as used in @satikusala’s demo above.

Thanks a lot, mark, for the class! If one day, maybe, I’ll be able to write expressions, it’s thanks to this forum.

I think I have done a mess editing directly the action code of the notes. I chose a note that was "untouched’ used the stamp and it worked.

Last question. If I apply the stamp to a prototype, it should propagate to all notes using this prototype, no?

I inserted it as an action in the prototype. It doesn’t work.

But when I stamp the note with the same code, it works…

No! Because of several things:

  • Although the stamp changes the $Text of the prototype, a prototype’s $Text is only inherited when the prototype is first applied to a note. Subsequent changes to text are not inherited.
  • If a note already has $Text when a prototype is assigned, the prototype’s $Text is not inherited.

If you want to apply this functionality to a prototype use an edict (a rule would be overkill and edicts can be run on demand if needed):

  • Select the prototype and open the Edict Inspector.
  • First set $EdictDisabled to false by unticking the enabled box at bottom left.
    • Why? Because you don’t want the edict running on the prototype itself and generating likely unwanted $Text.
  • Paste your (functioning) stamp code into the Edict code box and press Return. You have now set the code for $Edict.

Now, any note using this prototype will inherit an edict that periodically sets that note’s $Text as a list of that note’s child note titles ($Name)

By ‘action’ I guess you set the prototype’s $OnAdd (‘Action’ tab). As the OnAdd acts on new child notes, it isn’t what you want. You need to use a rule or as suggested above, an Edict.

If I’ve misunderstood, just ask! :slight_smile:

Great, Mark! It works perfectly. Thanks!

1 Like

Dear Dr.Mark Anderson and Mr. Michael Becker
How are you getting on ?
I have two questions.
Using TBX L - CollectChildrenText.tbx,

Question 1
If I have a text written in note 1,
How do I add a postscript using Stamp after the text?
How do I set up Stamp to work?
Question 2
If I have a linked sentence in Note 2, Note 3 & Note 4,
can I make the same change in Note 1 using Stamp?
Sincerely yours, WAKAMATSU

Question 1: The expression

$Text=$Text+"....something....";

appends a string at the end of the text of this note. A convenient thing to know is that “\n” is the conventional way to start a new paragraph. So

$Text=$Text+"\n’Tis true ’tis day, what though it be?";

adds a new paragraph after the end of whatever was in $Text.

Dear Eastgate,
Thank you immediately informative answer.
Sincerely yours, WAKAMATSU

1 Like

You’re welcome. I don’t quite follow the task you describe in question 2, alas.

About issue #2.

I am not sure the exact meaning here. If you use the solution for issue #1 and put that code in a stamp, then the note(s) you stamp will have the same result.

If note 1 has a link to a sentence in the $Text of Note 2, applying solution #1 to Note 1 will have no effect on Note 2.

Also solution #1 is assuming you want to add some text to the end of the contents of $Text. If you need to add text to the end of a sentence inside $Text, then you will need to take a different approach. let’s assume your $text is:

"It is Spring at last. I like roses. It will soon be warmer."

and you wish the second sentence to add " in Spring" (noting that we need to allow for the period at the end too. One way to do this is a stamp like so:

var:string vOld = "I like roses.";
var:string vNew = "I like roses in Spring.";
$Text = $Text.replace(vOld, vNew);

After applying the stamp the $Text is now:

"It is Spring at last. I like roses in Spring. It will soon be warmer."

Dear Dr.Mark Anderson,
Thank you for your detailed explanation.
The explanation for question 2 was insufficient.
I understand your suggestion for question 1.
Suppose Memo 2 has a link to another Note (say Note A).
If I insert this Memo2 into the text of Memo 1, using this method,
it will be added in the middle of the sentence.
However, the Memo 2 sentence I added should have a link to the other Note A,
Is there any way to keep the link to note A in Memo 1?
If possible, it would be great if I could use the Stamp function to do this.
Sincerely yours, WAKAMATSU

Ah. I think the question is … Can I insert text what contains a link into the $Text of another note? If so, no. Links are not stored in the note text, as in a Web page. Instead, Tinderbox uses the older, more powerful, hypertext approach of a ‘linkbase’ (see here). All links are stored separately from the notes. For text links, the link stores the starting character position for the anchor and the number of the characters: both these are calculated against the plaintext version of $Text.

So if using action code copying some $Text that has a link to another note’s $Text, any links are not retained as action code copies only the text and not style, links, etc.

But if you manually select the sentence in note ‘Memo 2’ that links to ‘Note A’ and copy/paste it to the $Text of note ‘Memo 1’ the link to ‘Note A’ should survive. So, ‘Memo 1’ text:

Untitled 2023-04-12 10-08-45

‘Memo 2’ text:

Untitled 2023-04-12 10-09-42

Now, ‘Memo 1’ with the manually copied/pasted $text of ‘Memo 2’ pasted into it:

The note is called ‘Memo 1a’ as I have made a TBX showing before and after states. ‘Memo 1a’ is what ‘Memo 1’ looks like after the paste. Note this is manual. In the TBX I give below, I have made additional pair of notes based on ‘Memo 1’: ‘Memo 1x’. Here I’ve used this stamp on note ‘Memo 1x’:

$Text("Memo 1x") += " " + $Text("Memo 2");

The result:

This proves action code can’t copy/move (pieces of) $Text between notes and retain the text in them. Here is the test file: text-copy-test.tbx (188.6 KB)

If I’ve still misunderstood your Issue #2, I suggest you upload a small TBX file here showing the before and after states so we can see both. That might help us work around the problems of translating between languages. :slight_smile:

Dear Dr.Mark Anderson,
Thank you very much for creating this example.
I think I understand your explanation.
So you are saying that I do manually copy and paste the text that created the link,
and it will be transferred with the information about the location of the link preserved.
For text with links, copy and paste should be performed manually.

Another question.
As question 1
If memo 1 has multiple paragraphs.
How can I modify the Stamp function to specify a paragraph in memo 1 to be appended to another memo?
Each paragraph should have a blank line between them.
If possible, I would like to assign a tag to each paragraph with the name of
”introduction”, ”development”, ”turn” and ”conclusion”.
Your wisdom would be greatly appreciated.
Sincerely yours, WAKAMATSU

Yes!

Handling paragraphs in action code

Or, if you already know the number of the paragraph you want, you can use String.paragraph(paraNum). In the latter case the ‘N’ number is zero-based so the third paragraph would be called as $Text.paragraph(2). So

$Text("Memo 3") += " " + $Text("Memo 4").paragraph(2);

That adds paragraph #2 of note ‘Memo 4’ to the end of the $Text of ‘Memo 3’. Observe that you need to first add a space otherwise the new test is added directly after the period. At least this matter only if you are worried about how the text looks when done! :slight_smile:

If you want to search for a specific paragraph, see String.paragraphList(). In the following example I’m going to use a `.beginsWith() match—and which I know matches only one paragraph. This is just an example to give a working demo, it is up to you how you want to match a paragraph—or multiple paragraphs:

var:string vWantedPara;
$Text("Memo 6").paragraphList().each(aPara){
   if(aPara.beginsWith("We want")){
	   vWantedPara = aPara;
   }
};
$Text("Memo 5") += " " + vWantedPara;

I’ve added these to the demo file: text-copy-test.tbx (219.2 KB). The new stamps have the target note hard coded so it doesn’t matter which note you stamp. Stamp “Copy para #3” copies text from 'Memo 4 to ‘Memo 3’. Stamp “Copy specific matched para” copies text from note ‘Memo 6’ to ‘Memo 5’.

1 Like

Dear Dr.Mark Anderson,
Thank you for all your careful explanations and advice.
I think I understand your explanation in general.
I will take a long course on the features (in your description)
that should be referred to when using Tinderbox.
Thank you very much for your time and effort.
I look forward to your continued guidance.
I would like to express my sincere gratitude.
Yours truly, WAKAMATSU

P.S.
This explanation of [In the latter case the ‘N’ number is zero-based]
reminded me of a mistake I made when using LaTeX using Emacs25
in the past with numbering in Sections.
I wrote it as Section{1}, but the PDF export changed it to Section 2.

1 Like