158

I compile most of my documents via Makefiles which take care of the bibliography, indexes, etc. Often I'd like to compile different versions from the same TeX file changing only small things (e.g. a beamer presentation plus a version with the handout option).

Is there any standard mechanism for passing parameters to the TeX file so that I can just type make handout to get the handout version in the above example?

5

15 Answers 15

30

I do this by using symlinks and testing the jobname. That is, I have a main (la)tex file and a bunch of symlinks to it. To find out which symlink was actually used, I examine the \jobname macro in my document and set certain parameters accordingly. In particular, if \jobname contains the string "handout", then the beamer class is called using the handout option. I do this by using a "wrapper" class which sets things up before calling the real class.

13
  • 6
    I like that way for its unix-yness, but it seems comparatively complicated. Also this probably would not work on Windows (not that I use Windows, but other people do).
    – Caramdir
    Aug 11, 2010 at 9:34
  • @Caramdir: I felt it was more of a tex-y solution than a unix-y one since apart from the symlinks, everything is happening inside TeX. I thought that Windows had an idea of a symlink, and I'd be surprised if TeX didn't set the jobname accordingly. Aug 11, 2010 at 10:34
  • By unix-y I meant that quite a lot of commands are actually symlinks on unix systems. For example latex and pdflatex are both just symlinks to pdftex in Tex Live. (My knowledge of the Windows filesystems mostly ends with FAT which didn't have real symlinks.)
    – Caramdir
    Aug 11, 2010 at 10:47
  • 19
    I am late to this party, but maybe I might point out that you can run latex --jobname=foo bar. No symlinks required. Oct 25, 2010 at 10:55
  • 1
    @AndrewStacey Could you please be more explicit on how you do this? How do you test for \jobname?
    – green diod
    Nov 27, 2021 at 15:46
174

Here's a hacky way, probably this is the wrong way :).

Instead of passing a filename, you can pass a sequence of commands. So in particular, you could do something like

pdflatex "\def\ishandout{1} \input{foo.tex}"

which defines the macro \ishandout (to be 1) and then reads foo.tex. And then, inside foo.tex, you can check whether \ishandout is defined:

\ifdefined\ishandout
  \documentclass[handout]{beamer}
\else
  \documentclass{beamer}
\fi
5
  • This would allow to emulate the ifdraft package when used with the word draft instead of handout, and specifying the appropriate lines inside the ifdefined, wouldn't it? Related question
    – Andrestand
    Oct 6, 2014 at 14:52
  • 4
    Best solution, all OS independent. Aug 10, 2015 at 13:46
  • 2
    Very nice solution, although having a foo-handout.tex that contains \def\ishandout{1} \input{foo.tex} in itself played out more nicely for me since I use latexmk. Aug 13, 2015 at 14:50
  • Will \ifdefined work on (for) any part of a (Xe)LaTeX document, or is it just for \documentclass{} options? Oct 10, 2015 at 16:24
  • Thank you! My standalone_verbatim.txt that renders text file given by \txtfile parameter offers nice "default usage" message, thanks to your answer! Here is source code for reference for other readers: gist.github.com/gwpl/5128cb3cd348c38492da59800b6ab3f2 May 9, 2016 at 20:47
46

I used to do it like in Neil Olver's answer, but found a better way:

Instead of:

pdflatex "\def\ishandout{1} \input{foo.tex}"

with a manual \ifdefined\ishandout statement, you can use:

pdflatex "\PassOptionsToClass{handout}{beamer}\input{foo}"

if you only want to set the a class option (use PassOptionsToPackage for package options).

In the case of beamer you can then also use the following statement in the main file:

\mode<handout>{%
    <code>
}

if you want to use different settings in that mode.

8
  • Interesting approach. I found PassOptionsToPackage in my ancient copy of Kopka and Daly, Third Edn, pg 334. It is however not that clear what this does. Does it override whatever option the package has, if an option is set? I tried it with the changes package. It seemed to work. K&D said I needed to use it with \RequirePackage, but I just used \usepackage{changes} and it still seemed to work. It there any documentation for this option online? Aug 14, 2011 at 18:07
  • Never mind, a Google search comes up with some stuff. In particular, tex.ac.uk/cgi-bin/texfaq2html?label=optionclash seems quite helpful. Aug 14, 2011 at 18:19
  • I'm unclear if this approach works with a arbitrary \newif\iffoo; \iffoo [...] \else [...] fi. What is the class or package in this case? Aug 14, 2011 at 18:59
  • 2
    \PassOptionsToPackage passes the given options to the package if the package is loaded afterwards (and wasn't loaded beforehand). This solution is more of less beamer specific. It works only if the setting you want to pass to a document is a class or package option. Aug 14, 2011 at 19:11
  • 1
    This solution hasn't been upvoted enough! Thanks, Martin.
    – jub0bs
    Nov 18, 2013 at 16:37
36

Have the target in your Makefile clobber a file that is \input by your Latex document, which, say, sets or resets a \newif conditional.

For example, let the Makefile run echo "\handouttrue">flags.tex; latex manuscript on the handout goal. Then manuscript.tex might begin:

\newif\ifhandout
\input{flags}
\documentclass...

in document:

\ifhandout
...
\else
...
\fi
1
  • This solution is so good and so underrated.
    – Alberto
    Nov 9, 2020 at 13:46
25

LuaTeX anyone? Inside the document, you can access the command line arguments through the arg table:

%luaargs.tex
\documentclass{article}

\begin{document}

Document args were:

\begin{description}

  \directlua{
    if not (arg == nil) then
      for i,v in pairs(arg) do
        tex.print("\string\\item[" .. i .. "]" .. v)
      end
    end
  }

\end{description}
\end{document}

The result of:

lualatex luaargs.tex foo bar bam biz

Is:

List of args passed to LuaLaTeX

3
  • 2
    You should consider using something like tex.tprint({ "\string\\item["}, {-2, i}, {"]"}, {-2, v}) for the print routine, as funny command line arguments result in funny output. - I know that this doesn't affect the (nice) given solution.
    – topskip
    May 23, 2011 at 13:06
  • For reference, @topskip 's suggestion involves setting n to -2 in tex.print(<number> n, <string> s, ...), where the docs explain: "If n is −2, [...] all category codes are 12 (other) except for the space character, that has category code 10 (space)." For example, this allows to print underscores without requiring math mode ("Missing $ inserted."). Otherwise, tex.write can be used for the same n = -2 effect.
    – Alex Povel
    Oct 29, 2020 at 14:57
  • Note: in addition to arg there's also arguments. There appears to be some difference, see discussion in tex.stackexchange.com/questions/388326/…
    – user202729
    Jul 8, 2022 at 5:29
22

Just for fun: instead of giving the arguments on the command-line before the filename, we can do the opposite. This allows a more natural syntax for arguments (which don't have to be TeX code like \def\flag{1}). Used as pdflatex file argument. The file is opened, \CommandLineArg is not yet defined, so TeX sees \endinput, and decides to stop reading that file at the end of the current line. The \expandafter expand the \fi, and expand beyond the end of the file (which has occured because of \endinput), to avoid some 'runaway argument' error. Then the file is input again with the flag set. In this second reading, \ifdefined is true, and \endinput is never read, so TeX happily continues with the main part of the file.

\def\ReadCommandLineArgI{\begingroup
  % \def\do##1{\catcode`##1=12 }\dospecials % uncomment this to get just characters (no macros)
  \futurelet\next\ReadCommandLineArgII}
\def\ReadCommandLineArgII{\endlinechar=13\catcode13=2\relax
  \expandafter\ReadCommandLineArgIII\expandafter{\iffalse}\fi}
\long\def\ReadCommandLineArgIII#1{\endgroup
  \long\def\CommandLineArg{#1}\input{\jobname}}
\unless\ifdefined\CommandLineArg\endinput\expandafter\ReadCommandLineArgI\fi

\documentclass{article}
\begin{document}
The formula is \CommandLineArg.
\end{document}

EDIT (May 2023): Based on a suggestion of user202729, I made the code more robust, it will grab everything on the command line (up to the first ^^M if the user is devious enough to put that in their command line) and store it into \CommandLineArg. This still does not work (errors/asks for more input) if there was no command line argument.

9
  • It works, and it can even handle more command line options, but it is not easy to understand or manipulate (not straightforward for people who are less familiar with LaTeX)
    – emem
    Aug 5, 2014 at 12:29
  • I do like this solution, that's almost what I would need, uo to one point. If I pass a parameter, it works fine. If I do not pass any parameter, it stops with a tex prompt *. Could you be so kind to modify this solution to handle the case where no parametre is passed? Thanks in advance...
    – Gherardo
    Jul 31, 2018 at 7:11
  • 1
    With some experiment I determine that an untokenized input character ^^M is used to terminate the argument, so that can be used to solve the situation where no argument is passed. (first used in tex.stackexchange.com/a/672229/250119) Also if it happens that the command-line argument starts with something expandable the \expandafter will have side-effect, \noexpand is safer, but this is even more academical...
    – user202729
    May 27 at 15:18
  • 1
    It's always exactly ^^M regardless of endlinechar though. (curiously)
    – user202729
    May 28 at 13:57
  • 1
    Very curious indeed. I've fixed that by setting \endlinechar=13, to be future-proof in case this bug is fixed (or differs between engines). May 28 at 14:12
16

I know that your question is focused on LaTeX. I just want to mention that ConTeXt provides such an option. You can use

context --mode=handout filename

to enable handout mode. See ConTeXt wiki for details

1
  • 2
    You are right, I'm most interested in a solution for LaTeX. But it is useful to know that it can easily be done with ConTeXt. I guess at some point I should take a closer look at ConTeXt.
    – Caramdir
    Aug 10, 2010 at 17:41
9

What ConTeXt does is, in simplified form, something like this:

# Makefile rule
handout:
      echo "\\RequirePackage[handout]{beamer}" > myfile-options.tex
      echo "\\endinput" >> myfile-options.tex
      pdflatex myfile
      rm myfile-options.tex

Where myfile.tex (loads a document class that ...) starts with

\InputIfFileExists{\jobname-options.tex}

You can then adjust the Makefile rule to put whatever you like in the options file.

1
  • ... which is the same trick Charles Stewart just posted ... Aug 10, 2010 at 18:41
7

If you are using Rubber to compile your documents, the following solution seems to work very well:

  • Put almost everything in main.tex.

  • Create files like slides.tex, handout.tex, etc. These are short files contain the parts that are different between the two versions, followed by \input{main}. For example, they may contain \documentclass with different options. Or they may load a different set of packages. Or they may define the same macro in two different ways, etc. These files may also contain rubber directives in comments.

  • Then I can simply run rubber -Wall slides.tex handout.tex and I will have up-to-date versions of both slides.pdf and handout.pdf. Or just rubber -Wall handout.tex if I don't need the slides.

You don't need to do any scripting or write complicated Makefiles. In many cases, you don't even need to use any \if... commands. Instead of defining a flag and doing something depending on the flag in main.tex, you can do the right thing directly in slides.tex and handout.tex. For example:

  • slides.tex:

    \documentclass{beamer}
    \input{main}
    
  • handout.tex:

    \documentclass[handout]{beamer}
    \input{main}
    

You can also re-use these files in different projects; just drop in a different main.tex.

3

Update: I have elaborated on the technique below in a recent (2020) TUGboat article.


My solution is a bit unique: docstrip. Instead of my master file being a .tex file, it's a docstrip file with .dtx extension. The header for each file is the docstrip \generate command, and the rest of the file uses docstrip's %<tag> mechanism to conditionally include/exclude stuff. For example (sorry, this isn't very minimal):

%<*driver>
\input docstrip.tex
\newwrite\configfile
\immediate\openout\configfile=config.def
\immediate\write\configfile{\string\def\string\rootjobname{\jobname}}
\immediate\closeout\configfile
\askforoverwritefalse
\generate{\file{\jobname.tex}{\from{\jobname.dtx}{source}}
          \file{\jobname_slides.tex}{\from{\jobname.dtx}{metadata,slides}}
          \file{\jobname_lp.tex}{\from{\jobname.dtx}{metadata,article}}          
          \file{\jobname_handout.tex}{\from{\jobname.dtx}{metadata,slides,handout}}        
          \file{\jobname_ws.tex}{\from{\jobname.dtx}{metadata,worksheet}}
          \file{\jobname_ws-sol.tex}{\from{\jobname.dtx}{metadata,worksheet,solutions}}
}
\endbatchfile
%</driver>
%<*metadata>
\input config.def
\let\oldrootjobname=\rootjobname
% Change these!
\def\longtitle{Section 3.7 \\ Indeterminate Forms and L'H\^opital's Rule}
\def\shorttitle{L'H\^opital's Rule}
\def\longcoursename{V63.0121.002.2010Su, Calculus I}
\def\shortcoursename{V63.0121, Calculus I}
%</metadata>
\author{\longcoursename}
%<*slides>
\documentclass[ignorenonframetext,
%<handout>handout
]{beamer} 
\usepackage[tikz,beamerpresentation]{V63-0121-2010Su}
\author[\shortcoursename]{\longcoursename}
\title[\shorttitle]{\longtitle}
%<*handout>
\usepackage{pgfpages}
\usepackage{handoutWithNotes}
\pgfpagesuselayout{3 on 1 with notes}[letterpaper]
%</handout>
%</slides>
%<*article>
\documentclass{article}
\usepackage{beamerarticle} 
\usepackage[tikz,
]{V63-0121-2010Su}
\title{\longtitle}
%</article>
%<*worksheet>
\documentclass{article}
\title{\longtitle}
\usepackage[worksheet,tikz,
%<solutions>solutions,
]{V63-0121-2010Su}
\author{\shortcoursename}
\date{Summer 2010}
%</worksheet>
%<*source>
\date{June 7, 2010}
% ... beamer slides ...        
\end{document}
%</source> 
%<*article>
\usepackage{beamerarticle} 
\setjobnamebeamerversion{\rootjobname_slides} 
%</article>
%<*slides|article>
\input{\rootjobname_\secnum.tex} 
%</slides|article>
%<*worksheet>
\begin{document}
\maketitle
% worksheet material ...
\end{document}
%</worksheet>

If you tex or latex the file foo.dtx, the individual files foo_slides.tex, foo_handout.tex, foo_lp.tex (for lesson plan, my personal notes), foo_ws.tex (worksheet), foo_ws-sol.tex (worksheet solutions) are all generated. Then you tex or latex whichever of these you want to produce.

Advantages of this method are that copying and reusing the file in the next semester involve copying a single file and editing. It's as portable as any .tex file—no extra utility or scripting language needed. The produced files don't have to be compiled with anything other than tex either. You get one document:one file which makes it easier to know what's in a document by its file name.

Disadvantages are that it's kinda crufty, and some people may not like running TeX on two files every time they want to preview something they are editing. With TeXShop this is actually pretty easy because you can open files for preview, which means you only see the pdf and not the source. So I edit the .dtx file, open the derivative .tex file for preview, and typeset the .dtx and derivative .pdf in a single sequence of keys. Works for me.

2

I propose a solution based on LaTeX3's l3keys package. It is more verbose in your .tex file than other solutions proposed here, but rather readable once you understand a bit the LaTeX3 programming conventions, and relatively nice on the “user end” (the command line or Makefile, etc., where you pass parameters to your LaTeX document). But really, the main advantages I see compared to other methods given here are:

  • very expressive, flexible and extensible;
  • the LaTeX3 kernel does all the boring parsing work for you, so end users are provided with easy to understand error messages if they pass unrecognized options or invalid values for an option.

Enough marketing, here is a relatively minimal example. :) In the end, this example just shows how to check the values of recognized options, without actually doing what the option (name, value) pairs suggest. This is in order to keep this first example not too long, despite all the comments I included. Later in this message, I'll include an expanded version that does interesting things with the options passed on the command line. So, the minimal example:

\documentclass{article}
\usepackage{expl3}

% TeX booleans start out as false.
\newif\ifMyScreenOutput
\newif\ifMyFullScreenOutput

% What follows uses LaTeX3 syntax.
\ExplSyntaxOn

% LaTeX3 bools start out as false too.
\bool_new:N \g_MyDocParams_screenOutput_bool
\bool_new:N \g_MyDocParams_fullScreen_bool

% Our LaTeX3 error message(s) for the option list parser (l10n-ready)
\msg_new:nnnn { MyDocParams } { unknown-choice-for-option }
  {
    Invalid~value~for~option~\exp_not:n {'#1'}:~\exp_not:n {'#3'}~
    (valid~choices~are~\exp_not:n {#2})
  }
  { You~may~optionally~put~a~more~verbose~message~here. }

% Option definitions for our pseudo-package 'MyDocParams' (this document). See
% l3keys in interface3.pdf as found at [1].
%
%   [1] https://ctan.org/pkg/l3kernel
\keys_define:nn { MyDocParams }
  {
    % First accepted key: 'outputType'. It takes an optional value among a
    % fixed, limited number of choices, as defined next.
    outputType .choice:,
    outputType / paper .code:n = {     % The first such value is 'paper'.
      \bool_gset_false:N \g_MyDocParams_screenOutput_bool },
    outputType / screen .code:n = {    % The second one is 'screen'.
      \bool_gset_true:N \g_MyDocParams_screenOutput_bool },
    outputType .initial:n = { paper }, % Default is 'paper'
    outputType / unknown .code:n = {   % Run this when passed an invalid value.
      \msg_error:nnxxx { MyDocParams } { unknown-choice-for-option }
        { outputType }                 % name of the choice key
        { 'paper'~and~'screen' }       % valid choices
        { \exp_not:n {#1} }            % invalid choice given
    },

    % Second accepted key: 'fullScreen'. It takes a boolean value.
    fullScreen .bool_gset:N = \g_MyDocParams_fullScreen_bool,
    fullScreen .initial:n = { false }, % the default is false
    % Used when the key is passed with no value ('fullScreen' as opposed to
    % 'fullScreen=true' or 'fullScreen=false').
    fullScreen .default:n = { true }
  }

% The option values may be set from the command line by means of the
% \MyDocParams macro, which may be defined this way before \input{}ing this
% file. For the precise option syntax, see l3keys in interface3.pdf[1].
%
%   \newcommand{\MyDocParams}{
%       outputType = screen,
%       fullScreen = false
%   }
%
% Since we already set defaults above with \keys_define:nn, no need to set
% any here.
\providecommand{\MyDocParams}{}

% This is where keys are set from the point of view of l3keys, and the action
% associated with each option set is carried out. In order to obtain the
% option list, we expand once ('o') the second argument of \keys_set:no,
% namely the \MyDocParams token.
\keys_set:no { MyDocParams } { \MyDocParams }

% Finally, convert our LaTeX3 booleans to \ifFooBar TeX conditionals. This is
% more or less needed, because control sequences such as
% \g_MyDocParams_screenOutput_bool will be difficult to enter in the main part
% of the document without using \ExplSyntaxOn ... \ExplSyntaxOff every time,
% which would be quite ugly. Of course, instead of the TeX conditionals, one
% could use booleans from the 'ifthen' or 'etoolbox' packages (see below).
\bool_if:NT \g_MyDocParams_screenOutput_bool
  { \MyScreenOutputtrue }
\bool_if:NT \g_MyDocParams_fullScreen_bool
  { \MyFullScreenOutputtrue }

\ExplSyntaxOff

\begin{document}
\ifMyScreenOutput
  Screen output selected
\else
  Paper output selected
\fi

\ifMyFullScreenOutput
  Full screen mode selected
\else
  Full screen mode not selected
\fi
\end{document}

% In order to use etoolbox's toggle macros instead of TeX's
% \ifFooBar ... \else ... \fi conditionals, one would use syntax like this:

% \usepackage{etoolbox}
%
% [...]
%
% \ExplSyntaxOn
%
% \newtoggle { myScreenOutput }
% \newtoggle { myFullScreenOutput }

% \bool_if:NT \g_MyDocParams_screenOutput_bool
%   { \toggletrue { myScreenOutput } }
% \bool_if:NT \g_MyDocParams_fullScreen_bool
%   { \toggletrue { myFullScreenOutput } }
%
% \ExplSyntaxOff
%
% [...]                 % What follows could be in the document body
%
% \iftoggle{myScreenOutput}{<code for true>}{<code for false>}
% \iftoggle{myFullScreenOutput}{<code for true>}{<code for false>}

Sample output for the print, screen and fullscreen variants
enter image description here enter image description here enter image description here

So, this document accepts two parameters:

  • outputType=paper or outputType=screen (defaults to paper);
  • fullScreen=true or fullScreen=false (defaults to false).

and you can pass them this way (I'll assume you saved the TeX file under the name parametrized_doc.tex):

pdflatex '\newcommand{\MyDocParams}{outputType=screen,fullScreen=false}' \
         '\input{parametrized_doc.tex}'

It's also possible to use \def instead of \newcommand, to put spaces around parameters (see l3keys in interface3.pdf), to use PGF-style hierarchical option names, to gather all the \newcommand{\MyDocParams}{...}\input{parametrized_doc.tex} as one argument to the latex|pdflatex|lualatex|xelatex program called, etc.

With the following Makefile, you may call make print, make screen or make fullscreen in order to build parametrized_doc.tex with either of the three meaningful combinations of our two options, and just make to build all three documents with one command. This Makefile uses the --jobname option mentioned above (thanks Harald) in order to produce parametrized_doc-{print,screen,fullscreen}.pdf from the same parametrized_doc.tex file, depending on the chosen variant as passed to make (no copying, renaming nor symlinking of the .tex file).

Beware: simply copying and pasting the following code block won't work, because the Markdown engine used on TeX.SE destroys tab characters, which are very important in Makefiles. It seems the easiest way to get a correct Makefile from this answer (i.e., what I posted) is to click on the edit link, select the whole Makefile code block, click on the {} button to unindent the block, copy/paste to the place you want and finally cancel your edit.

VARIANTS      := screen fullscreen print

all: $(VARIANTS) # ps

LATEX         := pdflatex -output-format dvi
PDFLATEX      := pdflatex

LATEX_ARGS    := -interaction=nonstopmode -halt-on-error
PDFLATEX_ARGS := $(LATEX_ARGS)
TEX_RUNS      := 2

SRC_BASE_NAME := parametrized_doc
SRC           := $(SRC_BASE_NAME).tex

# cf. GNU Make Manual (“Syntax of Functions”) and
# <https://stackoverflow.com/questions/28615974/wildcard-to-variable-to-comma-joined-string>
space :=
space += # $(space) is a space
comma := ,
# Function that converts a space-separated list into a comma-separated list
comma-separate = $(subst ${space},${comma},$(strip $(1)))

# Macro that expands to a Make rule for a parametrized document using the
# l3keys LaTeX3 module for parameters and \jobname for the output file name.
#
# $(1): variant name
# $(2): space-separated list of options to pass to l3keys (we can't
#       conveniently use the comma separator, because we'll expand this macro
#       with Make's $(call ...) function which separates arguments with
#       commas, precisely; therefore, we replace spaces with commas for l3keys).
define customPDF =
$(1): $$(SRC_BASE_NAME)-$(1).pdf

$$(SRC_BASE_NAME)-$(1).pdf: $$(SRC)
    for i in $$$$(seq 1 $$(TEX_RUNS)); do \
           $$(PDFLATEX) --jobname=$$(SRC_BASE_NAME)-$(1) \
            $$(PDFLATEX_ARGS) '\newcommand{\MyDocParams}{' \
            '$(call comma-separate,$(2)) }' '\input{$$<}'; \
        done
endef

$(eval $(call customPDF,screen, outputType=screen fullScreen=false))
$(eval $(call customPDF,fullscreen, outputType=screen fullScreen=true))
$(eval $(call customPDF,print, outputType=paper))

# Write a specific rule for this file (as opposed to a pattern rule starting
# with %.dvi: %.tex), because the suitable $(TEX_RUNS) value depends on the
# document, in general.
$(SRC_BASE_NAME).dvi: $(SRC)
    for i in $$(seq 1 $(TEX_RUNS)); do \
           $(LATEX) $(LATEX_ARGS) '\input{$<}'; \
        done

%.ps: %.dvi
    dvips -o '$@' '$<'

dvi: $(SRC_BASE_NAME).dvi
ps: $(SRC_BASE_NAME).ps

clean:
    for ext in dvi ps pdf out aux log idx ind ilg toc bbl blg bcf run.xml; \
          do rm -f "$(SRC_BASE_NAME).$$ext";                                   \
                                                                               \
            for variant in $(VARIANTS); do                                     \
                rm -f "$(SRC_BASE_NAME)-$$variant.$$ext";                      \
            done                                                               \
        done
    rm -f missfont.log

        # Stuff from preview-latex
    for ext in fmt ini log; do \
            rm -f "prv_$(SRC_BASE_NAME).$$ext"; \
        done

    rm -rf auctex-auto '$(SRC_BASE_NAME).prv' _region_.prv
    for ext in tex pdf log; do \
            rm -f "_region_.$$ext"; \
        done

.PHONY: all clean screen fullscreen print dvi ps

Finally, here is an expanded version of the same .tex file that actually adapts the layout based on the options passed using the mechanism just described. It uses the KOMA-Script scrartcl class, but obviously this has nothing to do with the parameters handling discussed here. I have removed most of the comments that were already in the “minimal example”, so if you find something unclear, look at the above LaTeX code and you should find what you are looking for. :-)

\documentclass[12pt]{scrartcl}
\usepackage{lmodern}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{textcomp}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{blindtext}
\usepackage[english]{babel}
\usepackage[final,babel]{microtype}

\usepackage{scrlayer-scrpage}   % used to customize headers and footers
\pagestyle{scrheadings}

\newif\ifMyScreenOutput
\newif\ifMyFullScreenOutput

\ExplSyntaxOn

\bool_new:N \g_MyDocParams_screenOutput_bool
\bool_new:N \g_MyDocParams_fullScreen_bool

\msg_new:nnnn { MyDocParams } { unknown-choice-for-option }
  {
    Invalid~value~for~option~\exp_not:n {'#1'}:~\exp_not:n {'#3'}~
    (valid~choices~are~\exp_not:n {#2})
  }
  { You~may~optionally~put~a~more~verbose~message~here. }

\keys_define:nn { MyDocParams }
  {
    outputType .choice:,
    outputType / paper .code:n = {
      \bool_gset_false:N \g_MyDocParams_screenOutput_bool },
    outputType / screen .code:n = {
      \bool_gset_true:N \g_MyDocParams_screenOutput_bool },
    outputType .initial:n = { paper },
    outputType / unknown .code:n = {
      \msg_error:nnxxx { MyDocParams } { unknown-choice-for-option }
        { outputType }                 % name of the choice key
        { 'paper'~and~'screen' }       % valid choices
        { \exp_not:n {#1} }            % invalid choice given
    },

    fullScreen .bool_gset:N = \g_MyDocParams_fullScreen_bool,
    fullScreen .initial:n = { false },
    % Used when the key is passed with no value
    fullScreen .default:n = { true }
  }

% The option values may be set from the command line by means of the
% \MyDocParams macro. If nothing is passed this way, the defaults come from
% the 'outputType .initial:n' and 'fullScreen .initial:n' settings above,
% but they could also be set here in the definition of \MyDocParams.
\providecommand{\MyDocParams}{}

% This is where keys are set from the point of view of l3keys.
\keys_set:no { MyDocParams } { \MyDocParams }

% Finally, convert our LaTeX3 booleans to \ifFooBar TeX conditionals.
\bool_if:NT \g_MyDocParams_screenOutput_bool
  { \MyScreenOutputtrue }
\bool_if:NT \g_MyDocParams_fullScreen_bool
  { \MyFullScreenOutputtrue }

\ExplSyntaxOff

% Customize the layout and colors depending on the selected output type.
\ifMyScreenOutput
  % Useful if you choose a two-sided layout for paper output (e.g., with the
  % scrbook class) but want to override it here in order to have a one-sided
  % layout for screen output.
  \KOMAoptions{twoside=false}

  \usepackage[svgnames]{xcolor}
  \pagecolor{yellow!9!white}

  % Let's choose a \textwidth containing a suitable number of characters for
  % convenient reading, and a \textheight such that if a page is filled with
  % “normal text” in the document font without any space between paragraphs,
  % then no vertical stretching nor shrinking is needed to fill the type area
  % (technique explained in the typearea/KOMA-Script documentation).
  \newlength{\MyTextWidthGoal}
  \newlength{\MyTextHeightGoal}
  \settowidth{\MyTextWidthGoal}{% 67 characters, incl. spaces and punctuation
    {\normalfont                % (recommended range is between 60 and 70)
      In this document, we'll show that in spite of its original syntax, }}
  \setlength{\MyTextHeightGoal}{\topskip}

  \ifMyFullScreenOutput
    \addtolength{\MyTextHeightGoal}{14\baselineskip} % 15 lines
    % Aspect ratio is 16:9 in this case
    \usepackage[papersize={17cm,9.5625cm},
                width=\MyTextWidthGoal,height=\MyTextHeightGoal]{geometry}
  \else
     % 55 lines (very tall!). I want this for screen reading as in a web
     % browser---without being disturbed by page separations.
    \addtolength{\MyTextHeightGoal}{54\baselineskip}
    \usepackage[papersize={17cm,31.5cm},
                width=\MyTextWidthGoal,height=\MyTextHeightGoal]{geometry}
  \fi

  % I want empty headers and footers for screen output (these are commands
  % from KOMA-Script's scrlayer-scrpage package).
  \ohead*{} \chead*{} \ihead*{}
  \ofoot*{} \cfoot*{} \ifoot*{}
\else
  % Paper output: just use typearea's automatic calculations, they work great!
  \KOMAoptions{paper=A4,BCOR=0mm,DIV=calc}
\fi

\usepackage[colorlinks=true]{hyperref}

\ifMyScreenOutput
  % Also available: filecolor, menucolor, runcolor
  \hypersetup{anchorcolor=Lime,linkcolor=DarkRed,urlcolor=RoyalBlue,
              citecolor=DarkRed}
  \ifMyFullScreenOutput
    \hypersetup{pdfpagemode=FullScreen}
  \fi
\else
  \hypersetup{allcolors=black}  % for print; other possibility: 'hidelinks'
\fi

% Define a few convenient document-level commands using the LaTeX3 framework.
\ExplSyntaxOn

% Insert a URL with optional link text. In print mode, if the link text is
% provided, then the URL is put inside a footnote tied to the link text.
%
% #1: URL (prefix any '%' or '#' characters with a backaslash)
% #2: link text (optional)
\NewDocumentCommand \myHref { m o }
{
  \IfValueTF {#2}
    { % The link text was provided (#2)
      \bool_if:nTF { \g_MyDocParams_screenOutput_bool }
        { \href {#1} {#2} }
        { #2 \footnote { \url {#1} } }
    }
    { % No link text provided
      \url {#1}
    }
}

% Typeset a LaTeX3 package name
\NewDocumentCommand \liiiPkg { m }
{
  \texttt {#1}
}

\ExplSyntaxOff

\begin{document}
\title{Gnus, gnats and armadillos}%
\subtitle{Their life in relation to the universe}%
\author{Joe R.~User}%
\date{}%
\maketitle

In this article, we are going to make a reference to
\autoref{sec:test-section} just to show the link color. And also add a pointer
to the very useful
\myHref{https://ctan.org/pkg/l3kernel}[\liiiPkg{l3kernel} documentation]
for people interested in \LaTeX3 programming. The \LaTeX3 source code
repository can be found on GitHub: \myHref{https://github.com/latex3/latex3}.

\section{This is a test section\label{sec:test-section}}

\blindtext                      % text that belongs to the section

\Blinddocument
\end{document}

Sample outputs for the print, screen and fullscreen variants

Print
enter image description here

Screen
enter image description here

Fullscreen
enter image description here


Detail on the differing handling of hyperlinks implemented in \myHref:

Print
enter image description here

Screen
enter image description here

Fullscreen
For this part of the document, it is identical to the screen variant, except that the page is shorter and thus the first paragraph doesn't entirely fit on the first page. Thus, I'm not including the screenshot in order to spare some bandwidth.

Notes:

  • I used LaTeX3 to parse the key/value pairs, but of course one could do something similar with xkeyval in pure LaTeX2e;
  • I implemented the fullscreen variant mainly to see what the result would look like with \hypersetup{pdfpagemode=FullScreen}; however, for real presentations, specialized packages such as beamer and pdfscreen should be considered too;
  • Since I'm using the outputType and fullScreen logic in several documents of mine, to avoid redundancy I've moved all this logic to a little package I called parmoutput.sty (for “parametrizable output”). In this setup, options can be passed in several ways:

    • with \PassOptionsToPackage{outputType=screen,...}{parmoutput}, which is convenient from the Makefile or any batch file controlling the compilation (this works because I use \ProcessKeysOptions from l3keys2e in parmoutput.sty, see here for explanations);
    • with \usepackage[outputType=screen,...]{parmoutput} if I want the format choice to be written in the document itself;
    • with \ParmOutputSetup{outputType=screen,...}: the same, but allows one to select these options later in the document, possibly in several steps (conceptually similar to hyperref's \hypersetup command).

    Currently, parmoutput.sty can be found here, but I can't guarantee the URL will remain stable (I don't guarantee its API will be stable either, yet).

  • I'm just starting with LaTeX3, so please forgive any mistakes in this area. :-)

1

I did something with a very naive approach, reading what is suggested here I definitively have to change my code. Anyway, if someone is interested here it is:

https://github.com/rvelseg/MuDoVLaGM

it uses mainly make, and sed to comment and uncomment fragments of a main document.

2
  • The comment package might be useful too for your approach.
    – Caramdir
    Oct 17, 2014 at 5:50
  • It would be helpful to include some code here, instead of elsewhere.
    – Teepeemm
    Apr 23, 2018 at 15:50
1

I found myself wanting to declare some rather long macros, including spaces and all that. The following approach worked best for me:

\read 16 to \file
\read 16 to \fname
\documentclass{ blah }
\begin{document}
\section{\fname}
\input \file
\end{document}

which is then called from my makefile with

( echo "mychapter" ; echo "This is about something" ) | pdflatex mainfile.tex

Summary: let TeX/LaTeX read macros from standard input, supply those interactively or through a script or whatever.

3
0

I found my way with arara. This is a slight modification of @MartinScharrer's answer. It assumes that the file-name is foo.

% arara: pdflatex: { options: [
% arara: --> '"\PassOptionsToClass{handout}{beamer}\input{foo}"'
% arara: --> ] }
% arara: pdflatex: { options: [
% arara: --> '"\PassOptionsToClass{handout}{beamer}\input{foo}"'
% arara: --> ] }
% arara: move: {
% arara: -->     files:  ['foo.pdf'],
% arara: -->     target: 'handouts/foo.pdf'
% arara: -->   }
% arara: pdflatex
% arara: pdflatex
% arara: clean: {
% arara: -->       extensions: [
% arara: -->         aux,log,toc,
% arara: -->         snm,out,nav,
% arara: -->         run.xml,tex~
%                    For biber+biblatex
% arara: -->         bcf,bbl,blg,
%                    For makeglossaries
% arara: -->         gls,glo,glg,
% arara: -->       ]
% arara: -->    }

This will produce a file without overlays in the working directory, move it in a directory (preexisting) called handouts/. Then it will again compile the code, but this time without the handout option and after the compilation, all the auxiliaries will be removed. The only painful thing with this approach is that one has to edit the file-name at three places if they want to paste it in a different file.

0

Compiling different versions from the same .tex-files implies different output files/different pdf-files with differet names.

With nowadays TeX-distributions compilers bring along the commandline-option -jobname=... for specifying what the primitive \jobname expands to and thus for specifying the filename of the .pdf-file, the main .aux-file, the .log-file, the .toc-file, the .lot-file, the .lof-file etc.

Expl3 brings along the l3str package whose routines can be used for examining the expansion of the primitive \jobname.

Thus you can create different versions of your document by providing different values for the -jobname=...-option and having LaTeX examine the result of expanding the primitive \jobname and fork according to the examination-results.

When on my system I save the following example as test.tex and on the shell (via chdir or cd or whatever) change the active directory to the directory where test.tex is stored, and then compile test.tex by calling latexmk from the shell/command-line via

latexmk -cd -gg -jobname="test_handout" -pdflua test.tex

, then I get test_handout.pdf containing stuff that is specific for handout.

If I compile test.tex by calling latexmk from the shell/command-line via

latexmk -cd -gg -pdflua test.tex

, then I get test.pdf without stuff that is specific for handout.

\ExplSyntaxOn
\cs_new:Npn \CheckWhetherJobnameContainsPhrase #1 {
  \exp_args:Nne \use:nn {\str_if_in:nnTF} {{\jobname} {#1}}
}
\ExplSyntaxOff

\newif\ifhandout

\CheckWhetherJobnameContainsPhrase{_handout}{\handouttrue}{\handoutfalse}

\documentclass{article}

\begin{document}

  This is a text.

  \ifhandout
    It is with handout.%
  \else
    It is without handout.
  \fi

\end{document}

You can create your main .tex-file to examine the expansion of \jobname and in case \jobname does not contain _ not to create a pdf-file at all but via \write18 or \directlua do a sequence of calls to latexmk where with each call the -jobname=...-option has another value and thus a pdf-file containing another variant of the document is created:

If I save the following example as test.tex and on the shell (via chdir or cd or whatever) change the active directory to the directory where test.tex is stored, and compile test.tex from the shell/command-line via

latex --shell-escape test.tex

(maybe on your platform you need --enable-write18 instead of --shell-escape)

, then I get

  • test_handout.pdf containing stuff that is specific for handout.
  • test_script.pdf containing stuff that is specific for script.
  • test_problemsheet.pdf containing stuff that is specific for problem sheet.
%=======================================================================================================
\ExplSyntaxOn
\cs_new:Npn \CheckWhetherJobnameContainsPhrase #1 {
  \exp_args:Nne \use:nn {\str_if_in:nnTF} {{\jobname} {#1}}
}
\ExplSyntaxOff

\CheckWhetherJobnameContainsPhrase{_}{}{%
  \RequirePackage{shellesc}% more recent releases of LuaTeX don't provide
                           % \write18 any more. This package makes sure
                           % under such LuaTeX \write18 is emulated by
                           % calls to \directlua.
  \ShellEscape{latexmk -jobname="\jobname\string_handout" -cd -gg -pdflua \jobname.tex}%
  \ShellEscape{latexmk -jobname="\jobname\string_script" -cd -gg -pdflua \jobname.tex}%
  \ShellEscape{latexmk -jobname="\jobname\string_problemsheet" -cd -gg -pdflua \jobname.tex}%
  \stop
}
\CheckWhetherJobnameContainsPhrase{_handout}{%
  \newcommand*\variantstring{Handout}%
}{%
  \CheckWhetherJobnameContainsPhrase{_script}{%
    \newcommand*\variantstring{Script}%
  }{%
    \CheckWhetherJobnameContainsPhrase{_problemsheet}{%
      \newcommand*\variantstring{Problem sheet}%
    }{%
      \message{No proper document variant specified}%
      \stop
    }%
  }%
}%
\ExplSyntaxOn
\cs_new:Npn \variantstringfork{\exp_args:No \str_case:nn {\variantstring}}
\ExplSyntaxOff
%=======================================================================================================

\documentclass{article}

\begin{document}

\variantstringfork{%
  {Handout}{\section{Handout}}%
  {Script}{\section{Script}}%
  {Problem sheet}{\section{Problem sheet}}%
}%

This is text all documents have in common.

\variantstringfork{%
  {Handout}{This is text specific to the handout.}%
  {Script}{This is text specific to the script.}%
  {Problem sheet}{This is text specific to the problem sheet.}%
}%

This is text all documents have in common.

\ifcase\variantstringfork{%
  {Handout}{0}%
  {Script}{1}%
  {Problem sheet}{2}%
} %
\begin{verbatim}
This is verbatim text in the handout.
\end{verbatim}
\or
\begin{verbatim}
This is verbatim text in the script.
\end{verbatim}
\or
\begin{verbatim}
This is verbatim text in the problem sheet.
\end{verbatim}
\fi

\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .