How combine string with evaluated value for a parameter value?

1,317 views
Skip to first unread message

Mat

unread,
Jul 22, 2015, 10:35:10 AM7/22/15
to TiddlyWiki
How does one concatenate a string and a calculated value (e.g a macro or a transclusion)?

For example this doesn't work:

<$set name="url" value="http://foo.com/#:"<<currentTiddler>>>

<$set name="url" value=http://foo.com/#:<<currentTiddler>>>

<$set name="url" value="http://foo.com/#:<<currentTiddler>>">


Doc on the setwidget doesn't make this clear. Nor does other places (ex). The issue is of course not specific for the setwidget but it is a bit ironic specifically for the setwidget as this, from what I understand, is used for avoiding these difficulties.

<:-)

Eric Shulman

unread,
Jul 22, 2015, 1:38:41 PM7/22/15
to TiddlyWiki
The $set widget only *stores* the value specified, it doesn't know how to assemble values from individual parts.  That's what macros are for: assembling and returning compound text strings.

To accomplish your goal, you can define a macro to concatenate the current tiddler title to the end of the string, and then assign the result using the $set widget.

Something like this:
\define makeurl(u) $u$$currentTiddler$
<$set name="url" value=<<makeurl "http://foo.com/#:">>>
...
</$set>

-e

Jed Carty

unread,
Jul 22, 2015, 1:57:36 PM7/22/15
to TiddlyWiki

Eric Shulman

unread,
Jul 22, 2015, 2:07:25 PM7/22/15
to TiddlyWiki
correction:

currentTiddler is a variable, not a macro parameter.  Thus, instead of $currentTiddler$ it should be $(currentTiddler)$

like this:
\define makeurl(u) $u$$(currentTiddler)$

Mat

unread,
Jul 22, 2015, 5:54:48 PM7/22/15
to TiddlyWiki
@Eric, @Jed - I appreciate your help!!!

However... I just can't get it to work, in spite of your multiple examples. Below is the more actual code. 

The idea is to display the current tiddlers title but with the tiddlers creators name prepended to it, so the title "Foo BarFrotz" display as "Bob/Foo BarFrotz"
(My odd choice for title is to make it clear that the camelcased word becomes a part of the full link via that longest code line below, see #1880. Not an issue for this thread though.)  

With your help, the $(currentTiddler)$ bit works, but the $creator$ part is problematic. My general question there is how do I get field data? I've tried with all variants I can think of. If possible, I would rather call the concat macro with the tiddler (i.e {{!!title}}) than with !!creator, so that I could extract other field data.

In the second tiddler, I don't include any argument for the <<pub>> macrocall because using {{!!title}} in the macros work and so I figure {{!!creator}} should work to. Right? (I've of course tried the other way too.)

Ok, help appreciated. 


tiddler: MyMacros
tags
: $:/tags/Macro

\define concat(creator) $creator$/$(currentTiddler)$

\define pub()
<$set name="rev" value=<<concat {{!!creator}}>>>
<$link to=<<rev>>><$view tiddler=<<rev>> field="title" format="text"><<rev>></$view></$link>
</$set>
\end

and

tiddler:MyTiddler

<<pub>>


Jed Carty

unread,
Jul 22, 2015, 6:05:26 PM7/22/15
to TiddlyWiki, matia...@gmail.com
The problem is

<$set name="rev" value=<<concat {{!!creator}}>>>

The input to the macro isn't wikified before the macro is evaluated in this context. Use this instead:

\define concat() $(ThisCreator)$/$(currentTiddler)$

\define pub()
<$set ThisCreator={{!!creator}}>
<$set name=rev value=<<concat>>>

<$link to=<<rev>>><$view tiddler=<<rev>> field="title" format="text"><<rev>></$view></$link>
</$set>
</$set>
\end

<<pub>>

Mat

unread,
Jul 22, 2015, 6:41:33 PM7/22/15
to tiddl...@googlegroups.com
Thanks for superfast reply, Jed!

