Procedure's Parameters Unexpectedly Unavailable in Action Sendmessage Widget

Using the old deprecated macros, one can use text substitution to populate the attributes of an action widget. For example:

\define newTiddlerActionWidget(title: "My Tiddler", tags: "[[My Tag]]")
<$action-sendmessage
    $message="tm-new-tiddler"
    title="$title$"
    tags="$tags$"
 />
\end

If testing this using something like <$button actions=<<newTiddlerActionWidget "Some Title">>>New Tiddler</$button> and click the button, you get a draft of a new tiddler titled “Some Title” (using the parameter specified in the macro call) and tagged My Tag (using the default parameter value).

However, I have found that this will not work if I use variable substitution in the macro instead (using <<__title__>> and <<__tags__>> instead of $title$ and $tags$); it will have no tags and the TiddlyWiki-wide default “New Tiddler” title.

If I use a procedure, since macros are deprecated, I get the same result.

\procedure newTiddlerActionWidget(title: "My Tiddler", tags: "[[My Tag]]")
<$action-sendmessage
    $message="tm-new-tiddler"
    title=<<title>>
    tags=<<tags>>
 />
\end

Since these parameters are needed in widget attributes, I figured I’d try the new attribute text substitution (note that the text substitution below isn’t a procedure thing but simply a widget attribute thing, using the procedure parameters as the variables):

\procedure newTiddlerActionWidget(title: "My Tiddler", tags: "[[My Tag]]")
<$action-sendmessage
    $message="tm-new-tiddler"
    title="$(title)$"
    tags="$(tags)$"
 />
\end

But when I tried this, I literally got a new tiddler draft titled “$(title)$” and tagged $(tags)$.

My initial conclusion was that TW wikifies the “actions” attribute of the button only once, and that the one-time wikification replaces the procedure or macro call with its contents, but doesn’t do any further processing or wikification of those contents, except for macro text substitution. I figured that unlike attribute text substitution within a procedure, macro text substitution occurs in the initial replacement of the macro call with the text of the macro.

But that’s not the reason either; at least some other things get further processed in both macros and procedures. For example:

\procedure newTiddlerActionWidget(title: "New Tagged Tiddler", tags: "[[My Tag]]")
<$action-sendmessage
    $message="tm-new-tiddler"
    title=<<title>>
    tags=<<tags>>
    timestamp=<<now "[UTC]YYYY0MM0DD0hh0mm0ss0XXX">>
 />
\end

When I click a button with the actions defined by that procedure, the timestamp field comes out to the current time in the specified format. (The same holds true for a macro.)

Additionally, if I surround the button with a <$let> widget defining values for title and tags, the variables defined by the $let widget are used. For example:

<$let title="Some Other Title" tags="[[Some Other Tag]]">
  <$button actions=<<newTiddlerActionWidget "Some Title" "[[Some Tag]]">>>New Tiddler</$button>
</$let>

Then if I click the button, the new tiddler will not be titled “Some Title” but “Some Other Title”, and it will not be tagged Some Tag but Some Other Tag.

In other words, the <$action-sendmessage> widget cannot use procedure parameters! It can use variables and macros etc.–for example, the <<now>> macro or variables defined in the <$let> widget surrounding the button. But it cannot use the values in procedure or macro parameters (except text substitution of macro parameters).

Why is this??? I don’t understand it. I’m losing my mind.

(Of course, if I want such a parameterizable action widget, I can always just use variables and set them with some other widget such as <$let> around whatever triggering widget I’m using… so it’s not like I need help on a solution… but I can’t understand why the behavior is the way it is.)

One other edit:

To demonstrate that not all widgets are like this:

\procedure testVariables(var1: "var1", var2: "var2") <$link to=<<var1>>><<var2>></$link>

<<testVariables "HelloThere" 'Link to "HelloThere" '>>

This produces a link to HelloThere with link text Link to "HelloThere", as one might expect. Thus, the <$link> widget can use the parameters of procedures.

I am not going to test all widgets to see if they can use procedure parameters, but my hunch is that the unexpected behavior is specifically for action widgets.

