Thread:Project:Support desk/Radically rethinking template syntax? (2)

Hello. I've been a Wikipedia editor for several years but I've only recently been poking around with templates. All the previous times I've tried to make sense of anything non-trivial with templates, my eyes basically just glaze over and I give up.

This time I've finally bitten the bullet and dug in. IMO the current template syntax is incredibly hostile. I'm a software developer with a lot of experience developing API's, software libraries and language extensions, and one of the most important things I've found that contributes to whether software quality is good or bad is the maintainability of the code. However, the very design of template syntax makes template code practically unmaintainable. So it's no surprise to me, reading through template code, to see all the hallmarks of poor-quality software: inconsistently structured code, brittle code that breaks easily if given arguments other than exactly what the designer expected, duplicated code (non-abstracted) both across templates and within templates, bit rot, etc.

So I'm proposing a different syntax, much more readable and much more similar to conventional programming languages. Here's an example, from en:Template:Harvtxt:

The current code:

The new version, which is a direct conversion of the old version, keeping the same logic, but adding in some comments to explain the code:

%% Here we define a macro that will be substituted inline, %% and won't lead to the extra load of transcluded sub-templates. %% This outputs something like "Pereira (1996" or %% Ladefoged &amp; Maddieson (2004". Paren is closed later.

%def %authoryear($1 $2 $3 $4 $5) ( %if $5 (($1 et al. \($5)) %elif $4 (($1, $2 &amp;amp; $3 \($4)) %elif $3 (($1 &amp;amp; $2 \($3)) %else (($1 \($2)) )

%% If Ref=none, just output the author/year directly ...

%ifeq $Ref none ( %authoryear($1 $2 $3 $4 $5) ) %else

%% ... otherwise, link it to a citation elsewhere. %authoryear($1 $2 $3 $4 $5) %% If no page location, close paren inside link.  %ifnot (%or $loc $p $pp) \)

%% If page location, output now, and close paren. %if $loc ((, $loc\))) %elif $p ((, p.&amp;nbsp;$p\))) %elif $pp ((, pp.&amp;nbsp;$pp\)))

The new version is much, much clearer, as well as shorter (esp. if you take out the comments, which aren't in the old version).

I'm right now writing code to implement this. The idea, at least for the moment, is that a preprocessor will convert the new code directly into the old code, so there's no need to change the underlying template-code engine itself. The preprocessor could actually be run totally separately from MediaWiki, and then the output pasted into the template edit box, but having it done inline would be more convenient and make the code more maintainable, as others could edit the new-style code and not ever worry about messing with the old-style code underneath.

The code I'm writing is in Python, and uses PLY (a pure-Python implementation of Lex and Yacc, i.e. a tokenizer and parser). It's not going to be especially long, and if necessary, it could certainly be converted to PHP.

The syntax itself is a bit in flux but the basic idea is that whitespace isn't significant except in double parens ((...)) or when escaped with a backslash; so you're free to space out the code to make it look nice. Single parens are used for grouping; the main use for this is in the arguments to constructs like %if, which need to be either a single word or a balanced expression.

Before I put too much effort into this, I'm wondering what people think of this? Has anyone suggested something like this before? Is there another place where it might be more appropriate to bring this up? Other comments?

Benwing 07:14, 11 May 2011 (UTC)