Problem importing contents of a macro definition from a TWCore shadow tiddler

Hi all,

I am working on improvements to my TiddlyTools AutoSaver, and I’ve run into an odd problem that I can’t figure out…

I want to get the list of tiddlers that will be saved when the core tm-save-wiki message is processed.

This list is defined by the <<saveTiddlerFilter>> macro in $:/core/save/all, which has the following contents:


\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\define saveTiddlerFilter()
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]]
-[status[pending]plugin-type[import]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]]
-[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
\end
{{$:/core/templates/tiddlywiki5.html}}

When I try to get the contents of that macro by using the following code:

<$importvariables filter="$:/core/save/all">
saveTiddlerFilter is: <$text text=<<saveTiddlerFilter>>/><br>
</$importvariables>

The text of the macro definition is blank! This is also the case if I try to retrieve the list as a variable, using:

<$importvariables filter="$:/core/save/all">
<$set name="tids" filter=<<saveTiddlerFilter>>>
saveTiddlerFilter is: <$text text=<<tids>>/><br>
</$set>
</$importvariables>

Any thoughts as to why this isn’t working?

-e

1 Like

Hi Eric,

From what I recall of the $importvariables widget it only works under a pretty narrow set of conditions (only $set widgets in the parse tree). I believe the presence of the import pragma in the tiddler that is being imported from, is causing the import to fail.

try: <$importvariables filter="[[$:/core/save/all]]">

edit: … did test it … it doesn’t work … I’m running the debugger atm

There seems to be a problem, if the tiddler that is imported also contains an <$importvariables widget. … The parse-tree, seems to contain the macro definition, but the while loop doesn’t find it.

I think you are right. I just tried:

  1. Clone $:/core/save/all to $:/core/save/all2
  2. Edit $:/core/save/all2 and remove the \import pragma from the first line
  3. Then, I tried:
<$importvariables filter="$:/core/save/all2">
saveTiddlerFilter is: <$text text=<<saveTiddlerFilter>>/><br>
</$importvariables>
  1. and it displays the value of <<saveTiddlerFilter>>!!!

Of course, this isn’t really a solution for my purpose, since I am trying to get the value directly from the shadow tiddler, and cloning the shadow isn’t really a viable option. My current workaround is to simply copy the definition of <<saveTiddlerFilter>> from $:/core/save/all and just paste it into my code. Of course, if the TWCore shadow definition is ever changed, I’ll have to remember to update the copy in my code to match the new TWCore definition.

I cannot think of a clean solution either at the moment and it would be worth giving some thought to how we could refactor the core template for reusability.

Regarding the behaviour of $importvariables, I cannot look at the source code at the moment but as I recall, the $importvariables widget assumes the parse tree starts with a $set widget and any children of that first $set widget are also $set widgets (which includes macros). Any sibling $set widgets of the first $set are also ignored. Not very intuitive and something we are tied to by backwards compatibility.

That’s right. …

It’s tricky. $:/core/save/all needs the \import pragma, because of the $(publishFilter)$ variable substitution in the saveTiddlerFilter macro. … So if the macro should be resolved in the right way, we would need to evaluate the $importvariables widget recursively :confused:

If we could solve the $(publishFilter)$ problem in a different way, the \import pragma could be removed again.

That is correct: <$importvariables> only imports <$set> widgets, and doesn’t recognise <$importvariables>, <$vars>or <$let>. I don’t think we could change it without breaking strict backwards compatibility, but it would be very useful.

Any sibling $set widgets of the first $set are also ignored. Not very intuitive and something we are tied to by backwards compatibility.

It’s not obvious what if anything we could do with such sibling widgets. Hoisting them up into the first $set widget would change the semantics.

What about a new <$usevariables> widget?

I actually think that in this case the backwards incompatibility is harmless.