r24 - 25 Jul 2006 - 03:36:56 - MartinCleaverYou are here: TWiki >  Codev Web > ParameterizedVariables
Tags:
, create new tag

Parametrized Variables

Basic concept

Like the ParameterizedIncludes, there should be the possibility to pass parameters when including (user definied) variables. When the variable is expanded, the parameters are inserted in place of placeholders (like $param("name")).

Examples

For example, there is a variable definition in the TWikiPreferences, looking like this:

      * Set ATTACHEDIMAGE = *$param("title")* %BR% <img src="%ATTACHURLPATH%/$param("filname")" alt="$param("filname") />

I have only to write

%ATTACHEDIMAGE{filename="mypicture.gif" title="This is my favorite picture"}%
in a topic to inline an attached image. There would be less html code and more readable text in the topics.

Another example, I want to link to a certain revision of a topic. The only way I know is to pass URL paramters. So I would define the variable

      * Set LINKREV = [[%SCRIPTURL%/view/%WEB%/$param("topic")?rev=$param("rev")][$param("topic") r$param("rev")]]
My link would look like this:
I refer to %LINKREV{topic="ParameterizedIncludes" rev="1.12"}%.

And would expand to:

I refer to ParameterizedIncludes 1.12.

A great enhancement could be made by defining search strings, so people don't have to use the whole syntax. What about writing

%TASKLIST{state="New"}%
%TASKLIST{state="InProgress"}%
That expands to somethink like
---++ Tasks New
%SEARCH{"META:FIELD{...ahorribleunreadableregularexpression ... New..." ... manymoreparameters ...}%

---++ Tasks InProgress
%SEARCH{"META:FIELD{...ahorribleunreadableregularexpression ... InProgress..." ... manymoreparameters ...}%

This could be done with ParameterizedIncludes as well, but this way there would be less small abstract topics containing only one or to lines of text.

Default Values

Default values could be practical. The above example of the LINKREV variable could be definied like this:

      * Set LINKREV = [[%SCRIPTURL%/$param("action" default="view")/$param("web" default="%WEB%")/$param("topic")?rev=$param("rev")][$param("topic") r$param("rev")]]

There would be a thousand possibilities to improve usability.

-- StefanSteinegger - 04 Nov 2004

Discussion

See TopicVarsPlugin and MacrosPlugin - one of the two might do what you want.

-- MartinCleaver - 04 Nov 2004

If you have CommentPlugin (16 Oct 2004 - 3.008) installed then you could probably use that with the noform parameter.

-- SamHasler - 05 Nov 2004

Ok, TopicVarsPlugin should work, but actually doesn't. The webserver doesn't respond anymore. (mod_perl?) If it would work, this topic would still be a syntax enhancement request :).

MacrosPlugin should also work (I have to try it first) and sounds more like what i need. It doesn't solve the problem of many small abstract topics, because macros are definied in topics, not in variables. But variables have some problems with linefeeds anyway.

Shouldn't there be a consolidation of TopicVarsPlugin, MacrosPlugin and ParameterizedIncludes? Many simple plugins could be defined just as a set of macros or includes. And html code, that is now everywhere in the topics, could be completly moved into macros. I mean, there could be a clean, simple syntax to do almost everything you want.

-- StefanSteinegger - 05 Nov 2004

MacrosPlugin works! BUT there is always a linefeed at the end of every topic. So I can't use it as a single expression, like my LINKREV example. It wouldn't work in tables for instance, I would always have to define a whole line. So this kind of macro can't be nested like variables. What I want is much simpler and possibly more powerful.

-- StefanSteinegger - 05 Nov 2004

Stefan, this an excellent idea, and based on the DEVELOP codebase would be very easy to do smile

It feels rather clunky to have two separate syntaxes for doing this. We should try to fold this spec together with ParameterizedIncludes spec. How about just using the same syntax? It would mean the * Set would look a bit strange in a normal view, but it should work otherwise. For example:

%UNLESS("cereal" default="Grape Nuts"}%
%UNLESS("juice" default="Ananas"}%
   * Set BREAKFAST = %cereal% and %fruit% juice
%cereal% is my favourite, especially with %fruit% juice. Today I'm having %BREAKFAST{cereal="Muesli" fruit="Orange"}%. Tomorrow I will have %BREAKFAST{juice="Carambola"}%
would appear when rendered as:
  • Set BREAKFAST = Grape Nuts and Ananas juice
Grape Nuts is my favourite, especially with Ananas juice. Today I'm having Muesli and Orange juice. Tomorrow I will have Grape Nuts and Carambola juice.

Does that make sense to you? If a parameter value is not given, the closest enclosing UNLESS applies.

BTW if you use %STRIP% in a MacrosPlugin macro, that final linefeed should disappear.

