Proposed <% if %> shortcut syntax

:open_mouth:

Thanks. Somehow I managed to miss this response. :roll_eyes:

Subject closed, methinks.

@jeremyruston Which I think is copacetic. However, you will have noticed there is some resistance to yet-another-syntax variant. Do you foresee that syntax (and alt grammar) being useful elsewhere going forward? Where?

For what it’s worth, I have put my <$if> widget PR on hold until consensus emerges, by setting it to draft mode so it can’t be merged by mistake. I’ll continue to work on my other TiddlyWiki contributions in the meantime. The options I have seen discussed here that I like (this is not an exhaustive list, as there might be something I missed) are:

  • A widget renaming tool, so that people using Evan’s existing plugin can easily rename his widgets to <$evanif> or <$eif> or something. Then after renaming the widgets, the upgrade path to TW 5.3.2 would be easy.
  • Putting my <$if> widget into a plugin, rather than in the core. It could even be enabled by default, allowing most people to use <$if> without having to do anything special during the upgrade process, but allowing anyone using Evan’s plugin to disable mine and not have to change their existing code.
  • Jeremy Ruston’s proposed {% if %} syntax – not because I think it’s per se better than an <$if> widget, but because it opens up possibilities for the {% whatever %} syntax to be used for several other things that the widget syntax might currently make more difficult than necessary. (A {% switch variableName %}{% case value %} syntax comes to mind, for example).

Anyway, I’ll be watching this discussion (though not every day), and I won’t merge the PR prematurely. Once there’s general consensus on what to do, I’ll go ahead and go that.

4 Likes

Thanks so much for your work on this Robin @rmunn it is an important feature and you have certainly stimulated the discussion. It may be worth your publishing it as a plugin, even if not compatible with existing ones, so the community can play and comment with your solution. This would solicit feedback and allow you to develop it further and assist in the decisions that need to come.

Thanks again

Good question. The challenge with using the widget based syntax is that it is verbose and finickity. For example, every “if” widget will need the characters filter=... repeated, and every widget needs to be explicitly closed.

For example, here is an example of the widget-based syntax:

\define num() 2

<$if filter="[<num>compare:number:gt[3]]">
<$then><<num>> is greater than 3</$then>
<$elseif filter="[<num>compare:number:gt[2]]"><<num>> is greater than 2</$elseif>
<$elseif filter="[<num>compare:number:gt[1]]"><<num>> is greater than 1</$elseif>
<$elseif filter="[<num>compare:number:gt[0]]"><<num>> is greater than 0</$elseif>
<$else><<num>> is negative or zero</$else>
</$if>

That’s a total of 397 characters. In contrast, the same example using the proposed shortcut syntax is 319 characters, and is much easier to read:

\define num() 2

{% if [<num>compare:number:gt[3]] %}
<<num>> is greater than 3
{% elseif [<num>compare:number:gt[2]] %}<<num>> is greater than 2
{% elseif [<num>compare:number:gt[1]] %}<<num>> is greater than 1
{% elseif [<num>compare:number:gt[0]] %}<<num>> is greater than 0
{% else %}<<num>> is negative or zero
{% endif %}

The roots of this proposal have been in my thoughts for a long time. There are many discussions over the years where I have advocated for the general principle of introducing shortcut syntaxes to more concisely express common idioms that can be done with raw widgets, but this is the first time we have a first firm proposal in that area.

A “shortcut syntax” means a special parse rule that matches instances of a particular syntactic construction. It has to be independent of the existing rules, so we can’t reuse the existing syntax markers << and <$, but need to choose a new way to mark not just these conditional operations, but also future shortcut syntaxes.

As @rmunn notes, a switch/case shortcut syntax would be very helpful and could be readily expressed using a similar shortcut syntax:

{% switch [<myvalue>] %}
{% case "one" %}
Something
{% case "two" %}
Another
{% default %}
More
{% endswitch %}

