On 02/05/12 04:51, Gabriel Wicke wrote:
frame.args.name.expandTo( 'text/x-mediawiki' ) --- returns "value"
This would make it possible to work with other formats apart from wikitext.
I can see how that would make sense when you're writing a parser, but given the target audience for the Lua API, I think I would prefer to provide an abbreviated interface.
How about frame.args.name as an abbreviation for frame:getArgument('name'):expandTo( 'text/x-mediawiki' ) ?
And how about frame.plainArgs.name as an abbreviation for frame:getArgument('name'):expandTo( 'text/plain' ) ?
I recently added an API like this in Parsoid (the method is called 'as' there), and liked the way that worked out for parser functions. I am currently using the 'text/plain' type to retrieve a text expansion with comments etc stripped, and 'tokens/x-mediawiki' for expanded tokens (~list of tags and strings).
I know you're not really asking for a review of Parsoid and its interfaces, but I worry as to whether your use of text/plain to indicate wikitext with comments stripped is appropriate.
In MediaWiki, PPFrame::expand() takes any combination of 5 boolean flags, and modifies its behaviour based on which of the Parser's 4 output types is selected, so if you were to match it for flexibility, you would need 128 MIME types.
If I were to provide Lua with a richer interface to PPFrame::expand(), I would be inclined to support at least some of those flags via named options, rather than rolling them up into a single string parameter. So instead of expandTo( 'text/plain' ) we might have:
frame:getArgument('name'):expand{ expand_args = false, expand_templates = false, respect_noinclude = false, strip_comments = true }
Or, if forwards-compatibility requires that we don't support so many orthogonal options, some of the options could be rolled in together. The preceding could perhaps be written as:
frame:getArgument('name'):expand{ plain = true }
That doesn't preclude the use of overrides:
frame:getArgument('name'):expand{ plain = true, strip_comments = false }
But it does seem like a can of worms. How about providing getArgument(), which will return an opaque ParserValue object with a single method called expand(). This method would theoretically take named parameters, but currently, none are defined. With no parameters, it provides some kind of reasonable template-expanding behaviour. Then frame.args would provide an abbreviated syntax for expand() with no parameters.
If there is a compelling use case for "plain" expansion, then we would have to decide what options to PPFrame::expand() are needed to support that use case, and then we would need to decide how to map them to parameters to ParserValue.expand().
The conversion of wikitext or other formats to an opaque value object could be achieved using an object constructor:
--- 'value text' is parsed lazily ParserValue( 'text/x-mediawiki', 'value text', frame )
The frame might be the passed-in parent frame, or a custom one constructed with args assembled from other ParserValues.
Yes, this is an interesting idea. But I think I would prefer the factory to be a frame method rather than a global function. Also, again, I am skeptical about the value of using a MIME type. How about an interface allowing either:
frame:newParserValue( 'value text' )
or named arguments:
frame:newParserValue{ text = 'value text', fruitiness = 'high', }
Calls to existing templates could be supported with a convenient TemplateParserValue constructor, which does not specify how a template call is represented internally.
TemplateParserValue( 'tpl', args ).expandTo( 'text/plain' )
Yes, this is attractive, and could be done in the same way as ParserValue objects above. But I think there is still a need for an abbreviated interface:
frame:newTemplateParserValue{title = 'tpl', args = args}:expand()
abbreviated to:
frame:expandTemplate{title = 'tpl', args = args}
It doesn't just make the text shorter, it also reduces the number of concepts that the user has to understand before they are able to use the interface.
I know that adding such concepts gives greater flexibility, but an increase in the number of concepts will steepen the learning curve, and the terminology required to explain them risks being daunting. For example, if someone has never programmed before, you can't expect them to understand terms like "opaque object".
Finally, a ParserValue (or a list of those) could be used for the return type of functions to support output formats other than plain text.
Overall, I would love to keep the access to values as opaque as possible to enable back-end optimizations and lazy expansions with sharing. Opening a path towards content representations other than plain (wiki-)text such as tokens, an AST or a DOM tree should be very useful for future parser development.
For me, the main motivation behind providing a parallel "advanced interface" along the lines you suggest would be to establish a direction for future interface development.
Interfaces evolve mostly by analogy, so providing a well thought-out "advanced interface" will influence future development even if nobody ever uses it.
-- Tim Starling