...but no luck. Merely adding some tests to your code, see below, gives this (non-)result:

1 MyTid 2 Mat 3 4 5 6
..and the single /

\define concat() $(ThisCreator)$/$(currentTiddler)$

\define pub()
1 {{!!title}} 2 {{!!creator}} 3
<$set ThisCreator={{!!creator}}>
4 {{!!title}} 5 <<ThisCreator>> 6

Jed Carty

unread,
Jul 22, 2015, 8:29:00 PM7/22/15
to TiddlyWiki, matia...@gmail.com
After a few minutes of some rather intense confusion I realized that I used the vars instead of set for the first definition when testing and wrote set when I put it in my answer to you. Sorry about that.

This time here is exactly what I have in the tiddler I am testing with on tiddlywiki.com:


\define concat() $(ThisCreator)$/$(currentTiddler)$

\define pub()
1 {{!!title}} 2 {{!!creator}} 3
<$vars ThisCreator={{!!creator}}>

4 {{!!title}} 5 <<ThisCreator>> 6

<$set name=rev value=<<concat>>>

<$link to=<<rev>>><$view tiddler=<<rev>> field="title" format="text"><<rev>></$view></$link>
</$set>
</$vars>
\end

<<pub>>

Mat

unread,
Jul 23, 2015, 5:51:17 AM7/23/15
to TiddlyWiki, inmy...@gmail.com
That did it! Excellent Jed!!!!! :-D

If you don't mind me asking - how did you figure out it should use a vars instead of a set? "!!creator" looks very non-variablish to me? (...and what would have happened pre-5.1.9 when there was no vars widget?)

<:-)

Eric Shulman

unread,
Jul 23, 2015, 7:55:54 AM7/23/15
to TiddlyWiki, inmy...@gmail.com, matia...@gmail.com
On Thursday, July 23, 2015 at 2:51:17 AM UTC-7, Mat wrote:
If you don't mind me asking - how did you figure out it should use a vars instead of a set? "!!creator" looks very non-variablish to me? (...and what would have happened pre-5.1.9 when there was no vars widget?)

Anything you can define with <$vars> can also be defined individually using <$set>.  <$vars> is merely a more compact syntax for defining multiple variables at once.  Thus, instead of writing:

<$vars ThisCreator={{!!creator}}>...</$vars>

you could simply write:

<$set name="ThisCreator" value={{!!creator}}>...</$set>


Note that in this particular use case, the second variable ("rev") has to be set using a separate widget, because it's value depends on already having "ThisCreator" defined.

-e

Mat

unread,
Jul 23, 2015, 12:26:04 PM7/23/15
to TiddlyWiki, inmy...@gmail.com, elsd...@gmail.com
Ah, thanks @Eric! Truly an easy syntactic mistake to make.

As far as I can tell, $vars thus makes $set superfluous. Do you happen to know why wasn't $set just enhanced instead of introducing also $vars? Would enhancing $set break backward compatability?

Thanx

<:-)

Eric Shulman

unread,
Jul 23, 2015, 2:00:55 PM7/23/15
to TiddlyWiki, inmy...@gmail.com, matia...@gmail.com
On Thursday, July 23, 2015 at 9:26:04 AM UTC-7, Mat wrote:
Ah, thanks @Eric! Truly an easy syntactic mistake to make.

As far as I can tell, $vars thus makes $set superfluous. Do you happen to know why wasn't $set just enhanced instead of introducing also $vars? Would enhancing $set break backward compatability?

see http://tiddlywiki.com/#VarsWidget, in which Jeremy wrote:
-------------------------
It should be noted that this widget differs from the set widget in the following ways:
* A fallback (also known as "emptyValue") cannot be specified
* Filters cannot be used to produce a conditional variable assignment
* Variable names must be literal strings 
-------------------------

Thus, while $set and $vars are very similar, they are not 100% equivalent... and yes, I think $set was left as-is because of backward-compatibility issues.

