[Tex/LaTex] Introducing courtesy folding marks in moderncv

koma-scriptlettersmoderncv

I have a new idea but it seems I don't know how to realise… as always!

I am doing some experiments with moderncv, and I would like to introduce folding marks like in scrlttr2 (KOMA 2 Letter format) – possibly on the cover letter only, not in the CV pages.

I did the following: I created a copy of moderncv in my local package repository (on Mac with MacTex: ~/Library/textmf/tex/latex) and registered it (with sudo texhash).

Since I am not familiar with the (sometimes) convoluted LaTeX commands that go beyond the normal usage, I diligently copied all the commands from scrlttr2.cls featuring the word "fold" to the beginning of my copy of moderncv.cls, just after the \ProvidesClass{moderncv} expression (line 13). Then I tried to compile my copy of the moderncv template, getting a few errors due to some missing expression that was required by the code I pasted. I identified those expressions in scrlttr2.cls and copied them in my copy of moderncv.cls as well. I reiterated this process a few times, until I got stuck.
The code I added is the following:

\RequirePackage{keyval}
\newcommand*{\KOMA@key}{\define@key{KOMA}}
\newif\if@fold\@foldtrue
\KOMA@key{foldmarks}[true]{\@setif[@fold]{foldmarks}{#1}}
\newcommand*{\foldmarkson}{%
  \@ObsoleteCommand{\foldmarkson}{foldmarks=on}}
\newcommand*{\foldmarksoff}{%
  \@ObsoleteCommand{\foldmarksoff}{foldmarks=off}}
\newcommand*{\@newplength}[1]{%
  \@ifundefined{ltr@len@#1}{%
    \expandafter\let\csname ltr@len@#1\endcsname=\z@%
    }{%
    \ClassError{scrlttr2}{%
      pseudo-length \expandafter\string\csname ltr@len@#1\endcsname
      already defined%
      }{%
      You tried to define a new pseudo-length using
      \string\@newplength\MessageBreak
      which is already defined. Try another name or
      better\MessageBreak
      Don't use this KOMA-Script internal macro}
    }
  }
\@newplength{foldmarkhpos}
\@newplength{tfoldmarkvpos}
\@newplength{bfoldmarkvpos}
\newcommand*{\@foldmark}[2]{%
  \vskip #1%
  \vb@t@z{\rlap{\move@topl\hskip\useplength{foldmarkhpos}%
    \rule{#2}{.2pt}}}%
  \vskip -#1\ignorespaces%
}
\newcommand*{\@foldmarks}{%
  \if@fold%
    \typeout{Foldmarks: yes}%
    \move@topt
    \@foldmark{\useplength{tfoldmarkvpos}}{2mm}
    \@foldmark{.5\paperheight}{4mm}
    \@foldmark{\useplength{bfoldmarkvpos}}{2mm}
    \move@frompt
  \else
    \typeout{Foldmarks: no}%
  \fi%
}

I also changed \newcommand*{\opening}[1]{\def\@opening{#1}} into \newcommand*{\opening}[1]{\def\@foldmarks\@opening{#1}} since something similar was also happening in scrlttr2.cls.

Now, apart from a few instructions still referring to scrlttr2 (like \ClassError{scrlttr2}{% for instance), I get the following error when I compile:

This is pdfTeX, Version 3.1415926-2.5-1.40.14 (TeX Live 2013
Processing: ./template.tex
Document Class: moderncv 2013/04/29 v1.5.1 modern curriculum vitae and letter document class
LaTeX Font Warning: Font shape `OMS/qpl/m/n' undefined
Latex Error: ./template.tex:68 Undefined control sequence.
LaTeX Font Warning: Font shape `T1/lmss/sb/n' undefined
LaTeX Warning: Citation `book1' on page 3 undefined on input line 145.
LaTeX Font Warning: Some font shapes were not available, defaults substituted.
LaTeX Warning: There were undefined references.
Output written on template.pdf (3 pages, 216601 bytes).
Complete transcript is in template.log
Found 1 errors, and 5 warnings in 1 runs
/Users/stefano/Library/Application\ Support/TextMate/Managed/Bundles/LaTeX.tmbundle/Support/bin/latexmk.pl -pdf -f -r /tmp/latexmkrc "template.tex" exited with status 12

The complaining command is \makelettertitle, the command that takes care of the rendering of the letter opening. I tried to figure out what else to change, but it is beyond my understanding. Can someone please explain me what I am missing and how to proceed? Thanks.

Best Answer

We can try to hijack the values for the fold mark positions provided by KOMA-Script and draw them with TikZ. This should work with any document class, I think.

\documentclass[a4paper]{article}

\usepackage{tikz}

\makeatletter
  \def\loadfoldmarkdims#1{%
    \begingroup
      \let\LetterOptionNeedsPapersize\@gobbletwo
      \def\setkomavar{\@ifstar{\@gobbletwo}{\@gobbletwo}}%
      \def\scr@compatibility##1\relax{0>0\relax}%
      \def\@alignfrom{0}%
      \let\KOMAoptions\@gobble
      \let\newkomavar\@gobble
      \let\l@addto@macro\@gobbletwo
      \let\addtoreffields\@gobble
      \let\setkomafont\@gobbletwo
      \newcommand*{\@newplength}[1]{%
        \@ifundefined{ltr@len@##1}{%
          \expandafter\let\csname notscr@len@##1\endcsname=\z@%
        }{}%
      }%
      \newcommand*{\useplength}[1]{%
        \glueexpr \csname notscr@len@##1\endcsname\relax}%
      \newcommand*{\setlengthtoplength}[3][]{%
        \setlength{##2}{\useplength{##3}}%
        \setlength{##2}{##1##2}}
      \newcommand*{\@setplength}[3][]{%
        \begingroup%
          \setlength{\@tempskipa}{\glueexpr ##3\relax}%
          \setlength{\@tempskipa}{##1\@tempskipa}%
          \edef\@tempa{\endgroup\def\expandafter\noexpand\csname notscr@len@##2\endcsname{\the\@tempskipa}}%
        \@tempa
      }%
      \newcommand*{\addtolengthplength}[3][]{%
        \begingroup%
          \setlengthtoplength[{##1}]{\@tempskipa}{##3}%
          \edef\@tempa{\endgroup\noexpand\addtolength{##2}{\the\@tempskipa}}%
        \@tempa%
      }%
      \newcommand*{\@addtoplength}[3][]{%
        \begingroup%
          \setlength{\@tempskipa}{\glueexpr ##3\relax}%
          \setlength{\@tempskipa}{##1\@tempskipa}%
          \addtolengthplength{\@tempskipa}{##2}%
          \edef\@tempa{\endgroup\def\expandafter\noexpand\csname ltr@len@##2\endcsname{\the\@tempskipa}}%
        \@tempa%
      }%
      \@newplength{foldmarkhpos}%
      \@newplength{foldmarkvpos}%
      \@newplength{tfoldmarkvpos}%
      \@newplength{mfoldmarkvpos}%
      \@newplength{bfoldmarkvpos}%
      \@newplength{lfoldmarkhpos}%
      \@newplength{pfoldmarklength}%
      \@newplength{tfoldmarklength}%
      \@newplength{mfoldmarklength}%
      \@newplength{bfoldmarklength}%
      \@newplength{lfoldmarklength}%
      \@newplength{foldmarkthickness}%
      \@setplength{foldmarkthickness}{.2pt}%
      \input{#1.lco}%
      \def\@makeglobal##1{%
        \global\expandafter\let\csname @##1\expandafter\endcsname\csname notscr@len@##1\endcsname
      }%
      \@makeglobal{foldmarkhpos}%
      \@makeglobal{foldmarkvpos}%
      \@makeglobal{tfoldmarkvpos}%
      \@makeglobal{mfoldmarkvpos}%
      \@makeglobal{bfoldmarkvpos}%
      \@makeglobal{lfoldmarkhpos}%
      \@makeglobal{pfoldmarklength}%
      \@makeglobal{tfoldmarklength}%
      \@makeglobal{mfoldmarklength}%
      \@makeglobal{bfoldmarklength}%
      \@makeglobal{lfoldmarklength}%
      \@makeglobal{foldmarkthickness}%
    \endgroup
  }
  \loadfoldmarkdims{DIN}

  \def\foldmarkdim#1#2{%
    \csname @#1foldmark#2\endcsname
  }
  \def\setfoldmarkdim#1#2#3{%
    \expandafter\def\csname @#1foldmark#2\endcsname{#3}%
  }

  \def\@new@foldmarkif#1{%
    \expandafter\newif\csname if@#1foldmark\endcsname
    \csname @#1foldmarktrue\endcsname
  }
  \@new@foldmarkif{p}
  \@new@foldmarkif{t}
  \@new@foldmarkif{m}
  \@new@foldmarkif{b}
  \@new@foldmarkif{l}
  \def\foldmarkifenabled#1{%
    \csname if@#1foldmark\endcsname
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
  }
  \def\foldmarkenable#1{%
    \csname @#1foldmarktrue\endcsname
  }
  \def\foldmarkdisable#1{%
    \csname @#1foldmarkfalse\endcsname
  }

  \def\@patch@foldmarkdims{%
    \ifdim \foldmarkdim{p}{length}=\z@
      \setfoldmarkdim{p}{length}{4mm}%
    \fi
    \ifdim \foldmarkdim{t}{length}=\z@
      \setfoldmarkdim{t}{length}{2mm}%
    \fi
    \ifdim \foldmarkdim{m}{length}=\z@
      \setfoldmarkdim{m}{length}{2mm}%
    \fi
    \ifdim \foldmarkdim{b}{length}=\z@
      \setfoldmarkdim{b}{length}{2mm}%
    \fi
    \ifdim \foldmarkdim{l}{length}=\z@
      \setfoldmarkdim{l}{length}{4mm}%
    \fi
    \setfoldmarkdim{p}{vpos}{.5\paperheight}%
  }

  \newcommand\drawfoldmarks{%
    \begingroup
      \@patch@foldmarkdims
      \begin{tikzpicture}[overlay, remember picture, line width=\foldmarkdim{}{thickness}]
        \foreach \mark in {p, t, m, b} {
          \foldmarkifenabled{\mark}{
            \ifdim \foldmarkdim{\mark}{vpos}=\z@\else
              \draw
                (current page.north west) ++(\foldmarkdim{}{hpos},-\foldmarkdim{\mark}{vpos})
                -- +(\foldmarkdim{\mark}{length},0);
            \fi
          }{}
        }
        \foreach \mark in {l} {
          \foldmarkifenabled{\mark}{
            \ifdim \foldmarkdim{\mark}{hpos}=\z@\else
              \draw
                (current page.north west) ++(\foldmarkdim{\mark}{hpos},-\foldmarkdim{}{vpos})
                 -- +(0,-\foldmarkdim{\mark}{length});
             \fi
           }{}
         }
      \end{tikzpicture}
    \endgroup
  }
\makeatother

\begin{document}

\drawfoldmarks

\end{document}

Usage notes:

  • KOMA-Script needs to be installed in order to find the .lco files with the dimensions (or you can write your own).
  • You can load the dimensions using \loadfoldmarkdims{<filename>}. I called \loadfoldmarkdims{DIN} in to provide some default values. This command is a bit hacky, since I just disabled all commands used in the .lco file that I do not care about. I successfully tested it with all the .lco files shipped with KOMA-Script except visualize.lco (which should not matter).
  • You can enable and disable fold marks with \foldmarkenable{<mark>} and \foldmarkdisable{<mark>}, where <mark> is one of p, t, m, b and l. By default, all are enabled.
  • You can manually set the fold mark dimensions using \setfoldmarkdim{<mark>}{<dim>}{<value>}, where <mark> is as above or empty and <dim> is a matching value of hpos, vpos, length or thickness.
  • The rules laid out in section 22.1.1 ("Fold Marks") of the KOMA-Script manual apply.
  • Put \drawfoldmarks on any page where you want fold marks.