Will Robertson wrote:
> So how would \my_sanitise:n above be written? If it's not expandable,
> then the results of modifying #1 must be written to a standard scratch
> variable (right?). At which stage I'm not convinced we've saved any
> confusion over the original way to write this sort of thing.
>
> For example:
>
> \cs_set:Nn \my_sanitise:n {
> \tl_set:Nn \l_scratch_tl {#1}
> \tl_replace_in:Nnn \l_scratch_tl {&} {&}
> % but what to do now with \l_scratch_tl ??
> }
>
> If it's easier to hook post-processing steps into the argument stage but
> *harder* to write the functions that do so, have we gained much? Enough
> to justify the initial increase in complexity?
>
> Maybe to re-write my concern; how could we simplify this example from
> xdoc2l3: (use as much hypothetical syntactic sugar as you like)
>
> \gdef\XD@gp@intrange#1#2#3\XD@endgrab#4{%
> \count@=#4\relax
> \ifnum #1>\count@
> \PackageError{xdoc2l3}%
> {Too small! Changed to minimum value #1}\@ehc
> \count@=#1\relax
> \else\ifnum #2<\count@
> \PackageError{xdoc2l3}%
> {Too large! Changed to maximum value #2}\@ehc
> \count@=#2\relax
> \fi\fi
> \expandafter\XD@gh@put \expandafter{\expandafter{\the\count@}}{#3}%
> }
> \gdef\XD@pgp@intrange#1#2{%
> \XD@macro@prepend\@tempa{\XD@gp@intrange{#1}{#2}}%
> \XD@parse@processor
> }
>
> In my opinion, based on this example, it will be easier for users of
> xparse to write their own argument-parsing functions as nested
> definitions inside \DeclareDocumentCommand than to write something like
> the above. Notice the number of necessary but implicit macros that the
> author must know about:
>
> \XD@gp@...
> \XD@pgp@...
> \XD@endgrab
> \XD@gh@put
> \XD@macro@prepend\@tempa
> \XD@parse@processor
>
> To be clear, I'm not yet opposed to this style of argument processing
> and I *do* think there are some simplifications that can be made to the
> code above to make it more palatable for users to write.
Perhaps best would be to design the system so that
\ArgProcessorFunction
would expand to
\arg_processors:nN
which then gets given the argument as #1 and the return variable as #2
(a toks, so that there is nothing going to go wrong with # tokens). As
long as it sets #2 to whatever #1 turns into, then the internal xparse
structure is not something it has to know about (except to return to a
toks). All we have to do is then put the value of the toks into the
correct part of the output toks we build.
> But before we agree to include such complex ideas into what is now a
> simple package (for end-users, I mean), I think it would be good to
> verify that a distillation of xdoc2l3 will "fit" into the philosophy of
> xparse.
I've already suggested that xparse should provide some basic processors,
if we are going to do this at all! It just depends how many.
> After I say that, I suppose it would be remiss of me to go away without
> actually mentioning how I think the ideas in xdoc2l3 might work in
> xparse(-alt).
>
> First of all, I think we should drop the idea of using more letters for
> shorthands. As we've discussed, each package will use different letters
> and clashes will occur very quickly.
>
> Secondly, for simplicity let's drop the idea of toks-grabbing as a proxy
> for argument grabbing.
>
> Thirdly, use actual function names rather than character strings to
> represent argument processors.
>
> From xdoc2l3, there seem to be two broad cases for argument processing:
> \argumentprocess{#1}
> and
> \argumentprocess#1<delimiter>
>
> These can be referred to in the argument definitions as something like
> >\CS
> and
> @\CS{DELIMITER}
> where \CS is the processing function and DELIMITER is what's inserted
> after the argument, in the second case.
>
> Finally, allow these to be chained together if necessary, as in
> something like this: (\foo takes one argument)
>
> \DeclareDocumentCommand \foo {
> @\foo_split_colons:n{::\q_nil} >\foo_range_check:nnn m
> }{...}
>
> Open questions:
>
> 1. Does this cover the functionality that you miss from xparse in xdoc2l3?
> 2. Is it simple enough for xparse?
> 3. Assuming that we must deal with both expandable and unexpandable
> argument processing, is there a straightforward way we can write the
> argument processors? (E.g., see how boolean expressions are written in
> expl3; a consistent interface is used for both expandable and
> unexpandable tests.)
> 4. Does that end up being any easier than writing things by hand?
>
> I've got some sort of niggling concern that this approach mixes "how the
> arguments are parsed" with "what the structure of the arguments are",
> which xparse is more careful not to do.
As I've indicated, I'm still more in favour of "grab arguments, then
process them in a separate step". I also feel that "daisy chaining" is
not that easy to implement, although you could imagine:
\DeclareDocumentCommand \foo { >{ \ProcessorOne \ProcessTwo }m }
where the processor is applied, returns the processed argument and it
can then be used for the next processor as input.
--
Joseph Wright
|