6

I am trying to make a signature block macro that accepts a variable number of text variables so that I can add or subtract the text without using empty fields "{}" as arguments.

\sigblock{0}{2}{Notary Public} produces:

enter image description here

and,

\sigblock{0}{3}{Notary Public}{At Large}

produces:

enter image description here

In the macros the first two variables are horizontal placement of a line and length of the line, the rest of the variables are text.

I tried this:

 \documentclass{article}
 \usepackage{ifthen}

\def\sigblock#1#2#3#4% Defined 4 arguments%
   {\singlespacing{\vbox{\vskip.75in\noindent\hskip#1in%
{\hbox to #2in{\leaders\hbox to 0.00625in{\hfil.\hfil}\hfill}}}%
    \par\noindent\hskip#1in#3\par\noindent\hskip#1in#4}}

\def\sigblockB#1#2#3% Defined 3 arguments%
{\singlespacing{\vbox{\vskip.75in\noindent\hskip#1in%
{\hbox to #2in{\leaders\hbox to 0.00625in{\hfil.\hfil}\hfill}}}%
    \par\noindent\hskip#1in#3}}

\ifthenelse{\equal{%
        \sigblock}{#1}{#2}{#3}}%
{\renewcommand{\sigblockB}{%
        \sigblock%
                    }}

\begin{document}

\sigblock{0}{3}{Notary Public}{At Large}

\sigblock{0}{3}{Notary Public}

\sigblockB{0}{3}{Notary Public}

\end{document}

Which, when compiled with lualatex produced:

enter image description here

Along with plenty of errors in the log file. In my MWE I tried using \renewcommand to replace \sigblock with \sigblockB. It did occur to me that there might be a solution involving \let. A solution that would "scale" to allow additional lines of text would be best.

When I fill out a signature block, I often have to cut and paste information. I personally find a series of brackets to be easier to do this with in the first instance and then later helpful in proof reading.

I realize that my question reflects my ignorance on how variables work. Both an explanation of what is fundamentally wrong with my attempt, and a solution, would be greatly appreciated.

Related: Creating a right aligned signature block

5
  • What is \ifthenelse{\equal{\...} test to do? That looks strange to me
    – user31729
    Apr 20 '16 at 17:05
  • Are you open to xparse and nice optional arguments or a key-value syntax?
    – user31729
    Apr 20 '16 at 17:07
  • Thanks for commenting, I am trying to test whether the variable is being used with 3 arguments, and if so then substitute \sigblock with \sigblockB rather than having to write \sigblock{0}{3}{Notary Public}{} If at all possible I would like to keep the syntax of using the macro as \sigblock{}{}...
    – A Feldman
    Apr 20 '16 at 17:08
  • I don't think equal is correct 'tool' for this
    – user31729
    Apr 20 '16 at 17:08
  • Related: tex.stackexchange.com/q/254303/21930
    – Manuel
    Apr 20 '16 at 17:33
2

Though I recommend to use the answer from @egreg here is a way to implement what you are looking for using \@ifnextchar. The idea is that \sigblock prepares everything until it comes to processing the lines beneath the signature field. Then \sigblock@ is invoked which will set the next grouped argument as a line beneath the signature field and starts a recursion. The recursion terminates when there are no arguments left over:

\def\sigblock@#1#2{%
  \par\hskip#1in#2
  \@ifnextchar\bgroup{\sigblock@{#1}}\endgroup
}

output1_cut output2_cut output3_cut

\documentclass{article}
\usepackage{lipsum}
\usepackage[doublespacing]{setspace}%doublespacing is active for testing purposes

\makeatletter
\def\sigblock#1#2#3{%
  \begingroup
  \singlespacing
  \parindent\z@
  \vskip.75in
  \vbox{%
    \hskip#1in%
    \hbox to #2in{%
      \leaders\hbox to 0.00625in{\hfil.\hfil}\hfill
    }
  }%
  \sigblock@{#1}{#3}
}
\def\sigblock@#1#2{%
  \par\hskip#1in#2\par
  \@ifnextchar\bgroup{\sigblock@{#1}}\endgroup
}
\makeatother


\begin{document}
\sigblock{0}{3}{Notary Public}{At Large}{At Large}{At Large}{At Large}{At Large}
\lipsum
\end{document}

Note. As the extra lines are optional you might want to write \sigblock{0}{3}{Notary Public}[At Large]... sticking to the standard interface design with brackets denoting optional arguments. In this case you would define:

\def\sigblock#1#2#3{%
  \begingroup
  \singlespacing
  \parindent\z@
  \vskip.75in
  \vbox{%
    \hskip#1in%
    \hbox to #2in{%
      \leaders\hbox to 0.00625in{\hfil.\hfil}\hfill
    }
  }%
  \sigblock@{#1}[#3]
}
\def\sigblock@#1[#2]{%
  \par\hskip#1in#2\par
  \@ifnextchar[{\sigblock@{#1}}\endgroup
}
2
  • Ruben thank you for this, very elegant, answer. I plus+ all of the answers, they all were great. This one addressed exactly what I was asking in a very clean, clear way.
    – A Feldman
    Apr 22 '16 at 14:07
  • Also, this answer works using `\\` for paragraphs.
    – A Feldman
    May 14 '16 at 18:02
7

You're overthinking: the tool is already there, namely tabular.

\documentclass{article}

\newcommand{\sigblock}[3]{%
  \par\vspace{\medskipamount}\noindent
  \hspace*{#1in}\makebox[#2in]{\hrulefill}\\*[.2ex]
  \hspace*{#1in}%
  \begin{tabular}{@{}l@{}}
  #3
  \end{tabular}%
}

\begin{document}

\sigblock{0}{3}{Notary Public \\ At Large}

\sigblock{0}{3}{Notary Public}

\sigblock{1}{3}{Notary Public \\ At Large \\ Again \\ What else?}

\end{document}

enter image description here

If you need to add \singlespacing, remember it is not a command with an argument, but a declaration. So you should have

\newcommand{\sigblock}[3]{%
  \par{\singlespacing\vspace{\medskipamount}\noindent
  \hspace*{#1in}\makebox[#2in]{\hrulefill}\\*[.2ex]
  \hspace*{#1in}%
  \begin{tabular}{@{}l@{}}
  #3
  \end{tabular}%
  \par}%
}
2

By trying to solve this problem I've come up with a possibly interesting macro, so I want to share it here. This macro is called \vardef and allows us to define a macro which can receive a variable number of arguments (any number, not limited to 9 arguments) enclosed in curly brackets.

Inside the definition of a \vardefined macro one can use the macro \NUMARGS for retrieving the number of arguments the macro receives when it is "executed"; and one can use the macros \ARG1, \ARG2, \ARG3,... for retrieving the arguments of the macro (if they exist).

If, for example, one \vardefines the macro \mymacro as follows,

\newcount\tmpnum
\vardef\mymacro{This macro is being used with \NUMARGS{} arguments.
  They are: \ifnum\NUMARGS>0 \tmpnum=1 \loop \ARG{\the\tmpnum}
  \ifnum\NUMARGS>\tmpnum \advance\tmpnum by 1 \repeat\fi}

then the "execution" of \mymacro{first}{second}{third} gives the "output"

 This macro is being used with 3 arguments. They are: first second third

and the "execution" of \mymacro{first}{second}{third}{fourth}{fifth} gives

This macro is being used with 5 arguments. They are: first second third fourth fifth

This is how \vardef is defined:

% Firstly we create a new counter to store the number 
% of the current argument that is being read. 
% Arguments start from 1, so we initially set it to 1.
\newcount\vardefnum
\vardefnum=1

% \vardef receives two arguments: the first is the name of
% the macro to be \vardef-ined and the second is its definition.
\def\vardef#1#2{%
  % We momentaneously store the definition in a macro called
  % \vardefinition for later use.
  \def\vardefinition{#2}
  % Now we actually define our control sequence.  We define it
  % basically to be \grab (a macro whose purpose is explained below).
  \def#1{%
    % Before actually grabbing arguments with \grab, we give
    % an empty useless definition to \invardef so  that we will be able
    % later to know that we are in the defining code  of a
    % \vardef-ined macro (we will see why later).
    \def\invardef{}%
    \grab}}

% The purpose of \grab is to collect and store all the arguments
% that follow him and to finally actually "execute" the code we
% previously stored in \vardefinition.
% To do that, \grab starts by saving into \next the first token
% after him. Then he passes the job to his sister \grabA.
\def\grab{\futurelet\next\grabA}

% \grabA checks if the token stored in \next is an opening curly
% brackets (or, more properly, a \bgroup). If so, she invokes
% the macro \storeargs. Otherwise she defines the number of
% arguments \numvarargs collected by now to be one less than
% \vardefnum;  then she expands \vardefinition and removes
% the traces of her job by calling \clearvardef.
\def\grabA{\ifx\next\bgroup\storearg\else\advance\vardefnum by-1
  \edef\numvarargs{\the\vardefnum}\vardefinition\clearvardef\fi}

% \clearvardef undefines \invardef (because now we are exiting
% the argument of the \vardef-ined macro) and restores the
% \vardefnum counter.
\def\clearvardef{\let\invardef\undefined \vardefnum=1\relax}

% \storearg, when is invoked by \grabA, finds on its way the
% sequence \else\advance\vardefnum ... \clearvardef\fi. He wants
% to get rid of it to be able to see what's behind it:  so he
% eats all of it using his first argument (the argument #1).
% Now \storearg sees after him an argument enclosed in curly
% brackets. So he puts it in his second argument (the argument #2).
% Next, to make TeX happy, \storearg has to regurgitate
% the \fi he has previously eaten up. After that he defines a new
% control sequence that stores his second argument he has just
% collected. The name of this control sequence starts with
% 'vararg' and ends with the number present in \vardefnum at that
% moment. Finally \storearg increments \vardefnum and takes a rest
% by giving the job back to \grab.
\def\storearg#1\fi#2{\fi
  \expandafter\def\csname vararg\the\vardefnum\endcsname{#2}%
  \advance\vardefnum by 1\grab}


% The following two macros, \ARG and \NUMARGS, are the user
% interface for actually using inside the \vardef-inition the
% (variable number of) arguments.  Ckecking if \invardef is
% defined, they can know if they are called inside the
% \vardef-inition of a macro, and they can throw an error message
% otherwise. What they do is quite self explanatory.
\def\ARG#1{\ifdefined\invardef\else\errmessage{%
  \string\ARG\space has meaning only inside a
  \string\vardef-ined macro.}\fi
  \ifnum#1<1\errmessage{The argument of \string\ARG\space
  must be greater than zero!}\fi
  \ifnum#1>\numvarargs\errmessage{\string\ARG#1 does not exist!}\fi
  \csname vararg#1\endcsname}

\def\NUMARGS{\ifdefined\invardef\numvarargs\else\errmessage{%
  \string\NUMARGS\space has meaning only inside a
  \string\vardef-ined macro.}\fi}

The solution to the asked question then is really simple: use \ARG1, \ARG2, \ARG3,... instead of #1, #2, #3,... and use \NUMARGS to check how many arguments have been passed to \sigblock.

\documentclass{article}
\usepackage{setspace}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% here goes the above definition of \vardef %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\vardef\sigblock{\singlespacing
  \vbox{\vskip.75in\noindent\hskip\ARG1in
  {\hbox to \ARG2in{\leaders\hbox to 0.00625in{\hfil.\hfil}\hfill}}\endgraf
  \noindent\hskip\ARG1in\ARG3
  \ifnum\NUMARGS=4\endgraf\noindent\hskip\ARG1 in\ARG4\fi}}

\begin{document}

\sigblock{0}{3}{Notary Public}{At Large}

\sigblock{0}{3}{Notary Public}

\end{document}

enter image description here

And now it is extremely easy to use any number of arguments in \sigblock.

NOTE: Differently from normal macros, in a \vardefined macro all arguments have to be enclosed in curly brackets and there can't be spaces between the closing brace of an argument and the opening brace of the following argument.

9
  • Please do add some comments to the code of \vardef. I am interested in understanding how it works.
    – A Feldman
    Apr 21 '16 at 13:15
  • @AFeldman Comments added :)
    – User
    Apr 21 '16 at 17:07
  • That way youre still limited to 4 arguments, even though you might drop the last one while using the command, i.e. what happens if you say \sigblock{0}{3}{Notary Public}{At Large}{foo}?
    – Ruben
    Apr 21 '16 at 17:21
  • @Ruben If you use \sigblock with more than four arguments than the last arguments get simply discarded. I don't know what the OP wants to do with the other arguments, so I wrote code only for up to four of them. But, if you want something that keeps doing the same for the other arguments, like in your answer, then you can simply define \sigblock to loop through all arguments as follows
    – User
    Apr 21 '16 at 17:42
  • \vardef\sigblock{\singlespacing \vbox{\vskip.75in\noindent\hskip\ARG1in {\hbox to \ARG2in{\leaders\hbox to 0.00625in{\hfil.\hfil}\hfill}} \newcount\tmpnum \tmpnum=3 \loop \endgraf\noindent\hskip\ARG1in\ARG{\the\tmpnum} \ifnum\NUMARGS>\tmpnum \advance\tmpnum by 1 \repeat}}
    – User
    Apr 21 '16 at 17:42
1

Here's a easy way with xparse and using an optional g argument, which allows to use an optional argument to be used with {...} group pair.

\documentclass{article}
\usepackage{setspace}
\usepackage{xparse}


\NewDocumentCommand{\sigblock}{mm+m+g}{%
\IfValueTF{#4}{%
  \singlespacing{\vbox{\vskip.75in\noindent\hskip#1in%
      {\hbox to #2in{\leaders\hbox to 0.00625in{\hfil.\hfil}\hfill}}}%
    \par\noindent\hskip#1in#3\par\noindent\hskip#1in#4}
}{%
  \singlespacing{\vbox{\vskip.75in\noindent\hskip#1in%
      {\hbox to #2in{\leaders\hbox to 0.00625in{\hfil.\hfil}\hfill}}}%
    \par\noindent\hskip#1in#3}%
}
}




\begin{document}

\sigblock{0}{3}{Notary Public}{At Large}

\sigblock{0}{3}{Notary Public}

\sigblock{0}{3}{Notary Public}

\end{document}
8
  • Thanks so much. If I wanted to extend this lets say starting with an additional text field, for a total of 5 arguments, so that I had 3 possibilities, how would it go?
    – A Feldman
    Apr 20 '16 at 17:15
  • @AFeldman: Use a comma separated list then -- but if I had known that you wanted such I thing I would not have wasted time with this.
    – user31729
    Apr 20 '16 at 17:17
  • I really appreciate your answer. I can see that my question is not clear on that point.
    – A Feldman
    Apr 20 '16 at 17:25
  • @AFeldman: The problem is: The more variables (you rather mean arguments) the more you get into troubles, besides the fact that you can't use more than 9 arguments (at least not without much efforts!) I suggest a list approach or a key-value syntax!
    – user31729
    Apr 20 '16 at 17:27
  • 1
    @AFeldman: Well, then have a look on the D or d argument specifier of xparse -- it allows to define your own pair of optional argument delimiters and with simplify the check which one is active (or was specified!)
    – user31729
    Apr 20 '16 at 17:59
1

Use a \Longstack.

\documentclass{article}
\documentclass{article}
\usepackage{stackengine,lipsum,setspace}
\setstackEOL{\cr}
\def\sigblock#1#2#3% Defined 3 arguments%
{\singlespacing{\vbox{\vskip.75in\noindent\hskip#1in%
{\hbox to #2in{\leaders\hbox to 0.00625in{\hfil.\hfil}\hfill}}}%
    \par\noindent\hskip#1in\Longstack[l]{#3}}}
\parindent 0pt
\begin{document}
\lipsum[1]

\sigblock{1}{2}{Notary Public\cr at Large}


\sigblock{0}{2.5}{Notary Public\cr at Large\cr State of Disorder}
\end{document}

enter image description here

0

Another answer from the perspective of "you don't need variable variables". This uses \long\def and adds a \vtop box to the material under the line.

\documentclass{article}
\usepackage{setspace}

\long\def\sigblockB#1#2#3%`\long\def` allows for paragraphs  
                         {
       \singlespacing 
       \vskip.75in\noindent\hskip#1in%
       \hbox to #2in{\leaders\hbox to 0.00625in{\hfil.\hfil}\hfill}%
       \par\noindent\hskip#1in%
       \vtop{\noindent#3}%
} 

\begin{document}

\sigblockB{0}{3}{Notary Public\\And then some\\And okay}    

\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.