Procedure's Parameters Unexpectedly Unavailable in Action Sendmessage Widget

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).

We have discuss this in [IDEA] procedure wikify mode · Issue #8072 · Jermolene/TiddlyWiki5 · GitHub before.

I already wasting a lot of time finding solution for this. So I’m wrapping many things in wikify widget recently when using /procedure and /function , while it is not recommended, but there is no other solution for this issue.

This all sounds correct;

Then you say

I don’t think this needs to be so, something else is wrong at my guess.

I think there is an understandable gap in your understanding, my response was a suggestion you use functions because they overcome the issue of macros and procedures not being evaluated before use unless you use wikify.

It is difficult to help you out of this mess with regard to the different replies in this thread. If you want to get further information, make sure your post is self contained and sets out the current problem, in the current reply without the reader needing to understand every reply above.

I already have the answer and avoid wikify totally. I can help if the questions are carefully stated, and illustrated with minimal examples or test cases.

@TW_Tones My 2 problems are stated in the github issue I posted. If you have any idea please answer them there. And the working example is in

And

You are asking me to read a novel just to find the details?

  • If I copy the code above to a tiddler it does nothing and I don’t know what the expected output is.

Please give me more details, or direct links, or restate the problem here. It should not be hard work to voluntarily help someone.

1 Like

The issue (my initial misunderstanding) is solved, so there is no longer any need.

Thanks for letting me know. I assumed that a self-contained post describing a self-contained current problem should be a new topic, and I assumed that the context of these posts within a topic is generally understood to be the original post of the topic, except where other posts or other material is quoted or linked. I didn’t want to repleatedly quote lengthy passages from the original post in several comments just because my focus never strayed from the original post. I guess I’ll have to have another look at the forum rules and guidelines.

My original post (which is what my focus has been on the whole time) wasn’t looking for any solutions or how-tos. It was looking for an explanation of why my code samples behaved the way they did:

Since the many-replied thread has been confusing to follow, I’ll recap what I have been trying to get at the whole time, in a self-contained way.

Here’s a code sample to start.

I was trying to understand why the parameters (title and tags) weren’t reflecting in the new tiddler, and I speculated at first that it was because they weren’t wikified (which is actually correct, and yes, when others gave that answer, it was correct when they gave it, too). (In the original post, I actually phrased it not as “not getting wikified” but as “getting wikified only once” - referring to the replacement of the macro call with the macro body as “getting wikified only once” - because Grok TiddlyWiki explained it as getting wikified only once to replace the macro call with its body but not further wikifying the contents.)

But I thought (at first) that lack of wikification couldn’t possibly be the reason, because:

This seemed to show that the text of the procedure clearly was getting wikified. And it wasn’t just <<now>>, but even other variables were evaluated (replaced with their values and assigned to the tiddler fields on button click):

I was observing that in the body of the procedure, both <<now>> and things like <<title>> (only when defined in the <$let> widget) were getting replaced with values, showing that the body of the procedure was getting wikified even though the procedure call was being used as a widget attribute - which seemed to contradict what others had correctly been saying.

The only way to clear up my confusion was for me to realize that the actions attribute string gets wikified on button click. Until I realized that, nothing anyone could tell me about JS macros being evaluated or when procedure calls don’t get wikified would convince me, because I had clear evidence that the body of the procedure was getting wikified. (More accurately, the action string was getting wikified when it was no longer the body of the procedure. That’s what I didn’t realize at the time.)

That is why I say that the actions string getting wikified on button click and not on procedure call was the issue at the heart of the original post. Once I understood that, I could understand how it can be true that procedure calls aren’t wikified when used as widget attributes, even though I was seeing wikification.

And once I understood this, all the behavior that was confusing to me became clear:

  • When the procedure is “called”, the procedure call is replaced with the procedure body as is (with no wikification, not even <<now>> is evaluated, it is just part of a string)
  • But on button click, the action string is wikified, but it is no longer in the context of the procedure body
  • Therefore, variables that existed (with values) in scope of the button widget were, on button click, replaced with their values (or in the case of <<now>>, the JS evaluated–that difference never part of what was confusing)
  • But at the time of the button click, parts of the action string that were intended to be the procedure’s parameters (like <<title>>) were not defined (unless they were separately defined and in scope, such as by the <$let> widget).
  • (On the other hand, text substitution in macros occurs as part of the replacement of the macro call with its body, prior to any wikification. That’s why using text substitution with macro parameters allowed the values given as parameters to ultimately show up in the fields.)

Is this cleared up now? The “not merely” referred to the fact that the totality of the behavior that seemed inconsistent and confusing to me (indeed, my confusion about the procedure call not getting wikified was fundamentally tied to the fact that I was seeing other variable references in the procedure body get values) was due to the fact that the action string was getting wikified on button click. The procedure call not getting wikified is the reason why parameters were getting “ignored” (as I put it when I didn’t yet understand it), but it is not why other variables in the procedure body were getting values.

