Folks,
I am writing a macro and/or custom widget that allows the user to provide a text reference in the following forms tiddlername, tiddlername!!fieldname or !!fieldname. See https://tiddlywiki.com/#TextReference
- I want this parameter to be converted to target-tiddler and target-field and when one or the other is not provided use a default eg
target-tiddler=<<currentTiddler>> and target-field=text
This seems to me a valid way to reference resources in tiddlywiki for which we do not have any helper macros.
- My attempts have being failing
eg
\procedure update.reference(text-reference target-tiddler target-field)
\function delimiter() !!
<$parameters target-tiddler={{{ [<text-reference>split<delimiter>first[]] :else[<currentTiddler>] }}} field={{{ [<text-reference>split<delimiter>last[]] :else[<target-field>] }}}>
text-reference: <<text-reference>>, target-tiddler: <<target-tiddler>>, field: <<field>>.
</$parameters>
\end
# <<update. Reference "tiddlername!!fieldname">>
# <<update. Reference "!!fieldname">>
Background;
I am trying to create a procedure or custom widget that allows you to provide a text references or tiddlername and fieldname, that transudes the value, however allows you to click it or an icon next to it to edit it in-line and/or allows you to select from a list (generated by a filter).
Why a text reference and not separate parameters?;
- Using a text reference implies a fixed reference that you do not change, it is a reference to a specific location tiddler and/or fieldname to store a global value.
- But you could use target-tiddler and/or target-field if you generate them programmatically.
You have a couple of typos (spaces/inconsistent capitalization in your macrocalls). But if I’m understanding your goal, I’m also not sure you need $parameters to do this. It seems to me that you don’t really need the target-tiddler/target-field parameters, either, since they can be derived from text-reference.
\procedure update.reference(text-reference delimiter:"!!")
<$let
target-tiddler={{{ [<text-reference>split<delimiter>first[]!match[]] ~[<currentTiddler>] }}}
field={{{ [<text-reference>search<delimiter>split<delimiter>last[]] ~[[text]] }}}
>
''text-reference:'' <<text-reference>>,
''target-tiddler:'' <<target-tiddler>>,
''field:'' <<field>>.
</$let>
\end
# <<update.reference "tiddlername!!fieldname">>
# <<update.reference "!!fieldname">>
# <<update.reference "tiddlername">>
Edit: Made some changes so it will fall back to “text” as standard when no field is specified.
Thanks for your response @etardiff
- I can’t see them, but discourse has a habit of changing them.
Of course if the text reference is given, but I want to allow in the same procedure/custom widget to also allow the separate values.
- I am using the parameters widget for “attribute processing”, think of also immediately using a $let widget, but I am using the $parameters widget to do two jobs.
I have now moved these into two functions, thinking they could be global
\function reference.tiddler(reference default:"currentTiddler") [<reference>split[!!]first[]else<reference>] :else[<currentTiddler>]
\function reference.field(reference default:"default") [<reference>split[!!]last[]else<reference>]
# <<reference.tiddler>>
# <<reference.field>>
# <<reference.tiddler "tiddlername!!fieldname">>
# <<reference.field "tiddlername!!fieldname">>
# <<reference.tiddler "!!fieldname">>
# <<reference.field "!!fieldname">>
# <<reference.tiddler "tiddlername">>
# <<reference.field "tiddlernamef">>
- Defaults are not yet working, The first two should use the default, as should any without a tiddlername or fieldname.
You need to exclude the blank results of the split, as I did with <<target-tiddler>> in my code above.
\function reference.tiddler(reference default) [<reference>split[!!]first[]!match[]] ~[<default>!match[]] ~[<currentTiddler>]
\function reference.field(reference default:"default") [<reference>split[!!]last[]!match[]] ~[<default>]
I’d also leave the reference.tiddler default blank, or it will give you the title “currentTiddler” rather than the actual contents of <<currentTiddler>>.
I solved the default issue too;
\function reference.tiddler(reference default:currentTiddler) [<reference>split[!!]first[]else<reference>!is[blank]else<default>]
\function reference.field(reference default:fieldname) [<reference>split[!!]last[]else<reference>!is[blank]else<default>]
- note how the defaults can be given as parameters.
However this is via functions, I wonder if there are other ways to simplify the retrieval of the value at the reference?
- I imagin these can be referenced from within a procedure
Working on that now.
[Edit]
- Dealing also with ## indexes would be good
Just in case you haven’t encountered this potential issue yet…
If you use default:currentTiddler, <<reference.tiddler>> will yield “currentTiddler”, not the actual value of <<currentTiddler>>. That’s why I omitted the default value from the default parameter in my version, and used ~[<default>!match[]] ~[<currentTiddler>] instead.
Thanks for pointing that out, I was planning to do this and forgot
:else[<default>getvariable[]]
In fact I have dropped the parameter reference and set it once outside the functions so I can do this;
\function reference.tiddler(default:currentTiddler) [<reference>split[!!]first[]else<reference>!is[blank]] :else[<default>getvariable[]]
\function reference.field(default:fieldname) [<reference>split[!!]last[]else<reference>!is[blank]else<default>]
<$let reference="$:/HistoryList!!current-tiddler">
<<reference.tiddler>> = <<reference.field>>
<$transclude $tiddler=<<reference.tiddler>> $field=<<reference.field>>/>
</$let>
<hr>
<$let reference="!!description">
<<reference.tiddler>> = <<reference.field>>
''returns:'' "<$transclude $tiddler=<<reference.tiddler>> $field=<<reference. Field>>/>"
</$let>
<$let reference="!!">
<<reference.tiddler>> = <<reference.field>>
''returns:'' "<$transclude $tiddler=<<reference.tiddler>> $field=<<reference.field>>/>"
</$let>
- Until I work out how to use preset variable OR parameter.