Tinderbox Training Video 31 - Integrating Export Code & Action Code in Your Text

Right, I think I’ve found a way to do this — but using runCommand and sed, rather than internally in Tinderbox.

Just to pull it all together for anyone coming to the thread afresh, the aim is to produce a Table of Contents of a note’s children, in markdown, with each heading a clickable link (for which the markdown syntax is [Heading Name](#heading-name).

The problem is that the method used to collect the headings from the children always add " " around the entries, because lists and sets always do that when ( ) are in a entry, and because replace() can’t deal with ", you can’t post-process the output in Tinderbox to remove the them…

But, if we use the command line program ‘sed’ we can strip the " from the elements.

Basically, we need

  1. A user attribute $SedCommand with the value sed 's/\"//g'. (I’ve put it in a note Config, so reference it with `$SedCommand(“Config”).

  2. A runCommand to apply SedCommand to the relevant set and remove the " into a string which can then be printed. The action code is:

Collect the names of the children and format them in a bullet point clickable list of headings:

^action($MySet=(collect(descendants(this),"[" + $Name+"](#" + $Name.lowercase.replace(" ","-") + ")")).unique.format("**TOC***\n","- ","\n",""))^

Echo the values of $MySet and $SedCommand into a single command run in the command line, and return the quote-less result back into $MyString:

^action($MyString=runCommand("echo '" + $MySet + "' | " + $SedCommand("Config")))^

Export the string in the normal way

^value($MyString)^

The result is:


**TOC**
- [Daily Notes](#daily-notes)
- [Markdown image links redux](#markdown-image-links-redux)
- [Playing with the grandkids](#playing-with-the-grandkids)

Hope this is useful for anyone else who wants to try something similar, and thanks to all on whose ideas this is built.

1 Like

Here’s a method avoiding use of run-Command so avoiding a slower trip out to the command line. this is the template for the container (template ‘md list’ in the demo file):

^action(
   $MyList =;
   $MyString =;
   $MyList = (collect(descendants,$Name)).unique;
   $MyList.each(X){
      $MyString = $MyString + "- [" + X +"](#" + X.lowercase.replace(" ","-") + ")\n";
   };
)^

^value($MyString)^

^action($MyList =;$MyString =;)^

Essentially, we do the concatenation inside an .each(){} loop making a string as we go. We then write out that string to export via ^value()^ tidying up the attributes used so as not to leave unneeded mess.

Note that we don’t need the this offset for the descendants as that is implicitly the case. I also suspect the unique is not needed either unless you have genuinely duplicate descendants (i.e. more than just same $Name).

You can lose one attribute to a variable, but sadly variables can’t be passed to export. But here’s that variant (template ‘md list2’ in the demo file):

^action(
   var vList();
   $MyString =;
   vList = (collect(descendants,$Name)).unique;
   vList.each(X){
      $MyString = $MyString + "- [" + X +"](#" + X.lowercase.replace(" ","-") + ")\n";
   };
)^

^value($MyString)^

^action($MyString =;)^

Here’s a demo of the above: md-list.tbx (105.2 KB)

That’s great, thanks Mark. As I said, I’ve never used loops in Tinderbox before, so it’s good to see how they can help in such circumstances.

To be fair, I’ve never used either runCommand or Sed much either and was quite chuffed when I got that to work as well — I’ve enjoyed learning all this.

Thanks again.

1 Like

Nothing wrong with runCommand and all the cool tools art your disposal and well done for breaking through to their use. :slight_smile:

My last was an alternate as opposed to an outright correction. If I’d not been rushed easier today, I’d probably have got to the loop method first time. As you note the collect issue is known (that aTbref cryptic note is now illustrated!). The Replace fail was more of a surprise but I’ve a feeling that too might be a (now forgotten) known limitation. Were we starting over with computers today I suspect we might have created some non standard text characters to use in code precisely to avoid this issue where it can be hard for the code to guess what the human means, contextually, by ‘(’.

2 Likes

Probably just as well we’re not trying to code Emacs Lisp in Tinderbox…

1 Like

Stupid me, .replace() was fine. I was escaping the wrong, being over focussed on parentheses. Consider:

.replace("{","(")

What’s wrong. We recall the first parameter is a regex. Doh, so both curly and straight brackets are characters with regex roles, so must be escaped, like so:

.replace("\{","(")

The second term is a literal string so the ( has no special meaning there). Thus my profuse apologies to @eastgate for a totally wrong call above.

As a result @brookter’s one-liner can be made to work with a bit of tweaking. First we work around collect() generating quotes in the output by using curly brackets instead of parentheses:

collect(descendants,"[" +$Name+"]{#"+$Name.lowercase.replace(" ","-")+"}").unique.format("","- ","\n","")

Then when the whole string is made, we replace the curly brackets with parentheses.

.replace("\{","(").replace("\}",")")

Here is the whole thing as a one liner. I’ve removed the redundant this reference and the extra parentheses enclosing collect :slight_smile:```
^value(collect(descendants,"[" +$Name+"]{#"+$Name.lowercase.replace(" “,”-")+"}").unique.format("","- “,”\n","").replace("{","(").replace("}",")"))^

Here is my earlier demo with the latter code as a new template 'md list3'. Try it out: [md-list2.tbx|attachment](upload://rgHVvVQoKWrCqEllyJPJJ6T8Nl8.tbx) (105.9 KB)
1 Like

Hah!

Well, if you hadn’t taken that initial wrong turn, I wouldn’t have looked at using sed, or read your tutorial on how to use each in this context, and I’d not have learnt as much — so it’s all good!

But I’m also grateful that you’ve unearthed this single line version as well — most helpful…

BTW, one of the difficulties with getting to grips with some of the arcania of Tinderbox is that really useful lessons like this can be buried at the bottom of threads which started off with something else.

If you don’t mind, I think I’ll summarise the results of this discussion as a new thread with its own title so it’s easier to find — I don’t think there’s been one explicitly considering creating markdown lists from child notes and the use of clickable headers and it may be useful for someone else. Won’t be tonight though.

Thanks again!

2 Likes

Could not agree more, that’s why I started the videos.

Do please. Sometimes it’s much better summarised from the POV of someone for whom the material is new. :slight_smile:

Here’s a summary of the final (much simplified!) position we reached — it incorporates Mark’s later refinements from this thread: Trying to pull a list with ^action()^ and it each item is quotes, how do I get rid of the quotes - #5 by satikusala)

1 Like