I don’t understand it either, nor do I have a solution. However…

I wish tiddlywiki .com didn’t markup \define as “deprecated” since that mechanism will be supported for the entire lifespan of TW5 (and, who knows, maybe even further). @jeremyruston has pretty much said as much.

We (most of us) know what deprecated means. It shouldn’t therefore be a topic of debate. But when tiddlywiki .com chooses to define deprecated like this…

Deprecated features of TiddlyWiki are those that have been superseded by newer, improved ways of doing the same thing.

Your post (and a wealth of my own code) proves that is indeed not the case.

$0.02.

Thanks for the info!

That said, regardless of deprecation, I also like to limit or avoid text substitution as a rule of thumb when I reasonably can. Even attribute text substitution limits the scope of the text substitution to the attribute so that it can’t mess up some anything other than the attribute value, which is a huge improvement over macro text substitution where the entire contents of the macro can be affected.

Still, good to know I don’t have to worry about losing \define any time soon for the cases where I really do need it.

Added one additional edit with an example to demonstrate that at least some other widgets in procedures have the procedure’s parameters available to them. (Thus, it is not all widgets that behave in the peculiar way pointed out in the post, but only some. My suspicion is that it is all action widgets and no other widgets that behave unexpectedly.)

Reason: TiddlyWiki goes to huge lengths in support of “backward compatibility”.

\define aint going anywhere.

1 Like

You can work around this problem using \parameters pragma.

@jeremyruston – I think we do have a bug here. Adding the default parameters to the procedure definition should do the same thing as using the parameters pragma - right?

\procedure test()
\parameters (title:"My Tiddler", tags:"[[My Tag]]")
<$action-sendmessage
    $message="tm-new-tiddler"
    title=<<title>>
    tags=<<tags>>
 />
\end

<$button actions=<<test>>>click</$button>

When I tried this, the action used default the parameters specified in the \parameters pragma, but it doesn’t seem to let me supply other parameters to the procedure in the same tiddler (i.e., by writing <$button actions=<<test "Supplied Title" "[[Supplied Tags]]">>>click</$button>). And I can’t use the <$transclude> widget to supply parameters because <$button actions=<$transclude ...>>click</$button> isn’t valid syntax.

As far as I can remember, that did never work with procedures. I’m not sure if it is supposed to evaluate macrocalls if they are used as parameter-values.

@jeremyruston should know the answer here.

I’m not quite sure if you mean “that (using parameters in procedure calls like <<proc “p1” “p2”>>) did never work with procedures” or if you mean “not sure if it’s supposed to evaluate(wikify) macrocalls if they are used as widget attributes (<$widget attribute=<<macro-call>>).”

Either way, I think my original post addressed both of those things.

As for the wikification:

\procedure newTiddlerActionWidget(title: "New Tagged Tiddler", tags: "[[My Tag]]")
<$action-sendmessage
    $message="tm-new-tiddler"
    title=<<title>>
    tags=<<tags>>
    timestamp=<<now "[UTC]YYYY0MM0DD0hh0mm0ss0XXX">>
 />
\end

If I use this in a button, the new tiddler’s timestamp field will be set appropriately, showing that the action widget contained in the procedure (in particular: timestamp=<<now "[UTC]YYYY0MM0DD0hh0mm0ss0XXX">>) was fully wikified.

And you can certainly use <<procedure "p1" "p2">>:

\procedure testParams(p1: "p1", p2: "p2") <$link to=<<var1>>><<var2>></$link>

<<testVariables "HelloThere" 'Link to "HelloThere" '>>

Assigning a macro or procedure to an attribute with the syntax attr=<<name>> does not wikify the macro or procedure.

See the docs here for more details:

https://tiddlywiki.com/#Variable%20Attribute%20Values

1 Like

I know this is correct, but, come to think of it, that makes the example of using <<now>> within the procedure even more befuddling (because that does seem to be wikified).

@jeremyruston – There is still this comment: Procedure's Parameters Unexpectedly Unavailable in Action Sendmessage Widget - #6 by pmario – Where the \parameters pragma works for the default values, but the \procedure test(params) to not work.

