3

I have produced the below macros for generating the custom acronym

\def\myacro#1[#2]#3{%
\newcounter{#1}%
\expandafter\edef\csname#1Acrshort\endcsname{#2}
\expandafter\edef\csname#1Acrlong\endcsname{#3 (#2)}
}%


\def\an#1{\stepcounter{#1}%
\ifnum\csname the#1\endcsname>1%
\csname#1Acrshort\endcsname%
\else%
\csname#1Acrlong\endcsname%
\fi
}

\myacro{cd}[CD]{Compact Disk}
\myacro{floppy}[Floppy]{Floppy Disk}

My TeX files is

\documentclass{book}

\begin{document}

This is a sample text \an{cd} This is a sample text \an{cd}.

\end{document}

My Question is when i'm removing the optional argument, i'm getting the the error message.

\myacro{cd}{Compact Disk}

Runaway argument?
{\@newctr {{cd}{Compact Disk} \myacro {floppy}}}{}\expandafter \edef \ETC.
! Paragraph ended before \myacro was complete.
<to be read again>
                   \par

Could you please advice. how to handle such cases. Thanks for your help in advance.

Saravanan.O
  • 595
  • 2
  • 5
  • 15

1 Answers1

2

The TeX primitive \def doesn't know the concept of an “optional argument”. The optional arguments are an abstraction that is implemented at a higher level (with \newcommand or \NewDocumentCommand or the like) which check for the specified delimiters and provide the base definition an appropriate default in case the optional argument is not passed by the user.

You can use LaTeX's \@ifnextchar to check for an optional argument there. In your case the definition of \myacro grabs the first argument and checks if the next character is a [. If it is, call the actual code in \@myacro and let it grab the argument in [...]. Otherwise you provide the \@myacro with the default for the optional argument. You have to make sure that whatever was in the <paremeter text> of the definition is found when TeX is looking for the arguments.

\documentclass{book}

\makeatletter
\def\myacro#1{%
  \@ifnextchar[%]
    {\@myacro{#1}}% If the next token is a [, read the argument
    {\@myacro{#1}[#1]}% otherwise pass #1 as default
  }
\def\@myacro#1[#2]#3{%
  \newcounter{#1}%
  \expandafter\edef\csname#1Acrshort\endcsname{#2}
  \expandafter\edef\csname#1Acrlong\endcsname{#3 (#2)}
}
\makeatother

\def\an#1{%
  \stepcounter{#1}%
  \ifnum\csname the#1\endcsname>1
    \csname#1Acrshort\endcsname
  \else
    \csname#1Acrlong\endcsname
  \fi
}

\myacro{cd}[CD]{Compact Disk}
\myacro{floppy}{Floppy Disk}

\begin{document}

This is a sample text \an{cd} This is a sample text \an{cd}.

This is a sample text \an{floppy} This is a sample text \an{floppy}.

\end{document}

Or you can use xparse's \NewDocumentCommand:

\documentclass{book}
\usepackage{xparse}

\NewDocumentCommand\myacro
  { m % mandatory
    O{#1} % optional whose default is the same as #1
    m } % mandatory again
  {%
    \newcounter{#1}%
    \expandafter\edef\csname#1Acrshort\endcsname{#2}
    \expandafter\edef\csname#1Acrlong\endcsname{#3 (#2)}
  }

\def\an#1{%
  \stepcounter{#1}%
  \ifnum\csname the#1\endcsname>1
    \csname#1Acrshort\endcsname
  \else
    \csname#1Acrlong\endcsname
  \fi
}

\myacro{cd}[CD]{Compact Disk}
\myacro{floppy}{Floppy Disk}

\begin{document}

This is a sample text \an{cd} This is a sample text \an{cd}.

This is a sample text \an{floppy} This is a sample text \an{floppy}.

\end{document}

LaTeX's \newcommand wouldn't work here because it requires the optional argument to be the first one.


A slightly different approach using property lists that doesn't consume a counter for each acronym and lets you have an expandable \an command:

\documentclass{book}
\usepackage{xparse}

\ExplSyntaxOn
\prop_new:N \g_saravanan_acro_prop
\NewDocumentCommand \myacro { m O{#1} m }
  {
    \prop_gput:Nnn \g_saravanan_acro_prop { #1~short } { #2 }
    \prop_gput:Nnn \g_saravanan_acro_prop { #1~long } { #3 }
    \prop_gput:Nnn \g_saravanan_acro_prop { #1~full } { #3~(#2) }
  }
\NewExpandableDocumentCommand\an{ O{short} m }
  { \prop_item:Nn \g_saravanan_acro_prop { #2~#1 } }
\ExplSyntaxOff

\myacro{cd}[CD]{Compact Disk}
\myacro{floppy}{Floppy Disk}

\begin{document}

This is a sample text \an[full]{cd} This is a sample text \an{cd}.

This is a sample text \an[full]{floppy} This is a sample text \an{floppy}.

\end{document}