It’s a big step to introduce such a fundamental new feature, but I think would open the door to further improvements that together would greatly improve the expressiveness and readability of wikitext. A new character sequence like {% is bound to look strange and out of place to all of us familiar with the existing syntax, but it is entirely complementary to the existing syntax, and deals with different situations.

4 Likes

this syntax does seem to be a new beginning of something that is not widgets or filter syntax, which is interesting and can enable other things in the future, though there is a cumulatively increasing barrier to entry for learning new syntax types for new users.

on a separate note, you mention this {% %} as a “shortcut syntax”. does that mean there is a “long form” within the existing syntax that it is abbreviating? if that is the case, i see it as a win-win solution - people could use the new syntax if they are comfortable with it, while still being able to fall back on the widget syntax (which may be more lengthy) while learning or for consistency etc.

1 Like

Yes, the long form of the conditional shortcut syntax is a series of nested list widgets. You can see how things work by creating a new tiddler in the preview and switching on the preview pane to show the parse tree. Try typing an example of the conditional shortcut syntax and in the preview pane you’ll see a rendering of the corresponding parse tree, showing the underlying widgets.

1 Like

@jeremyruston

And the reason this is beneficial, is that the list widget is already (heavily?) optimized. Correct?

(Just so it’s “out there”.)

I’m curious as to whether <% ... %> was also considered and, if so, why it wasn’t selected. It just seems more in line with << ... >> and <$... > ... </$...>. No objection here, just curiousity.

We already have similar wikitext shortcuts in the core, for example the closest are probably {{title}} as a shortcut for a tiddler widget wrapping a transclude widget, and {{{filter}}} as a shortcut for a list widget. As such the proposed {% %} is more consistent in my opinion.

\procedure test(animal)
{% if [<animal>match[Elephant]] %}
  It is an elephant
{% elseif [<animal>match[Giraffe]] %}
    It is a giraffe
{% else %}
    It is completely unknown
{% endif %}
\end

<<test "Giraffe">>

The {% syntax was influenced by templating engines such as Jinja, but I agree that there is a good case for using <% which I had not considered. Perhaps it would better convey that the shortcut syntax is transformed into the underlying widgets.

It might be argued that { is the marker for transclusion within TiddlyWiki, and < is the marker for macros/widgets/variables. As such, { is perhaps not a good match for the conditional shortcut syntax because it has nothing to do with transclusion.

I’d welcome other views on this, and will give it some more thought.

I was thinking more in terms of structure vs content, but I don’t think that breakdown really holds up to closer examination. I do think that those in the know might do well to detail what sorts of other things seem likely to use the new syntax, and see if the whole set seems closer to < or to {. The trouble is that if the answer is “Neither”, the decision would still probably have to come down to one of them, or to [; it’s really hard to imagine adding a fourth symbol.

Agreed, as I asked earlier. @rmunn pointed out switch/case/default. I don’t think I can think of any other possibilities - which doesn’t mean much :blush:

But I agree that <% seems better in the proposed role.

Makes me wonder, is there a case for <{ or {% (transcluded directive?) lurking in the shadows on the horizon? Or is my crystal ball in need of a spit-shine?

Thank you for clarification.

The problem I see with comparing start and end-markers only is that they are missing context. I think they should be compared with some code.

\procedure test(animal)
<% if [<animal>match[Elephant]] %>
  It is an elephant
<% elseif [<animal>match[Giraffe]] %>
    It is a giraffe
<% else %>
    It is completely unknown
<% endif %>
\end

\procedure test(animal)
{% if [<animal>match[Elephant]] %}
  It is an elephant
{% elseif [<animal>match[Giraffe]] %}
    It is a giraffe
{% else %}
    It is completely unknown
{% endif %}
\end

<<test "Giraffe">>

I personally think the second syntax is more visible. Especially if we compare the first line with the filter syntax and variables in them. I think the similarity to existing << markers is more of a disadvantage than an advantage

<% if [<animal>match[Elephant]] %>

vs

{% if [<animal>match[Elephant]] %}

For tiddler titles we do have a warning in the UI that says:

Warning: avoid using any of the characters | [ ] { } in tiddler titles

There is a higher chance that tiddler titles end with %> than %}. Usually the end-marker can cause problems with the TW parser.

Just my thoughts
-m

On further reflection it occurs to me that the proposed syntax is too similar to the new text substitution syntax and that using an angle bracket would indeed be a better choice.

Substitution syntax:
${ filter expression }$

\procedure test(animal)
{% if [<animal>match[Elephant]] %}
  It is an elephant
{% else %}
  {% if [<animal>match[Giraffe]] %}
    It is a giraffe
  {% else %}
    It is completely unknown
  {% endif %}
{% endif %}
\end

<% if [<animal>match[Elephant]] %>
  It is an elephant
<% elseif [<animal>match[Giraffe]] %>
    It is a giraffe
<% else %>
    It is completely unknown
<% endif %>
2 Likes

That’s a point but the substitution syntax is either part of a filter or a widget parameter.

So it’s either covered in braces or back-ticks. I think it’s not stand alone as in your example.

I agree. I take @pmario’s point that the substitution syntax is localised to parameters using textual substitution, but I don’t like that the two usages invert the ordering (ie ${thing}$ vs. {%thing%}). I’m going to go ahead and change the PR.