I think I may have figured it out.

@jeremyruston Are action widget strings, when given as attributes to triggering widgets (for example, <$button actions="[Some action string]" ...>) wikified on triggering events (e.g., on click for buttons or on keypress for edit text widgets)?

If so, that explains all the behavior I found peculiar and I will close the topic.

The <<now>> macro is 1 of 12 javascript macros, which returns a formatted string, that’s why they work that way.

Because it is a JS macro, it will be fully displayed if used directly as the attribute of a widget. That is true. But in all the examples, we were using <<now>> inside a procedure.

And in such cases, <<now>> normally does not get wikified/evaluated:

\procedure linkNow() <<now>>

<$link to=<<linkNow>>>

This creates a link to a (missing) tiddler titled <<now>> (not to a tiddler titled with some formatted timestamp).

So that does not explain why <<now>> was getting evaluated in the examples used in a procedure for the action widget.

So I’m 95% sure I know what’s going on.

I think the answer is that, the body of the procedure is retrieved as is (without any wikification), at which point, not even the <<now>> macro call inside the procedure is wikified/evaluated; but when the user clicks the button, wikification occurs.

At the time of the actual wikification - that is, on button click - TiddlyWiki isn’t wikifying a procedure call, but simply wikifying the string that was given as the actions attribute. Therefore, the parts of the string that were intended to refer to the parameters of the procedure, are actually just unset variables at that point (unless they have also been defined such as by <$let> or <$set> widgets surrounding the button).

Thus, global macros like <<now>> and variables defined in the button’s ancestor <$set>, <$set>, and <$set> widgets get wikified (because they exist in the context of the button), but procedure parameters are no longer procedure parameters at the time of wikification (on button click) and thus are just empty variables.

I will probably mark this comment as the solution, since it is the explanation to all the behavior in the original post.

Hi @bluepenguindeveloper you can make that 100%: your explanation is entirely correct. The inconsistency is frustrating for users.

One way to think about it that can be helpful is to consider <<name>> as always returning plain text, and the context where it is used determining whether the returned text is wikified: text within an element tag is never wikified; text outside element tags is always wikified.

1 Like

@bluepenguindeveloper I feel for you as it has taken me years to come to terms with these issues in part because tiddlywiki achieves what it does through rendering. We instinctively use variables as the name for something and think that is exactly what it contains, and this is not always true, at least until it is displayed in the final render.

The not recommended wikify widget can be used to force this rendering, so the result can be used before the final render. I call this evaluation. Use it to learn but not to design.

The issue is

  • if a macro is javascript it returns a value
  • define or procedure macros can contain wiki text and to work need wikification, thats why they are harder to use before the automatic final render.

With the 5.3.x versions the functions (predefined filters) and back tick attributes, now do this evaluation and create usable content before the final render. Most of these issues you raise can now be overcome.

Functions have their own quirks but allow you do this evaluation when needed as long as you learn how to express it as a filter.

Alternatvly back tick attriblutes can also use filters and even something very similar to simple substitution, and get evaluated before the final render but are only available as attribute values.

I hope this helps.

1 Like

A very informative thread, kind of “learn as you go along”. Excellent.

Thanks @bluepenguindeveloper @pmario @jeremyruston @TW_Tones

:trophy:

1 Like

All this is true. It’s just not “the” issue at the heart of the original post. (I also tried with other available variables that weren’t JS macros, and was confused because, even in the same procedure call, such variables would be replaced with their values, while the procedure’s parameters would come up as empty. It wasn’t merely because the procedure doesn’t get wikified, because if it never got wikified, then even <<now>> would have been spat back out as <now>.)

The issue has to do with the fact that the actions attribute doesn’t get wikified at first, but does get wikified when the user clicks the button - at which point, what used to be procedure’s parameters are getting evaluated outside the context of the procedure call, and are therefore undefined/empty - whereas other available variables (not just <<now>>, but variables defined by <$set> widgets as well) get evaluated to have values (which creates the appearance that the procedure was getting wikified while ignoring the values of parameters).