-e

Felix Küppers

unread,
Dec 30, 2015, 7:44:56 AM12/30/15
to TiddlyWiki
Hi Mat,

I know this is an old thread but I just wanted to add my solution.

If you only want to concatenate variables, macros and literals (but no transclusions), you can use the following technique, which allows you to dynamically concatenate strings without having to specifiy the concatination in the concat macro itself:

\define concat(str) $str$

<<concat "Hi my name is $(currentTiddler)$ I like TW $(version)$.">>

This technique makes use of TW's ability to parameterize variable calls.

The trick is to inject the whole macro body as string.


So we refer to variables and macros via

$(…)$

notation and embedd everything in a single string that is then passed to the concat macro as param. This has a huge advantage over hardcoding the macro body.

<$set name="url" value=<<concat "http://foo.com/#:$(currentTiddler)$">>>
<$set name="url" value=<<concat "http://foo.com/#:$(currentTiddler)$ Hello world $(version)$">>>

You see the advantage? you can use the same single concat macro for several dynamic concatination tasks

-Felix

Tobias Beer

unread,
Dec 30, 2015, 8:06:30 AM12/30/15
to tiddl...@googlegroups.com
Hi Mat,

You can easily achieve that using tobibeer/setvars:

<$setvars url="\http://tiddlywiki.com/#\ current" _current=<<currentTiddler>>>
<
<url>>
</$setvars>

However, this requires for the tiddler title to not have spaces in order for the link to work with a TiddlyWiki.

While not officially released, here's a little macro module called x that does what you want,
by default pointing to http://tiddlywiki.com:


syntax:
  • <<x title>>
  • <<x "tiddler title">>
  • <<x "tiddler title" "pretty title">>
If you want it to point to another domain, simply create a global macro called x-url and have it return your base-url, e.g.:

title: $:/config/x-url
tags
: $:/tags/Macro

\define x-url()
\end

Alternatively, you can, of course overwrite the x-url for each tiddler individually by declaring it at the start:

\define x-url() http://tobibeer.github.io/tw5-plugins

Best wishes,

Tobias.

Matabele

unread,
Dec 30, 2015, 7:34:47 PM12/30/15
to TiddlyWiki
Hi Felix

Really useful trick :-) Many thanks for this.

regards

Tobias Beer

unread,
Dec 31, 2015, 5:00:11 AM12/31/15
to TiddlyWiki
Hi Mat,

you may be interested in the new tobibeer/hash filter plugin (announced here),
which allows to uri-encode one or more tiddler titles to proper uri hashes.

Especially the syntax-example for generating a full url may be of interest to you:


Best wishes,

Tobias.

Mat

unread,
Jan 1, 2016, 6:03:46 AM1/1/16
to TiddlyWiki
My goodness! @Felix, to pick up on this old issue is very kind of you! And it seems to have really started a flow of useful solutions. Wow!


The trick is to inject the whole macro body as string.

Ahaaa - very tricky! I would have never thought of it. I know I'll face this issue again - really valuable!

Thank you Felix!

<:-)

Tobias Beer

unread,
Jan 1, 2016, 9:40:47 AM1/1/16
to TiddlyWiki
Hi Felix,
 
I know this is an old thread but I just wanted to add my solution.

Wow. This is something to ponder:

\define =(text,1,2,3,4,5,6,7,8,9,10) $text$

<<= "I am $(currentTiddler)$ in a TW $(version)$. And here is $1$." "foo">>

Best wishes,

Tobias.

Mat

unread,
Jan 1, 2016, 11:15:06 AM1/1/16
to TiddlyWiki
Tobias, thank you!

Setvars is really, really cool!

That's really interesting how vars are called already in the setting of the other vars!

<:-)

Mat

unread,
Jan 1, 2016, 11:47:36 AM1/1/16
to TiddlyWiki
Tobias,


you may be interested in the new tobibeer/hash filter plugin (announced here),

