A command challenge
Clash Royale CLAN TAG#URR8PPP
Here's a little challenge. The goal is to create a command that takes is two or three arguments without using square brackets for optional arguments. The first and second argument are separated by a comma and a space, while the second and the third (if present) are separated by a dash. This means that both of the following inputs should be acceptable
mycommandarg_1, arg_2
and
mycommandarg_1, arg_2-arg_3
The definition of what mycommand
does with the two/three arguments is irrelevant to the problem.
macros expl3 xparse
add a comment |
Here's a little challenge. The goal is to create a command that takes is two or three arguments without using square brackets for optional arguments. The first and second argument are separated by a comma and a space, while the second and the third (if present) are separated by a dash. This means that both of the following inputs should be acceptable
mycommandarg_1, arg_2
and
mycommandarg_1, arg_2-arg_3
The definition of what mycommand
does with the two/three arguments is irrelevant to the problem.
macros expl3 xparse
2
That's one argument from a TeX point of view ... I guess you want a parser for that one document-level argument.
– Joseph Wright♦
Feb 8 at 17:46
Trydefmycommand#1,space#2-#3...
.
– John Kormylo
Feb 8 at 21:41
Since I assume this is more or less a follow-up to tex.stackexchange.com/q/473949/35864, let me please re-iterate that I believe that the usualbiblatex
syntax is not really inferior to this syntax. In fact the syntax proposed here has the serious drawback that it removes the ability to cite several entries in one cite commandautocitesugfridsson,worman,nussbaum
as that uses the comma-separated syntax in one argument already.
– moewe
Feb 9 at 8:00
add a comment |
Here's a little challenge. The goal is to create a command that takes is two or three arguments without using square brackets for optional arguments. The first and second argument are separated by a comma and a space, while the second and the third (if present) are separated by a dash. This means that both of the following inputs should be acceptable
mycommandarg_1, arg_2
and
mycommandarg_1, arg_2-arg_3
The definition of what mycommand
does with the two/three arguments is irrelevant to the problem.
macros expl3 xparse
Here's a little challenge. The goal is to create a command that takes is two or three arguments without using square brackets for optional arguments. The first and second argument are separated by a comma and a space, while the second and the third (if present) are separated by a dash. This means that both of the following inputs should be acceptable
mycommandarg_1, arg_2
and
mycommandarg_1, arg_2-arg_3
The definition of what mycommand
does with the two/three arguments is irrelevant to the problem.
macros expl3 xparse
macros expl3 xparse
asked Feb 8 at 17:42
noibenoibe
435113
435113
2
That's one argument from a TeX point of view ... I guess you want a parser for that one document-level argument.
– Joseph Wright♦
Feb 8 at 17:46
Trydefmycommand#1,space#2-#3...
.
– John Kormylo
Feb 8 at 21:41
Since I assume this is more or less a follow-up to tex.stackexchange.com/q/473949/35864, let me please re-iterate that I believe that the usualbiblatex
syntax is not really inferior to this syntax. In fact the syntax proposed here has the serious drawback that it removes the ability to cite several entries in one cite commandautocitesugfridsson,worman,nussbaum
as that uses the comma-separated syntax in one argument already.
– moewe
Feb 9 at 8:00
add a comment |
2
That's one argument from a TeX point of view ... I guess you want a parser for that one document-level argument.
– Joseph Wright♦
Feb 8 at 17:46
Trydefmycommand#1,space#2-#3...
.
– John Kormylo
Feb 8 at 21:41
Since I assume this is more or less a follow-up to tex.stackexchange.com/q/473949/35864, let me please re-iterate that I believe that the usualbiblatex
syntax is not really inferior to this syntax. In fact the syntax proposed here has the serious drawback that it removes the ability to cite several entries in one cite commandautocitesugfridsson,worman,nussbaum
as that uses the comma-separated syntax in one argument already.
– moewe
Feb 9 at 8:00
2
2
That's one argument from a TeX point of view ... I guess you want a parser for that one document-level argument.
– Joseph Wright♦
Feb 8 at 17:46
That's one argument from a TeX point of view ... I guess you want a parser for that one document-level argument.
– Joseph Wright♦
Feb 8 at 17:46
Try
defmycommand#1,space#2-#3...
.– John Kormylo
Feb 8 at 21:41
Try
defmycommand#1,space#2-#3...
.– John Kormylo
Feb 8 at 21:41
Since I assume this is more or less a follow-up to tex.stackexchange.com/q/473949/35864, let me please re-iterate that I believe that the usual
biblatex
syntax is not really inferior to this syntax. In fact the syntax proposed here has the serious drawback that it removes the ability to cite several entries in one cite command autocitesugfridsson,worman,nussbaum
as that uses the comma-separated syntax in one argument already.– moewe
Feb 9 at 8:00
Since I assume this is more or less a follow-up to tex.stackexchange.com/q/473949/35864, let me please re-iterate that I believe that the usual
biblatex
syntax is not really inferior to this syntax. In fact the syntax proposed here has the serious drawback that it removes the ability to cite several entries in one cite command autocitesugfridsson,worman,nussbaum
as that uses the comma-separated syntax in one argument already.– moewe
Feb 9 at 8:00
add a comment |
5 Answers
5
active
oldest
votes
You can do it with xparse
:
documentclassarticle
usepackagexparse
% split at the comma
NewDocumentCommandmycommand >SplitArgument1,m %
mycommandA#1%
% do something with #1 and split the second part at the hyphen
NewDocumentCommandmycommandA m >SplitArgument1-m %
Main is #1%
IfNoValueTF#2.; mycommandB#2%
% do something with the second part
NewDocumentCommandmycommandBmm%
Secondary is #1IfValueT#2 plus #2.%
begindocument
mycommandarg1
mycommandarg1, arg2
mycommandarg1, arg2-arg3
enddocument
An advantage: it's irrelevant if you forget the space after the comma.
add a comment |
documentclassarticle
defmycommand#1xmycommand#1--relax
defxmycommand#1,#2-#3-#4relax[#1][#2][#3]
begindocument
$mycommandarg_1, arg_2$
$mycommandarg_1, arg_2-arg3$
enddocument
6
Even without electricity. I'm impressed!
– marmot
Feb 8 at 17:53
How about adding some mortar to the bricks!?
– Werner
Feb 8 at 18:06
@Werner where I come from we prefer this style: derbyshireuk.net/derbyshire_drystonewalls.html
– David Carlisle
Feb 8 at 18:12
5
@noibe oh no a disaster! I don't mind not getting the tick (I have more than enough points) but seeing points go to egreg is so depressing:)
– David Carlisle
Feb 8 at 18:49
2
Nozzz
? :'-(
– Henri Menke
Feb 9 at 6:02
|
show 4 more comments
Some crocheting/knitting by hand (or whatever)... ;-)
I suppose this question came into being while you thought about your other question: Custom cite command. In that question you ask for a customized cite
-command with the same syntax.
Be that as it may.
The challenge is doing it in a way where desired space-removal but no undesired removal of argument-braces takes place.
E.g., with things like mycommandarg_1a, arg_2
the braces surrounding arg_1
should probably be preserved while with things like mycommandarg_1 , arg_2
they should probably be removed.
Also probably only space-tokens surrounding the entire arguments/surrounding those commas and those dashes that are taken for argument-separators should get removed.
Below is an approach where comma takes precedence over the dash and where the leftmost unhidden comma delimits the first argument from the remaining arguments and where the first unhidden dash following that comma delimits the second from the third argument.
Exactly one pair of matching curly braces will be removed in case after removing surrounding spaces it surrounds an entire argument as in that case it is assumed that the braces serve for hiding commas/dashes/spaces/emptiness. In all other cases braces will be preserved.
E.g., with things like mycommand arg_1 , arg_2-2 - arg_3
you should get:
First argument: arg_1
Second argument: arg_2-2
Third argument: arg_3
.
E.g., with things like mycommand arg 1,a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b
you should get:
First argument (left from the first unhidden comma, surrounding spaces and outermost brace-level that surrounds the entire argument removed): arg 1,a - arg 1b
Second argument (right from the first unhidden comma, left from the first unhidden dash following the comma): arg 2-2 , 2
Third argument (the remainder, right from the first unhidden dash following the comma): arg 3a - arg 3b
.
E.g., with things like mycommandarg 1, arg 2-2 , 2 - arg 3a - arg 3b
you should get:
First argument (left from the first unhidden comma): arg 1
Second argument (right from the first unhidden comma, left from the first unhidden dash following the comma): arg 2-2 , 2
Third argument (the remainder, right from the first unhidden dash following the comma): arg 3a - arg 3b
.
You may not be familiar to methods for removing space-tokens that surround arguments, thus a quote from the manual of my deprecated labelcas-package:
A note about removing leading and trailing spaces
The matter of removing trailing spaces from an (almost) arbitrary
token-sequence is elaborated in detail by Michael Downes, 'Around the
Bend #15, answers', a summary of internet-discussion which took place
under his guidance primarily at the INFO-TEX list, but also at
comp.text.tex (usenet) and via private email; December 1993. Online
archived at http://www.tug.org/tex-archive/info/arobend/answer.015.
One basic approach suggested therein is using TeX's scanning of
delimited parameters in order to detect and discard the ending space
of an argument:
... scan for a pair of tokens: a space-token and some well-chosen
bizarre token that can't possibly occur in the scanned text. If you
put the bizarre token at the end of the text, and if the text has a
trailing space, then TeX's delimiter matching will match at that point
and not before, because the earlier occurrences of space don’t have
the requisite other member of the pair.
Next consider the possibility that the trailing space is absent: TeX
will keep on scanning ahead for the pair
⟨space⟩⟨bizarre⟩
until either it finds them or it decides to give up and signal a
'Runaway argument?' error. So you must add a stop pair to catch the
runaway argument possibility: a second instance of the bizarre
token, preceded by a space. If TeX doesn't find a match at the
first bizarre token, it will at the second one.
(Look up the macros
KV@@sp@def
,KV@@sp@b
,KV@@sp@c
andKV@@sp@d
in
David Carlisle’s keyval-package for an interesting variation on this
approach.)
When scanning for parameters
##1⟨space⟩⟨bizarre⟩##2⟨B1⟩
the sequence:⟨stuff where to remove trail-space⟩⟨bizarre⟩⟨space⟩⟨bizarre⟩⟨B1⟩
, you can fork two cases:
Trailing-space:
##1
=⟨stuff where to remove trail-space⟩
, but with removed space. (And possibly one
removed brace-level!)##2
=⟨space⟩⟨bizarre⟩
.
No trailing-space:
##1
=⟨stuff where to remove trail-space⟩⟨bizarre⟩
.##2
is empty.
So forking can be implemented depending on the emptiness of
##2
.
You can easily prevent the brace-removal in the first case, e.g., by adding (and
later removing) something (e.g., a space-token) in front of the
⟨stuff where to remove trail-space⟩
.
You can choose
⟨B1⟩=⟨bizarre⟩⟨space⟩
.
The link in the quote is out of date.
Nowadays you can find the entire "Around the bend" -collection at http://mirrors.ctan.org/info/challenges/AroBend/AroundTheBend.pdf.
As you see, the methods for space-removal exhibited in the quote above do rely on some sequence of tokens that must not occur within the argument.
In the example below it is relied on the token UD@seldom
not occurring within arguments.
In other words: You must not use the token UD@seldom
within your arguments.
If you don't like that restriction, then I can deliver space-removal-routines which do without such restrictions, but they are slower and they form another huge load of code.
documentclassarticle
makeatletter
%%-----------------------------------------------------------------------------
%% Paraphernalia ;-) :
%%.............................................................................
newcommandUD@firstoftwo[2]#1%
newcommandUD@secondoftwo[2]#2%
newcommandUD@exchange[2]#2#1%
newcommandUD@removespaceUD@firstoftwodefUD@removespace %
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% UD@CheckWhetherNull<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% which is to be checked is empty>%
%% <Tokens to be delivered in case that argument
%% which is to be checked is not empty>%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%.............................................................................
newcommandUD@CheckWhetherNull[1]%
romannumeral0expandafterUD@secondoftwostringexpandafter
UD@secondoftwoexpandafterexpandafterstring#1expandafter
UD@secondoftwostringexpandafterUD@firstoftwoexpandafterexpandafter
UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
UD@secondoftwoexpandafterexpandafterUD@firstoftwo UD@firstoftwo%
%
%%-----------------------------------------------------------------------------
%% Check whether brace-balanced argument starts with a space-token
%%.............................................................................
%% UD@CheckWhetherLeadingSpace<Argument which is to be checked>%
%% <Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% space-token>%
%% <Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a space-token>%
newcommandUD@CheckWhetherLeadingSpace[1]%
romannumeral0UD@CheckWhetherNull#1%
expandafterexpandafterUD@firstoftwo UD@secondoftwo%
expandafterUD@secondoftwostringUD@CheckWhetherLeadingSpaceB.#1 %
%
newcommandUD@CheckWhetherLeadingSpaceB%
longdefUD@CheckWhetherLeadingSpaceB#1 %
expandafterUD@CheckWhetherNullexpandafterUD@secondoftwo#1%
UD@exchangeUD@firstoftwoUD@exchangeUD@secondoftwo%
UD@exchange expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafterexpandafterexpandafter
expandafterexpandafterUD@secondoftwoexpandafterstring%
%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%.............................................................................
%% UD@ExtractFirstArgABCDE yields A
%%
%% UD@ExtractFirstArgABCDE yields AB
%%
%% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
%% You can check for emptiness via UD@CheckWhetherNull before applying
%% UD@ExtractFirstArg.
%%.............................................................................
newcommandUD@RemoveTillUD@SelDOm%
longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
newcommandUD@ExtractFirstArg[1]%
romannumeral0%
UD@ExtractFirstArgLoop#1UD@SelDOm%
%
newcommandUD@ExtractFirstArgLoop[1]%
expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
#1%
expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#1%
%
%%-----------------------------------------------------------------------------
%% UD@RemoveSpacesAndOneLevelOfBraces<argument> removes leading and
%% trailing spaces from <argument>.
%% If after that the <argument> is something that is entirely nested
%% between at least one pair of matching curly braces, the outermost
%% pair of these braces will be removed.
%%
%% !!!! <argument> must not contain the token UD@seldom !!!!
%%.............................................................................
begingroup
newcommandUD@RemoveSpacesAndOneLevelOfBraces[1]%
endgroup
newcommandUD@RemoveSpacesAndOneLevelOfBraces[1]%
romannumeral0%
UD@trimtrailspaceloop#1##1UD@seldom#1UD@seldomUD@seldom#1##1%
%
newcommandUD@trimtrailspaceloop%
longdefUD@trimtrailspaceloop##1#1UD@seldom##2UD@seldom#1##3%
UD@CheckWhetherNull##2%
UD@trimleadspaceloop##3%
%
UD@trimtrailspaceloop##1UD@seldom#1UD@seldomUD@seldom#1##1%
%
%
%
UD@RemoveSpacesAndOneLevelOfBraces %
newcommandUD@trimleadspaceloop[1]%
UD@CheckWhetherLeadingSpace#1%
expandafterUD@trimleadspaceloopexpandafterUD@removespace#1%
%
UD@CheckWhetherNull#1 %
expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
UD@exchange expandafterUD@secondoftwo#1%
#1%
%
%
%
%%-----------------------------------------------------------------------------
%% Check whether argument contains no comma which is not nested
%% in braces:
%%.............................................................................
%% UD@CheckWhetherNoComma<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% contains no comma>%
%% <Tokens to be delivered in case that argument
%% contains comma>%
%%
newcommandUD@GobbleToCommalongdefUD@GobbleToComma#1,%
newcommandUD@CheckWhetherNoComma[1]%
expandafterUD@CheckWhetherNullexpandafterUD@GobbleToComma#1,%
%
%%-----------------------------------------------------------------------------
%% Check whether argument contains no dash which is not nested
%% in braces:
%%.............................................................................
%% UD@CheckWhetherNoDash<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% contains no dash>%
%% <Tokens to be delivered in case that argument
%% contains dash>%
%%
newcommandUD@GobbleToDashlongdefUD@GobbleToDash#1-%
newcommandUD@CheckWhetherNoDash[1]%
expandafterUD@CheckWhetherNullexpandafterUD@GobbleToDash#1-%
%
%%-----------------------------------------------------------------------------
%% Take a comma-delimited/dash-delimited argument where a space was
%% prepended for preventing brace-removal and wrap it in curly braces.
%%.............................................................................
newcommandUD@SplitCommaArg%
longdefUD@SplitCommaArg#1,%
romannumeral0UD@exchange expandafterexpandafterUD@removespace#1%
%
newcommandUD@SplitDashArg%
longdefUD@SplitDashArg#1-%
romannumeral0UD@exchange expandafterexpandafterUD@removespace#1%
%
%%-----------------------------------------------------------------------------
%% Now we have the tools for creating the desired mycommand-macro:
%%.............................................................................
newcommandmycommand[1]%
romannumeral0%
UD@CheckWhetherNoComma#1%
expandaftermycommand@oneargumentexpandafter%
romannumeral0UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
expandafterUD@exchangeexpandafterexpandafter
UD@GobbleToComma#1%
%
expandafter@mycommand
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@ExtractFirstArgexpandafter%
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@SplitCommaArg
UD@firstoftwo #1%
%
%
%
newcommand@mycommand[2]%
UD@CheckWhetherNoDash#2%
expandafterUD@exchangeexpandafterexpandafter
%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#2%
%
%
expandaftermycommand@twoargumentsexpandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
%
expandafterUD@exchangeexpandafterexpandafter%
UD@GobbleToDash#2%
%
expandafter@@mycommand
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@ExtractFirstArgexpandafter%
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@SplitDashArg
UD@firstoftwo #2%
%
#1%
%
%
newcommand@@mycommand[3]%
expandafterUD@exchangeexpandafter%
expandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#2%
%
%
expandafterUD@exchangeexpandafter%
expandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
expandaftermycommand@threeargumentsexpandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#3%
%
%
%
%
newcommandmycommand@oneargument[1]%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is no comma or only empty args after the comma, thus:\
argument 1 = printmeaning#1%
%
newcommandmycommand@twoarguments[2]%
UD@CheckWhetherNull#2%
mycommand@oneargument#1%
%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is a comma but either no dash or only one non-empty argument near
the dash, thus:\
argument 1 = printmeaning#1\
argument 2 = printmeaning#2%
%
%
newcommandmycommand@threearguments[3]%
UD@CheckWhetherNull#2%
UD@CheckWhetherNull#3%
mycommand@oneargument#1%
%x
mycommand@twoarguments#1#3%
%
%
UD@CheckWhetherNull#3%
mycommand@twoarguments#1#2%
%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is a comma and a dash, thus:\
argument 1 = printmeaning#1\
argument 2 = printmeaning#2\
argument 3 = printmeaning#3%
%
%
%
newcommandprintmeaning[1]%
defUD@tempa#1%
fboxtextttexpandafterstrip@prefixmeaningUD@tempa%
%
makeatother
parindent=0ex
parskip=smallskipamount
pagestyleempty%
begindocument
vspace*-3.5cm%
enlargethispage7cm%
verb|mycommand arg 1 |:\
mycommand arg 1 \
nullhrulefillnull
verb|mycommand arg 1 , |:\
mycommand arg 1 , \
nullhrulefillnull
verb|mycommand arg 1 , - |:\
mycommand arg 1 , - \
nullhrulefillnull
verb|mycommand arg 1 , arg 2 |:\
mycommand arg 1 , arg 2 \
(Be aware that (only) the outermost braces get removed from
an argument if surrounding the entire argument after removal
of surrounding spaces.)\
nullhrulefillnull
verb|mycommand arg 1 , arg 2 - |:\
mycommand arg 1 , arg 2 - \
nullhrulefillnull
verb|mycommand arg 1 , arg 2 - arg 3|:\
mycommand arg 1 , arg 2 - arg 3\
nullhrulefillnull
verb|mycommand arg 1 , - arg 3|:\
mycommand arg 1 , - arg 3\
nullhrulefillnull
verb|mycommand arg 1a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b|:\
mycommand arg 1a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b\
nullhrulefillnull
verb|mycommand arg 1 , arg 2-2 , 2 - arg 3a - arg 3b|:\
mycommand arg 1 , arg 2-2 , 2 - arg 3a - arg 3b
enddocument
add a comment |
A listofitems
approach.
By setting a nested parsing with setsepchar,/-
prior to reading the list into myargs
, everything to the left of the 1st comma is read into myargs[1]
, everything to the right of the comma (and before the next comma) is read into myargs[2]
.
Within myargs[2]
, everything to the left of the first dash is assigned to myargs[2,1]
, and everything after the dash (and before the next dash) is assigned to myargs[2,2]
.
The number of sub-elements within myargs[2]
is available through listlenmyargs[2]
.
All these elements and list length variables are fully expandable.
documentclassarticle
usepackagelistofitems
newcommandmycommand[1]setsepchar,/-readlist*myargs#1%
noindent Arg 1 is myargs[1]\
Arg 2 is myargs[2,1]\
Arg 3 is ifnumlistlenmyargs[2]=1relax Absentelsemyargs[2,2]fi%
begindocument
mycommandarg1, arg2
and
mycommandarg1, arg2-arg3
enddocument
add a comment |
One more:
documentclassarticle
usepackagexstring
defmycommand#1,#2 IfSubStr#2-[[#1],
[StrBefore#2-]-[StrBehind#2-]] [[#1],[#2]]
begindocument
mycommand aaa,bbb-ccc
mycommand aaa,bbb
enddocument
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "85"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f473965%2fa-command-challenge%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can do it with xparse
:
documentclassarticle
usepackagexparse
% split at the comma
NewDocumentCommandmycommand >SplitArgument1,m %
mycommandA#1%
% do something with #1 and split the second part at the hyphen
NewDocumentCommandmycommandA m >SplitArgument1-m %
Main is #1%
IfNoValueTF#2.; mycommandB#2%
% do something with the second part
NewDocumentCommandmycommandBmm%
Secondary is #1IfValueT#2 plus #2.%
begindocument
mycommandarg1
mycommandarg1, arg2
mycommandarg1, arg2-arg3
enddocument
An advantage: it's irrelevant if you forget the space after the comma.
add a comment |
You can do it with xparse
:
documentclassarticle
usepackagexparse
% split at the comma
NewDocumentCommandmycommand >SplitArgument1,m %
mycommandA#1%
% do something with #1 and split the second part at the hyphen
NewDocumentCommandmycommandA m >SplitArgument1-m %
Main is #1%
IfNoValueTF#2.; mycommandB#2%
% do something with the second part
NewDocumentCommandmycommandBmm%
Secondary is #1IfValueT#2 plus #2.%
begindocument
mycommandarg1
mycommandarg1, arg2
mycommandarg1, arg2-arg3
enddocument
An advantage: it's irrelevant if you forget the space after the comma.
add a comment |
You can do it with xparse
:
documentclassarticle
usepackagexparse
% split at the comma
NewDocumentCommandmycommand >SplitArgument1,m %
mycommandA#1%
% do something with #1 and split the second part at the hyphen
NewDocumentCommandmycommandA m >SplitArgument1-m %
Main is #1%
IfNoValueTF#2.; mycommandB#2%
% do something with the second part
NewDocumentCommandmycommandBmm%
Secondary is #1IfValueT#2 plus #2.%
begindocument
mycommandarg1
mycommandarg1, arg2
mycommandarg1, arg2-arg3
enddocument
An advantage: it's irrelevant if you forget the space after the comma.
You can do it with xparse
:
documentclassarticle
usepackagexparse
% split at the comma
NewDocumentCommandmycommand >SplitArgument1,m %
mycommandA#1%
% do something with #1 and split the second part at the hyphen
NewDocumentCommandmycommandA m >SplitArgument1-m %
Main is #1%
IfNoValueTF#2.; mycommandB#2%
% do something with the second part
NewDocumentCommandmycommandBmm%
Secondary is #1IfValueT#2 plus #2.%
begindocument
mycommandarg1
mycommandarg1, arg2
mycommandarg1, arg2-arg3
enddocument
An advantage: it's irrelevant if you forget the space after the comma.
answered Feb 8 at 18:22
egregegreg
724k8819173221
724k8819173221
add a comment |
add a comment |
documentclassarticle
defmycommand#1xmycommand#1--relax
defxmycommand#1,#2-#3-#4relax[#1][#2][#3]
begindocument
$mycommandarg_1, arg_2$
$mycommandarg_1, arg_2-arg3$
enddocument
6
Even without electricity. I'm impressed!
– marmot
Feb 8 at 17:53
How about adding some mortar to the bricks!?
– Werner
Feb 8 at 18:06
@Werner where I come from we prefer this style: derbyshireuk.net/derbyshire_drystonewalls.html
– David Carlisle
Feb 8 at 18:12
5
@noibe oh no a disaster! I don't mind not getting the tick (I have more than enough points) but seeing points go to egreg is so depressing:)
– David Carlisle
Feb 8 at 18:49
2
Nozzz
? :'-(
– Henri Menke
Feb 9 at 6:02
|
show 4 more comments
documentclassarticle
defmycommand#1xmycommand#1--relax
defxmycommand#1,#2-#3-#4relax[#1][#2][#3]
begindocument
$mycommandarg_1, arg_2$
$mycommandarg_1, arg_2-arg3$
enddocument
6
Even without electricity. I'm impressed!
– marmot
Feb 8 at 17:53
How about adding some mortar to the bricks!?
– Werner
Feb 8 at 18:06
@Werner where I come from we prefer this style: derbyshireuk.net/derbyshire_drystonewalls.html
– David Carlisle
Feb 8 at 18:12
5
@noibe oh no a disaster! I don't mind not getting the tick (I have more than enough points) but seeing points go to egreg is so depressing:)
– David Carlisle
Feb 8 at 18:49
2
Nozzz
? :'-(
– Henri Menke
Feb 9 at 6:02
|
show 4 more comments
documentclassarticle
defmycommand#1xmycommand#1--relax
defxmycommand#1,#2-#3-#4relax[#1][#2][#3]
begindocument
$mycommandarg_1, arg_2$
$mycommandarg_1, arg_2-arg3$
enddocument
documentclassarticle
defmycommand#1xmycommand#1--relax
defxmycommand#1,#2-#3-#4relax[#1][#2][#3]
begindocument
$mycommandarg_1, arg_2$
$mycommandarg_1, arg_2-arg3$
enddocument
answered Feb 8 at 17:48
David CarlisleDavid Carlisle
493k4111371885
493k4111371885
6
Even without electricity. I'm impressed!
– marmot
Feb 8 at 17:53
How about adding some mortar to the bricks!?
– Werner
Feb 8 at 18:06
@Werner where I come from we prefer this style: derbyshireuk.net/derbyshire_drystonewalls.html
– David Carlisle
Feb 8 at 18:12
5
@noibe oh no a disaster! I don't mind not getting the tick (I have more than enough points) but seeing points go to egreg is so depressing:)
– David Carlisle
Feb 8 at 18:49
2
Nozzz
? :'-(
– Henri Menke
Feb 9 at 6:02
|
show 4 more comments
6
Even without electricity. I'm impressed!
– marmot
Feb 8 at 17:53
How about adding some mortar to the bricks!?
– Werner
Feb 8 at 18:06
@Werner where I come from we prefer this style: derbyshireuk.net/derbyshire_drystonewalls.html
– David Carlisle
Feb 8 at 18:12
5
@noibe oh no a disaster! I don't mind not getting the tick (I have more than enough points) but seeing points go to egreg is so depressing:)
– David Carlisle
Feb 8 at 18:49
2
Nozzz
? :'-(
– Henri Menke
Feb 9 at 6:02
6
6
Even without electricity. I'm impressed!
– marmot
Feb 8 at 17:53
Even without electricity. I'm impressed!
– marmot
Feb 8 at 17:53
How about adding some mortar to the bricks!?
– Werner
Feb 8 at 18:06
How about adding some mortar to the bricks!?
– Werner
Feb 8 at 18:06
@Werner where I come from we prefer this style: derbyshireuk.net/derbyshire_drystonewalls.html
– David Carlisle
Feb 8 at 18:12
@Werner where I come from we prefer this style: derbyshireuk.net/derbyshire_drystonewalls.html
– David Carlisle
Feb 8 at 18:12
5
5
@noibe oh no a disaster! I don't mind not getting the tick (I have more than enough points) but seeing points go to egreg is so depressing:)
– David Carlisle
Feb 8 at 18:49
@noibe oh no a disaster! I don't mind not getting the tick (I have more than enough points) but seeing points go to egreg is so depressing:)
– David Carlisle
Feb 8 at 18:49
2
2
No
zzz
? :'-(– Henri Menke
Feb 9 at 6:02
No
zzz
? :'-(– Henri Menke
Feb 9 at 6:02
|
show 4 more comments
Some crocheting/knitting by hand (or whatever)... ;-)
I suppose this question came into being while you thought about your other question: Custom cite command. In that question you ask for a customized cite
-command with the same syntax.
Be that as it may.
The challenge is doing it in a way where desired space-removal but no undesired removal of argument-braces takes place.
E.g., with things like mycommandarg_1a, arg_2
the braces surrounding arg_1
should probably be preserved while with things like mycommandarg_1 , arg_2
they should probably be removed.
Also probably only space-tokens surrounding the entire arguments/surrounding those commas and those dashes that are taken for argument-separators should get removed.
Below is an approach where comma takes precedence over the dash and where the leftmost unhidden comma delimits the first argument from the remaining arguments and where the first unhidden dash following that comma delimits the second from the third argument.
Exactly one pair of matching curly braces will be removed in case after removing surrounding spaces it surrounds an entire argument as in that case it is assumed that the braces serve for hiding commas/dashes/spaces/emptiness. In all other cases braces will be preserved.
E.g., with things like mycommand arg_1 , arg_2-2 - arg_3
you should get:
First argument: arg_1
Second argument: arg_2-2
Third argument: arg_3
.
E.g., with things like mycommand arg 1,a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b
you should get:
First argument (left from the first unhidden comma, surrounding spaces and outermost brace-level that surrounds the entire argument removed): arg 1,a - arg 1b
Second argument (right from the first unhidden comma, left from the first unhidden dash following the comma): arg 2-2 , 2
Third argument (the remainder, right from the first unhidden dash following the comma): arg 3a - arg 3b
.
E.g., with things like mycommandarg 1, arg 2-2 , 2 - arg 3a - arg 3b
you should get:
First argument (left from the first unhidden comma): arg 1
Second argument (right from the first unhidden comma, left from the first unhidden dash following the comma): arg 2-2 , 2
Third argument (the remainder, right from the first unhidden dash following the comma): arg 3a - arg 3b
.
You may not be familiar to methods for removing space-tokens that surround arguments, thus a quote from the manual of my deprecated labelcas-package:
A note about removing leading and trailing spaces
The matter of removing trailing spaces from an (almost) arbitrary
token-sequence is elaborated in detail by Michael Downes, 'Around the
Bend #15, answers', a summary of internet-discussion which took place
under his guidance primarily at the INFO-TEX list, but also at
comp.text.tex (usenet) and via private email; December 1993. Online
archived at http://www.tug.org/tex-archive/info/arobend/answer.015.
One basic approach suggested therein is using TeX's scanning of
delimited parameters in order to detect and discard the ending space
of an argument:
... scan for a pair of tokens: a space-token and some well-chosen
bizarre token that can't possibly occur in the scanned text. If you
put the bizarre token at the end of the text, and if the text has a
trailing space, then TeX's delimiter matching will match at that point
and not before, because the earlier occurrences of space don’t have
the requisite other member of the pair.
Next consider the possibility that the trailing space is absent: TeX
will keep on scanning ahead for the pair
⟨space⟩⟨bizarre⟩
until either it finds them or it decides to give up and signal a
'Runaway argument?' error. So you must add a stop pair to catch the
runaway argument possibility: a second instance of the bizarre
token, preceded by a space. If TeX doesn't find a match at the
first bizarre token, it will at the second one.
(Look up the macros
KV@@sp@def
,KV@@sp@b
,KV@@sp@c
andKV@@sp@d
in
David Carlisle’s keyval-package for an interesting variation on this
approach.)
When scanning for parameters
##1⟨space⟩⟨bizarre⟩##2⟨B1⟩
the sequence:⟨stuff where to remove trail-space⟩⟨bizarre⟩⟨space⟩⟨bizarre⟩⟨B1⟩
, you can fork two cases:
Trailing-space:
##1
=⟨stuff where to remove trail-space⟩
, but with removed space. (And possibly one
removed brace-level!)##2
=⟨space⟩⟨bizarre⟩
.
No trailing-space:
##1
=⟨stuff where to remove trail-space⟩⟨bizarre⟩
.##2
is empty.
So forking can be implemented depending on the emptiness of
##2
.
You can easily prevent the brace-removal in the first case, e.g., by adding (and
later removing) something (e.g., a space-token) in front of the
⟨stuff where to remove trail-space⟩
.
You can choose
⟨B1⟩=⟨bizarre⟩⟨space⟩
.
The link in the quote is out of date.
Nowadays you can find the entire "Around the bend" -collection at http://mirrors.ctan.org/info/challenges/AroBend/AroundTheBend.pdf.
As you see, the methods for space-removal exhibited in the quote above do rely on some sequence of tokens that must not occur within the argument.
In the example below it is relied on the token UD@seldom
not occurring within arguments.
In other words: You must not use the token UD@seldom
within your arguments.
If you don't like that restriction, then I can deliver space-removal-routines which do without such restrictions, but they are slower and they form another huge load of code.
documentclassarticle
makeatletter
%%-----------------------------------------------------------------------------
%% Paraphernalia ;-) :
%%.............................................................................
newcommandUD@firstoftwo[2]#1%
newcommandUD@secondoftwo[2]#2%
newcommandUD@exchange[2]#2#1%
newcommandUD@removespaceUD@firstoftwodefUD@removespace %
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% UD@CheckWhetherNull<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% which is to be checked is empty>%
%% <Tokens to be delivered in case that argument
%% which is to be checked is not empty>%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%.............................................................................
newcommandUD@CheckWhetherNull[1]%
romannumeral0expandafterUD@secondoftwostringexpandafter
UD@secondoftwoexpandafterexpandafterstring#1expandafter
UD@secondoftwostringexpandafterUD@firstoftwoexpandafterexpandafter
UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
UD@secondoftwoexpandafterexpandafterUD@firstoftwo UD@firstoftwo%
%
%%-----------------------------------------------------------------------------
%% Check whether brace-balanced argument starts with a space-token
%%.............................................................................
%% UD@CheckWhetherLeadingSpace<Argument which is to be checked>%
%% <Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% space-token>%
%% <Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a space-token>%
newcommandUD@CheckWhetherLeadingSpace[1]%
romannumeral0UD@CheckWhetherNull#1%
expandafterexpandafterUD@firstoftwo UD@secondoftwo%
expandafterUD@secondoftwostringUD@CheckWhetherLeadingSpaceB.#1 %
%
newcommandUD@CheckWhetherLeadingSpaceB%
longdefUD@CheckWhetherLeadingSpaceB#1 %
expandafterUD@CheckWhetherNullexpandafterUD@secondoftwo#1%
UD@exchangeUD@firstoftwoUD@exchangeUD@secondoftwo%
UD@exchange expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafterexpandafterexpandafter
expandafterexpandafterUD@secondoftwoexpandafterstring%
%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%.............................................................................
%% UD@ExtractFirstArgABCDE yields A
%%
%% UD@ExtractFirstArgABCDE yields AB
%%
%% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
%% You can check for emptiness via UD@CheckWhetherNull before applying
%% UD@ExtractFirstArg.
%%.............................................................................
newcommandUD@RemoveTillUD@SelDOm%
longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
newcommandUD@ExtractFirstArg[1]%
romannumeral0%
UD@ExtractFirstArgLoop#1UD@SelDOm%
%
newcommandUD@ExtractFirstArgLoop[1]%
expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
#1%
expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#1%
%
%%-----------------------------------------------------------------------------
%% UD@RemoveSpacesAndOneLevelOfBraces<argument> removes leading and
%% trailing spaces from <argument>.
%% If after that the <argument> is something that is entirely nested
%% between at least one pair of matching curly braces, the outermost
%% pair of these braces will be removed.
%%
%% !!!! <argument> must not contain the token UD@seldom !!!!
%%.............................................................................
begingroup
newcommandUD@RemoveSpacesAndOneLevelOfBraces[1]%
endgroup
newcommandUD@RemoveSpacesAndOneLevelOfBraces[1]%
romannumeral0%
UD@trimtrailspaceloop#1##1UD@seldom#1UD@seldomUD@seldom#1##1%
%
newcommandUD@trimtrailspaceloop%
longdefUD@trimtrailspaceloop##1#1UD@seldom##2UD@seldom#1##3%
UD@CheckWhetherNull##2%
UD@trimleadspaceloop##3%
%
UD@trimtrailspaceloop##1UD@seldom#1UD@seldomUD@seldom#1##1%
%
%
%
UD@RemoveSpacesAndOneLevelOfBraces %
newcommandUD@trimleadspaceloop[1]%
UD@CheckWhetherLeadingSpace#1%
expandafterUD@trimleadspaceloopexpandafterUD@removespace#1%
%
UD@CheckWhetherNull#1 %
expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
UD@exchange expandafterUD@secondoftwo#1%
#1%
%
%
%
%%-----------------------------------------------------------------------------
%% Check whether argument contains no comma which is not nested
%% in braces:
%%.............................................................................
%% UD@CheckWhetherNoComma<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% contains no comma>%
%% <Tokens to be delivered in case that argument
%% contains comma>%
%%
newcommandUD@GobbleToCommalongdefUD@GobbleToComma#1,%
newcommandUD@CheckWhetherNoComma[1]%
expandafterUD@CheckWhetherNullexpandafterUD@GobbleToComma#1,%
%
%%-----------------------------------------------------------------------------
%% Check whether argument contains no dash which is not nested
%% in braces:
%%.............................................................................
%% UD@CheckWhetherNoDash<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% contains no dash>%
%% <Tokens to be delivered in case that argument
%% contains dash>%
%%
newcommandUD@GobbleToDashlongdefUD@GobbleToDash#1-%
newcommandUD@CheckWhetherNoDash[1]%
expandafterUD@CheckWhetherNullexpandafterUD@GobbleToDash#1-%
%
%%-----------------------------------------------------------------------------
%% Take a comma-delimited/dash-delimited argument where a space was
%% prepended for preventing brace-removal and wrap it in curly braces.
%%.............................................................................
newcommandUD@SplitCommaArg%
longdefUD@SplitCommaArg#1,%
romannumeral0UD@exchange expandafterexpandafterUD@removespace#1%
%
newcommandUD@SplitDashArg%
longdefUD@SplitDashArg#1-%
romannumeral0UD@exchange expandafterexpandafterUD@removespace#1%
%
%%-----------------------------------------------------------------------------
%% Now we have the tools for creating the desired mycommand-macro:
%%.............................................................................
newcommandmycommand[1]%
romannumeral0%
UD@CheckWhetherNoComma#1%
expandaftermycommand@oneargumentexpandafter%
romannumeral0UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
expandafterUD@exchangeexpandafterexpandafter
UD@GobbleToComma#1%
%
expandafter@mycommand
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@ExtractFirstArgexpandafter%
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@SplitCommaArg
UD@firstoftwo #1%
%
%
%
newcommand@mycommand[2]%
UD@CheckWhetherNoDash#2%
expandafterUD@exchangeexpandafterexpandafter
%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#2%
%
%
expandaftermycommand@twoargumentsexpandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
%
expandafterUD@exchangeexpandafterexpandafter%
UD@GobbleToDash#2%
%
expandafter@@mycommand
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@ExtractFirstArgexpandafter%
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@SplitDashArg
UD@firstoftwo #2%
%
#1%
%
%
newcommand@@mycommand[3]%
expandafterUD@exchangeexpandafter%
expandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#2%
%
%
expandafterUD@exchangeexpandafter%
expandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
expandaftermycommand@threeargumentsexpandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#3%
%
%
%
%
newcommandmycommand@oneargument[1]%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is no comma or only empty args after the comma, thus:\
argument 1 = printmeaning#1%
%
newcommandmycommand@twoarguments[2]%
UD@CheckWhetherNull#2%
mycommand@oneargument#1%
%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is a comma but either no dash or only one non-empty argument near
the dash, thus:\
argument 1 = printmeaning#1\
argument 2 = printmeaning#2%
%
%
newcommandmycommand@threearguments[3]%
UD@CheckWhetherNull#2%
UD@CheckWhetherNull#3%
mycommand@oneargument#1%
%x
mycommand@twoarguments#1#3%
%
%
UD@CheckWhetherNull#3%
mycommand@twoarguments#1#2%
%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is a comma and a dash, thus:\
argument 1 = printmeaning#1\
argument 2 = printmeaning#2\
argument 3 = printmeaning#3%
%
%
%
newcommandprintmeaning[1]%
defUD@tempa#1%
fboxtextttexpandafterstrip@prefixmeaningUD@tempa%
%
makeatother
parindent=0ex
parskip=smallskipamount
pagestyleempty%
begindocument
vspace*-3.5cm%
enlargethispage7cm%
verb|mycommand arg 1 |:\
mycommand arg 1 \
nullhrulefillnull
verb|mycommand arg 1 , |:\
mycommand arg 1 , \
nullhrulefillnull
verb|mycommand arg 1 , - |:\
mycommand arg 1 , - \
nullhrulefillnull
verb|mycommand arg 1 , arg 2 |:\
mycommand arg 1 , arg 2 \
(Be aware that (only) the outermost braces get removed from
an argument if surrounding the entire argument after removal
of surrounding spaces.)\
nullhrulefillnull
verb|mycommand arg 1 , arg 2 - |:\
mycommand arg 1 , arg 2 - \
nullhrulefillnull
verb|mycommand arg 1 , arg 2 - arg 3|:\
mycommand arg 1 , arg 2 - arg 3\
nullhrulefillnull
verb|mycommand arg 1 , - arg 3|:\
mycommand arg 1 , - arg 3\
nullhrulefillnull
verb|mycommand arg 1a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b|:\
mycommand arg 1a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b\
nullhrulefillnull
verb|mycommand arg 1 , arg 2-2 , 2 - arg 3a - arg 3b|:\
mycommand arg 1 , arg 2-2 , 2 - arg 3a - arg 3b
enddocument
add a comment |
Some crocheting/knitting by hand (or whatever)... ;-)
I suppose this question came into being while you thought about your other question: Custom cite command. In that question you ask for a customized cite
-command with the same syntax.
Be that as it may.
The challenge is doing it in a way where desired space-removal but no undesired removal of argument-braces takes place.
E.g., with things like mycommandarg_1a, arg_2
the braces surrounding arg_1
should probably be preserved while with things like mycommandarg_1 , arg_2
they should probably be removed.
Also probably only space-tokens surrounding the entire arguments/surrounding those commas and those dashes that are taken for argument-separators should get removed.
Below is an approach where comma takes precedence over the dash and where the leftmost unhidden comma delimits the first argument from the remaining arguments and where the first unhidden dash following that comma delimits the second from the third argument.
Exactly one pair of matching curly braces will be removed in case after removing surrounding spaces it surrounds an entire argument as in that case it is assumed that the braces serve for hiding commas/dashes/spaces/emptiness. In all other cases braces will be preserved.
E.g., with things like mycommand arg_1 , arg_2-2 - arg_3
you should get:
First argument: arg_1
Second argument: arg_2-2
Third argument: arg_3
.
E.g., with things like mycommand arg 1,a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b
you should get:
First argument (left from the first unhidden comma, surrounding spaces and outermost brace-level that surrounds the entire argument removed): arg 1,a - arg 1b
Second argument (right from the first unhidden comma, left from the first unhidden dash following the comma): arg 2-2 , 2
Third argument (the remainder, right from the first unhidden dash following the comma): arg 3a - arg 3b
.
E.g., with things like mycommandarg 1, arg 2-2 , 2 - arg 3a - arg 3b
you should get:
First argument (left from the first unhidden comma): arg 1
Second argument (right from the first unhidden comma, left from the first unhidden dash following the comma): arg 2-2 , 2
Third argument (the remainder, right from the first unhidden dash following the comma): arg 3a - arg 3b
.
You may not be familiar to methods for removing space-tokens that surround arguments, thus a quote from the manual of my deprecated labelcas-package:
A note about removing leading and trailing spaces
The matter of removing trailing spaces from an (almost) arbitrary
token-sequence is elaborated in detail by Michael Downes, 'Around the
Bend #15, answers', a summary of internet-discussion which took place
under his guidance primarily at the INFO-TEX list, but also at
comp.text.tex (usenet) and via private email; December 1993. Online
archived at http://www.tug.org/tex-archive/info/arobend/answer.015.
One basic approach suggested therein is using TeX's scanning of
delimited parameters in order to detect and discard the ending space
of an argument:
... scan for a pair of tokens: a space-token and some well-chosen
bizarre token that can't possibly occur in the scanned text. If you
put the bizarre token at the end of the text, and if the text has a
trailing space, then TeX's delimiter matching will match at that point
and not before, because the earlier occurrences of space don’t have
the requisite other member of the pair.
Next consider the possibility that the trailing space is absent: TeX
will keep on scanning ahead for the pair
⟨space⟩⟨bizarre⟩
until either it finds them or it decides to give up and signal a
'Runaway argument?' error. So you must add a stop pair to catch the
runaway argument possibility: a second instance of the bizarre
token, preceded by a space. If TeX doesn't find a match at the
first bizarre token, it will at the second one.
(Look up the macros
KV@@sp@def
,KV@@sp@b
,KV@@sp@c
andKV@@sp@d
in
David Carlisle’s keyval-package for an interesting variation on this
approach.)
When scanning for parameters
##1⟨space⟩⟨bizarre⟩##2⟨B1⟩
the sequence:⟨stuff where to remove trail-space⟩⟨bizarre⟩⟨space⟩⟨bizarre⟩⟨B1⟩
, you can fork two cases:
Trailing-space:
##1
=⟨stuff where to remove trail-space⟩
, but with removed space. (And possibly one
removed brace-level!)##2
=⟨space⟩⟨bizarre⟩
.
No trailing-space:
##1
=⟨stuff where to remove trail-space⟩⟨bizarre⟩
.##2
is empty.
So forking can be implemented depending on the emptiness of
##2
.
You can easily prevent the brace-removal in the first case, e.g., by adding (and
later removing) something (e.g., a space-token) in front of the
⟨stuff where to remove trail-space⟩
.
You can choose
⟨B1⟩=⟨bizarre⟩⟨space⟩
.
The link in the quote is out of date.
Nowadays you can find the entire "Around the bend" -collection at http://mirrors.ctan.org/info/challenges/AroBend/AroundTheBend.pdf.
As you see, the methods for space-removal exhibited in the quote above do rely on some sequence of tokens that must not occur within the argument.
In the example below it is relied on the token UD@seldom
not occurring within arguments.
In other words: You must not use the token UD@seldom
within your arguments.
If you don't like that restriction, then I can deliver space-removal-routines which do without such restrictions, but they are slower and they form another huge load of code.
documentclassarticle
makeatletter
%%-----------------------------------------------------------------------------
%% Paraphernalia ;-) :
%%.............................................................................
newcommandUD@firstoftwo[2]#1%
newcommandUD@secondoftwo[2]#2%
newcommandUD@exchange[2]#2#1%
newcommandUD@removespaceUD@firstoftwodefUD@removespace %
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% UD@CheckWhetherNull<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% which is to be checked is empty>%
%% <Tokens to be delivered in case that argument
%% which is to be checked is not empty>%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%.............................................................................
newcommandUD@CheckWhetherNull[1]%
romannumeral0expandafterUD@secondoftwostringexpandafter
UD@secondoftwoexpandafterexpandafterstring#1expandafter
UD@secondoftwostringexpandafterUD@firstoftwoexpandafterexpandafter
UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
UD@secondoftwoexpandafterexpandafterUD@firstoftwo UD@firstoftwo%
%
%%-----------------------------------------------------------------------------
%% Check whether brace-balanced argument starts with a space-token
%%.............................................................................
%% UD@CheckWhetherLeadingSpace<Argument which is to be checked>%
%% <Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% space-token>%
%% <Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a space-token>%
newcommandUD@CheckWhetherLeadingSpace[1]%
romannumeral0UD@CheckWhetherNull#1%
expandafterexpandafterUD@firstoftwo UD@secondoftwo%
expandafterUD@secondoftwostringUD@CheckWhetherLeadingSpaceB.#1 %
%
newcommandUD@CheckWhetherLeadingSpaceB%
longdefUD@CheckWhetherLeadingSpaceB#1 %
expandafterUD@CheckWhetherNullexpandafterUD@secondoftwo#1%
UD@exchangeUD@firstoftwoUD@exchangeUD@secondoftwo%
UD@exchange expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafterexpandafterexpandafter
expandafterexpandafterUD@secondoftwoexpandafterstring%
%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%.............................................................................
%% UD@ExtractFirstArgABCDE yields A
%%
%% UD@ExtractFirstArgABCDE yields AB
%%
%% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
%% You can check for emptiness via UD@CheckWhetherNull before applying
%% UD@ExtractFirstArg.
%%.............................................................................
newcommandUD@RemoveTillUD@SelDOm%
longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
newcommandUD@ExtractFirstArg[1]%
romannumeral0%
UD@ExtractFirstArgLoop#1UD@SelDOm%
%
newcommandUD@ExtractFirstArgLoop[1]%
expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
#1%
expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#1%
%
%%-----------------------------------------------------------------------------
%% UD@RemoveSpacesAndOneLevelOfBraces<argument> removes leading and
%% trailing spaces from <argument>.
%% If after that the <argument> is something that is entirely nested
%% between at least one pair of matching curly braces, the outermost
%% pair of these braces will be removed.
%%
%% !!!! <argument> must not contain the token UD@seldom !!!!
%%.............................................................................
begingroup
newcommandUD@RemoveSpacesAndOneLevelOfBraces[1]%
endgroup
newcommandUD@RemoveSpacesAndOneLevelOfBraces[1]%
romannumeral0%
UD@trimtrailspaceloop#1##1UD@seldom#1UD@seldomUD@seldom#1##1%
%
newcommandUD@trimtrailspaceloop%
longdefUD@trimtrailspaceloop##1#1UD@seldom##2UD@seldom#1##3%
UD@CheckWhetherNull##2%
UD@trimleadspaceloop##3%
%
UD@trimtrailspaceloop##1UD@seldom#1UD@seldomUD@seldom#1##1%
%
%
%
UD@RemoveSpacesAndOneLevelOfBraces %
newcommandUD@trimleadspaceloop[1]%
UD@CheckWhetherLeadingSpace#1%
expandafterUD@trimleadspaceloopexpandafterUD@removespace#1%
%
UD@CheckWhetherNull#1 %
expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
UD@exchange expandafterUD@secondoftwo#1%
#1%
%
%
%
%%-----------------------------------------------------------------------------
%% Check whether argument contains no comma which is not nested
%% in braces:
%%.............................................................................
%% UD@CheckWhetherNoComma<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% contains no comma>%
%% <Tokens to be delivered in case that argument
%% contains comma>%
%%
newcommandUD@GobbleToCommalongdefUD@GobbleToComma#1,%
newcommandUD@CheckWhetherNoComma[1]%
expandafterUD@CheckWhetherNullexpandafterUD@GobbleToComma#1,%
%
%%-----------------------------------------------------------------------------
%% Check whether argument contains no dash which is not nested
%% in braces:
%%.............................................................................
%% UD@CheckWhetherNoDash<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% contains no dash>%
%% <Tokens to be delivered in case that argument
%% contains dash>%
%%
newcommandUD@GobbleToDashlongdefUD@GobbleToDash#1-%
newcommandUD@CheckWhetherNoDash[1]%
expandafterUD@CheckWhetherNullexpandafterUD@GobbleToDash#1-%
%
%%-----------------------------------------------------------------------------
%% Take a comma-delimited/dash-delimited argument where a space was
%% prepended for preventing brace-removal and wrap it in curly braces.
%%.............................................................................
newcommandUD@SplitCommaArg%
longdefUD@SplitCommaArg#1,%
romannumeral0UD@exchange expandafterexpandafterUD@removespace#1%
%
newcommandUD@SplitDashArg%
longdefUD@SplitDashArg#1-%
romannumeral0UD@exchange expandafterexpandafterUD@removespace#1%
%
%%-----------------------------------------------------------------------------
%% Now we have the tools for creating the desired mycommand-macro:
%%.............................................................................
newcommandmycommand[1]%
romannumeral0%
UD@CheckWhetherNoComma#1%
expandaftermycommand@oneargumentexpandafter%
romannumeral0UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
expandafterUD@exchangeexpandafterexpandafter
UD@GobbleToComma#1%
%
expandafter@mycommand
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@ExtractFirstArgexpandafter%
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@SplitCommaArg
UD@firstoftwo #1%
%
%
%
newcommand@mycommand[2]%
UD@CheckWhetherNoDash#2%
expandafterUD@exchangeexpandafterexpandafter
%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#2%
%
%
expandaftermycommand@twoargumentsexpandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
%
expandafterUD@exchangeexpandafterexpandafter%
UD@GobbleToDash#2%
%
expandafter@@mycommand
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@ExtractFirstArgexpandafter%
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@SplitDashArg
UD@firstoftwo #2%
%
#1%
%
%
newcommand@@mycommand[3]%
expandafterUD@exchangeexpandafter%
expandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#2%
%
%
expandafterUD@exchangeexpandafter%
expandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
expandaftermycommand@threeargumentsexpandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#3%
%
%
%
%
newcommandmycommand@oneargument[1]%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is no comma or only empty args after the comma, thus:\
argument 1 = printmeaning#1%
%
newcommandmycommand@twoarguments[2]%
UD@CheckWhetherNull#2%
mycommand@oneargument#1%
%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is a comma but either no dash or only one non-empty argument near
the dash, thus:\
argument 1 = printmeaning#1\
argument 2 = printmeaning#2%
%
%
newcommandmycommand@threearguments[3]%
UD@CheckWhetherNull#2%
UD@CheckWhetherNull#3%
mycommand@oneargument#1%
%x
mycommand@twoarguments#1#3%
%
%
UD@CheckWhetherNull#3%
mycommand@twoarguments#1#2%
%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is a comma and a dash, thus:\
argument 1 = printmeaning#1\
argument 2 = printmeaning#2\
argument 3 = printmeaning#3%
%
%
%
newcommandprintmeaning[1]%
defUD@tempa#1%
fboxtextttexpandafterstrip@prefixmeaningUD@tempa%
%
makeatother
parindent=0ex
parskip=smallskipamount
pagestyleempty%
begindocument
vspace*-3.5cm%
enlargethispage7cm%
verb|mycommand arg 1 |:\
mycommand arg 1 \
nullhrulefillnull
verb|mycommand arg 1 , |:\
mycommand arg 1 , \
nullhrulefillnull
verb|mycommand arg 1 , - |:\
mycommand arg 1 , - \
nullhrulefillnull
verb|mycommand arg 1 , arg 2 |:\
mycommand arg 1 , arg 2 \
(Be aware that (only) the outermost braces get removed from
an argument if surrounding the entire argument after removal
of surrounding spaces.)\
nullhrulefillnull
verb|mycommand arg 1 , arg 2 - |:\
mycommand arg 1 , arg 2 - \
nullhrulefillnull
verb|mycommand arg 1 , arg 2 - arg 3|:\
mycommand arg 1 , arg 2 - arg 3\
nullhrulefillnull
verb|mycommand arg 1 , - arg 3|:\
mycommand arg 1 , - arg 3\
nullhrulefillnull
verb|mycommand arg 1a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b|:\
mycommand arg 1a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b\
nullhrulefillnull
verb|mycommand arg 1 , arg 2-2 , 2 - arg 3a - arg 3b|:\
mycommand arg 1 , arg 2-2 , 2 - arg 3a - arg 3b
enddocument
add a comment |
Some crocheting/knitting by hand (or whatever)... ;-)
I suppose this question came into being while you thought about your other question: Custom cite command. In that question you ask for a customized cite
-command with the same syntax.
Be that as it may.
The challenge is doing it in a way where desired space-removal but no undesired removal of argument-braces takes place.
E.g., with things like mycommandarg_1a, arg_2
the braces surrounding arg_1
should probably be preserved while with things like mycommandarg_1 , arg_2
they should probably be removed.
Also probably only space-tokens surrounding the entire arguments/surrounding those commas and those dashes that are taken for argument-separators should get removed.
Below is an approach where comma takes precedence over the dash and where the leftmost unhidden comma delimits the first argument from the remaining arguments and where the first unhidden dash following that comma delimits the second from the third argument.
Exactly one pair of matching curly braces will be removed in case after removing surrounding spaces it surrounds an entire argument as in that case it is assumed that the braces serve for hiding commas/dashes/spaces/emptiness. In all other cases braces will be preserved.
E.g., with things like mycommand arg_1 , arg_2-2 - arg_3
you should get:
First argument: arg_1
Second argument: arg_2-2
Third argument: arg_3
.
E.g., with things like mycommand arg 1,a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b
you should get:
First argument (left from the first unhidden comma, surrounding spaces and outermost brace-level that surrounds the entire argument removed): arg 1,a - arg 1b
Second argument (right from the first unhidden comma, left from the first unhidden dash following the comma): arg 2-2 , 2
Third argument (the remainder, right from the first unhidden dash following the comma): arg 3a - arg 3b
.
E.g., with things like mycommandarg 1, arg 2-2 , 2 - arg 3a - arg 3b
you should get:
First argument (left from the first unhidden comma): arg 1
Second argument (right from the first unhidden comma, left from the first unhidden dash following the comma): arg 2-2 , 2
Third argument (the remainder, right from the first unhidden dash following the comma): arg 3a - arg 3b
.
You may not be familiar to methods for removing space-tokens that surround arguments, thus a quote from the manual of my deprecated labelcas-package:
A note about removing leading and trailing spaces
The matter of removing trailing spaces from an (almost) arbitrary
token-sequence is elaborated in detail by Michael Downes, 'Around the
Bend #15, answers', a summary of internet-discussion which took place
under his guidance primarily at the INFO-TEX list, but also at
comp.text.tex (usenet) and via private email; December 1993. Online
archived at http://www.tug.org/tex-archive/info/arobend/answer.015.
One basic approach suggested therein is using TeX's scanning of
delimited parameters in order to detect and discard the ending space
of an argument:
... scan for a pair of tokens: a space-token and some well-chosen
bizarre token that can't possibly occur in the scanned text. If you
put the bizarre token at the end of the text, and if the text has a
trailing space, then TeX's delimiter matching will match at that point
and not before, because the earlier occurrences of space don’t have
the requisite other member of the pair.
Next consider the possibility that the trailing space is absent: TeX
will keep on scanning ahead for the pair
⟨space⟩⟨bizarre⟩
until either it finds them or it decides to give up and signal a
'Runaway argument?' error. So you must add a stop pair to catch the
runaway argument possibility: a second instance of the bizarre
token, preceded by a space. If TeX doesn't find a match at the
first bizarre token, it will at the second one.
(Look up the macros
KV@@sp@def
,KV@@sp@b
,KV@@sp@c
andKV@@sp@d
in
David Carlisle’s keyval-package for an interesting variation on this
approach.)
When scanning for parameters
##1⟨space⟩⟨bizarre⟩##2⟨B1⟩
the sequence:⟨stuff where to remove trail-space⟩⟨bizarre⟩⟨space⟩⟨bizarre⟩⟨B1⟩
, you can fork two cases:
Trailing-space:
##1
=⟨stuff where to remove trail-space⟩
, but with removed space. (And possibly one
removed brace-level!)##2
=⟨space⟩⟨bizarre⟩
.
No trailing-space:
##1
=⟨stuff where to remove trail-space⟩⟨bizarre⟩
.##2
is empty.
So forking can be implemented depending on the emptiness of
##2
.
You can easily prevent the brace-removal in the first case, e.g., by adding (and
later removing) something (e.g., a space-token) in front of the
⟨stuff where to remove trail-space⟩
.
You can choose
⟨B1⟩=⟨bizarre⟩⟨space⟩
.
The link in the quote is out of date.
Nowadays you can find the entire "Around the bend" -collection at http://mirrors.ctan.org/info/challenges/AroBend/AroundTheBend.pdf.
As you see, the methods for space-removal exhibited in the quote above do rely on some sequence of tokens that must not occur within the argument.
In the example below it is relied on the token UD@seldom
not occurring within arguments.
In other words: You must not use the token UD@seldom
within your arguments.
If you don't like that restriction, then I can deliver space-removal-routines which do without such restrictions, but they are slower and they form another huge load of code.
documentclassarticle
makeatletter
%%-----------------------------------------------------------------------------
%% Paraphernalia ;-) :
%%.............................................................................
newcommandUD@firstoftwo[2]#1%
newcommandUD@secondoftwo[2]#2%
newcommandUD@exchange[2]#2#1%
newcommandUD@removespaceUD@firstoftwodefUD@removespace %
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% UD@CheckWhetherNull<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% which is to be checked is empty>%
%% <Tokens to be delivered in case that argument
%% which is to be checked is not empty>%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%.............................................................................
newcommandUD@CheckWhetherNull[1]%
romannumeral0expandafterUD@secondoftwostringexpandafter
UD@secondoftwoexpandafterexpandafterstring#1expandafter
UD@secondoftwostringexpandafterUD@firstoftwoexpandafterexpandafter
UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
UD@secondoftwoexpandafterexpandafterUD@firstoftwo UD@firstoftwo%
%
%%-----------------------------------------------------------------------------
%% Check whether brace-balanced argument starts with a space-token
%%.............................................................................
%% UD@CheckWhetherLeadingSpace<Argument which is to be checked>%
%% <Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% space-token>%
%% <Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a space-token>%
newcommandUD@CheckWhetherLeadingSpace[1]%
romannumeral0UD@CheckWhetherNull#1%
expandafterexpandafterUD@firstoftwo UD@secondoftwo%
expandafterUD@secondoftwostringUD@CheckWhetherLeadingSpaceB.#1 %
%
newcommandUD@CheckWhetherLeadingSpaceB%
longdefUD@CheckWhetherLeadingSpaceB#1 %
expandafterUD@CheckWhetherNullexpandafterUD@secondoftwo#1%
UD@exchangeUD@firstoftwoUD@exchangeUD@secondoftwo%
UD@exchange expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafterexpandafterexpandafter
expandafterexpandafterUD@secondoftwoexpandafterstring%
%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%.............................................................................
%% UD@ExtractFirstArgABCDE yields A
%%
%% UD@ExtractFirstArgABCDE yields AB
%%
%% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
%% You can check for emptiness via UD@CheckWhetherNull before applying
%% UD@ExtractFirstArg.
%%.............................................................................
newcommandUD@RemoveTillUD@SelDOm%
longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
newcommandUD@ExtractFirstArg[1]%
romannumeral0%
UD@ExtractFirstArgLoop#1UD@SelDOm%
%
newcommandUD@ExtractFirstArgLoop[1]%
expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
#1%
expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#1%
%
%%-----------------------------------------------------------------------------
%% UD@RemoveSpacesAndOneLevelOfBraces<argument> removes leading and
%% trailing spaces from <argument>.
%% If after that the <argument> is something that is entirely nested
%% between at least one pair of matching curly braces, the outermost
%% pair of these braces will be removed.
%%
%% !!!! <argument> must not contain the token UD@seldom !!!!
%%.............................................................................
begingroup
newcommandUD@RemoveSpacesAndOneLevelOfBraces[1]%
endgroup
newcommandUD@RemoveSpacesAndOneLevelOfBraces[1]%
romannumeral0%
UD@trimtrailspaceloop#1##1UD@seldom#1UD@seldomUD@seldom#1##1%
%
newcommandUD@trimtrailspaceloop%
longdefUD@trimtrailspaceloop##1#1UD@seldom##2UD@seldom#1##3%
UD@CheckWhetherNull##2%
UD@trimleadspaceloop##3%
%
UD@trimtrailspaceloop##1UD@seldom#1UD@seldomUD@seldom#1##1%
%
%
%
UD@RemoveSpacesAndOneLevelOfBraces %
newcommandUD@trimleadspaceloop[1]%
UD@CheckWhetherLeadingSpace#1%
expandafterUD@trimleadspaceloopexpandafterUD@removespace#1%
%
UD@CheckWhetherNull#1 %
expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
UD@exchange expandafterUD@secondoftwo#1%
#1%
%
%
%
%%-----------------------------------------------------------------------------
%% Check whether argument contains no comma which is not nested
%% in braces:
%%.............................................................................
%% UD@CheckWhetherNoComma<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% contains no comma>%
%% <Tokens to be delivered in case that argument
%% contains comma>%
%%
newcommandUD@GobbleToCommalongdefUD@GobbleToComma#1,%
newcommandUD@CheckWhetherNoComma[1]%
expandafterUD@CheckWhetherNullexpandafterUD@GobbleToComma#1,%
%
%%-----------------------------------------------------------------------------
%% Check whether argument contains no dash which is not nested
%% in braces:
%%.............................................................................
%% UD@CheckWhetherNoDash<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% contains no dash>%
%% <Tokens to be delivered in case that argument
%% contains dash>%
%%
newcommandUD@GobbleToDashlongdefUD@GobbleToDash#1-%
newcommandUD@CheckWhetherNoDash[1]%
expandafterUD@CheckWhetherNullexpandafterUD@GobbleToDash#1-%
%
%%-----------------------------------------------------------------------------
%% Take a comma-delimited/dash-delimited argument where a space was
%% prepended for preventing brace-removal and wrap it in curly braces.
%%.............................................................................
newcommandUD@SplitCommaArg%
longdefUD@SplitCommaArg#1,%
romannumeral0UD@exchange expandafterexpandafterUD@removespace#1%
%
newcommandUD@SplitDashArg%
longdefUD@SplitDashArg#1-%
romannumeral0UD@exchange expandafterexpandafterUD@removespace#1%
%
%%-----------------------------------------------------------------------------
%% Now we have the tools for creating the desired mycommand-macro:
%%.............................................................................
newcommandmycommand[1]%
romannumeral0%
UD@CheckWhetherNoComma#1%
expandaftermycommand@oneargumentexpandafter%
romannumeral0UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
expandafterUD@exchangeexpandafterexpandafter
UD@GobbleToComma#1%
%
expandafter@mycommand
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@ExtractFirstArgexpandafter%
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@SplitCommaArg
UD@firstoftwo #1%
%
%
%
newcommand@mycommand[2]%
UD@CheckWhetherNoDash#2%
expandafterUD@exchangeexpandafterexpandafter
%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#2%
%
%
expandaftermycommand@twoargumentsexpandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
%
expandafterUD@exchangeexpandafterexpandafter%
UD@GobbleToDash#2%
%
expandafter@@mycommand
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@ExtractFirstArgexpandafter%
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@SplitDashArg
UD@firstoftwo #2%
%
#1%
%
%
newcommand@@mycommand[3]%
expandafterUD@exchangeexpandafter%
expandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#2%
%
%
expandafterUD@exchangeexpandafter%
expandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
expandaftermycommand@threeargumentsexpandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#3%
%
%
%
%
newcommandmycommand@oneargument[1]%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is no comma or only empty args after the comma, thus:\
argument 1 = printmeaning#1%
%
newcommandmycommand@twoarguments[2]%
UD@CheckWhetherNull#2%
mycommand@oneargument#1%
%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is a comma but either no dash or only one non-empty argument near
the dash, thus:\
argument 1 = printmeaning#1\
argument 2 = printmeaning#2%
%
%
newcommandmycommand@threearguments[3]%
UD@CheckWhetherNull#2%
UD@CheckWhetherNull#3%
mycommand@oneargument#1%
%x
mycommand@twoarguments#1#3%
%
%
UD@CheckWhetherNull#3%
mycommand@twoarguments#1#2%
%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is a comma and a dash, thus:\
argument 1 = printmeaning#1\
argument 2 = printmeaning#2\
argument 3 = printmeaning#3%
%
%
%
newcommandprintmeaning[1]%
defUD@tempa#1%
fboxtextttexpandafterstrip@prefixmeaningUD@tempa%
%
makeatother
parindent=0ex
parskip=smallskipamount
pagestyleempty%
begindocument
vspace*-3.5cm%
enlargethispage7cm%
verb|mycommand arg 1 |:\
mycommand arg 1 \
nullhrulefillnull
verb|mycommand arg 1 , |:\
mycommand arg 1 , \
nullhrulefillnull
verb|mycommand arg 1 , - |:\
mycommand arg 1 , - \
nullhrulefillnull
verb|mycommand arg 1 , arg 2 |:\
mycommand arg 1 , arg 2 \
(Be aware that (only) the outermost braces get removed from
an argument if surrounding the entire argument after removal
of surrounding spaces.)\
nullhrulefillnull
verb|mycommand arg 1 , arg 2 - |:\
mycommand arg 1 , arg 2 - \
nullhrulefillnull
verb|mycommand arg 1 , arg 2 - arg 3|:\
mycommand arg 1 , arg 2 - arg 3\
nullhrulefillnull
verb|mycommand arg 1 , - arg 3|:\
mycommand arg 1 , - arg 3\
nullhrulefillnull
verb|mycommand arg 1a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b|:\
mycommand arg 1a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b\
nullhrulefillnull
verb|mycommand arg 1 , arg 2-2 , 2 - arg 3a - arg 3b|:\
mycommand arg 1 , arg 2-2 , 2 - arg 3a - arg 3b
enddocument
Some crocheting/knitting by hand (or whatever)... ;-)
I suppose this question came into being while you thought about your other question: Custom cite command. In that question you ask for a customized cite
-command with the same syntax.
Be that as it may.
The challenge is doing it in a way where desired space-removal but no undesired removal of argument-braces takes place.
E.g., with things like mycommandarg_1a, arg_2
the braces surrounding arg_1
should probably be preserved while with things like mycommandarg_1 , arg_2
they should probably be removed.
Also probably only space-tokens surrounding the entire arguments/surrounding those commas and those dashes that are taken for argument-separators should get removed.
Below is an approach where comma takes precedence over the dash and where the leftmost unhidden comma delimits the first argument from the remaining arguments and where the first unhidden dash following that comma delimits the second from the third argument.
Exactly one pair of matching curly braces will be removed in case after removing surrounding spaces it surrounds an entire argument as in that case it is assumed that the braces serve for hiding commas/dashes/spaces/emptiness. In all other cases braces will be preserved.
E.g., with things like mycommand arg_1 , arg_2-2 - arg_3
you should get:
First argument: arg_1
Second argument: arg_2-2
Third argument: arg_3
.
E.g., with things like mycommand arg 1,a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b
you should get:
First argument (left from the first unhidden comma, surrounding spaces and outermost brace-level that surrounds the entire argument removed): arg 1,a - arg 1b
Second argument (right from the first unhidden comma, left from the first unhidden dash following the comma): arg 2-2 , 2
Third argument (the remainder, right from the first unhidden dash following the comma): arg 3a - arg 3b
.
E.g., with things like mycommandarg 1, arg 2-2 , 2 - arg 3a - arg 3b
you should get:
First argument (left from the first unhidden comma): arg 1
Second argument (right from the first unhidden comma, left from the first unhidden dash following the comma): arg 2-2 , 2
Third argument (the remainder, right from the first unhidden dash following the comma): arg 3a - arg 3b
.
You may not be familiar to methods for removing space-tokens that surround arguments, thus a quote from the manual of my deprecated labelcas-package:
A note about removing leading and trailing spaces
The matter of removing trailing spaces from an (almost) arbitrary
token-sequence is elaborated in detail by Michael Downes, 'Around the
Bend #15, answers', a summary of internet-discussion which took place
under his guidance primarily at the INFO-TEX list, but also at
comp.text.tex (usenet) and via private email; December 1993. Online
archived at http://www.tug.org/tex-archive/info/arobend/answer.015.
One basic approach suggested therein is using TeX's scanning of
delimited parameters in order to detect and discard the ending space
of an argument:
... scan for a pair of tokens: a space-token and some well-chosen
bizarre token that can't possibly occur in the scanned text. If you
put the bizarre token at the end of the text, and if the text has a
trailing space, then TeX's delimiter matching will match at that point
and not before, because the earlier occurrences of space don’t have
the requisite other member of the pair.
Next consider the possibility that the trailing space is absent: TeX
will keep on scanning ahead for the pair
⟨space⟩⟨bizarre⟩
until either it finds them or it decides to give up and signal a
'Runaway argument?' error. So you must add a stop pair to catch the
runaway argument possibility: a second instance of the bizarre
token, preceded by a space. If TeX doesn't find a match at the
first bizarre token, it will at the second one.
(Look up the macros
KV@@sp@def
,KV@@sp@b
,KV@@sp@c
andKV@@sp@d
in
David Carlisle’s keyval-package for an interesting variation on this
approach.)
When scanning for parameters
##1⟨space⟩⟨bizarre⟩##2⟨B1⟩
the sequence:⟨stuff where to remove trail-space⟩⟨bizarre⟩⟨space⟩⟨bizarre⟩⟨B1⟩
, you can fork two cases:
Trailing-space:
##1
=⟨stuff where to remove trail-space⟩
, but with removed space. (And possibly one
removed brace-level!)##2
=⟨space⟩⟨bizarre⟩
.
No trailing-space:
##1
=⟨stuff where to remove trail-space⟩⟨bizarre⟩
.##2
is empty.
So forking can be implemented depending on the emptiness of
##2
.
You can easily prevent the brace-removal in the first case, e.g., by adding (and
later removing) something (e.g., a space-token) in front of the
⟨stuff where to remove trail-space⟩
.
You can choose
⟨B1⟩=⟨bizarre⟩⟨space⟩
.
The link in the quote is out of date.
Nowadays you can find the entire "Around the bend" -collection at http://mirrors.ctan.org/info/challenges/AroBend/AroundTheBend.pdf.
As you see, the methods for space-removal exhibited in the quote above do rely on some sequence of tokens that must not occur within the argument.
In the example below it is relied on the token UD@seldom
not occurring within arguments.
In other words: You must not use the token UD@seldom
within your arguments.
If you don't like that restriction, then I can deliver space-removal-routines which do without such restrictions, but they are slower and they form another huge load of code.
documentclassarticle
makeatletter
%%-----------------------------------------------------------------------------
%% Paraphernalia ;-) :
%%.............................................................................
newcommandUD@firstoftwo[2]#1%
newcommandUD@secondoftwo[2]#2%
newcommandUD@exchange[2]#2#1%
newcommandUD@removespaceUD@firstoftwodefUD@removespace %
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% UD@CheckWhetherNull<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% which is to be checked is empty>%
%% <Tokens to be delivered in case that argument
%% which is to be checked is not empty>%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%.............................................................................
newcommandUD@CheckWhetherNull[1]%
romannumeral0expandafterUD@secondoftwostringexpandafter
UD@secondoftwoexpandafterexpandafterstring#1expandafter
UD@secondoftwostringexpandafterUD@firstoftwoexpandafterexpandafter
UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
UD@secondoftwoexpandafterexpandafterUD@firstoftwo UD@firstoftwo%
%
%%-----------------------------------------------------------------------------
%% Check whether brace-balanced argument starts with a space-token
%%.............................................................................
%% UD@CheckWhetherLeadingSpace<Argument which is to be checked>%
%% <Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% space-token>%
%% <Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a space-token>%
newcommandUD@CheckWhetherLeadingSpace[1]%
romannumeral0UD@CheckWhetherNull#1%
expandafterexpandafterUD@firstoftwo UD@secondoftwo%
expandafterUD@secondoftwostringUD@CheckWhetherLeadingSpaceB.#1 %
%
newcommandUD@CheckWhetherLeadingSpaceB%
longdefUD@CheckWhetherLeadingSpaceB#1 %
expandafterUD@CheckWhetherNullexpandafterUD@secondoftwo#1%
UD@exchangeUD@firstoftwoUD@exchangeUD@secondoftwo%
UD@exchange expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafterexpandafterexpandafter
expandafterexpandafterUD@secondoftwoexpandafterstring%
%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%.............................................................................
%% UD@ExtractFirstArgABCDE yields A
%%
%% UD@ExtractFirstArgABCDE yields AB
%%
%% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
%% You can check for emptiness via UD@CheckWhetherNull before applying
%% UD@ExtractFirstArg.
%%.............................................................................
newcommandUD@RemoveTillUD@SelDOm%
longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
newcommandUD@ExtractFirstArg[1]%
romannumeral0%
UD@ExtractFirstArgLoop#1UD@SelDOm%
%
newcommandUD@ExtractFirstArgLoop[1]%
expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
#1%
expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#1%
%
%%-----------------------------------------------------------------------------
%% UD@RemoveSpacesAndOneLevelOfBraces<argument> removes leading and
%% trailing spaces from <argument>.
%% If after that the <argument> is something that is entirely nested
%% between at least one pair of matching curly braces, the outermost
%% pair of these braces will be removed.
%%
%% !!!! <argument> must not contain the token UD@seldom !!!!
%%.............................................................................
begingroup
newcommandUD@RemoveSpacesAndOneLevelOfBraces[1]%
endgroup
newcommandUD@RemoveSpacesAndOneLevelOfBraces[1]%
romannumeral0%
UD@trimtrailspaceloop#1##1UD@seldom#1UD@seldomUD@seldom#1##1%
%
newcommandUD@trimtrailspaceloop%
longdefUD@trimtrailspaceloop##1#1UD@seldom##2UD@seldom#1##3%
UD@CheckWhetherNull##2%
UD@trimleadspaceloop##3%
%
UD@trimtrailspaceloop##1UD@seldom#1UD@seldomUD@seldom#1##1%
%
%
%
UD@RemoveSpacesAndOneLevelOfBraces %
newcommandUD@trimleadspaceloop[1]%
UD@CheckWhetherLeadingSpace#1%
expandafterUD@trimleadspaceloopexpandafterUD@removespace#1%
%
UD@CheckWhetherNull#1 %
expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
UD@exchange expandafterUD@secondoftwo#1%
#1%
%
%
%
%%-----------------------------------------------------------------------------
%% Check whether argument contains no comma which is not nested
%% in braces:
%%.............................................................................
%% UD@CheckWhetherNoComma<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% contains no comma>%
%% <Tokens to be delivered in case that argument
%% contains comma>%
%%
newcommandUD@GobbleToCommalongdefUD@GobbleToComma#1,%
newcommandUD@CheckWhetherNoComma[1]%
expandafterUD@CheckWhetherNullexpandafterUD@GobbleToComma#1,%
%
%%-----------------------------------------------------------------------------
%% Check whether argument contains no dash which is not nested
%% in braces:
%%.............................................................................
%% UD@CheckWhetherNoDash<Argument which is to be checked>%
%% <Tokens to be delivered in case that argument
%% contains no dash>%
%% <Tokens to be delivered in case that argument
%% contains dash>%
%%
newcommandUD@GobbleToDashlongdefUD@GobbleToDash#1-%
newcommandUD@CheckWhetherNoDash[1]%
expandafterUD@CheckWhetherNullexpandafterUD@GobbleToDash#1-%
%
%%-----------------------------------------------------------------------------
%% Take a comma-delimited/dash-delimited argument where a space was
%% prepended for preventing brace-removal and wrap it in curly braces.
%%.............................................................................
newcommandUD@SplitCommaArg%
longdefUD@SplitCommaArg#1,%
romannumeral0UD@exchange expandafterexpandafterUD@removespace#1%
%
newcommandUD@SplitDashArg%
longdefUD@SplitDashArg#1-%
romannumeral0UD@exchange expandafterexpandafterUD@removespace#1%
%
%%-----------------------------------------------------------------------------
%% Now we have the tools for creating the desired mycommand-macro:
%%.............................................................................
newcommandmycommand[1]%
romannumeral0%
UD@CheckWhetherNoComma#1%
expandaftermycommand@oneargumentexpandafter%
romannumeral0UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
expandafterUD@exchangeexpandafterexpandafter
UD@GobbleToComma#1%
%
expandafter@mycommand
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@ExtractFirstArgexpandafter%
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@SplitCommaArg
UD@firstoftwo #1%
%
%
%
newcommand@mycommand[2]%
UD@CheckWhetherNoDash#2%
expandafterUD@exchangeexpandafterexpandafter
%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#2%
%
%
expandaftermycommand@twoargumentsexpandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
%
expandafterUD@exchangeexpandafterexpandafter%
UD@GobbleToDash#2%
%
expandafter@@mycommand
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@ExtractFirstArgexpandafter%
romannumeral0%
UD@exchange %
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
%
expandafterUD@SplitDashArg
UD@firstoftwo #2%
%
#1%
%
%
newcommand@@mycommand[3]%
expandafterUD@exchangeexpandafter%
expandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#2%
%
%
expandafterUD@exchangeexpandafter%
expandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#1%
%
%
expandaftermycommand@threeargumentsexpandafter%
romannumeral0%
UD@exchange expandafterexpandafterexpandafter%
UD@RemoveSpacesAndOneLevelOfBraces#3%
%
%
%
%
newcommandmycommand@oneargument[1]%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is no comma or only empty args after the comma, thus:\
argument 1 = printmeaning#1%
%
newcommandmycommand@twoarguments[2]%
UD@CheckWhetherNull#2%
mycommand@oneargument#1%
%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is a comma but either no dash or only one non-empty argument near
the dash, thus:\
argument 1 = printmeaning#1\
argument 2 = printmeaning#2%
%
%
newcommandmycommand@threearguments[3]%
UD@CheckWhetherNull#2%
UD@CheckWhetherNull#3%
mycommand@oneargument#1%
%x
mycommand@twoarguments#1#3%
%
%
UD@CheckWhetherNull#3%
mycommand@twoarguments#1#2%
%
UD@secondoftwo%
%We need a space to stop romannumeral-expansion.
%
There is a comma and a dash, thus:\
argument 1 = printmeaning#1\
argument 2 = printmeaning#2\
argument 3 = printmeaning#3%
%
%
%
newcommandprintmeaning[1]%
defUD@tempa#1%
fboxtextttexpandafterstrip@prefixmeaningUD@tempa%
%
makeatother
parindent=0ex
parskip=smallskipamount
pagestyleempty%
begindocument
vspace*-3.5cm%
enlargethispage7cm%
verb|mycommand arg 1 |:\
mycommand arg 1 \
nullhrulefillnull
verb|mycommand arg 1 , |:\
mycommand arg 1 , \
nullhrulefillnull
verb|mycommand arg 1 , - |:\
mycommand arg 1 , - \
nullhrulefillnull
verb|mycommand arg 1 , arg 2 |:\
mycommand arg 1 , arg 2 \
(Be aware that (only) the outermost braces get removed from
an argument if surrounding the entire argument after removal
of surrounding spaces.)\
nullhrulefillnull
verb|mycommand arg 1 , arg 2 - |:\
mycommand arg 1 , arg 2 - \
nullhrulefillnull
verb|mycommand arg 1 , arg 2 - arg 3|:\
mycommand arg 1 , arg 2 - arg 3\
nullhrulefillnull
verb|mycommand arg 1 , - arg 3|:\
mycommand arg 1 , - arg 3\
nullhrulefillnull
verb|mycommand arg 1a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b|:\
mycommand arg 1a - arg 1b , arg 2-2 , 2 - arg 3a - arg 3b\
nullhrulefillnull
verb|mycommand arg 1 , arg 2-2 , 2 - arg 3a - arg 3b|:\
mycommand arg 1 , arg 2-2 , 2 - arg 3a - arg 3b
enddocument
edited Feb 9 at 13:34
answered Feb 8 at 22:53
Ulrich DiezUlrich Diez
5,105618
5,105618
add a comment |
add a comment |
A listofitems
approach.
By setting a nested parsing with setsepchar,/-
prior to reading the list into myargs
, everything to the left of the 1st comma is read into myargs[1]
, everything to the right of the comma (and before the next comma) is read into myargs[2]
.
Within myargs[2]
, everything to the left of the first dash is assigned to myargs[2,1]
, and everything after the dash (and before the next dash) is assigned to myargs[2,2]
.
The number of sub-elements within myargs[2]
is available through listlenmyargs[2]
.
All these elements and list length variables are fully expandable.
documentclassarticle
usepackagelistofitems
newcommandmycommand[1]setsepchar,/-readlist*myargs#1%
noindent Arg 1 is myargs[1]\
Arg 2 is myargs[2,1]\
Arg 3 is ifnumlistlenmyargs[2]=1relax Absentelsemyargs[2,2]fi%
begindocument
mycommandarg1, arg2
and
mycommandarg1, arg2-arg3
enddocument
add a comment |
A listofitems
approach.
By setting a nested parsing with setsepchar,/-
prior to reading the list into myargs
, everything to the left of the 1st comma is read into myargs[1]
, everything to the right of the comma (and before the next comma) is read into myargs[2]
.
Within myargs[2]
, everything to the left of the first dash is assigned to myargs[2,1]
, and everything after the dash (and before the next dash) is assigned to myargs[2,2]
.
The number of sub-elements within myargs[2]
is available through listlenmyargs[2]
.
All these elements and list length variables are fully expandable.
documentclassarticle
usepackagelistofitems
newcommandmycommand[1]setsepchar,/-readlist*myargs#1%
noindent Arg 1 is myargs[1]\
Arg 2 is myargs[2,1]\
Arg 3 is ifnumlistlenmyargs[2]=1relax Absentelsemyargs[2,2]fi%
begindocument
mycommandarg1, arg2
and
mycommandarg1, arg2-arg3
enddocument
add a comment |
A listofitems
approach.
By setting a nested parsing with setsepchar,/-
prior to reading the list into myargs
, everything to the left of the 1st comma is read into myargs[1]
, everything to the right of the comma (and before the next comma) is read into myargs[2]
.
Within myargs[2]
, everything to the left of the first dash is assigned to myargs[2,1]
, and everything after the dash (and before the next dash) is assigned to myargs[2,2]
.
The number of sub-elements within myargs[2]
is available through listlenmyargs[2]
.
All these elements and list length variables are fully expandable.
documentclassarticle
usepackagelistofitems
newcommandmycommand[1]setsepchar,/-readlist*myargs#1%
noindent Arg 1 is myargs[1]\
Arg 2 is myargs[2,1]\
Arg 3 is ifnumlistlenmyargs[2]=1relax Absentelsemyargs[2,2]fi%
begindocument
mycommandarg1, arg2
and
mycommandarg1, arg2-arg3
enddocument
A listofitems
approach.
By setting a nested parsing with setsepchar,/-
prior to reading the list into myargs
, everything to the left of the 1st comma is read into myargs[1]
, everything to the right of the comma (and before the next comma) is read into myargs[2]
.
Within myargs[2]
, everything to the left of the first dash is assigned to myargs[2,1]
, and everything after the dash (and before the next dash) is assigned to myargs[2,2]
.
The number of sub-elements within myargs[2]
is available through listlenmyargs[2]
.
All these elements and list length variables are fully expandable.
documentclassarticle
usepackagelistofitems
newcommandmycommand[1]setsepchar,/-readlist*myargs#1%
noindent Arg 1 is myargs[1]\
Arg 2 is myargs[2,1]\
Arg 3 is ifnumlistlenmyargs[2]=1relax Absentelsemyargs[2,2]fi%
begindocument
mycommandarg1, arg2
and
mycommandarg1, arg2-arg3
enddocument
edited Feb 9 at 14:15
answered Feb 8 at 18:54
Steven B. SegletesSteven B. Segletes
157k9202411
157k9202411
add a comment |
add a comment |
One more:
documentclassarticle
usepackagexstring
defmycommand#1,#2 IfSubStr#2-[[#1],
[StrBefore#2-]-[StrBehind#2-]] [[#1],[#2]]
begindocument
mycommand aaa,bbb-ccc
mycommand aaa,bbb
enddocument
add a comment |
One more:
documentclassarticle
usepackagexstring
defmycommand#1,#2 IfSubStr#2-[[#1],
[StrBefore#2-]-[StrBehind#2-]] [[#1],[#2]]
begindocument
mycommand aaa,bbb-ccc
mycommand aaa,bbb
enddocument
add a comment |
One more:
documentclassarticle
usepackagexstring
defmycommand#1,#2 IfSubStr#2-[[#1],
[StrBefore#2-]-[StrBehind#2-]] [[#1],[#2]]
begindocument
mycommand aaa,bbb-ccc
mycommand aaa,bbb
enddocument
One more:
documentclassarticle
usepackagexstring
defmycommand#1,#2 IfSubStr#2-[[#1],
[StrBefore#2-]-[StrBehind#2-]] [[#1],[#2]]
begindocument
mycommand aaa,bbb-ccc
mycommand aaa,bbb
enddocument
answered Feb 9 at 18:13
FranFran
52.8k6118182
52.8k6118182
add a comment |
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f473965%2fa-command-challenge%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
That's one argument from a TeX point of view ... I guess you want a parser for that one document-level argument.
– Joseph Wright♦
Feb 8 at 17:46
Try
defmycommand#1,space#2-#3...
.– John Kormylo
Feb 8 at 21:41
Since I assume this is more or less a follow-up to tex.stackexchange.com/q/473949/35864, let me please re-iterate that I believe that the usual
biblatex
syntax is not really inferior to this syntax. In fact the syntax proposed here has the serious drawback that it removes the ability to cite several entries in one cite commandautocitesugfridsson,worman,nussbaum
as that uses the comma-separated syntax in one argument already.– moewe
Feb 9 at 8:00