-- CrawfordCurrie - 05 Nov 2004

I found out about %STRIP%. It solves many of my problems. Thanks.

I still would like to have my macros in variables, rather then topics. Im not sure if the %UNLESS% syntax fits in this situation. It seems to define default values on topic level (or even more globally), not variable (= macro) level. In other words: if there is another macro that uses cereal or fruit, it wants to define its own defaults. Maybe, the $param("name" default="value") syntax is more appropriate, even if you have to retype the default value several times. May be you know a better solution for that.

I think, most important is the usage of the macro, beacuse the definition could be done by administrators and experienced users. It should be possible to define easy-to-use macros to encapsulate more complicated expressions. I write lots of variables to define stuff like urls, table headers, search strings and so on. They're easy to use even for newbies (%INCLUDE{}% and %CALLMACRO{}% look more cryptic). But it's just not generic enough.

-- StefanSteinegger - 05 Nov 2004

The best idea is probably to think in terms of an existing, effective template system, and model on that. For example, cpp has a very effective approach where parameters to a macro are formally declared before being used. That would allow the assignment of a default in the formal parameters, rather than in the body. For example:

   * Set BREAKFAST(cereal="Grape Nuts" fruit) = %cereal% and %fruit% juice

BTW I am dead set against the $param(...) syntax. I think it's really, really horrible, not least because it has all the same expansion order problems as the %% syntax, without the advantage of being able to share the same parser.

-- CrawfordCurrie - 05 Nov 2004

I understand. I like your syntax. If you declare all the parameters you need for a macro, you should not be able to mix them with other TWikiVaribles:

      * Set juice = "Orange"
      * Set breakfast(juice) = %juice% juice
In another topic you write
Today, I'm having %juice{"apple"}% for breakfast.
Will I have %juice% tomorrow?
This should not work. Default values should always be in the scope of the macro, never taken from other TWikiVariables. The output could be like this:

Today, I'm having apple juice for breakfast. Will I have <missing parameter =juice=> juice tomorrow?

What are we doing if someone writes

      * Set SPECIALSEARCH(REGEX, TOPIC="MyDefaultTopic") = %SEARCH{"%REGEX%" topic="%TOPIC%", format="..." header="..." ...}%

There are the expansion order problems, of course. Is there any topic discussing / documenting this?

-- StefanSteinegger - 08 Nov 2004

Agreed about the scoping, though I think your example is wrong? Shouldn't is be %breakfast{juice="apple"}%.? Note that if a parameter is given without a key (as in %breakfast{"apple"}%) then that value is always associated with the key _DEFAULT. For consistency I think this use of _DEFAULT should require declaration as well, as in

   * Set breakfast(_DEFAULT juice="orange") = %_DEFAULT% and %juice% juice
Today, I'm having %breakfast{"porridge" juice="grape"}% for breakfast.

There should be no expansion order problems if the code on DEVELOP is used, because it always fully expands parameters to a macro before the macro itself. It won't work with MAIN, of course. It will always be possible to defeat, as any macro language is, but as long as the user is sensible it should be OK.

-- CrawfordCurrie - 08 Nov 2004

You're right, my example is wrong. I forgot the params name.

_DEFAULT looks nice. But what are you doing to simulate behaviour of %SEARCH%, where you can write %SEARCH{search="..."}% or just %SEARCH{"..."}%. To make TWiki truly expansible, users shouldn't have to distinguish between built in and user defined variables. (Maybe %SEARCH% should be redefined?)

-- StefanSteinegger - 09 Nov 2004

I suppose one could always dosomething like this:

   * Set guide(_DEFAULT="city" city country="Sweden") = %city% is a city in %country%
%guide{"Frankfurt" country="Poland"}%
%guide{city="Dusseldorf"}%
but TBH, I think this is a bit confusing. Let's keep it simple and quietly ignore %SEARCH%.

-- CrawfordCurrie - 09 Nov 2004

Although I have not yet studied this proposal, parametrized variables are useful for TWikiApplications. In essence these are macros. I suggest not to diverge too much from the existing syntax.

-- PeterThoeny - 09 Nov 2004

You mean the %TMPL:P syntax? From a user perspective, IMHO the proposal here is a heck of a lot less divergent than suddenly introducing TMPL:DEF and TMPL:P to end users. The existing * Set is already a macro definition:

   * Set MYVARIABLE = MyValue
is almost exactly equivalent to
%TMPL:DEF{"MYVARIABLE"}%MyValue%TMPL:END%
(yes, I know about the whitespace problems, but both implementations currently have issues)

Also, %TMPL:P doesn't support parameters ATM, so would end up having to be extended in the same way.

