\newcommand / \newenvironment - optional parameters - latex

I'm experimenting with my own commands and environments and now I'm facing those problems:
How to create command \foo{parameter}[optional] or environment called \begin{bar}{parameter}[optional]?
How to create command \foo[optional_1]...[optional_n]{parameter}
I've tried
\newcommand{\foo}[3][][]{#1#2#3} - failed
\newcommand{\foo}[3][2][][]{#1#2#3} - failed
Does anyone know some hint? Thanks a lot.

You can't create a \foo{parameter}[optional] command simply; you can, however, create a \foo[optional]{parameter} command with
\newcommand{\foo}[2][default]{Mandatory: #2; optional: #1}
If you call it as \foo{given}, it will produce Mandatory: given, optional: default; if you call it as \foo[bonus]{given}, it will produce Mandatory: given, optional: bonus. This is probably how you should do it—that will look better with the rest of your LaTeX code. Creating a new environment with optional parameters is done similarly with
\newenvironment{env}[2][def]{(#1,#2)\begingroup}{\endgroup}
where #1 is again the optional argument; this is again written as \begin{env}[opt]{req}...\end{env}. If you really want a command in the other form, see the end of my answer.
The TeX FAQ has an answer about writing commands with more than one optional argument. There are two options to how to do it. The underlying idea is to define a command which takes an optional argument, and then runs another command which itself takes an optional argument, etc.; the twoopt package encapsulates this.
If you really want a command like \reversed{mandatory}[optional], you can do it like so. First, you define a command which takes a required argument, stores it in a macro, and then forward it onto another command. This second command takes an optional argument, and uses the defined command and the optional argument. Putting this all together, we get
\makeatletter
\newcommand{\reversed}[1]{\def\reversed#required{#1}\reversed#opt}
\newcommand{\reversed#opt}[1][def]{Required: \reversed#required; optional: #1}
\makeatother
You can then use \reversed{mandatory}[optional] or just \reversed{mandatory}, and everything should work.

Using the xparse package (part of the LaTeX3 development efforts):
\usepackage{xparse}
\NewDocumentCommand\foo{O{}O{}m}{%
% Code with optional #1 and #2 with empty defaults
}
\NewDocumentCommand\foo{mO{}}{%
% Code with optional #2 with empty default
}
\NewDocumentEnvironment{foo}{O{}}{%
% Start code with optional #1
}{%
% End code with optional #1
}
Optional arguments are a bit different in xparse to with \newcommand. You can detect whether one is given or not:
\NewDocumentCommand\foo{mo}{%
\IfNoValueTF{#2}
{Code without #2}
{Code with #2}%
}
You'll see that this works by using a lower case 'o', whereas the upper case 'O' then requires a default value (which I've made empty by including an empty group).

Consider also the xargs package. The following is an example from its documentation.
Set it up in the usual way,
\usepackage{xargs}
and then if you define
\newcommandx*\coord[3][1=1, 3=n]{(#2_{#1},\ldots,#2_{#3})}
(which means to use "1" for the first argument, if it is not specified, and to use "n" for the third). Then
$\coord{x}$
yields (sans subscripts)
(x1, . . . , xn)
and
$\coord[0]{y}$
yields (again, sans subscripts, and y replaces the mandatory parameter)
(y0, ..., yn)

I know there are already comprehensive answers, but is some cases, I want to give different definitions for different situations. There is a still very basic yet simple solution for this. I write it down in case any other need it.
% ----------------------------------
%! TEX program = XeLaTeX
% !TeX encoding = UTF-8
% Author: Troy_Daniel
% Email: Troy_Daniel#163.com
% ----------------------------------
\documentclass{article}
\usepackage{xcolor}
\newcommand{\Caption}[3]{%
\textcolor[rgb]{0.36, 0.72, 0.80}{\Large #1}
{\def\tmp{#3}
\ifx\tmp\empty % the third parameter is not provieded
\textcolor[rgb]{0.96, 0.66, 0.35}{\small#2}
\else % non-empty third parameter
\textcolor[rgb]{0.96, 0.66, 0.35}{\small[#3]#2}
\fi}}
\begin{document}
\Caption{First}{Second}{}
\Caption{First}{Second}{Third}
\end{document}
And the result is shown below, different definitions for optional parameter(s):

Related

What does this required empty parameter mean, when defining something?

\newenvironment{nameOfEnvironment}[1][]%
Can someone explain the empty bracket?
You should consider reading Is there a comprehensive and complete LaTeX reference? where you'll find information on all sorts of LaTeX2e sources.
Technically, \newenvironment{<cmd>}[<num>][<default>]{<beg-def>}{<end-def>} uses \newcommand as base, so understanding the latter will help you understand the former.
Specific to your case, LaTeX2e for authors user guide mentions the following about \newcommand:
...the command:
\newcommand{<cmd>}[<num>][<default>]{<definition>}
defines <cmd> to be a command with <num> arguments, the first of which is
optional and has default value <default>.
Note that there can only be one optional argument but, as before, there can be
up to nine arguments in total.
So,
\newenvironment{nameOfEnvironment}[1][]%
{<beg-def>}
{<end-def>}
defines an environment nameOfEnvironment that takes a single argument (as a result of [1]). This single argument is an optional argument (as a result of the second []) that, if not specified, has an empty default value.
You would be able to use it as
\begin{nameOfEnvironment}
<stuff>
\end{nameOfEnvironment}
or
\begin{nameOfEnvironment}[something]
<stuff>
\end{nameOfEnvironment}
In the former case, the optional argument #1 is empty, while the second has an optional argument value of something.
The following explanation is taken from LaTeX: Structured documents for TeX (unofficial LaTeX reference manual):
13.5 \newenvironment & \renewenvironment
Synopses:
\newenvironment[*]{env}[nargs][default]{begdef}{enddef}
\renewenvironment[*]{env}[nargs]{begdef}{enddef}
These commands define or redefine an environment env, that is, \begin{env} ... \end{env}.
*
The *-form of these commands requires that the arguments (not the contents
of the environment) not contain multiple paragraphs of text.
env
The name of the environment. For \newenvironment, env must not be
an existing environment, and the command \env must be undefined. For
\renewenvironment, env must be the name of an existing environment.
nargs
An integer from 1 to 9 denoting the number of arguments of the newly-defined
environment. The default is no arguments.
default
If this is specified, the first argument is optional, and default gives the default value for that argument.
begdef
The text expanded at every occurrence of \begin{env}; a construct of the form #n in begdef is replaced by the text of the nth argument.
enddef
The text expanded at every occurrence of \end{env}. It may not contain any
argument parameters.

Building Latex/Tex arguments in lua

I use lua to make some complex job to prepare arguments for macros in Tex/LaTex.
Part I
Here is a stupid minimal example :
\newcommand{\test}{\luaexec{tex.print("11,12")}}% aim to create 11,12
\def\compare#1,#2.{\ifthenelse{#1<#2}{less}{more}}
\string\compare11,12. : \compare11,12.\\ %answer is less
\string\test : \test\\ % answer is 11,12
\string\compare : \compare\test. % generate an error
The last line creates an error. Obviously, Tex did not detect the "," included in \test.
How can I do so that \test is understood as 11 followed by , followed by 12 and not the string 11,12 and finally used as a correctly formed argument for \compare ?
There are several misunderstandings of how TeX works.
Your \compare macro wants to find something followed by a comma, then something followed by a period. However when you call
\compare\test
no comma is found, so TeX keeps looking for it until finding either the end of file or a \par (or a blank line as well). Note that TeX never expands macros when looking for the arguments to a macro.
You might do
\expandafter\compare\test.
provided that \test immediately expands to tokens in the required format, which however don't, because the expansion of \test is
\luaexec{tex.print("11,12")}
and the comma is hidden by the braces, so it doesn't count. But it wouldn't help nonetheless.
The problem is the same: when you do
\newcommand{\test}{\luaexec{tex.print("11,12")}}
the argument is not expanded. You might use “expanded definition” with \edef, but the problem is that \luaexec is not fully expandable.
If you do
\edef\test{\directlua{tex.sprint("11,12")}}
then
\expandafter\compare\test.
would work.

Triple-wrapping of \colorbox → \NewEnviron → \newenvironment fails

I am trying to wrap an environment created with \NewEnviron (package 'environ') into an old good \newenvironment:
\NewEnviron{test}{\colorbox[gray]{0.7}{\BODY}}
\newenvironment{wrapper}{\begin{test}}{\end{test}}
\begin{wrapper}
debug me
\end{wrapper}
However, this gives me a strange error:
LaTeX Error: \begin{test} on input line 15 ended by \end{wrapper}.
LaTeX Error: \begin{wrapper} on input line 15 ended by \end{document}.
If I replace \NewEnviron{test}{aaa(\BODY)bbb} with \newenvironment{test}{aaa(}{)bbb} — everything works as expected! It seems like \NewEnviron fails to find its end for some reason.
I'm trying to do some magic with 'floatfig' wrapped into a \colorbox so I need a way to convert \colorbox to an environment and wrap it into another one. I can define a new command but it's not a very good idea.
The thing is that \NewEviron and \newenvironment works in different ways.
1) \newenvironment{test}{aaa(}{)bbb} defines two commands: \test is aaa( and \endtest is )bbb.
\begin{test} is expanded to \test.
\end{test} is expanded to \endtest and checks that your scope begins with begin{test} rather \begin{something else}, for example \begin{wrapper}.
2) \NewEviron{test}{aaa(\BODY)bbb} defines \test in different way. First of all \test catches the \BODY using the following trick
\def\test#1\end{\def\BODY{#1}aaa(\BODY)bbb\testcontinue}
(name \testcontinue may be different) and inserts aaa(\BODY)bbb. Then \testcontinue checks that \end on some input line ended by \end{test} rather than \end{something else}. Macro \endtest
is not needed because it is never executed.
Look on your code:
\begin{wrapper}
debug me
\end{wrapper}
\begin{wrapper} is expanded to \begin{test}. Then
\begin{test} is expanded to \test. \test catch \BODY.
Attention! \BODY is equal to debug me. And now \testcontionue checks
that \end after \BODY ended by \end{test}. It is not true. \end{test} is absent.
There is \end{wrapper}.
You want to say that \end{wrapper} must be expanded to \end{test}. But \end before wrapper was eaten by
macro \test: #1\end{\def\BODY{#1}aaa(\BODY)bbb\testcontinue}
and can not be executed.
I hope I success to explain.
I've found a hacky trick to create an environment that can be wrapped in another one. One should use saveBoxes like this:
\newenvironment{example}[2][]{%
\newsavebox{\exampleStore} % Box storage
\begin{lrbox}{\exampleStore} % Start capturing the input
}{%
\end{lrbox} % Stop capturing the input
\colorbox[gray]{0.7}{%
\usebox{\NBstorage} % Load the box's contents
}%
}%
}%

LaTeX: Redefining starred command

I want to redefine the \part* command so that it automatically adds a contents line. This proves difficult since I want to reuse the original \part* command inside my starred version.
Normally (i.e. for unstarred commands) I would do it like this:
\let\old#part\part
\renewcommand\part[2][]{
\old#part[#1]{#2}
… rest of definition}
That is, I would save the original definition of \part in \old#part and use that.
However, this doesn’t work for starred commands since they don’t define a single lexeme (unlike the \part command in the example above). This boils down to the following question: How can I save a starred command?
Notice that I already know how to redefine a starred command itself, using the \WithSuffix command from the suffix package. This isn’t the problem.
There is no \part* command. What happens is the \part command takes a look at the next character after it (with \#ifstar) and dispatches to one of two other routines that does the actual work based on whether there's an asterisk there or not.
Reference: TeX FAQ entry Commands defined with * options
Thanks to #smg’s answer, I’ve cobbled together a solution that works perfectly. Here’s the complete source, along with explanatory comments:
% If this is in *.tex file, uncomment the following line.
%\makeatletter
% Save the original \part declaration
\let\old#part\part
% To that definition, add a new special starred version.
\WithSuffix\def\part*{
% Handle the optional parameter.
\ifx\next[%
\let\next\thesis#part#star%
\else
\def\next{\thesis#part#star[]}%
\fi
\next}
% The actual macro definition.
\def\thesis#part#star[#1]#2{
\ifthenelse{\equal{#1}{}}
{% If the first argument isn’t given, default to the second one.
\def\thesis#part#short{#2}
% Insert the actual (unnumbered) \part header.
\old#part*{#2}}
{% Short name is given.
\def\thesis#part#short{#1}
% Insert the actual (unnumbered) \part header with short name.
\old#part*[#1]{#2}}
% Last, add the part to the table of contents. Use the short name, if provided.
\addcontentsline{toc}{part}{\thesis#part#short}
}
% If this is in *.tex file, uncomment the following line.
%\makeatother
(This needs the packages suffix and ifthen.)
Now, we can use it:
\part*{Example 1}
This will be an unnumbered part that appears in the TOC.
\part{Example 2}
Yes, the unstarred version of \verb/\part/ still works, too.

LaTeX \newcommand default argument: is empty?

I'm trying to write a simple example command that prints nothing without an argument, but with an argument it surrounds it with something.
I've read that the default value should be \#empty and the simple \ifx\#empty#1 condition should do the job:
\newcommand{\optarg}[1][\#empty]{%
\ifx\#empty#1 {} \else {(((#1)))} \fi
}
\optarg % (((empty)))
\optarg{} % (((empty)))
\optarg{test} % (((empty))) test
The latter three commands all print the empty word for some reason, and I want the first two to print nothing and the last to print (((test))).
I'm using TeXLive/Ubuntu. An ideas?
Try the following test:
\documentclass{article}
\usepackage{xifthen}% provides \isempty test
\newcommand{\optarg}[1][]{%
\ifthenelse{\isempty{#1}}%
{}% if #1 is empty
{(((#1)))}% if #1 is not empty
}
\begin{document}
Testing \verb|\optarg|: \optarg% prints nothing
Testing \verb|\optarg[]|: \optarg[]% prints nothing
Testing \verb|\optarg[test]|: \optarg[test]% prints (((test)))
\end{document}
The xifthen package provides the \ifthenelse construct and the \isempty test.
Another option is to use the ifmtarg package (see the ifmtarg.sty file for the documentation).
Using the LaTeX3 xparse package:
\usepackage{xparse}
\NewDocumentCommand\optarg{g}{%
\IfNoValueF{#1}{(((#1)))}%
}
In the underlying TeX engine with which LaTeX is written, the number of arguments a command can take is fixed. What you've done with the default [\#empty] is ask LaTeX to examine the next token to see if it is an open square bracket [. If so, LaTeX takes the contents of square brackets as the argument, if not, the next token is put back into the input stream and the default \#empty argument is used instead. So to get your idea to work, you have to use square brackets to delimit the optional argument when present:
\optarg
\optarg[]
\optarg[test]
You should have better luck with this notation.
It's annoying that you can't use the same brackets for an optional argument as you use for a required argument, but that's the way it is.
\documentclass{article}
\usepackage{ifthen} % provides \ifthenelse test
\usepackage{xifthen} % provides \isempty test
\newcommand{\inlinenote}[2][]{%
{\bfseries{Note:}}%
\ifthenelse{\isempty{#1}}
{#2} % if no title option given
{~\emph{#1} #2} % if title given
}
\begin{document}
\inlinenote{
simple note
}
\inlinenote[the title]{
simple note with title
}
\end{document}

Resources