[v5.4.0] Dynamic parameters for macro/procedure/function calls

Introduction

I am both pleased and embarrassed to announce a new PR that is planned for v5.4.0. It makes an important change to the handling of macro calls by finally allowing parameters to be specified as dynamic transclusions instead of just constant strings.

PR: Dynamic parameters for macro/procedure/function calls by Jermolene · Pull Request #9055 · TiddlyWiki/TiddlyWiki5 · GitHub

Preview build: https://deploy-preview-9055–tiddlywiki-previews.netlify.app

By changing the usual colon into an equals sign it is now possible to do things like this:

<<mymacro param={{Something}}>>

Or even this:

<div class=<<mymacro param={{Something}}>>>

Not to mention this:

<div class=<<mymacro param={{{ [<myvar>addprefix[https:] }}}>>>

We can even specify parameters for the inner call:

<div class=<<mymacro param={{{ [<innermacro p={{Something}}>addprefix[https:] }}}>>>

I am pleased about this change for obvious reasons: it removes a long-standing irregularity from TiddlyWiki’s syntax, and it adds flexibility and expressiveness that will be appreciated by all wikitext authors.

The reason I am embarrassed is that it has taken so long to address this issue, particularly as it has turned out that the implementation is not enormously complex. In mitigation the changes in v5.3.0 laid a lot of the groundwork for this change.

Background

In fact, “macro calls” has become an increasingly ill-fitting term since v5.3.0 when the same syntax was extended to allow it to be used to invoke functions and procedures. I propose we use the term “call” to refer generally to all three formulations, and “macro call”, “procedure call” and “function call” for the specific variants.

The call syntax can be used in three different settings:

  • As a standalone construction
  • As a widget attribute value
  • As a filter operand value

In all cases, it is now possible to use an equals sign instead of a colon to allow parameter values to be passed as a transclusion, filter expression or nested call.

Backwards Compatibility

The backwards compatibility issues with this change are fairly extreme edge cases. In particular, previously a construction like this would have been interpreted as an unquoted parameter with the value “name=background”:

<<mymacro name=background>>

So, this change will break code that invokes a macro with an unquoted parameter that contains an equals sign. There is no restriction on parameters with double or single quotes.

Progress

This PR is not yet complete:

  • [ ] Enforcing new syntax to only work with equals signs (currently equals and colon are considered equivalent)
  • [ ] Calls within filters
  • [ ] Documentation
  • [x] Calls as attribute values
  • [x] Standalone calls

Idea: Block Parameters

I have been toying with the idea of further extending the call syntax to allow blocks to be passed (which would be $fill widgets under the covers). This would allow for things like an inline version of the tabs macro:

<<inline-tabs mode="vertical"
:> Help
Some useful and interesting content, including wikitext like <<now>>
:> About
More useful and interesting information.
>>
12 Likes

this is incredibly convenient, thanks! if nested calls are supported, does that allow for recursion in the shortcut syntax as well?
<<myprocedure param=<<myprocedure>>>> :thinking:

This is very welcome!

I’ve gotten to the point where I rarely make the mistake of trying to do this in my new code, but the switch from the nice shorthand syntax to a full transclude widget is a jarring break to my workflow. It’s also the source of endless questions here in these forum. Having it just work as one would hope/expect will be a serious relief.

I wonder about two things. First:

and

Is that a problem? I know there have been requests – here at least, if not on GitHub – to make these equivalent. I often use <<list-links>> as scaffolding. Switching it to a <$list> when I’m ready is mechanical: take out the initial angle brackets and the final one, change list-links into $list, add contents and the end tag <$/list>, and replace the filter: with filter=. Far too often I end up forgetting that last step and have to scratch my head for a few seconds before seeing it. When I was a beginner, that would often be a few minutes. Is there some technical reason that these could not become interchangeable, with the possible goal of one day deprecating the : -version? It would just feel more consistent with widgets and plain HTML. Moreover, requiring users to use one symbol for dynamic parameters and another for static ones just sounds confusing. Are there technical reasons this would be required?

Second, block parameters sound like a really good idea, but could I suggest that they be a second PR built atop the first one? The dynamic parameters are an obvious idea with obvious syntax, and except for the :/= confusion above, should cause no concerns from anyone. Block parameters involve a very new syntax, one that might be a bit controversial. I would hate for objections to the latter to slow down the former.

Not without a base case, damn it! :wink:

2 Likes

@jeremyruston this is an opportunity I have being interested in for some time, I think you imply it, but do we retain the : format at the same time?

I think it does no harm permiting both and it will help transition,
Even if colon is depricated, although hopefully not.

I would assume <<mymacro param="{{Something}}">> would still pass the literal text {{Something}} rather than evaluate it first?

  • The reason I ask it is helpful to keep in mind what if the designer wants to use, build or manipulate tiddlywiki itself. That is maintain the ability to get all meta so for example a smart solution may generate tiddlywiki statements.

and we could use backtick evaluation as well?

<<mymacro param=`Something`>>

About $fill

As raised previously we have the ts-raw slot but it would be helpful if we have a ts-body that returned the body without other fill definitions, and this may assist building this new dynamic parameters.

Thanks @jeremyruston for your ongoing love and attention to TiddlyWiki :heart:

1 Like

Actually, I use this to detect if I have mistakenly used = instead of : when using a certain macro (which happens more often than it should and in this case leads to weird output that can be difficult to detect at first) by checking if the first parameter string contains a =. Since this will no longer cause problems with the proposed change I do not think this is an edge case that needs to be considered, though.

Please merge my to-string PR before making syntax change…While I like this new feature, but I hope you could also write the serialization part for it :wink:

We may need to work together on this; there’ll be more work involved than if we were just adding a new parse rule.

1 Like