5

I'm using the classic thesis style with the \graffito command (example here). How can I modify the command below to add some vertical spacing before the text which is set to a standard value by default but can be changed by including a parameter?

% Graffiti as in GKP's book "Concrete Mathematics"
% thanks to Lorenzo Pantieri and Enrico Gregorio
\def\graffito@setup{%
    \vspace{0.7em}
%   \slshape\footnotesize% this was due to \slhape in above book
   \itshape\footnotesize\leavevmode\color{Black}%
   \parindent=0pt \lineskip=0pt \lineskiplimit=0pt %
   \tolerance=2000 \hyphenpenalty=300 \exhyphenpenalty=300%
   \doublehyphendemerits=100000%
   \finalhyphendemerits=\doublehyphendemerits}

My first approach would be to add a \vspace{#1} into the beginning, but I'm not aware how to include (i) this parameter #1 into the definition; (ii) include a default value for the parameter. I also didn't managed to translate the code snippet below into a \newcommand definition which, as I am aware, supports default parameters.

  • 2
    Why not use \newcommand\graffito@setup[1][0.7em]{\vspace{#1}...} instead (since you use LaTeX syntax anyway)? Then you can call \graffito@setup[1em] to use something else than the default. – Skillmon Jan 15 at 11:49
  • @Skillmon Good idea, but I might have to switch frequently between the default and a custom offset. So rather than re-specifying the offset explicitly, I'd prefer to have a default setup that the command falls back to if no parameter is given. – Chris Jan 15 at 12:00
  • Also, I do not understand the @setup notation: how come that we define a \graffito@setup command which is later used as \graffito{text}? I'd appreciate some intuitions here, too. – Chris Jan 15 at 12:01
  • I need more information, can you create a complete MWE? I don't know what \graffito should do and how it is defined, what you want to do with it, and where your optional parameter should be. The easiest way to patch above's definition to include a changeable offset, is to define a length and change the definition to use that length: \newlength\mylength\setlength\mylength{.7em} and then \vspace{\mylength} instead of \vspace{0.7em}. To change it, just change the length. No argument hacking needed. – Skillmon Jan 15 at 12:26
  • 1
    The % after 300 and 10000 are definitely not mine. ;-) – egreg Jan 15 at 12:36
6

Just define \graffito with an optional argument:

\documentclass{article}
\usepackage{lipsum}

\makeatletter
\newcommand{\graffito}[2][0.7em]{%
  \marginpar
    [\graffito@setup{#1}\raggedleft\hspace{0pt}#2]
    {\graffito@setup{#1}\raggedright\hspace{0pt}#2}%
}
\newcommand\graffito@setup[1]{%
   \vspace{#1}%
   \parindent=0pt \lineskip=0pt \lineskiplimit=0pt
   \tolerance=2000 \hyphenpenalty=300 \exhyphenpenalty=300
   \doublehyphendemerits=100000
   \finalhyphendemerits=\doublehyphendemerits
   \itshape\footnotesize
   \leavevmode\color{Black}%
}
\makeatother

\begin{document}

This has a graffito\graffito{This is a standard graffito}
\lipsum[1][1-5]

This has a graffito\graffito[-0.7em]{This is a moved up graffito}
\lipsum[1][1-5]

This has a graffito\graffito[1cm]{This is a moved down graffito}
\lipsum[1][1-5]

\end{document}

enter image description here

Side note: the original code has % after 300 and 100000: they are wrong.

  • Great answer and mwe example appreciated for others who are not familiar with the command / style. – Chris Jan 15 at 14:17
  • Btw this only works for me (TexLive2018 on OSX) if I change 'Black' to 'black' and add \usepackage{xcolor} before. – Chris Jan 15 at 16:40
  • 1
    @Chris That might depend on the release of LaTeX you're using. Use black if that works for you. – egreg Jan 15 at 18:54
4

Since you're using LaTeX syntax anyway, you can use the LaTeX command \newcommand to set a default argument with: \newcommand\graffito@setup[1][0.7em]{\vspace{#1}...}. If you want to not use LaTeX syntax for educational purposes, you can do the following:

We need a first macro which checks whether the optional argument follows. For this we use \futurelet (definition made \protected because we need an assignment here):

\protected\def\mycmd{\futurelet\next\mycmd@a}

We need to check whether the next token is a bracket, if it is the next macro reads its argument, else we give it its default.

\def\mycmd@a
  {%
    \ifx[\next
      \afterelsefi{\mycmd@b}%
    \else
      \afterfi{\mycmd@b[0.7em]}%
    \fi
  }

Here I use the macros \afterelsefi and \afterfi for some logic branching. They eat their argument and put it after \fi.

\long\def\afterelsefi#1\else#2\fi{\fi#1}
\long\def\afterfi#1\fi{\fi#1}

Finally the last macro needed for this, this one is the one generating the output:

\long\def\mycmd@b[#1]%
  {%
    Argument was: \texttt{\detokenize{#1}}%
  }

Complete MWE:

\documentclass[]{article}

\makeatletter
\long\def\afterelsefi#1\else#2\fi{\fi#1}
\long\def\afterfi#1\fi{\fi#1}
\protected\def\mycmd{\futurelet\next\mycmd@a}
\def\mycmd@a
  {%
    \ifx[\next
      \afterelsefi{\mycmd@b}%
    \else
      \afterfi{\mycmd@b[0.7em]}%
    \fi
  }
\long\def\mycmd@b[#1]%
  {%
    Argument was: \texttt{\detokenize{#1}}%
  }
\makeatother

\begin{document}
\mycmd

\mycmd[1em]
\end{document}
  • Great elaborate response @skillmon, thanks very much. Would love to accept both answers but since this isn't possible, I go for the quickest one. – Chris Jan 15 at 14:16
  • @Chris quicker was mine, but egregs is the one solving your problem, so accepting his is fine. If an answer helps you and you want to say thank you, you might consider upvoting it, if you deem it worth it. – Skillmon Jan 15 at 14:20

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.