[Tex/LaTex] Putting a function into a new command with optional arguments

macrosmath-modeoptional arguments

I know I have asked this before. But I just can not wrap my head around some things in LaTeX. Like the optional arguments. I have gotten some clues how to do it for comands, but not quite sure how to do it for commands.

What I am looking for is putting @egreg's answer here into my own environment.

Best way to create an system of equations environment?

Now here is how I would like the output to be

\begin{SysOfEq}
 ax^2 + bx + c = 0,
 3y^2 + 8x - 5 = 0,
  z   +  x     = 0
\end{SysOfEq}

 \begin{SysOfEq}[2pt]
 ax^2 + bx + c = 0,
 3y^2 + 8x - 5 = 0,
  z   +  x     = 0
\end{SysOfEq}

Now if I am not using the optional argument, the default spacing should be 3pt. When using the optional spacing, it should be 3pt + input.

The code alone, without the optional arguments looks like this

\documentclass[10pt,a4paper]{article}
\usepackage[hmargin=3cm,vmargin=3.5cm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[norsk]{babel}
\usepackage{amsmath}
\usepackage{mathtools}
\usepackage{systeme}

\makeatletter
\def\SYS@makesyspreamble@i#1{%
  \ifnum#1<\SYS@preamblenum
    \SYS@addtotok\SYS@systempreamble{\hfil$##$&\hfil$##$&}% 
    \expandafter\SYS@makesyspreamble@i\expandafter{\number\numexpr#1+    \@ne\expandafter}%
  \else
    \SYS@addtotok\SYS@systempreamble{\hfil$##$&$##$&\hfil$##$\null}% 
    \ifSYS@extracol
      \SYS@addtotok\SYS@systempreamble{&\SYS@extracolstart##\SYS@extracolend    \hfil\null}% 
    \fi
    \SYS@addtotok\SYS@systempreamble{\cr\SYS@strutup}% 
  \fi
}
\makeatother

\newcommand{\SysOfEq}[1]{$
\syslineskipcoeff{1.2}\setlength{\tabskip}{#1}
\sysdelim..\systeme{#1}$}


\begin{document}

\SysOfEq{1cm}{
     ax^2 + bx + c = 0,
     3y^2 + 8x - 5 = 0,
      z   +  x     = 0}

\end{document}

The code above does not work. The clock is almost 4am here, so I should really go to bed. It is just kind of frustrating to not complete something as simple as the code above.

  • Make a new command that uses the code above (from @egreg).
  • Optional argument for horizontal spacing (perhaps also vertical).
  • These new values should just add to the existing ones.

Best Answer

Here is how you can add an optional argument to you \SysOfEq command:

enter image description here

\documentclass[10pt,a4paper]{article}
\usepackage{systeme}% http://ctan.org/pkg/systeme

\makeatletter
\def\SYS@makesyspreamble@i#1{%
  \ifnum#1<\SYS@preamblenum
    \SYS@addtotok\SYS@systempreamble{\hfil$##$&\hfil$##$&}% 
    \expandafter\SYS@makesyspreamble@i\expandafter{\number\numexpr#1+    \@ne\expandafter}%
  \else
    \SYS@addtotok\SYS@systempreamble{\hfil$##$&$##$&\hfil$##$\null}% 
    \ifSYS@extracol
      \SYS@addtotok\SYS@systempreamble{&\SYS@extracolstart##\SYS@extracolend    \hfil\null}% 
    \fi
    \SYS@addtotok\SYS@systempreamble{\cr\SYS@strutup}% 
  \fi
}
\makeatother
\begin{document}
\newcommand*{\SysOfEq}[2][0pt]{
\syslineskipcoeff{1.2}\setlength{\tabskip}{\dimexpr3pt+#1\relax}
\systeme{#2}}

\[
\syslineskipcoeff{1.2}\setlength{\tabskip}{3pt}
\systeme{
2x  +   y  +  3z  =  10,
 x  +   y  +   z  =   6,
 x  +  3y  +  2z  =  13}
\]

\[
  \SysOfEq{%
2x  +   y  +  3z  =  10,
 x  +   y  +   z  =   6,
 x  +  3y  +  2z  =  13}  
\]

\[
  \SysOfEq[1cm]{%
2x  +   y  +  3z  =  10,
 x  +   y  +   z  =   6,
 x  +  3y  +  2z  =  13}  
\]
\end{document}

This allows for a single optional argument that has a default spacing of 3pt (if not specified) or "3pt + input" if it is specified.

A little background on \newcommand, which was used to produce \SysOfEq:

\newcommand{<cmd>}[<nargs>][<opt>]{<definition>}

<cmd> is the command that you want to define. This should be undefined at the time you call \newcommand, otherwise you will receive a

LaTeX Error: Command \SysOfEq already defined.

error (here I tried to define \SysOfEq and it was already defined). In those cases, you need to use \renewcommand (or \providecommand in LaTeX2e) with the same argument definitions. <nargs> refers to the number of arguments <cmd> should take. This can be anything from 1 to 9. Note that this specification is optional, so you can create a command that takes 0 arguments if you leave out <nargs>. If you did specify <nargs>, then you can specify <opt> (again optional, so it's not necessary). Whatever you specify in <opt> will be the default value to the first argument which is necessarily optional. This first argument will be referred to in <definition> as #1, while subsequent (mandatory) arguments will be referred to as #2...#9 or however many you specified in <nargs>.

From the above discussion you can see that wherever I refer to #1, it means the optional argument that you specify. Wherever I refer to #2, it implies what I specify after that - in this case you system of equations.

Using \newcommand in this way is the standard way to define commands (or control sequences) in LaTeX and it allows for a single optional argument. If you want a more advanced way of defining commands (including intermixed optional/mandatory arguments), you can use the interface provided by xparse - see @Gonzalo's answer for this.


When writing a macro that has many possible modifications to it, optional arguments are always great, since you can use them at your leisure. However, without knowing what the argument order is and which ones are optional/mandatory, it could be difficult to maintain. Symbolic references to options is a better option when it comes to this. As such, a key-value pair approach would work well. To this end, consider reading How to create a command with key values?

Here is a view on such an approach:

enter image description here

\documentclass[10pt,a4paper]{article}
\usepackage{keyval}% http://ctan.org/pkg/keyval
\usepackage{systeme}% http://ctan.org/pkg/systeme

\makeatletter
\def\SYS@makesyspreamble@i#1{%
  \ifnum#1<\SYS@preamblenum
    \SYS@addtotok\SYS@systempreamble{\hfil$##$&\hfil$##$&}% 
    \expandafter\SYS@makesyspreamble@i\expandafter{\number\numexpr#1+    \@ne\expandafter}%
  \else
    \SYS@addtotok\SYS@systempreamble{\hfil$##$&$##$&\hfil$##$\null}% 
    \ifSYS@extracol
      \SYS@addtotok\SYS@systempreamble{&\SYS@extracolstart##\SYS@extracolend    \hfil\null}% 
    \fi
    \SYS@addtotok\SYS@systempreamble{\cr\SYS@strutup}% 
  \fi
}
% ========= KEY DEFINITIONS =========
\newlength{\sys@width}%
\define@key{systeme}{vskip}{\def\sys@vskip{#1}}
\define@key{systeme}{width}{\setlength{\sys@width}{#1}}
% ========= KEY DEFAULTS =========
\setkeys{systeme}{vskip=1.2,width=0pt}%
\newcommand*{\SysOfEq}[2][,]{%
  \setkeys{systeme}{#1}% Set new keys
  \syslineskipcoeff{\sys@vskip}\setlength{\tabskip}{\dimexpr3pt+\sys@width\relax}% Use keys
  \systeme{#2}}% Typeset system
\makeatother
\begin{document}

\[
\syslineskipcoeff{1.2}\setlength{\tabskip}{3pt}
\systeme{
2x  +   y  +  3z  =  10,
 x  +   y  +   z  =   6,
 x  +  3y  +  2z  =  13}
\]

\[
  \SysOfEq{%
2x  +   y  +  3z  =  10,
 x  +   y  +   z  =   6,
 x  +  3y  +  2z  =  13}  
\]

\[
  \SysOfEq[width=1cm]{%
2x  +   y  +  3z  =  10,
 x  +   y  +   z  =   6,
 x  +  3y  +  2z  =  13}  
\]

\[
  \SysOfEq[width=5pt,vskip=2]{%
2x  +   y  +  3z  =  10,
 x  +   y  +   z  =   6,
 x  +  3y  +  2z  =  13}  
\]
\end{document}

The key-value definitions are provided by the keyval package.