Difference between revisions of "Modes"
m (→Conditional processing based on modes: changing tags) |
(Lots of changes. Just replacing with the new version) |
||
Line 1: | Line 1: | ||
< [[The ConTeXt Way]] | [[Inside ConTeXt]] | [[Project structure]] > | < [[The ConTeXt Way]] | [[Inside ConTeXt]] | [[Project structure]] > | ||
− | + | Very often, you want to generate multiple versions of the same document: | |
− | + | one version for printing and one for viewing on the screen, one version for | |
− | + | students and one version for the instructor, and so on. You can do this in a | |
− | + | simple but naive way: create different files set up for the different versions and | |
− | students and one version for the instructor | ||
− | naive way | ||
<code>\input</code> the common material, or create some new conditional flags using | <code>\input</code> the common material, or create some new conditional flags using | ||
<code>\newif</code> and set them appropriately for conditional processing. Or you | <code>\newif</code> and set them appropriately for conditional processing. Or you | ||
− | could use | + | could use <em>modes</em>—the ConTeXt way of doing conditional processing. |
− | |||
= Introduction = | = Introduction = | ||
− | A mode is similar to a conditional flag, but with a few advantages | + | A mode is similar to a conditional flag, but with a few advantages: new modes |
need not be explicitly defined (no need for something like <code>\newif</code>), | need not be explicitly defined (no need for something like <code>\newif</code>), | ||
− | multiple modes can be simultaneously enabled or disabled, the status of multiple | + | multiple modes can be simultaneously enabled or disabled, and the status of multiple |
modes can be checked easily. Moreover, modes can be set from a command line | modes can be checked easily. Moreover, modes can be set from a command line | ||
− | switch. | + | switch. As a result, multiple versions of a document can be generated without changing |
the source file. | the source file. | ||
Line 24: | Line 21: | ||
spaces. Names starting with <code>*</code> are reserved for system modes. | spaces. Names starting with <code>*</code> are reserved for system modes. | ||
+ | In this article I explain how to activate a mode and how to check if a mode is | ||
+ | active or not. | ||
= Setting modes = | = Setting modes = | ||
Line 29: | Line 28: | ||
ConTeXt has three commands for setting modes: | ConTeXt has three commands for setting modes: | ||
− | * <code><cmd>enablemode</cmd> [...]</code> | + | * <code><cmd>enablemode </cmd>[...]</code> |
* <code><cmd>disablemode</cmd>[...]</code> | * <code><cmd>disablemode</cmd>[...]</code> | ||
* <code><cmd>preventmode</cmd>[...]</code> | * <code><cmd>preventmode</cmd>[...]</code> | ||
− | The names are self | + | The names are self-descriptive. <cmd>enablemode</cmd> activates a mode, |
<cmd>disablemode</cmd> deactivates a mode, and <cmd>preventmode</cmd> permanently | <cmd>disablemode</cmd> deactivates a mode, and <cmd>preventmode</cmd> permanently | ||
deactivates a mode. All three commands take a list of modes as an argument. For | deactivates a mode. All three commands take a list of modes as an argument. For | ||
− | example, you can activate < | + | example, you can activate modes named <code>screen</code> and <code>solution</code> with |
<texcode> | <texcode> | ||
− | \enablemode[screen,solution] | + | \enablemode[screen,solution] |
</texcode> | </texcode> | ||
Modes can also be activated by a command line switch <code>--modes</code> to | Modes can also be activated by a command line switch <code>--modes</code> to | ||
− | <code>texexec</code> | + | <code>texexec</code> or <code>context</code>. For example, another way to activate the <code>screen</code> and |
− | < | + | <code>solution</code> modes, to run ConTeXt using one of: |
− | + | texexec --mode=screen,solution ... | |
+ | context --mode=screen,solution ... | ||
− | |||
− | |||
− | + | = Conditional processing based on modes = | |
− | + | You may want to process or ignore a chunk of code if a particular mode is enabled | |
− | + | or disabled. Such a chunk of code is specified using <code>\startmode</code> and | |
− | + | <code>\startnotmode</code> environments. Their usable is best explained by an example. | |
Suppose you want to change the paper size of a document depending on whether it | Suppose you want to change the paper size of a document depending on whether it | ||
− | is for print or screen. This can be done in multiple ways. You could | + | is for print or screen. This can be done in multiple ways. You could set |
− | + | the default paper size for print and change it in screen mode: | |
<texcode> | <texcode> | ||
− | \setuppapersize[letter][letter] | + | \setuppapersize[letter][letter] |
− | + | \startmode[screen] | |
− | \startmode[screen] | + | \setuppapersize[S6][S6] |
− | + | \stopmode | |
− | \stopmode | ||
</texcode> | </texcode> | ||
(S6 is one of the screen-optimized paper sizes in ConTeXt; the paper size has a | (S6 is one of the screen-optimized paper sizes in ConTeXt; the paper size has a | ||
− | 4:3 aspect ratio and a width equal to the width of A4 paper.) Alternatively, you | + | 4:3 aspect ratio and a width equal to the width of A4 paper.) |
− | could set a default paper size for screen and change it if | + | |
+ | Alternatively, you | ||
+ | could set a default paper size for the screen and change it if screen mode is | ||
not enabled: | not enabled: | ||
<texcode> | <texcode> | ||
− | \setuppapersize[S6][S6] | + | \setuppapersize[S6][S6] |
− | + | \startnotmode[screen] | |
− | \startnotmode[screen] | + | \setuppapersize[letter][letter] |
− | + | \stopnotmode | |
− | \stopnotmode | ||
</texcode> | </texcode> | ||
− | < | + | <code>\startmode</code> and <code>\startnotmode</code> can check for multiple modes, |
− | + | by giving a list of modes as their arguments. <code>\startmode</code> | |
− | < | + | processes its contents (everything until the next |
− | < | + | <code>\stopmode</code>, thus <code>\startmode</code> cannot be |
− | if any of the modes are enabled, otherwise (i.e., when all the modes are | + | nested.) if any of the modes are enabled, otherwise (i.e., when all |
− | disabled) < | + | the modes are disabled) <code>\startmode</code> ignores its |
− | + | contents. The opposite is <code>\startnotmode</code>: it processes its | |
− | < | + | contents (everything until the next <code>\stopnotmode</code>) if any of the |
− | the | + | modes are disabled, otherwise—when all the modes are enabled—the contents are ignored. |
− | < | + | <code>\startmode</code> and <code>\startnotmode</code> are "<em>or</em>" environments. They |
process their contents if any of the modes satisfy the required condition. Their | process their contents if any of the modes satisfy the required condition. Their | ||
− | <em>and</em> counterparts are < | + | "<em>and</em>" counterparts are also available: <code>\startallmodes</code> and <code>\startnotallmodes</code> |
− | + | process their contents only if all the given modes satisfy the required | |
− | condition. For example, suppose you want to enable interaction (hyperlinks) | + | condition. For example, suppose you want to enable interaction (e.g., hyperlinks) |
− | only when both < | + | only when both <code>screen</code> and <code>solution</code> modes are enabled. Then you can |
use: | use: | ||
<texcode> | <texcode> | ||
− | \startallmodes[screen,solution] | + | \startallmodes[screen,solution] |
− | + | \setupinteraction[state=start] | |
− | \stopallmodes | + | \stopallmodes |
</texcode> | </texcode> | ||
Line 105: | Line 103: | ||
<texcode> | <texcode> | ||
\startmode[mode1, mode2, ...] | \startmode[mode1, mode2, ...] | ||
− | % | + | % Processed if any of the modes is enabled |
\stopmode | \stopmode | ||
\startnotmode[mode1, mode2, ...] | \startnotmode[mode1, mode2, ...] | ||
− | % | + | % Processed if any of the modes is disabled |
\stopnotmode | \stopnotmode | ||
\startallmodes[mode1, mode2, ...] | \startallmodes[mode1, mode2, ...] | ||
− | % | + | % Processed if all the modes are enabled |
\stopallmodes | \stopallmodes | ||
\startnotallmodes[mode1, mode2, ...] | \startnotallmodes[mode1, mode2, ...] | ||
− | % | + | % Processed if all the modes are disabled |
\stopnotallmodes | \stopnotallmodes | ||
</texcode> | </texcode> | ||
− | These environments have | + | These environments have <code>\doif...</code> alternatives that are useful for short |
− | setups | + | setups. Also, they can be nested. |
<texcode> | <texcode> | ||
Line 130: | Line 128: | ||
\doifnotallmodes {modes} {content} | \doifnotallmodes {modes} {content} | ||
</texcode> | </texcode> | ||
− | + | The logic for determining when the content is processed is exactly the same as | |
− | The logic for determining when the content is | + | for the <code>start</code>-<code>stop</code> commands. |
− | for the <code>start</code>-<code>stop</code> | ||
− | These <code>\doif</code> commands have a variant | + | These <code>\doif</code> commands each have a variant to process alternative code if |
the conditions are not satisfied (like the <code>\else</code> branch of <code>\if</code>). | the conditions are not satisfied (like the <code>\else</code> branch of <code>\if</code>). | ||
<texcode> | <texcode> | ||
− | \doifmodeelse | + | \doifmodeelse {modes} {content} {alt} |
− | \doifnotmodeelse | + | \doifnotmodeelse {modes} {content} {alt} |
− | \doifallmodeselse | + | \doifallmodeselse {modes} {content} {alt} |
− | \doifnotallmodeselse {modes} {content} { | + | \doifnotallmodeselse{modes} {content} {alt} |
</texcode> | </texcode> | ||
= System modes = | = System modes = | ||
− | + | Besides allowing user-definable modes, ConTeXt provides some system | |
− | modes start with a <code>*</code>. Here I will only | + | modes. These modes start with a <code>*</code> character. Here I will explain |
− | system modes | + | only the more commonly used system modes; see the ConTeXt [http://pragma-ade.com/general/manuals/mmodes.pdf modes manual] |
− | for a complete list | + | for a complete list. |
Perhaps the most useful system modes are <code>*mkii</code> and <code>*mkiv</code> which | Perhaps the most useful system modes are <code>*mkii</code> and <code>*mkiv</code> which | ||
− | determine whether | + | determine whether MKII or MKIV is being used. These modes are handy when you |
− | want different setups for | + | want different setups for MKII and MKIV. |
Other modes are useful for very specific situations. Some of these are described | Other modes are useful for very specific situations. Some of these are described | ||
below. | below. | ||
− | A document multiple times to get the cross referencing, table of contents, etc. | + | A document must be run multiple times to get the cross referencing, |
− | right. However, sometimes you need to do some external processing ( | + | table of contents, etc. |
− | conversion) that only needs to be done | + | right. However, sometimes you need to do some external processing (e.g., graphic |
− | <code>*first</code> mode is handy | + | conversion) that only needs to be done once. In such cases, the |
+ | <code>*first</code> mode is handy—it is active only on the first run of the | ||
+ | document. | ||
You can use the project-product-component structure for managing large projects | You can use the project-product-component structure for managing large projects | ||
like a book series. See [[Project structure]] | like a book series. See [[Project structure]] | ||
− | for details. | + | for details of this approach. A product or its components may be compiled |
− | + | separately, and you may want to do something different when a product is | |
− | + | compiled or when a component is compiled. To do so, you need to check for | |
− | + | modes <code>*project</code>, <code>*product</code>, <code>*component</code>, and | |
− | + | <code>*environment</code>; these modes are set when the corresponding structure file | |
− | product file is read | + | is processed. For example, the <code>*product</code> mode is set whenever a |
− | encountered | + | product file is read; more specifically, when <code>\startproduct</code> is |
− | <code>\starttext</code> is encountered. | + | encountered. Similarly, a mode <code>*text</code> is enabled when |
+ | <code>\starttext</code> is encountered, and likewise for the others. | ||
− | A large document is | + | A large document is typically broken down into different section blocks: |
frontmatter, bodymatter, appendices, and backmatter. Internally, these section | frontmatter, bodymatter, appendices, and backmatter. Internally, these section | ||
− | blocks are | + | blocks are referred to as <code>frontpart</code>, <code>bodypart</code>, <code>appendix</code>, and |
− | <code> | + | <code>backpart</code>. Each section block sets a system mode with the same name. So, |
− | if you want macros that work differently | + | if you want macros that work differently in different section blocks, you can |
− | check for <code>* | + | check for modes <code>*frontpart</code>, <code>*bodypart</code>, and so on. |
− | |||
− | ConTeXt provides support for multiple | + | ConTeXt provides support for multiple languages. Languages are recognized by |
− | their IETF language tags, like <code>en-us</code> for US English, <code>en-gb</code> | + | their IETF language tags, like <code>en-us</code> for US |
+ | English, <code>en-gb</code> | ||
for British English, <code>nl</code> for Dutch, <code>de</code> for German, etc. A document | for British English, <code>nl</code> for Dutch, <code>de</code> for German, etc. A document | ||
− | has a main language set | + | has a main language, set with the command <code>\mainlanguage[...]</code>, |
+ | that is used for | ||
translated labels like <em>chapter</em> and <em>figure</em>. You can also switch the | translated labels like <em>chapter</em> and <em>figure</em>. You can also switch the | ||
current language using <code>\language[...]</code> to change the hyphenation rules. | current language using <code>\language[...]</code> to change the hyphenation rules. | ||
− | Whenever a language is chosen, its | + | Whenever a language is chosen, its identifier is set as a mode. The mode for the main |
− | language starts with two <code>*</code>. For example, when the main language is US | + | language starts with two <code>*</code>. For example, when the main language |
+ | is US | ||
English and the current language is Dutch, the modes <code>**en-us</code> and | English and the current language is Dutch, the modes <code>**en-us</code> and | ||
<code>*nl</code> are set (notice the extra <code>*</code> in <code>**en-us</code>). | <code>*nl</code> are set (notice the extra <code>*</code> in <code>**en-us</code>). | ||
− | Other system modes | + | Other system modes: <code>*figure</code> is set when a graphic is found, |
− | <code>*interaction</code> | + | <code>*interaction</code> is set when interaction is enabled, <code>*grid</code> |
− | is set when grid typesetting is enabled, and <code>*pdf</code> and <code>*dvi</code> | + | is set when grid typesetting is enabled, and <code>*pdf</code> and <code>*dvi</code> |
− | are set | + | are set when the output is PDF or DVI. Others |
− | are too esoteric to | + | are too esoteric to describe here. If you are interested, see the |
− | + | modes manual mentioned earlier. | |
− | = | + | = Specific Examples = |
− | |||
− | + | == Different fonts == | |
− | + | Suppose you want to generate two versions of a document, one with times font and one with palatino. One way to do this is as follows: | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
<texcode> | <texcode> | ||
\startmode[palatino] | \startmode[palatino] | ||
− | |||
\usetypescript[palatino][8r] | \usetypescript[palatino][8r] | ||
\setupbodyfont[palatino,12pt] | \setupbodyfont[palatino,12pt] | ||
Line 247: | Line 214: | ||
\startmode[times] | \startmode[times] | ||
− | |||
\usetypescript[postscript][8r] | \usetypescript[postscript][8r] | ||
\setupbodyfont[postscript,12pt] | \setupbodyfont[postscript,12pt] | ||
Line 254: | Line 220: | ||
\starttext | \starttext | ||
\input knuth | \input knuth | ||
− | |||
\stoptext | \stoptext | ||
</texcode> | </texcode> | ||
+ | and run with one of the following: | ||
− | + | texexec --mode=palatino filename | |
− | + | texexec --mode=times filename | |
− | |||
− | |||
− | |||
− | + | == Running external commands once == | |
− | |||
− | |||
− | == | ||
− | |||
− | |||
+ | Suppose you want to run some external program, say to generate a figure. Unfortunately, the program only generates postscript figure. So you want to convert it to pdf. This can be done as follows: | ||
<texcode> | <texcode> | ||
− | \ | + | \startmode[*first] |
− | % external program which creates a file | + | % external program which creates a file fig-1.ps |
\executesystemcommand{some_external_program ...} | \executesystemcommand{some_external_program ...} | ||
% convert PS into PDF | % convert PS into PDF | ||
− | \executesystemcommand{texmfstart pstopdf | + | \executesystemcommand{texmfstart pstopdf fig-1.ps} |
− | + | \stopmode | |
% include the resulting PDF | % include the resulting PDF | ||
− | \externalfigure[ | + | \externalfigure[fig-1] |
</texcode> | </texcode> | ||
+ | = Summary = | ||
+ | |||
+ | In summary, modes provide generalized conditional processing. A rich set of | ||
+ | built-in modes is available. | ||
[[Category:ConTeXt programming]] | [[Category:ConTeXt programming]] |
Revision as of 07:56, 12 May 2010
< The ConTeXt Way | Inside ConTeXt | Project structure >
Very often, you want to generate multiple versions of the same document:
one version for printing and one for viewing on the screen, one version for
students and one version for the instructor, and so on. You can do this in a
simple but naive way: create different files set up for the different versions and
\input
the common material, or create some new conditional flags using
\newif
and set them appropriately for conditional processing. Or you
could use modes—the ConTeXt way of doing conditional processing.
Contents
Introduction
A mode is similar to a conditional flag, but with a few advantages: new modes
need not be explicitly defined (no need for something like \newif
),
multiple modes can be simultaneously enabled or disabled, and the status of multiple
modes can be checked easily. Moreover, modes can be set from a command line
switch. As a result, multiple versions of a document can be generated without changing
the source file.
The name or identifier of a mode can be any combination of letters, digits, or
spaces. Names starting with *
are reserved for system modes.
In this article I explain how to activate a mode and how to check if a mode is active or not.
Setting modes
ConTeXt has three commands for setting modes:
\enablemode [...]
\disablemode[...]
\preventmode[...]
The names are self-descriptive. \enablemode activates a mode,
\disablemode deactivates a mode, and \preventmode permanently
deactivates a mode. All three commands take a list of modes as an argument. For
example, you can activate modes named screen
and solution
with
\enablemode[screen,solution]
Modes can also be activated by a command line switch --modes
to
texexec
or context
. For example, another way to activate the screen
and
solution
modes, to run ConTeXt using one of:
texexec --mode=screen,solution ... context --mode=screen,solution ...
Conditional processing based on modes
You may want to process or ignore a chunk of code if a particular mode is enabled
or disabled. Such a chunk of code is specified using \startmode
and
\startnotmode
environments. Their usable is best explained by an example.
Suppose you want to change the paper size of a document depending on whether it is for print or screen. This can be done in multiple ways. You could set the default paper size for print and change it in screen mode:
\setuppapersize[letter][letter] \startmode[screen] \setuppapersize[S6][S6] \stopmode
(S6 is one of the screen-optimized paper sizes in ConTeXt; the paper size has a 4:3 aspect ratio and a width equal to the width of A4 paper.)
Alternatively, you could set a default paper size for the screen and change it if screen mode is not enabled:
\setuppapersize[S6][S6] \startnotmode[screen] \setuppapersize[letter][letter] \stopnotmode
\startmode
and \startnotmode
can check for multiple modes,
by giving a list of modes as their arguments. \startmode
processes its contents (everything until the next
\stopmode
, thus \startmode
cannot be
nested.) if any of the modes are enabled, otherwise (i.e., when all
the modes are disabled) \startmode
ignores its
contents. The opposite is \startnotmode
: it processes its
contents (everything until the next \stopnotmode
) if any of the
modes are disabled, otherwise—when all the modes are enabled—the contents are ignored.
\startmode
and \startnotmode
are "or" environments. They
process their contents if any of the modes satisfy the required condition. Their
"and" counterparts are also available: \startallmodes
and \startnotallmodes
process their contents only if all the given modes satisfy the required
condition. For example, suppose you want to enable interaction (e.g., hyperlinks)
only when both screen
and solution
modes are enabled. Then you can
use:
\startallmodes[screen,solution] \setupinteraction[state=start] \stopallmodes
To summarize, the four start-stop environments for checking modes are:
\startmode[mode1, mode2, ...] % Processed if any of the modes is enabled \stopmode \startnotmode[mode1, mode2, ...] % Processed if any of the modes is disabled \stopnotmode \startallmodes[mode1, mode2, ...] % Processed if all the modes are enabled \stopallmodes \startnotallmodes[mode1, mode2, ...] % Processed if all the modes are disabled \stopnotallmodes
These environments have \doif...
alternatives that are useful for short
setups. Also, they can be nested.
\doifmode {modes} {content} \doifnotmode {modes} {content} \doifallmodes {modes} {content} \doifnotallmodes {modes} {content}
The logic for determining when the content is processed is exactly the same as
for the start
-stop
commands.
These \doif
commands each have a variant to process alternative code if
the conditions are not satisfied (like the \else
branch of \if
).
\doifmodeelse {modes} {content} {alt} \doifnotmodeelse {modes} {content} {alt} \doifallmodeselse {modes} {content} {alt} \doifnotallmodeselse{modes} {content} {alt}
System modes
Besides allowing user-definable modes, ConTeXt provides some system
modes. These modes start with a *
character. Here I will explain
only the more commonly used system modes; see the ConTeXt modes manual
for a complete list.
Perhaps the most useful system modes are *mkii
and *mkiv
which
determine whether MKII or MKIV is being used. These modes are handy when you
want different setups for MKII and MKIV.
Other modes are useful for very specific situations. Some of these are described below.
A document must be run multiple times to get the cross referencing,
table of contents, etc.
right. However, sometimes you need to do some external processing (e.g., graphic
conversion) that only needs to be done once. In such cases, the
*first
mode is handy—it is active only on the first run of the
document.
You can use the project-product-component structure for managing large projects
like a book series. See Project structure
for details of this approach. A product or its components may be compiled
separately, and you may want to do something different when a product is
compiled or when a component is compiled. To do so, you need to check for
modes *project
, *product
, *component
, and
*environment
; these modes are set when the corresponding structure file
is processed. For example, the *product
mode is set whenever a
product file is read; more specifically, when \startproduct
is
encountered. Similarly, a mode *text
is enabled when
\starttext
is encountered, and likewise for the others.
A large document is typically broken down into different section blocks:
frontmatter, bodymatter, appendices, and backmatter. Internally, these section
blocks are referred to as frontpart
, bodypart
, appendix
, and
backpart
. Each section block sets a system mode with the same name. So,
if you want macros that work differently in different section blocks, you can
check for modes *frontpart
, *bodypart
, and so on.
ConTeXt provides support for multiple languages. Languages are recognized by
their IETF language tags, like en-us
for US
English, en-gb
for British English, nl
for Dutch, de
for German, etc. A document
has a main language, set with the command \mainlanguage[...]
,
that is used for
translated labels like chapter and figure. You can also switch the
current language using \language[...]
to change the hyphenation rules.
Whenever a language is chosen, its identifier is set as a mode. The mode for the main
language starts with two *
. For example, when the main language
is US
English and the current language is Dutch, the modes **en-us
and
*nl
are set (notice the extra *
in **en-us
).
Other system modes: *figure
is set when a graphic is found,
*interaction
is set when interaction is enabled, *grid
is set when grid typesetting is enabled, and *pdf
and *dvi
are set when the output is PDF or DVI. Others
are too esoteric to describe here. If you are interested, see the
modes manual mentioned earlier.
Specific Examples
Different fonts
Suppose you want to generate two versions of a document, one with times font and one with palatino. One way to do this is as follows:
\startmode[palatino] \usetypescript[palatino][8r] \setupbodyfont[palatino,12pt] \stopmode \startmode[times] \usetypescript[postscript][8r] \setupbodyfont[postscript,12pt] \stopmode \starttext \input knuth \stoptext
and run with one of the following:
texexec --mode=palatino filename texexec --mode=times filename
Running external commands once
Suppose you want to run some external program, say to generate a figure. Unfortunately, the program only generates postscript figure. So you want to convert it to pdf. This can be done as follows:
\startmode[*first] % external program which creates a file fig-1.ps \executesystemcommand{some_external_program ...} % convert PS into PDF \executesystemcommand{texmfstart pstopdf fig-1.ps} \stopmode % include the resulting PDF \externalfigure[fig-1]
Summary
In summary, modes provide generalized conditional processing. A rich set of built-in modes is available.