Help: macro with complex parameter

I want to write a macro that accepts one argument with the following logic:

  • the argument can have ‘|’ acting as separator.
  • If there is just one element (no ‘|’), then set ‘tiddler’ to it
  • if there are two, then set ‘tiddler’ to the first, and ‘anchor’ to the second
  • if there are three, then set ‘text’ to the first, ‘tiddler’ to the second and ‘anchor’ to the third.
1 Like

Hi @Ittayd!

You can retrieve the desired element from an |-separated argument using the following filter:
[<arg>split[|]nth[1]]
where <arg> is the argument, and the parameter of the nth[] operator indicates which part you want to retrieve. So e.g. output of [[a|b|c]split[|]nth[2]] is b.

What exactly do you mean by this? Do you want to set the values of the variables text, tiddler, anchor, and have these variables available inside the macro? You could do it like this (if using newer TW version it’s better to use procedure instead of macro, although it would be very similar for macro):

\procedure foo(arg)
<$let
    tiddler={{{ [<arg>split[|]nth[1]] }}}
    anchor={{{ [<arg>split[|]nth[2]] }}}
    text={{{ [<arg>split[|]nth[3]] }}} >

<!-- the rest of your procedure/macro -->

</$let>
\end

Edit: I edited the discussions’s title to make it a little bit more informative.

One more thought. I don’t know the context, but it might not be necessary or worth it to use a complex parameter and then split it. If the parameters in the macro/procedure call are given in the same order as in the macro/procedure definition, they do not have to be named in the macro/procedure call.

So instead of <<foo "a|b|c">> and then splitting the parameter, you could do <<foo "a" "b" "c">>. If you use a procedure instead of macro, you can even skip the $let widget in the procedure definition, as the parameters are automatically assigned as variables:

\procedure foo(tiddler,anchor,text)
<!-- the variables tiddler, anchor, text can be used within procedure definition here -->
\end

if arg will be “a|b|c” then tiddler will be “a”, anchor will be “b” and text will be “c”. But in this case I want text to be “a”, tiddler to be “b” and anchor to be “c”

I missed this detail. It will be more complex in this situation.
May I ask, why do you want the order of the “sub-arguments” to be different in the case where you use all three? If it is just for the ease of typing the macro call, one workaround would be to use a different macro for one/two-part argument and a different one for the three-part argument.

Anyway, assuming this “complex parameter” with variable order of sub-parameters is the best/most comfortable solution for whatever reason, I would do it like this:

\procedure foo(arg)
<$let
    text={{{ [<arg>split[|]count[]match[3]] :then[<arg>split[|]nth[1]] }}}
    tiddler={{{ [<arg>split[|]count[]match[3]] :then[<arg>split[|]nth[2]] :else[<arg>split[|]nth[1]] }}}
    anchor={{{ [<arg>split[|]count[]match[3]] :then[<arg>split[|]nth[3]] :else[<arg>split[|]nth[2]] }}} >

<!-- you can use variables text, tiddler, anchor here -->

</$let>
\end

I have done something very similar in the past because I wanted to store multiple filter definitions in a variable or string. Perhaps you could share your intention, a broader scope. There are many ways to achieve the same thing in TiddlyWiki.

  • The reason I wanted these as a single parameter was to store field related filters in a single field, I was looking at the ability to define a way to encode a number of actions into a single statement.

Anyway I hope you have your answer, but I also hope you can share more.

I want a macro that looks like a wiki link but supports anchors (through navigation and scrolling). So the single parameter is just to mimic the syntax of wiki links with a ‘|’ character to separate arguments. Another benefit is that I need to quote once and not per argument.

1 Like

I really like the idea. You’re wishing to “marshal” parameters in a single quoted string.

I’m with @TW_Tones, I need to see an example of it as you’d like it to be implemented. That is, show me the wikitext as you’d like to use it.

I kind if see where you are going, and happy to explore this with you but still have insufficient info available to help as @CodaCoder also suggests.

  • I have being working on something not dissimilar “External links that support a target”
  • How are you handling anchors in TiddlyWiki ?
    • (or in external links) because this is in itself not strait forward.
  • For example, we can now write custom widgets and use genesis widget to redefine existing widget like $link

I have just revisited the Top of this thread, and with a different set of eyes can now see at least two other approaches to this made available in recent versions. Some of which may arguably change your algorithm.

  • Since you do not care about individual parameter names just the order in which they are given (with a twist when there are three) we can now use the $parameters widget to extract parameter titles and values.
<<mymacro value1 value2 value3>> 
  • I am calling the above values, but they are treated as parameter names
  • Inside the procedure, and $parmeters widget the $params can give you a list of all parameters and their values, they become values of the parameters 0, 1 and 2.
  • However we can then treat this list of parameter names as values.
  • In this case rather than using | you can seperate each value with a space.

Just as a quick example try this on tiddlywiki.com

\procedure test()
<$parameters $params=params>
<<params>>
</$parameters>
\end

<<test value1 value2 "value 3">>

Returns {"0":"value1","1":"value2","2":"value 3"}

  • Then there are a number of ways to make use of the incoming parameter names as values.
    • Use the params variable in a set multiple variables widget and more

I will only go into this further if you are interested in exploring this and other approaches.

Thank you. Not sure what $parameters gives me that I couldn’t do before, my intent was to be able to write <<test “my text|Tiddler Name|AnchorName”>> rather than <<test “my text” “Tiddler Name” “AnchorName”>> saving on some typing and noise.
But even if the parameters are separated, I’m not sure I know how to do the logic I want in the “tiddlywiki language”

Ok, Each to their own;

<<test “my text|Tiddler Name|AnchorName”>>
  • Then split the single parameter

vs

<<test “my text" "Tiddler Name" AnchorName>>
  • Then split the params variable.

Note: however in the first case your must provide the literal parameter “my text|Tiddler Name|AnchorName” and to assemble it from its parts would need substitution.

In the second example you could call the “procedure” like this;

<$transclude $variable=test P1={{template}}  p2=<<currentTiddler>> p3={{!!subtiutle}}/>
  • With different sources for each parameter value.
  • No need to assemble the parameter.

I was only demonstrating there are different mechanisms to design what you are after, I and others will help take the solution to the end if you describe your intentions a little more.

  • That is your question has being answered, but perhaps there is a better question to ask.