If you still think so, please explain. I have laid out my complete understanding of the matter (along with what I had misunderstood before, according to my present understanding) in this self-contained post, so now you won’t have to try to sort through a mess of threads to identify the gap in my understanding.

1 Like

Its late here, I will look at in detail tomorrow + 9 hours. But can you show me how you invoke or call the procedure?

These are easily the same thing.

Greate.

Notes:
I have reproduced the problem, on TiddlyWiki.com and it is confusing. This needs to be addressed here is my code example;

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

<$button actions=<<newTiddlerAction "via actions">> >
Go fails
</$button>

<$button >
Go works
<<newTiddlerAction>>
</$button>

As far as I can see so far, the actions parameter is not working. It appears to be a Bug.

  • I will investigate further.

Not according to this:

image

https://tiddlywiki.com/#Variable%20Usage

Since the actions parameter seems to be failing here is a workaround.

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

<$button actions=<<newTiddlerAction "via actions">> >
Go fails
</$button>

<$button >
Go works
<<newTiddlerAction>>
</$button>
  • Rather than provide the parameters in the procedure clause do it with the parameters widget.
  • I would however suggest you look @bluepenguindeveloper to using a unique title because if the tiddler already exists it edits it again.

The problem

The failure to use the parameters in an actions procedure seems to me a serious bug that needs to be addressed. I have found the same on tiddlywiki.com but we need to check another version or empty.html to see if it occurs elsewhere.

1 Like

It implies differently here Pragma: \procedure

But this seems a veritable mess. It means the procedure cant be used effectively as actions parameters?

And my example workaround above contradicts this?

Or am I missing something?

No worries, and no need to hurry.

Looks like you have already seen that I was calling the procedure to populate the actions attribute of a button widget, and your first code sample (with the “Go Fails” button) is equivalent to mine.

