[TW5] Use of variables within curly brackets

1,308 views
Skip to first unread message

mauloop

unread,
Mar 2, 2017, 10:53:30 AM3/2/17
to TiddlyWiki
Is there a way to use variables within curly brackets transclusion?
Something like:

<$set name="t" value="myTiddler">
{{<
<t>>}}
</$set>

I know that I could use the transclude widget, but I need a syntax that is embeddable in another macrocall.

Jed Carty

unread,
Mar 2, 2017, 11:10:25 AM3/2/17
to TiddlyWiki
The links I give in this thread (https://groups.google.com/forum/#!topic/tiddlywiki/PKtw-uJyVZQ) explain more, but you need to have it inside a macro and use $(variable)$. Depending on what you actually need there may be a better way to do it.

mauloop

unread,
Mar 2, 2017, 11:49:50 AM3/2/17
to TiddlyWiki
Thanks, Jed. I'll take a deeper look later at the thread you linked to (there is a lot to read and I-m not comfortable with English).

I tried too make my question simple, but the real scenery is little bit more complicated.

The (parametrized) transclusion I need stand within the body of two nested list widgets, that sets the tiddlers and the fields to be transluded, which in turns are concatenated using a wikitext macro. I pass variable to the macro using the syntax:

{{$(currentTiddler)$!!$(field)$}}

and everything works fine.

But when I try to move all of this code into a a macro tiddler (tagged $:/tags/Macro) the $(currentTiddler)$ value is empty. Forcing the list widget with a non default variable name does not solve.

I found that using <<currentTiddler>> instead of $(currentTiddler)$ works, but I cannot use this syntax within curly brackets.

I ended with this workaround:

<$set name=v value=<<str """<$transclude tiddler=<$1$> field=<$2$> />""" """<r>""" """<i>""">> >
<
<v>>
</$set>

Where:
  •  r and i are the variable set by the containing list widgets
  • str is the name of the concatenating macro

It works but I am looking for something better (simpler).


Eric Shulman

unread,
Mar 2, 2017, 1:09:20 PM3/2/17
to TiddlyWiki
On Thursday, March 2, 2017 at 8:49:50 AM UTC-8, mauloop wrote:
The (parametrized) transclusion I need stand within the body of two nested list widgets, that sets the tiddlers and the fields to be transluded, which in turns are concatenated using a wikitext macro. I pass variable to the macro using the syntax:
{{$(currentTiddler)$!!$(field)$}}
and everything works fine.

But when I try to move all of this code into a a macro tiddler (tagged $:/tags/Macro) the $(currentTiddler)$ value is empty. Forcing the list widget with a non default variable name does not solve.

That's odd.  *Within* a macro definition, the value of $(currentTiddler)$ is always defined.   However, the $(...)$ syntax only works within the body of the macro; so, *outside* a macro definition, $(currentTiddler)$ has no defined value and is treated as literal text.

You said that "everything works fine" before you "moved all this code into a macro tiddler".  When you moved your code, did you retain the complete macro definition, including everything from the "\define macroname(params)" through "\end"?

I found that using <<currentTiddler>> instead of $(currentTiddler)$ works, but I cannot use this syntax within curly brackets.

Again, $(currentTiddler)$ only works within a macro, while <<currentTiddler>> can be used either inside or outside a macro (but only in certain syntax, as you've noted).  This further suggests that your moved macro code is no longer being defined properly.

If you post the complete contents of the macro tiddler, perhaps we could see where things have gone wrong.

-e
Eric Shulman
TiddlyTools: Small Tools for Big Ideas (tm)
InsideTiddlyWiki: The Missing Manuals

mauloop

unread,
Mar 2, 2017, 6:38:17 PM3/2/17
to TiddlyWiki
Here I am, Eric, and thanks for your help. I hope I'll be able to explain clearly.

Let's have a bunch of dictionary tiddlers to work with (note that the first one is used as tag for the others):

title: Music
type
: application/x-tiddler-dictionary

Album:
Artist:
Genre:

title: Music 1
tags
: Music
type
: application/x-tiddler-dictionary

Album: Wish You Were Here
Artist: Pink Floyd
Genre: Progressive Rock

title: Music 2
tags
: Music
type
: application/x-tiddler-dictionary

Album: Never Mind the Bollocks
Artist: Sex Pistols
Genre: Punk

title: Music 3
tags
: Music
type
: application/x-tiddler-dictionary

Album: Nevermind
Artist: Nirvana
Genre: Grunge

title: Music 4
tags
: Music
type
: application/x-tiddler-dictionary

Album: The Future
Artist: Leonard Cohen
Genre: Folk

And the macro used for strings concat (stolen from Tobias Beer Ad-Hoc macro, http://tobibeer.github.io/tb5/#Ad-Hoc%20Macro)

title: StrMacro
tags
: $:/tags/Macro

\define str(text,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,19,20)
$text$
\end

Now if I create a tiddler like the following, it works, displaying a grid with dict's indexes names as header and indexes value in the rows:

title: Music Table (code within tiddler)

<$set name="t" value="Music" >
<table>
<!--------------
-- Table header
-->
<tr>
<$list filter="""[<t>indexes[]]""" variable="i">
<th>
<<i>>
</th>
</
$list>
</tr>
<!------------
-- Table rows
-->
<$list filter="""[tag<t>sort[sort]]""">
<tr>
<$list filter="""[<t>indexes[]]""" variable="i">
<td>
<<str "{{$(currentTiddler)$##$(i)$}}">>
</
td>
</$list>
</
tr>
</$list>
<!--
-- Table rows end
------------------>
</
table>
</$set>

Now I would like to create more tables without duplicating the code, so I make a macro from the previous one:

title: TableMacro
tags
: $:/tags/Macro

\define table(t)
<$set name="t" value="$t$" >
<table>
<!--------------
-- Table header
-->
<tr>
<$list filter="""[<t>indexes[]]""" variable="i">
<th>
<<i>>
</th>
</
$list>
</tr>
<!------------
-- Table rows
-->
<$list filter="""[tag<t>sort[sort]]""">
<tr>
<$list filter="""[<t>indexes[]]""" variable="i">
<td>
<<str "{{$(currentTiddler)$##$(i)$}}">>
</
td>
</$list>
</
tr>
</$list>
<!--
-- Table rows end
------------------>
</
table>
</$set>
\end

The only differences are:
  • define and end pragmas
  • the value for the beginning set widget ($t$ instead of Music)

Finally I can change my Music Table content with this one:


title: Music Table (code from TableMacro)

<<table "Music">>

But unluckly it renders in an empty grid, but table headers.


You said: "$(currentTiddler)$ only works within a macro"

I learned that I can use it in the macro invocation too


You said: "*Within* a macro definition, the value of $(currentTiddler)$ is always defined"

You're right, but it's not always defined the way I expect.


In this case I tried to remove the curly brackets, changing...


<<str "{{$(currentTiddler)$##$(i)$}}">>

... with...


<<str "$(currentTiddler)$##$(i)$">>


in my TableMacro. Now the grid is not empty anymore. Every single cell, but the headers, just as before, contains: "Music Table (code from TableMacro)##"

It is the title of the tiddler from which the macro is invoked and not the tiddlers that the list widget should return.


The real code is much more complex. I added stuff to sort columns, edit inline, select/unselect all or single rows, add fields, add records, change table and create a new one, everything using just vanilla TW5. I was excited for my results, but I'm only able to use all of this copying/pasting code from one tiddler to another.


I don't know what's wrong, but I'm sure there should be a better way. The code of my previous post was an attempt to find a workaround.





Eric Shulman

unread,
Mar 2, 2017, 11:44:11 PM3/2/17
to TiddlyWiki
On Thursday, March 2, 2017 at 3:38:17 PM UTC-8, mauloop wrote:
Here I am, Eric, and thanks for your help. I hope I'll be able to explain clearly.
<<str "{{$(currentTiddler)$##$(i)$}}">>

When <<str ...>> is invoked outside a macro (your initial, successful implementation), the quoted text parameter, "{{$(currentTiddler)$##$(i)$}}" is simply passed into the macro, which then expands the $(currentTiddler)$ and $(i)$ references, producing the desired result.

However... when the <<str ...>> syntax is moved inside of another macro (i.e., the <<table>> macro definition), all $(...)$ references within the <<table>> macro are expanded as soon as the macro is invoked.  This includes expanding the $(currentTiddler)$ and $(i)$ references within the quoted text argument to the <<str>> macro.  Thus, by the time <<str ...>> is actually invoked within the <<table>> macro, it's param no longer contains the literal "$(currentTiddler)$" text to be passed down to the <<str>> macro handler, but has already been replaced by the value of $(currentTiddler)$ that was defined when the <<table>> macro was invoked.

To work around this, you can create your own little use-case specific helper macro as an alternative to the general-purpose <<str>> macro.

Something like this:
\define showIndexValue() {{$(currentTiddler)$##$(i)$}}

Then, instead of
<<str ...>>
you would just write
<<showIndexValue>>

Note that this new macro achieves the same effect as the <<str ...>> usage (i.e., joining together the title (currentTiddler) and index name (i) and then retrieving that value using transclusion {{...}}).  However, because <<showIndexValue>> does not use parameter passing, the references to $(currentTiddler)$ and $(i)$ are left unchanged until <<showIndexValue>> is actually invoked, rather than when the containing <<table>> macro is first entered.

I hope this explanation doesn't make your head spin too much!

Let me know how it goes.

enjoy,
-e
Eric Shulman
TiddlyTools: Small Tools for Big Ideas! (tm)
InsideTiddlyWiki: The Missing Manuals




mauloop

unread,
Mar 3, 2017, 3:49:09 PM3/3/17
to TiddlyWiki
Thanks Eric,

don't mind for my head, it was spinning long before your explanation ;^)))

What can I say? Uh! Stupid me, it's obvious. After it's always easier. I will change my code and will use the trick you suggested. I had something similar in my spinning mind, but I don't like workarounds without a valid reason to be applied. Now I realize that your way is not just a workaround, since the resulting code is cleaner than my generic strings concat macro.

Otherwise I don't want to lose the chance to learn something, so I fall back to the title of this thread. Searching for a way to use str macro I ended up with this (in this example <<r>> stands in place od <<currentTiddler>>:

<$set name=v value=<<str """<$transclude tiddler=<$1$> index=<$2$> />""" """<r>""" """<i>""">> >
<
<v>>
</$set>


This code, included in the two nested list widget, displays the expected values (yes, I know, three nested macro calls are really an ugly workaround, I'm just investigating tw syntax secrets). This was the alternative I found  to something like:

{{<<r>>!!<<i>>}}

The first question is simply: is there a particular reason for the variables to be not working inside curly brackets?

The second one requires to consider the following code:

<!------------
-- Table rows
-->
<$list filter="""[tag<t>sort[sort]]""" variable="r">
<tr>
<$list filter="""[<t>indexes[]]""" variable="i">
<$set name=v value=<<str """<$transclude tiddler=<$1$> index=<$2$> />""" """<r>""" """<i>""">> >
<$set name=s value=<<str """<$transclude tiddler=<$1$> field=<$2$> />""" """<r>""" """<i>""">> >
<td>
<!--------------------
-- View mode field
-->
<$reveal state=<<s>> type="nomatch" text="edit">
<$button class="tc-btn-invisible tc-tiddlylink" set=<<s>> setTo="edit">
<<v>>
</$button>
</$reveal>
<!-----------------
-- Edit mode field
-->
<$reveal state=<<s>> type="match" text="edit">
<$edit-text tiddler=<<r>> index=<<i>> tag="input" size=10/>
<$button class="tc-btn-invisible" set=<<s>> setTo="view">
<small>{{$:/core/images/close-button}}</small>
</$button>
</$reveal>
</td>
</$set>
</$set>
</$list>

I intended to use a field, with the same name of the index, as state tiddler for the reaveal widget that allows to switch between edit or view mode for any single cell in the table. But I found that a tiddler with title "<$transclude tiddler=<<r>> field=<<i>> />" has been created.

Now it's my turn to be worried about your headache.

Reply all
Reply to author
Forward
0 new messages