I'm all in favour of normalising to a single syntax, but from a perspective of making life easier for end users (and TWikiApplications), this is the more sensible route. Replacing %TMPL:XX in templates would be a lot less work than replacing every * Set* with a %TMPL:DEF and every %VARIABLE% with a %TMPL:P, surely?

Here is the full spec of what we have been discussing, suitable for inclusion in the documentation:

Using TWiki Variables as Macros

The "*   Set" syntax can also be used to define a macro. A macro is a piece of text with placeholders. These placeholders are filled in with text you supply when the macro is expanded.

You must list the placeholders that your macro uses, before you use them. Placeholders used by a macro must be listed in curly braces immediately after the macro name, like this:

   * Set CARS{mycar hercar pourcar}% = My car is a %mycar%, my partner's car is an %hercar% and our shared car is a %ourcar%

   %CARS{hercar="Audi TT" ourcar="Land Rover Discovery" mycar="Aston-Martin DB9"}%
In this example, the last line will expand to My car is an Aston-Martin DB9, my partner's car is an Audi TT and our shared car is a Land Rover Discovery. Note that the convention is to give parameters lower case names. This is to avoid the risk of confusion with other TWiki variables.

Macros can also take a single unnamed placeholder, like this: %MYMACRO{"myvalue"}%. The unnamed placeholder will be assigned to the special name _DEFAULT. If you want your macro to support the unnamed placeholder, you have to declare _DEFAULT in the curly braces, same as any other placeholders.

   * Set CRUSTACEAN{_DEFAULT} = A %_DEFAULT% is a crustacean

   %CRUSTACEAN{"lobster"}%

A placeholder that is not defined when the macro is called will be given the value "" (i.e. the empty string). This includes _DEFAULT. So:

   * Set CRUSTACEAN{_DEFAULT predator} = A %_DEFAULT% is a crustacean, eaten by %predator%

   %CRUSTACEAN{"lobster" predator="octopus"}% will expand to "A lobster is a crustacean eaten by octopus"
   %CRUSTACEAN{"lobster"}% will expand to "A lobster is a crustacean eaten by "
   %CRUSTACEAN{predator="octopus"}% will expand to "A  is a crustacean eaten by octopus"
   %CRUSTACEAN% will expand to "A  is a crustacean eaten by "
This rule applies even when a placholder has the same name as a TWiki variable.

You can also specify a default value for the placeholder, to be used if no value is given. You do this in the macro definition. For example,

   * Set CRUSTACEAN{_DEFAULT="prawn" predator="cuttlefish"} = A %_DEFAULT% is a crustacean, eaten by %predator%

   %CRUSTACEAN{"lobster" predator="octopus"}% will expand to "A lobster is a crustacean eaten by octopus"
   %CRUSTACEAN{"lobster"}% will expand to "A lobster is a crustacean eaten by cuttlefish"
   %CRUSTACEAN{predator="whales"}% will expand to "A prawn is a crustacean eaten by whales"
   %CRUSTACEAN% will expand to "A prawn is a crustacean eaten by cuttlefish"

See also %INCLUDE for another way to define macros, more suitable for larger amounts of text.

-- CrawfordCurrie - 09 Nov 2004

That's it!

-- StefanSteinegger - 11 Nov 2004

What happened to this feature? Did it make it into Cairo or Dakar?

-- PankajPant - 09 Mar 2006

nope

-- RafaelAlvarez - 09 Mar 2006

Shame, this would be very useful for a TWiki Knowledgebase application I'm developing. It would make things like uniformly formatted literature references much easier (e.g. like the cite templates used in Wikipedia, see http://en.wikipedia.org/wiki/Wikipedia:Template_messages/Sources_of_articles/Generic_citations)

-- LevienVanZon - 23 Jun 2006

So, a case of the TWiki community thinking of something way before the competition but executing way after.

-- MartinCleaver - 22 Jul 2006

We really need to stop calling the variables. I understand that there's history for calling stuff TWikiVariables, but variables do not take parameters; functions do.

-- MeredithLesly - 24 Jul 2006

Or macros.

-- ArthurClemens - 24 Jul 2006

On 09 Nov 2004 PeterThoeny said:

> Although I have not yet studied this proposal, parametrized variables are useful for TWikiApplications. In essence these are macros. I suggest not to diverge too much from the existing syntax.

Two issues:

  1. Have you read this now?
  2. What do you think?
  3. How flexible are you on the naming of the 'essence of macros'

Related is AreVariablesReallyDirectives.

-- MartinCleaver - 25 Jul 2006

 
Edit | WYSIWYG | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r24 < r23 < r22 < r21 < r20 | More topic actions
Codev.ParameterizedVariables moved from Codev.ParametrizedVariables on 09 Nov 2004 - 09:59 by CrawfordCurrie - put it back
 
Powered by TWiki
This site is powered by the TWiki collaboration platformCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback SourceForge.net Logo