Again my warmest thanks to you!

Just to make sure I get it right, this is only for cases using URI, right?

In your examples given there to decode... I can't quite tell what is supposedly encoded? Do you think you could refer to the external tiddlers example from tiddlywiki.com/prerelease? ...or maybe the the different domain prevents this. Plus it no worky worky in Chrome. ...but hypothetically; the canonical_uri there is

./text/Alice%2520in%2520Wonderland.tid

How would this be decoded? (Or am I just totally misunderstanding something?) 

Again, thanks Tobias! You're creating amazing things - and to say you're generously sharing is a definite understatement!

<:-)

Tobias Beer

unread,
Jan 1, 2016, 12:55:05 PM1/1/16
to TiddlyWiki
Hi Mat,
 
Just to make sure I get it right, this is only for cases using URI, right?

Try to create a permalink for a tiddler containing spaces, or even a permaview for multiple tiddlers, including those containing spaces. You'll see that you cannot just create the proper link solely with a given title, but that it needs to be uri-encoded, so TiddlyWiki knows how to read out the contents of the address bar.

In your examples given there to decode... I can't quite tell what is supposedly encoded?

The decoding examples are pretty straight forward: First I use the hash filter to encode a title, and right after that use it again with the decode suffix to decode them back. So, in a way I am proving that, in the end, you get back what you started out with. Makes sense?

I could have just taken any cryptic url, but then others may not have understood what that url is and why the hash filter does its decoding the way it does it. By showing that decoding is simply doing the reverse of encoding, I figured, it would be pretty clear what's going on.
 
Do you think you could refer to the external tiddlers example from tiddlywiki.com/prerelease?

What do you mean by that?

...or maybe the different domain prevents this. Plus it no worky worky in Chrome.

To be able to create a properly encoded link to any external TiddlyWiki is precisely what the hash filter is intended for. Simply give it the un-encoded title either as an input title or via the operand and it will create the proper uri-encoded link for you... but you will have to add the proper domain yourself using the addprefix operator.
 
...but hypothetically; the canonical_uri there is

./text/Alice%2520in%2520Wonderland.tid

How would this be decoded? (Or am I just totally misunderstanding something?)

The problem with these links is that they are DOUBLE uri encoded, for reasons I have not quite grasped yet ...so you actually need to decode them twice to have them fully decoded:

{{{ [[./text/Alice%2520in%2520Wonderland.tid]hash:decode[]hash:decode[]] }}}

Again, thanks Tobias! You're creating amazing things - and to say you're generously sharing is a definite understatement!

Thanks, Mat... and ...you're welcome. :-)

Best wishes,

Tobias.

Felix Küppers

unread,
Jan 1, 2016, 4:10:24 PM1/1/16
to TiddlyWiki
Ahaaa - very tricky! I would have never thought of it. I know I'll face this issue again - really valuable!

Thanks @Mat

\define =(text,1,2,3,4,5,6,7,8,9,10) $text$

<<= "I am $(currentTiddler)$ in a TW $(version)$. And here is $1$." "foo">>

Ha! Nice @Tobias, didn't think of this. Now we almost got the equivalent to "printf" (https://en.wikipedia.org/wiki/Printf_format_string) :D

\define concat(text,1,2,3,4,5,6,7,8,9,10) $text$
 
<<concat "Hello $1$. I am $(currentTiddler)$ in a TW $(version)$. Good bye $1$. Hope to see you again $1$." "foo">>

Felix Küppers

unread,
Jan 1, 2016, 4:12:19 PM1/1/16
to tiddl...@googlegroups.com
Hi Matabele

> Really useful trick :-) Many thanks for this.

Thanks, sometimes really handy.

Tobias Beer

unread,
Jan 12, 2016, 11:18:20 AM1/12/16
to TiddlyWiki
Hi Felix,

Ha! Nice @Tobias, didn't think of this. Now we almost got the equivalent to "printf" (https://en.wikipedia.org/wiki/Printf_format_string) :D 
 
