56

Sometimes, I define new commands such as the following.

\newcommand{\comment}[1]{\textbf{#1}}
%\necommand{\comment}[1]{\emph{#1}} 

The above commands enable me to change the style of parts of my code all at once. If I want to generate both of the possible styles, I have to compile my LaTeX document two times each time modifying the source code to enable the desired style.

Is there a way to avoid the source code modification in such cases? That is, can I pass latex some command-line arguments so that I can choose which style to use based on that argument?

reprogrammer
  • 14,298
  • 16
  • 57
  • 93
  • 1
    See also [Passing parameters to a document](http://tex.stackexchange.com/questions/1492/passing-parameters-to-a-document) at tex.SX. – fbmd Feb 07 '13 at 07:08
  • Take a look on [Pandoc templates](https://pandoc.org/MANUAL.html#templates). It supports specifying keys in either the command or files: `-M KEY[=VAL], --metadata=KEY[:VAL]`. – AvidSeeker Apr 19 '23 at 20:03

4 Answers4

79

That is, can I pass latex some command-line arguments so that I can choose which style to use based on that argument?

Yes. Three options:

One

In your source file, write

\providecommand{\comment}[1]{\emph{#1}}% fallback definition

and then compile the LaTeX document ("myfile.tex") as

pdflatex (whatever options you need) "\newcommand\comment[1]{\textbf{#1}}\input{myfile}"

Two

Alternatively,

pdflatex "\let\ifmyflag\iftrue\input{myfile}"

and then have in the source

\ifcsname ifmyflag\endcsname\else
  \expandafter\let\csname ifmyflag\expandafter\endcsname
                  \csname iffalse\endcsname
\fi
...
\ifmyflag
  \newcommand\comment[1]{\emph{#1}}
\else
  \newcommand\comment[1]{\textbf{#1}}
\fi

Three

Or even

pdflatex "\def\myflag{}\input{myfile}"

with

\ifdefined\myflag
  \newcommand\comment[1]{\emph{#1}}
\else
  \newcommand\comment[1]{\textbf{#1}}
\fi

which is probably the shortest, albeit slightly fragile because you never know when a package might define \myflag behind your back.

Will Robertson
  • 62,540
  • 32
  • 99
  • 117
  • Can you do similar tricks with "latex" or these are specific to "pdflatex"? – reprogrammer Sep 23 '09 at 15:13
  • 1
    Can you elaborate on what the code starting with `\ifcsname` in the second option does? – Faheem Mitha Aug 16 '11 at 06:54
  • 1
    I do like your answer. Is there a way to use this approach with latexmk? – kuszi Sep 24 '13 at 14:50
  • 3
    With latexmk something like this works: `latexmk -pdf -pdflatex='pdflatex -interaction=nonstopmode -shell-escape "\newcommand{\pdfTitle}{MyTitle}\include{filename}"' filename.tex`. See also: [Passing parameters to a document](https://tex.stackexchange.com/questions/1492/passing-parameters-to-a-document) – Sr. Schneider Jan 14 '21 at 12:25
5

You should use Will's approaches when you need fairly flexible one-off options, like say changing the position line on your resume. If otoh you are producing the same selection of options over & over, then you should consider avoiding command line arguments, or working them into a build script or makefile.

I'll give two techniques for avoiding command line arguments :

Trick 1: If you're producing a fixed array of documents that must remain accessible, like your two styles example, then I'd recommend simply implementing Will's latex code inside another tex file, i.e. thesis.tex contains a \providecommand\comment[1]{\emph{#1}} and thesis-ugly.tex consists of \newcommand\comment[1]{\textbf{#1}} \input thesis.tex.

You must of course rerun tools like bibtex when using this technique, unless you symlink the intermediary files, ala ln -s thesis.aux thesis-ugly.aux and ln -s thesis.bbl thesis-ugly.bbl.

Trick 2: I found trick 1 awkward for changing document papersizes, so I wrote the following perl script, called simply papersize. The command papersize A4 teaching.tex modifies teaching.tex in place, and symlinks teaching.pdf to teaching-A4.pdf, so that running pdflatex teaching creates teaching-A4.pdf, but does not disturb the pre-existing teaching-letter.pdf and does not require rerunning bibtex teaching. It does obviously require rerunning pdflatex twice for documents with internal references.

#!/usr/bin/perl -i~ -n

BEGIN {
die "Usage: papersize letter/A4/etc. [filename]\n" if ($#ARGV < 0);
$SIZE = shift @ARGV;  @files=@ARGV;
$FLAG = "% paper size :: ";
}

if (/$FLAG(\w+)/) {
    if ($1 eq $SIZE) {
        s/^\% //;
    } else {
        s/^([^\%])/\% \1/;
    }
}
print $_;

END {
foreach (@files) {
    if (s/\.tex//) {
    $l = "$_-$SIZE.pdf";  $_ .= ".pdf";
    unlink($_) if (-l $_);
    symlink($l,$_) if (! -e $_);
} }
}

You must add the special comments % paper size :: ... to every file line that should be changed when you change the paper size.

\documentclass[letterpaper,11pt]{article}  % paper size :: letter
% \documentclass[a4paper,11pt]{article}  % paper size :: A4
\usepackage[text={6.5in,8.8in}]{geometry}  % paper size :: letter
% \usepackage[text={16.4cm,24.5cm}]{geometry}  % paper size :: A4

You could obviously work papersize into a build script or makefile too or modify the above script for .dvi files.. or generalize the script to other modifications.

Jeff Burdges
  • 4,204
  • 23
  • 46
1

This may not be the optimal solution for the situation in question (also a very old post), but I thought I'd present an alternative solution which was useful for me. It is simply to define the two commands in two different files, link a third file to the desired choice, and \input that third file. For example, define:

% in main.tex
\input{options}
% ...

.

% in option1.tex
\newcommand{\comment}[1]{\textbf{#1}}

.

% in option2.tex
\newcommand{\comment}[1]{\emph{#1}} 

Then to compile with option1, simply run:

> ln -s option1.tex options.tex && pdflatex main.tex

I prefer this because I am more comfortable with bash than obscure latex, have no problem with a proliferation of files (these can easily be organized in subdirectories), and have scripts compile my document anyway so this additional step comes at little cost.

Evan
  • 429
  • 4
  • 7
  • This will create race conditions though, and you will have to take care not to run these shell functions concurrently. Of course, one can add some locking, but that would become much too complicated. Anyhow, interesting workflow. – HappyFace Oct 05 '21 at 20:34
0

To provide my dissertation in both the required, ugly, tree wasting format, and a compact prettier version, I used ifthen an a kludge of make and sed that rewrote a bit of the header.

I think Will's approaches are all nicer.

Community
  • 1
  • 1
dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234