Body text [of procedure] is retrieved as-is and used as the attribute’s value [when invoked via widget attribute <div class=<<macro>>/>

I just read that whole thing… where does it imply differently?

Not sure. When I tried your examples at tiddlywiki.com, both buttons produced a tiddler tagged My Tag but used the default unused title. I believe this part of your workaround snippet is the reason: {{{ [<new-title><unusedtitle>] }}}. The <unusedtitle> is a title constructor and thus <new-title> is ignored. I’m not quite sure what you were intending… perhaps something like {{{ [<new-title>!match[]else<unusedtitle>] }}}? If I make that replacement, then both of your buttons in the workaround result in opening Draft of ‘New Tagged Tiddler’. (Note that the “Go Fails” button in this case still opens Draft of ‘New Tagged Tiddler’ and importantly, not Draft of ‘via actions’. The default parameters are being used, while the value given in <<newTiddlerAction "via actions">> is not used.)

In my analysis, these results are consistent with the statement that the procedure body is copied into the widget attribute value as is, but I’ll spare you my analysis for now - at least until you confirm if my observation about {{{ [<new-title><unusedtitle>] }}} solves anything for you.

This is a great tip, thanks!

Sorry, I made a mistake, I just meant to leave <<new-title>> there.

This what we call unwikified. That is you get the content of the macro or procedure without it being rendered before using it an an attribute.

  • To have “dynamic attributes”, once that are evaluated, we can use functions, backtick attribuites, Triple curly braces {{{ }}} calleds filtered transclusions.
  • Do you not want the edit mode?
  • It is a new tiddler so it is not the drafty of anything.

Thanks, I will adjust my terminology accordingly.

No, I was just observing that the value of <<new-title>> ended up as “New Tagged Tiddler” (the default parameter defined by the \parameters pragma) and not “via actions” (the parameter given in the procedure call <<newTiddlerAction "via actions">>).

Possibly. The image of the documentation I posted shows how \define and \procedure differ when a given variable (or macro) is called – in this case (your code) accessing the variable via a widget’s attribute assignment.

Not that I can see. That tiddler (page) does not discuss attribute assignment. It should, probably, but it doesn’t.

One thing is certain (to me), https://tiddlywiki.com/#Variable%20Usage is hard to fully grasp in one sitting.

A couple of observations here.

There are two differences between the buttons. To isolate just one difference, try adding a parameter to the second button:

<$button >
Go works
<<newTiddlerAction "Not via actions">>
</$button>

If you do this, you will see that the “Go fails” button opens a new tiddler with the default parameter value (as specified by the $parameters widget), while the “Go works” button opens a new tiddler with the title specified in the macro call (“Not via actions”). So even with the workaround the results of the two buttons are not the same. (This is because the procedure body is wikified when it is called in the “Go works” button, but not in the “Go fails” button.)

The behavior, in both your original procedure and in the workaround can be explained by manually replacing the “Go fails” button with the unwikified procedure body.

The first example:

By replacing the procedure call with the procedure body, we see that the button is essentially equivalent to:

<$button actions='<$action-sendmessage $message="tm-new-tiddler" title=<<new-title>> tags=<<tags>> timestamp=<<now "[UTC]YYYY0MM0DD0hh0mm0ss0XXX">> />' >
Go fails
</$button>

When you click the button, that action string gets evaluated, but in a context where <<new-title>> and <<new-tags>> are not set. They’re empty.

(Whereas in the “Go works” button, the procedure body is wikified at the time of the call, and thus, whatever is specified in the procedure call is used for the title and tags, unless empty, in which case the procedure’s default parameters are used.)

In the workaround:

If you replace the procedure call with the procedure body unwikified, you essentially get:

<$button actions='<$parameters new-title="New Tagged Tiddler" tags="[[My Tag]]">
<$action-sendmessage $message="tm-new-tiddler" title=<<new-title>> tags=<<tags>> timestamp=<<now "[UTC]YYYY0MM0DD0hh0mm0ss0XXX">> />
</$parameters>' >
Go fails
</$button>

In this case, when you click the button and the action string gets evaluated, the action widget is surrounded by a <$parameters> widget, which gives default values to <<new-title>> and <<new-tag>>. That is why the workaround results in the default parameter values getting used.

To me, this isn’t a full workaround. I would want whatever I passed in to the procedure call (in this case, “via actions”) to take precedence over the procedure’s default parameters (like it does if you modify the “Go works” button to pass parameters).

I figured out a fairly simple way to achieve that using the $transclude widget to call the procedure:

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

<$button actions='<$transclude $variable="newTiddlerAction" new-title="via transclusion"/>' >
Go really succeeds
</$button>
2 Likes

I now see why I don’t normally face this problem.

At most I name the actions macro or procedure, I don’t typically use any parameters within the calling of the macro.

<$button actions=<<newTiddlerAction>> >
Go button
</$button>

To accommodate this you can do as much as you want in the newTiddlerAction procedure.

  • For example in the procedure determine the tiddler title using the currentTiddler variable.
  • Rather than something as generic as “newTiddlerAction” I would normally call this something like newTodoTiddler and in that I would set the todo tag.
    • In an action procedures you can have other tiddlywiki script, it need “not only be” actions.

However If I really wanted to parametize the new tiddler button, I would even move the button into a procedure.

\procedure newTiddlerAction()
<$action-sendmessage $message="tm-new-tiddler" title=<<new-title>> tags=<<tags>> timestamp=<<now "[UTC]YYYY0MM0DD0hh0mm0ss0XXX">> />
\end newTiddlerAction

\procedure new-tagged-tiddler(new-title:"default" tags:"default")
<$button actions=<<newTiddlerAction>> tooltip=`tagged $(tags)$`>
New <<new-title>> tiddler
</$button>
\end new-tagged-tiddler

<<new-tagged-tiddler "Tagged Tiddler" "[[My Tag]]">>
  • You can see here I use the parameters to the new-tagged-tiddler procedure as it effectively sets the new-title and tags variables. This is how procedures work, the parameters become variables.
  • Then when the button calls the newTiddlerAction I do not need to give it parameters, because this info is already available in the known variables.

However now we can define newTiddlerAction within new-tagged-tiddler

\procedure new-tagged-tiddler(new-title:"default" tags:"default")
   \procedure newTiddlerAction() <$action-sendmessage $message="tm-new-tiddler" title=<<new-title>> tags=<<tags>> timestamp=<<now "[UTC]YYYY0MM0DD0hh0mm0ss0XXX">> />
<$button actions=<<newTiddlerAction>> tooltip=`tagged $(tags)$`>
New <<new-title>> tiddler
</$button>
\end new-tagged-tiddler

<<new-tagged-tiddler "Tagged Tiddler" "[[My Tag]]">>
  • I am now working on the best way to make a unique tiddler title, based on the one in the parameter, that works with tm-new-tiddler message, however if you change this to an ActionCreateTiddlerWidget this is built in.

The final solution?

Rather than call the above procedure “new-tagged-tiddler” with the short call syntax, use the macrocall widget (Yes it still works for procedures), you could use the <$transclude $variable=new-tagged-tiddler ... way if you want. I then call the above procedure, with the unused title macro providing the title name.

<$macrocall $name=new-tagged-tiddler new-title=<<unusedtitle baseName:"Tagged Tiddler">>  tags="[[My Tag]]"/>

Please note all the above are working examples on tiddlywiki.com

[End Note]

  • If you provide parameters to your actions macro, if they worked at all, they are defined when the button is displayed, so they are fixed, by keeping the actions parameter limited to a unparametised macro, the content of newTiddlerAction will be determined when the button is clicked.
  • The problem is not giving the actions macro, parameters, but giving it parameters that first need to be evaluated, literal strings should be fine.

Is this referring to giving parameters when using the <$macrocall> widget (as in your Final Solution)?

Yes and No, Not within the buttons actions= attribute, but yes when called from the body text, as its above.