\define concat(text,1,2,3,4,5,6,7,8,9,10) $text$
 
 <<concat "Hello $1$. I am $(currentTiddler)$ in a TW $(version)$. Good bye $1$. Hope to see you again $1$." "foo">>

I added the above here:


Thanks again. That's some nifty-cool stuff.

Best wishes,

Tobias.

Xavier Cazin

unread,
Jan 12, 2016, 11:31:43 AM1/12/16
to tiddl...@googlegroups.com
Hi everyone,

Loved the trick, but it exhibits a parsing glitch when you try to put the variable values in bold
​ using single quotes​
. Try <<concat "Hello $1$. I am ''$(currentTiddler)
​$'​
' in a TW $(version)$. Good bye $1$. Hope to see you again $1$." "foo">> for instance.

X.

-- Xavier Cazin

--
You received this message because you are subscribed to the Google Groups "TiddlyWiki" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywiki+...@googlegroups.com.
To post to this group, send email to tiddl...@googlegroups.com.
Visit this group at https://groups.google.com/group/tiddlywiki.
To view this discussion on the web visit https://groups.google.com/d/msgid/tiddlywiki/b7fffef4-505a-4b64-9b3b-7e79bd51bae7%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Tobias Beer

unread,
Jan 12, 2016, 11:57:31 AM1/12/16
to tiddl...@googlegroups.com
 Hi Xavier,
 
Loved the trick, but it exhibits a parsing glitch when you try to put the variable values in bold
​ using single quotes​
. Try <<concat "Hello $1$. I am ''$(currentTiddler)
​$'​
' in a TW $(version)$. Good bye $1$. Hope to see you again $1$." "foo">> for instance.

Two options to go about it:
  1. you can always use single quotes instead
  2. use triple double-quotes to allow single double-quotes within
Best wishes,

Tobias. 

Xavier Cazin

unread,
Jan 12, 2016, 12:08:32 PM1/12/16
to tiddl...@googlegroups.com
Hi Tobias,

This is not really a matter of quote parsing but rather of wikitext parsing. Try <$macrocall $name="=" text="""I am ''$(currentTiddler)$'' for TiddlyWiki $(version)$. This is rather $1$.""" 1="boldish"/> somewhere in http://tobibeer.github.io/tb5/.

X.

-- Xavier Cazin

  1. use triple double-quotes to allow single-double within
Best wishes,

Tobias. 

--
You received this message because you are subscribed to the Google Groups "TiddlyWiki" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywiki+...@googlegroups.com.
To post to this group, send email to tiddl...@googlegroups.com.
Visit this group at https://groups.google.com/group/tiddlywiki.

Tobias Beer

unread,
Jan 12, 2016, 12:21:58 PM1/12/16
to TiddlyWiki
 Hi again, Xavier,
 
This is not really a matter of quote parsing but rather of wikitext parsing. Try <$macrocall $name="=" text="""I am ''$(currentTiddler)$'' for TiddlyWiki $(version)$. This is rather $1$.""" 1="boldish"/> somewhere in http://tobibeer.github.io/tb5/.


Mhhh, not sure what's going on here, I would consider this a core bug. 

It's got something to do with the sequence $'', or just $' because this works:

<$macrocall $name="=" text="""I am ''$(currentTiddler)$ ''for TiddlyWiki $(version)$. This is rather $1$.""" 1="boldish"/>

Notice the space before the closing single-quotes.

Best wishes,

Tobias.

Felix Küppers

unread,
Jan 13, 2016, 3:51:34 PM1/13/16
to tiddl...@googlegroups.com

Felix Küppers

unread,
Jan 13, 2016, 3:54:32 PM1/13/16
to tiddl...@googlegroups.com
Hi Xavier.

I agree, strange indeed. Maybe raise an issue at the TW GitHub repo?

-Felix
Reply all
Reply to author
Forward
0 new messages