What is the relationship between the stamp entered in the Document Inspector Stamps dialog window and the same stamp located in the /Hints/Stamps folder.
I have one Tinderbox document where it seems that editing in one changes the other.
But I have another Tinderbox document where they do not seem to be connected at all.
What is the proper sequence of initiating a stamp and where is that done? In the Document Inspector or in the /Hints/Stamps folder? Does it (should it) make a difference?
They ought to be connected. In a very large document, that connection might be delayed for some seconds. If thatâs not the issue, Iâd like to see the document (bernstein@eastgate.com).
It is a very small document. I will upload it to you with an explanation of what I am attempting to accomplish. Thank you.
For other readers there are 3 ways to run a stamp and none is more correct. Rather, the choice reflects task context or style of work.
Leaving aside the glitch being resolved above, stamps are created in one of two places:
- The Document Inspector, Stamps tab. This is the original way of entering stamps. All stamps in the current TBX are listed in the top list box. If multiple TBX are open the Inspector shows the stamps only for the front-most (currently active) TBX. The lower box holds the stamp code. De-focussing the input box saves the code present at that timeâthere is no âSaveâ button as such.
- The Stamps folder inside the
/Hints
container. The latter does not exist by default, but adding it to a TBX adds a container with each stamp as a note whose $Name is the stampâs name and whose $Text is the stampâs code. A stamp is added here by adding a now note to the container and typing the stamp code into the note $Text. Additions/deletions here are reflected in the Inspector. If the/Hints
container were to be deleted (unlikely!) the stamps are retained and still visible in the Inspector.
All stamps defined in a document (by either/both of the above methods) are listed in the TBXâs Stamps menu.
Stamp code can also be accessed in action code via the stamp([scope, ]stampName) operator.
This allows for 3 equally valid methods to initiate a stamp:
- The Document Inspector, Stamps tab. As long as one (or more) notes are selected in the current view pane, and a stamp is selected in the top list box, the âApplyâ button is active. Pressing it runs the selected stamp once on each selected item.
- The Stamps menu. Clicking an item in this menu runs the chosen stamp one on each of the item(s) currently selected in the view pane.
- Action code. Calling the stamp([scope, ]stampName) operator runs the nominated stamp (in argument
stampName
) on the note in current action code focus.
A stamp created in one context should be callable/usable in any of the other methods.
The âbestâ choice of calling a stamp is subjective. In a long-lasting document, once youâve set up and understand the use of a set of stamps, the Stamps menu is probably most convenient trigger.
As regards stamps when still testing/tuning them. As the Inspector shows the code in Inspector it is easy to see the stamp code whilst the main UI shows the note(s) being stamps so the effect of the stamp is easily assessed. The Inspector can be dragged larger to increases the size of the code box, but my experience is that if/once stamps contain a lot of action code (i.e. many lines), using the Stamps container is easier.
Why so? Because when a stamp note is selected the whole of $Text holds the stampâs code, making it easier to see the layout (e.g. if youâve conditional branches or loops). If using stamp notes, then you will need to use the stamps menu to call the stamp. This leads to one further tip for testing: open the stamp you are working on as a stand alone window. Now the main app window can select (focus on) the note to be stamped. For those with bigger/multiple screens this means you can see the stamp code and the stamped note(s). When making regular use of the stamp during creation/testing of new code, it is then easy to (re-)edit the stamp code, run it via the stamps menu, see the effect on the stamped note in the main window. Rinse/repeat until the stamp is correct, at which point you can close the standalone window as the stamp code is essentially finished.
A reinforcing point here. Tinderbox is a toolbox not a set of push-for result wizards, unlike many apps. Thus while there may be bad/wrong ways to use a feature there is often no one right way. âRightâ is a balance of task type and personal style.
HTH
I received a very helpful reply from Mark Bernstein. This is what he said:
I think your stamp likely IS running, but itâs not doing what you expect.
When I worry that an action isnât running, I add an extra statement that does something I cannot miss. Some examples:
if ($Color==âredâ) {$Color=âgreenâ} else {$Color=âredâ}
show(âI made it!â);
speak(âhereâ);
Specifically to your stamp, consider this line:
if (aLine.contains(â$Audio-Transcriptionâ)){$TanaVoiceCaptureLink=aLine.substr(22);};
Unfortunately, .contains(âŚ) searches for strings that match a regular expression, and in regular expressions the symbol â$â matches the end of a line. So this will never match.
Some more info on the .contains() operator.
My hunch is that where you used:
if (aLine.contains("$Audio-Transcription"))
you wanted to test the value of the attribute named âAudio-Transcriptionâ. If so, the code would be:
if (aLine.contains("Audio-Transcription"))
Unwittingly, your present code looks for a string value stating with (i.e. invoked by the regex ` special character) the characters âAudio-Transcriptionâ
An edge case remains. Iâll add it, lest a completist ask: but what if you wanted to match a literal string value â$Audio-Transcriptionâ? If so, then youâd use this code:
if (aLine.contains("\$Audio-Transcription"))
The added backslash tells the Tinderbox parser treat the next character, i.e. the `, as a literal character. IOW, treat it as a dollar-sign character and not as regex start of string marker.
So if you want to reference an attribute or action code variable value, donât use enclosing quotes. so for an attribute âAudio-Transcriptionâ:
if (aLine.contains($Audio-Transcription))
Or, a variable âvAudio-Transcriptionâ:
if (aLine.contains(vAudio-Transcription))
Note the absence in both cases of enclosing quotes. Regex are powerful and precise and all this can be baffling at first encounter. But, if your .contains()
query fails, step back and ask yourself, am I testing:
- a literal string
- a regex pattern
- an attribute or variable value
Tinderbox treats the first two the same wayâas a quoted stringâand assumes any regex special characters are just that unless you escape them. If there are no enclosing quotes inside the operatorâs trailing parentheses, Tinderbox will look for an action code object (attribute/variable/function) of that name, and use its value.
What I am attempting to do in this particular .tbx file (which I have done successfully in other .tbx files) is the following:
- The input note is a .md file generated by Xojo that assembles other .md files from Tana Voice Capture and Otter.ai of voice transcriptions and summaries from YouTube training lessons. I was identifying the captured meta data and identifying it with that â$â symbol (which I now understand is a regex symbol and have replaced it with a â symbol) at the beginning of lines that I wanted to use to populate attributes in Tinderbox.
- Then, using a stamp to parse the contents of the .md file pasted into Tinderbox, populate the note, populate notes for keywords, and explode the note into separate transcriptions and summaries for this video.
- I have another use case for processing Kindle highlights similarly that works without a hitch.
- But I am now back to the original problem I encountered: The code for the stamp located in the /Hints/Stamps container does not interact with the code in the Documents/Stamps dialog box. If I make a change in one location, it is not replicated in the other. And it seems like the only response to the menu selection of the desired stamp works with the code in the Documents/Stamps dialog box and not the code in the /Hints/Stamps container.
- Since this is still a small enough Tinderbox instance for this project, I am just going to start with a new, clean Tinderbox document (and yes, I have just upgraded to 10.0.2) and try again.
The code for the stamp located in the /Hints/Stamps container does not interact with the code in the Documents/Stamps dialog box. If I make a change in one location, it is not replicated in the other.
OK: I suspect that, in addition to other questions, thereâs something amiss here. This may take a couple of days.
I initiated a nascent .tbx document and built the container structure and stamps, and this one is working as expected.
I suspect that I broke some internal ID linkage dealing with the stamps in the broken .tbx document. This is likely a fluke edge case, and whatever it was that I did, has a really low probability of happening again.
Thank you all for your help.
Just received a note from Mark Bernsteinâhe found my error. This was his diagnosis:
Tinderbox locates its collection of stamps by finding /Hints/Stamps. Unfortunately, your document had a separator, also called Stamps â and that separator has no children:
If there are two notes /Hints, Tinderbox chooses the first one. So, Tinderbox decided you did not want to use the Hints folder at all.
Sure enough! That is what I did. It didnât occur to me there is a connection between the names of separators and containers.
This exposes a misunderstandingâalbeit unintentionalâof a wider point about $Name in Tinderbox: Uniqueness, duplicates and matching notes. It is quite natural to assume the app somehow knows what we consider to be different, but in cases of failure like above then (unintended) naming collisions are a thing to look forâ .
Tinderbox is happy to have a document where several, indeed all notes/containers have the same name, as each note has a unique $ID. But such use is likely a show-stopper for any task using a user query or doing a task requiring internal queries of the TBX by the app. This is because, where there is more than one match for a $Name value, Tinderbox uses the first match by $OutlineOrder as the item to use.
In a user query, this can be mitigated by using $Path instead of $Name. If the same-$Name notes are in the same container, then $ID or $IDString needs to be used in place of $Name in the query.
But here, the look-up is internal so we users canât insert a $Path or $ID as an alternate identifier.
A separator is essentially a note with a special (Outline view) presentation and purpose. Originally intended as a note only, by mistake it allowed nesting (i.e. acting as a container) and users asked to keep that featureâso it stayed. But separators like adornments or agents are addressable objects so when naming them do consider naming collisions.
Tip. Worried about possible duplicate $Name values and how to find them? See isDuplicateName().
â . This has been, and remains, a challenge when writing a resource like aTbRef and explains why sometimes my articleâs source note $Name might seem longer or more specific than necessary: duplicate $Name values, where possible, should be avoided.
BTW, this is why Iâve adopted a note-naming strategy for my âatomic resourceâ and project notes vs. my writing notes. My resource notes get a prefix, e.g., ent-, prod-, crs-, proj-, trm-, etc. This helps me stray from duplications that may lead to experiences like the one noted here. It also helps with discovery and action code operators.
As a side note, if you use Preview as I do, you may also run into a problem when notes are named the same within the same container. When you try to preview, Tinderbox will preview the first note rather than any following, not that youâre trying to look at. it is part of the design tradeoffs that I believe @eastgate needed to make. My solution for this is to assign the $ID to the $HTML ExportFileName, that way my exported note name are guaranteed to be unique regardless of the note name and preview and export will always work. For me, I donât need the file name on the hard drive to be human-readable, so file names with strings of numbers is just fine. Weâve covered this point in meetups in the past.