next up previous contents
Next: Optional arguments Up: Writing Subroutines to Translate Previous: Commands without an argument   Contents


Commands with arguments

The previous example did not have any arguments, so let's try one with an argument. The mydate package described above is now going to be modified so that it defines the command \monthname which takes one argument--the number of the current month (from 1 to 12.) The command \today will be modified so that it uses the month name instead of a number. The LaTeX code in mydate.sty now looks like:

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{mydate}

\newcommand{\monthname}[1]{%
\ifcase#1
\or January%
\or February%
\or March%
\or April%
\or May%
\or June%
\or July%
\or August%
\or September%
\or October%
\or November%
\or December%
\fi}

\renewcommand{\today}{%
\number\year-\monthname{\month}-\number\day}

\endinput
LaTeX2HTML defines the array @Monthname="@Month,sort=Month,description=The month names in the currect language are stored in this array. Note that $Month[0] is empty, so subscripts effectively start from 1.@Month which contains the month names in the currently defined language, so the &do_cmd_monthname subroutine can use this, but first it needs to determine the month number which is passed as the argument. Recall that braces are replaced by markups with unique identifiers in the form $OPn$CP. This means that you need to search for these identifiers at the start of the string passed to the &do_cmd_monthname subroutine. Rather than having to remember the form of these identifiers, you can use the variable $next_pair_pr_rxname=$next_pair_pr_rx,sort=nextpairprrx,description=Regular expression used to extract the group at the start of $_ delimited by $OPn$CP. The contents of the group is given by $2, the unique identifier belonging to that group is given by $1.$next_pair_pr_rx which provides the correct regular expression, where $1 will contain the unique identifier, and $2 will contain the text found inside the set of braces corresponding to that identifier.

For example, suppose your LaTeX code looked something like:

\documentclass[a4paper]{article}

\usepackage{mydate}

\begin{document}
\monthname{1} is a very chilly month
in Britain.
\end{document}
then the argument passed to &do_cmd_monthname will be the string
<#4#>1<#4#> is a very chilly month
in Britain.
The Perl code
s/$next_pair_pr_rx/$month=$2;''/eo;
will set $month equal to $2, which in this case is simply 1. The value of the identifier in this instance is not necessary, but if you wanted to know it for some reason, you can add $id=$1. Note that if a match is found, the empty string '' will be substituted, which means the substring <#4#>1<#4#> will be removed from $_.

It is possible that the user may have omitted the braces around the argument to the command (e.g. \monthname 1), in which case you need to get the first character, and warn about the missing braces. This can be done using the &missing_bracesname=&missing_braces,sort=missingbraces,description=Generate a warning message and extract first character from $_.&missing_braces subroutine:

unless (s/$next_pair_pr_rx/$month=$2;''/eo)
{
   $month = &missing_braces;
}
or more succinctly:
$month = &missing_braces unless s/$next_pair_pr_rx/$month=$2;''/eo;
So the whole subroutine should look like:
sub do_cmd_monthname{
   local($_) = @_;
   local($month);

   $month = &missing_braces unless
                s/$next_pair_pr_rx/$month=$2;''/eo;

   $Month[$month] . $_;
}

The subroutine &do_cmd_today can now be modified so that it uses the \monthname command:

sub do_cmd_today{
   local($_) = @_;
   local($sec,$min,$hr,$day,$month,$year) = localtime(time);
   $year += 1900;
   $month++;

   local($id) = ++$global{'max_id'};

   join('-', 
        $year, 
        "\\monthname${OP}${id}${CP}$month${OP}${id}${CP}",
        $day) . $_;
}
Of course, it would be even easier to use $Month[$month]name="@Month,sort=Month,description=The month names in the currect language are stored in this array. Note that $Month[0] is empty, so subscripts effectively start from 1.$Month[$month] instead of
\\monthname${OP}${id}${CP}$month${OP}${id}${CP}
but this way illustrates the use of $OP, $CP and $global{'max_id'}name=$global{'max_id'},sort=global,description=This is the maximum number of unique identifiers.$global{'max_id'}.

The basic principle can be extended to commands with more than one argument. Each argument is dealt with in the same way. For example, suppose you have a command called, say \fmtdate that formats a specific date in a certain way, then this command would need to take three arguments representing the day, month and year. The LaTeX code might look something like:

\newcommand{\fmtdate}[3]{#3-#2-#1}
The Perl subroutine &do_cmd_fmtdate would then look something like:
sub do_cmd_fmtdate{
   local($_) = @_;
   local($day,$month,$year);
   
   $day = &missing_braces unless
             s/$next_pair_pr_rx/$day=$2;''/eo;
   
   $month = &missing_braces unless
             s/$next_pair_pr_rx/$month=$2;''/eo;
   
   $year = &missing_braces unless
             s/$next_pair_pr_rx/$year=$2;''/eo;

   join('-', $year, $month, $day) . $_;
}


next up previous contents
Next: Optional arguments Up: Writing Subroutines to Translate Previous: Commands without an argument   Contents
Dr Nicola L C Talbot 2005-06-10