Difference between revisions of "Commands with optional arguments"

From Wiki
Jump to navigation Jump to search
m
(7 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
< [[Inside ConTeXt]] | [[Commands with KeyVal arguments]] >
 
< [[Inside ConTeXt]] | [[Commands with KeyVal arguments]] >
  
In LaTeX you define a new command with an optional argument with "newcommand":
+
In ConTeXt, the optional argument processing is handled as a two-step process.  First, we write the command for the end-user as a wrapper command, which calls {{cmd|dosingleempty}}, {{cmd|dodoubleempty}}, {{cmd|dotripleempty}}, ... (from {{src|syst-aux.mkiv}} or {{src|syst-gen.mkii}}) to handle the arguments properly -- including the optional ones -- and then calls a "private" command that contains the internals of the macro.  Note that this function call does not explicitly refer to the arguments at all.
 
 
<texcode>
 
\newcommand{\MyCommand}[2][World]{{#2Hello #1!}}
 
\MyCommand{\bfseries}
 
\MyCommand[Hans]{\scshape}
 
</texcode>
 
 
 
<context>
 
{\bf Hello World!}
 
{\sc Hello Hans!}
 
</context>
 
 
 
In ConTeXt, the optional argument processing is handled as a two-step process.  First, we write the command for the end-user as a wrapper command, which calls <cmd>dodoubleempty</cmd> (from [http://source.contextgarden.net/tex/context/base/syst-gen.tex syst-gen.tex]) to handle the arguments properly -- including the optional ones -- and then calls a "private" command that contains the internals of the macro.  Note that this function call does not explicitly refer to the arguments at all.
 
  
 +
For a command with two optional arguments, we use:
 
<texcode>
 
<texcode>
 
\def\MyCommand{\dodoubleempty\doMyCommand}
 
\def\MyCommand{\dodoubleempty\doMyCommand}
 
</texcode>
 
</texcode>
  
We then create the "private" macro (<tt>\doMacroName</tt> is the traditional ConTeXt name for these), with all the arguments defined as nonoptional.  Default values for the arguments need to be handled somewhat more explicitly than with LaTeX; macros such as <cmd>ifsecondargument</cmd> are used to determine whether the given argument was specified, as follows:
+
We then create the "private" macro (<tt>\doMacroName</tt> is the traditional ConTeXt name for these), with all the arguments defined as nonoptional.  Default values for the arguments need to be handled somewhat more explicitly than with LaTeX; macros such as {{cmd|ifsecondargument}} are used to determine whether the given argument was specified, as follows:
  
 
<texcode>
 
<texcode>
Line 54: Line 42:
 
</context>
 
</context>
  
If you ''don't'' want any optional arguments, but still want your arguments enclosed in <tt>[]</tt> with appropriate handling for spaces (or line breaks) between the square brackets, use <cmd>dodoubleargument</cmd> instead of <cmd>dodoubleempty</cmd>.  There are of course versions for other numbers of arguments, found by replacing <tt>double</tt> with <tt>single</tt> through <tt>seventuple</tt>; see [http://source.contextgarden.net/tex/context/base/syst-gen.mkii syst-gen.tex] for the exact names.
+
If you ''don't'' want any optional arguments, but still want your arguments enclosed in <tt>[]</tt> with appropriate handling for spaces (or line breaks) between the square brackets, use {{cmd|dodoubleargument}} instead of {{cmd|dodoubleempty}}.  There are of course versions for other numbers of arguments, found by replacing <tt>double</tt> with <tt>single</tt> through <tt>seventuple</tt>; see {{src|syst-aux.mkiv}} for the exact names.
  
 
=== Examples ===
 
=== Examples ===
  
To define <tt>\mycommand[.1.][.2.]{.3.}</tt>, i.e., with curly braces around a non-optional third argument, you just define
+
To define <code>\mycommand[#1]{#2}</code> with one optional argument and one mandatory argument, do the following
 
+
<context source="yes">
<texcode>
 
\def\mycommand{\dodoubleempty\doMycommand}
 
\def\doMycommand[#1][#2]#3{whatever}
 
</texcode>
 
 
 
 
 
 
 
 
 
To define <code>\mycommand[optional]{text}</code>, do the following
 
 
 
<texcode>
 
 
 
 
\def\mynewcommand{\dosingleempty\doMyNewCommand}
 
\def\mynewcommand{\dosingleempty\doMyNewCommand}
 
\def\doMyNewCommand[#1]#2{%
 
\def\doMyNewCommand[#1]#2{%
 
  \iffirstargument
 
  \iffirstargument
   There is an optional parameter: {\bf #1}\par
+
   There is an optional parameter: {\bf #1}\par%
 
  \else
 
  \else
   No optional parameter\par
+
   No optional parameter\par%
 
  \fi
 
  \fi
   This is the mandatory text: {\em #2}
+
   This is the mandatory text: {\em #2}%
 
}
 
}
  
 
\starttext
 
\starttext
 
\mynewcommand[opt]{Hello People}
 
\mynewcommand[opt]{Hello People}
 
+
\blank
 
\mynewcommand{Hello People}
 
\mynewcommand{Hello People}
 
\stoptext
 
\stoptext
</texcode>
+
</context>
  
<context>
 
  
\def\mynewcommand{\dosingleempty\doMyNewCommand}
+
To define <code>\mycommand[#1][#2]{#3}</code> with two optional arguments and one mandatory argument, do
\def\doMyNewCommand[#1]#2{%
 
\iffirstargument
 
  There is an optional parameter: {\bf #1}\par
 
\else
 
  No optional parameter\par
 
\fi
 
  This is the mandatory text: {\em #2}
 
}
 
  
\starttext
+
<texcode>
\mynewcommand[opt]{Hello People}
+
\def\mycommand{\dodoubleempty\doMycommand}
\blank
+
\def\doMycommand[#1][#2]#3{whatever}
\mynewcommand{Hello People}
+
</texcode>
\stoptext
 
</context>
 
  
 
=== Pitfalls ===
 
=== Pitfalls ===
Line 117: Line 82:
 
  \startalignment[center]
 
  \startalignment[center]
 
  \iffirstargument
 
  \iffirstargument
   There is an optional parameter: {\bf #1}\par
+
   There is an optional parameter: {\bf #1}\par%
 
  \else
 
  \else
   No optional parameter\par
+
   No optional parameter\par%
 
  \fi
 
  \fi
   This is the mandatory text: {\em #2}
+
   This is the mandatory text: {\em #2}%
 
  \stopalignment
 
  \stopalignment
 
}
 
}
Line 136: Line 101:
 
\def\mynewcommand{\dosingleempty\doMyNewCommand}
 
\def\mynewcommand{\dosingleempty\doMyNewCommand}
 
\def\doMyNewCommand[#1]#2{%
 
\def\doMyNewCommand[#1]#2{%
  \startalignment[center]
+
  \startalignment[center]%
 
  \doifsomethingelse{#1}
 
  \doifsomethingelse{#1}
 
   {There is an optional parameter: {\bf #1}\par}
 
   {There is an optional parameter: {\bf #1}\par}
 
   {No optional parameter\par}
 
   {No optional parameter\par}
 
   This is the mandatory text: {\em #2}
 
   This is the mandatory text: {\em #2}
  \stopalignment
+
  \stopalignment%
 
}
 
}
 
\starttext
 
\starttext
Line 151: Line 116:
  
  
 +
On a final note, for comparative purposes: in LaTeX, a new command with an optional argument is defined with <code>\newcommand</code>.
 +
 +
<texcode>
 +
\newcommand{\MyCommand}[2][World]{{#2Hello #1!}}
 +
\MyCommand{\bfseries}
 +
\MyCommand[Hans]{\scshape}
 +
</texcode>
 +
 +
Reference:
 +
http://archive.contextgarden.net/message/20101215.225603.cc903e62.en.html
  
[[Category:Inside ConTeXt]]
+
[[Category:Programming and Databases]]
 +
[[Category:Tools]]

Revision as of 17:04, 8 June 2020

< Inside ConTeXt | Commands with KeyVal arguments >

In ConTeXt, the optional argument processing is handled as a two-step process. First, we write the command for the end-user as a wrapper command, which calls \dosingleempty, \dodoubleempty, \dotripleempty, ... (from syst-aux.mkiv or syst-gen.mkii) to handle the arguments properly -- including the optional ones -- and then calls a "private" command that contains the internals of the macro. Note that this function call does not explicitly refer to the arguments at all.

For a command with two optional arguments, we use:

\def\MyCommand{\dodoubleempty\doMyCommand}

We then create the "private" macro (\doMacroName is the traditional ConTeXt name for these), with all the arguments defined as nonoptional. Default values for the arguments need to be handled somewhat more explicitly than with LaTeX; macros such as \ifsecondargument are used to determine whether the given argument was specified, as follows:

 \def\doMyCommand[#1][#2]{#1Hello
    \ifsecondargument
       #2%
    \else
       World%
    \fi
    !}

Note that this makes both arguments optional -- something that is much more difficult to do in LaTeX (but can be done). This also means that we should reverse the order of arguments, since if the user specifies only one argument it will be treated as the first argument.

(Also, note that \MyCommand without the second argument ends up gobbling the following spaces, so we need to explicitly include one with "\ ".)

\MyCommand[\bf]\ %
\MyCommand[\sc][Hans]

If you don't want any optional arguments, but still want your arguments enclosed in [] with appropriate handling for spaces (or line breaks) between the square brackets, use \dodoubleargument instead of \dodoubleempty. There are of course versions for other numbers of arguments, found by replacing double with single through seventuple; see syst-aux.mkiv for the exact names.

Examples

To define \mycommand[#1]{#2} with one optional argument and one mandatory argument, do the following

\def\mynewcommand{\dosingleempty\doMyNewCommand}
\def\doMyNewCommand[#1]#2{%
 \iffirstargument
  There is an optional parameter: {\bf #1}\par%
 \else
  No optional parameter\par%
 \fi
  This is the mandatory text: {\em #2}%
}

\starttext
\mynewcommand[opt]{Hello People}
\blank
\mynewcommand{Hello People}
\stoptext


To define \mycommand[#1][#2]{#3} with two optional arguments and one mandatory argument, do

\def\mycommand{\dodoubleempty\doMycommand}
\def\doMycommand[#1][#2]#3{whatever}

Pitfalls

Please keep in mind that \iffirstargument will always return true if you put before it a command which itself has an argument. See the following example:

\def\mynewcommand{\dosingleempty\doMyNewCommand}
\def\doMyNewCommand[#1]#2{%
 \startalignment[center]
 \iffirstargument
  There is an optional parameter: {\bf #1}\par%
 \else
  No optional parameter\par%
 \fi
  This is the mandatory text: {\em #2}%
 \stopalignment
}
\starttext
\mynewcommand[opt]{Hello People}
\blank
\mynewcommand{Hello People}
\stoptext

produces

Use \doifsomethingelse instead:

\def\mynewcommand{\dosingleempty\doMyNewCommand}
\def\doMyNewCommand[#1]#2{%
 \startalignment[center]%
 \doifsomethingelse{#1}
   {There is an optional parameter: {\bf #1}\par}
   {No optional parameter\par}
  This is the mandatory text: {\em #2}
 \stopalignment%
}
\starttext
\mynewcommand[opt]{Hello People}
\blank
\mynewcommand{Hello People}
\stoptext

this time is correct:


On a final note, for comparative purposes: in LaTeX, a new command with an optional argument is defined with \newcommand.

\newcommand{\MyCommand}[2][World]{{#2Hello #1!}}
\MyCommand{\bfseries}
\MyCommand[Hans]{\scshape}

Reference: http://archive.contextgarden.net/message/20101215.225603.cc903e62.en.html