Difference between revisions of "Unexpected behavior"
BruceH2020 (talk | contribs) (Added a hidden anchor because you can't link to a heading that has command names in it.) |
|||
Line 112: | Line 112: | ||
This is a [[Right_and_left|FAQ item]]. | This is a [[Right_and_left|FAQ item]]. | ||
+ | <span id="setupnotation v setupnote"></span> | ||
== Footnotes: The Difference between {{cmd|setupnotation}} and {{cmd|setupnote}} == | == Footnotes: The Difference between {{cmd|setupnotation}} and {{cmd|setupnote}} == | ||
Line 182: | Line 183: | ||
(For more definite answers concerning the ''notes'' mechanism, use the | (For more definite answers concerning the ''notes'' mechanism, use the | ||
source, Luke: {{src|strc-not.mkvi}}.) | source, Luke: {{src|strc-not.mkvi}}.) | ||
− | |||
== Float Insertion Issues == | == Float Insertion Issues == |
Revision as of 17:31, 4 August 2022
If ConTeXt appears to behave in a counterintuitive way, chances are that it’s actually your intuitions that lack calibration.
Contents
Controlling Page Break Before Headings
If you add the option page=yes
to a heading setup, this
will cause ConTeXt to break the page.
Ordinarily this works as expected, unless, however, the heading
immediately follows a previous section heading with no text in between.
The rationale behind this is that consecutive headings are conceived of
collectively as one single structural element.
For example, the following code will generate only a single page
break although the unit \section appears twice.
\setuphead[section][page=yes] %% toggle page breaking \starttext \chapter{foo} %% structural inhibits breaking \section{bar} \input knuth %% -> no break! \section{baz} \input dawkins %% -> break \stoptext
In order to get the page break at the section regardless of surrounding
structurals elements, you need to unset the heading parameter
continue
as well.
[1]
\setuphead[section][page=yes,continue=no] \starttext \chapter{foo} \section{bar} \input knuth %% -> break \section{baz} \input dawkins %% -> break \stoptext
(For the curious, the explanation can be found in the definition of the macro \strc_sectioning_handle_page_nop in strc-sec.mkiv).
Unsolicited Vertical Mode
Some commands like \framed cause line breaks to happen if used in vertical mode, e.g. at the beginning of a line. Example:
\starttext \framed{foo} bar. \stoptext
The explanation according to the corresponding
FAQ item
is that before the token \frame
is encountered, TEX is
in vertical mode.
This state is preserved until after TEX finishes typesetting the
\framed
macro.
Consequently, horizontal mode (where paragraphs are made) is entered
only at the tokens bar
.
To have the frame begin the paragraph instead, horizontal mode will
have to be initiated explicitly.
There are a couple macros for this purpose: the very basic
\leavevmode (syst-ini.mkiv; inserts an empty box, same
as in the Plain format) and the more familiar \dontleavehmode
(syst-aux.mkiv).
Just use the chosen macro immediately before the \framed
macro and
everything should be fine:
\starttext \leavevmode \framed{foo} bar.\par \dontleavehmode \framed{foo} bar. \stoptext
Disappearing Crop Marks
Crop marks, activated as \setuplayout[marking=on]
, are a
useful feature that Context supports out of the box.
They have a peculiarity, though, which my make them useless in specific
cases: They are, by definition, located outside the page dimension.
This means that they show up iff the paper size exceeds the page size.
Thus if you need auxiliary lines for cutting but have the pages fit the paper size exactly, you can instead resort to enabling the page background frame. This example sums up the solutions posted by Wolfgang and Marco on [http://archive.contextgarden.net/message/20120605.202113.0989aa34.en.html the Context Mailing List].
%% the paper size will be a multiple of the page sizes \setuppapersize [A6,landscape] [A3] \setuplayout [nx=2,ny=4]%, marking=on] %% enable the page frame \setupbackgrounds [page] [frame=on] %% some further display setups \setuppagenumbering [location=] \setupbackgrounds [page] [background=color, backgroundcolor=gray] \setupbodyfont [sans,58pt] %% testing ... \starttext \dorecurse{4} {\null\vfill\centerline\recurselevel\vfill\null\page} \stoptext
Left and Right
When it comes to the justification of paragraphs, do not trust your intuitions about handedness. This is a FAQ item.
Footnotes: The Difference between \setupnotation and \setupnote
There is a bit of terminology mess concerning notes.
Instruction | Goal |
---|---|
\setupnotation | This command configures the note insert, i.e. the textual content that will usually be placed at the bottom (with footnotes) or the end of the text (with endnotes). (The control sequence used to be \setupnotedefinition .)
|
\setupnote | Configure the note environment where the inserts will be located. Inherits some parameters from \framed. |
\setupnote[textstyle=,textcommand=]
|
Configure the note symbol as appears in the main text, where the note macro is called. |
Plural forms \setupnotes, \setupnotations | These are synonyms for their singular forms. |
\setupfootnotes | This is equivalent to \setupnote[footnote] .
|
Summary: to setup a blue note, you would first need to define and configure the insert via \setupnotation:
\definenote [bluenote] [footnote] \setupnotation [bluenote] [ color=blue, style=bf, ] \starttext foo\bluenote{bar} baz \stoptext
Now adjust the container where the blue notes will reside at the bottom of the page (\setupnote):
\definenote [bluenote] [footnote] \setupnote [bluenote] [ frame=on, %% frame containing all inserts framecolor=blue, background=screen, rulecolor=blue, %% the line above the inserts rulethickness=1pt, %% both the frame and line width ] \starttext foo\bluenote{bar} baz \bluenote{xyzzy} \stoptext
Finally, direct your attention to the note indicator, most commonly a
number or a symbol.
For precise control over the placement define a monadic macro and hook
it into textcommand
.
\setupnote [bluenote] [ textstyle=\tx\sans\bold\blue, textcommand=\myfootnotecommand, ] \define[1]\myfootnotecommand{\rotate[rotation=42]{#1}} \starttext foo\bluenote{bar} baz \bluenote{xyzzy} \stoptext
(For more definite answers concerning the notes mechanism, use the source, Luke: strc-not.mkvi.)
Float Insertion Issues
Floating objects can be tricky. Deciding where they fit best is hard enough, actually getting them there may be a lot tougher. Inserting a float will force a line break where the object is referenced in the source code. Thus, very long paragraphs may not leave an opportunity to inject the float if they cover the entire page. [2]
\starttext Cows make \placefigure[top]{A genuine Dutch cow.}{\externalfigure[cow]} great pets. \stoptext
In these cases the postponing mechanism offers a reliable way out
(\startpostponing).
It lets you specify an offset (in pages) by which the content of the
postponing environment will be delayed.
In order to place a floating object at the top of the nth page from
the location it is encountered, its argument has needs to be
[+n]
.
(Absolute pages can be specified as simply [n]
.)
E. g. to put the foat on the following page:
\starttext \startpostponing[+1] \placefigure[top]{A genuine Dutch cow.}{\externalfigure[cow.pdf]} \stoppostponing \input knuth \page Cows make great pets. \stoptext
Another solution can be the less-known hangaround environment (\starthangaround, cf. Hangaround). It lets the text of a given paragraph (the content of the environment) flow around a box (the first argument). In contrast to real floats it does not place a caption. This poses a problem in MkIV as the new code will not allow placing captions arbitrarily. [[3]] (If you desparately need separate captions please send a feature request to one of the Mailing_Lists).
\starttext \input dawkins \starthangaround{ \framed[align=right,frame=off,width=.3\textwidth]{ \externalfigure [cow] [width=.3\textwidth]\crlf %% NB the fake caption works *only in mkii* \placefloatcaption [figure] [ref:acow] {A smiling Dutch cow. {\italic Bos primigenius taurus}} } } \input dawkins \stophangaround \input dawkins \stoptext
internal error: copy error TXyllZ/cropped.pdf
The “paragraph in a group” problem
Another common issue with sidefloats is starting a paragraph in a group.
\placefigure[right,none]{}{\externalfigure[cow][width=0.25\textwidth]} Lorem ipsum dolor sit amet, consectetur adipiscing elit. {\bf Oeps} \samplefile{lorem}
As you can see the paragraph starting with “Oeps” just overflows into the picture.
That is a well-known problem and there are posts about it on the mailing
list every once in a while. The sidefigure mechanism uses \parshape
to
make the paragraph flow around the figure. The \parshape
primitive only
applies to a single paragraph, so ConTeXt communicates the current
\parshape
settings to the next paragraph using \everypar
. However, when
a new paragraph starts in a group, i.e.
{\bf Oeps} ...
TeX inserts the \everypar
tokens inside that group because only the
first letter starts the paragraph. That is to say is effectively looks
like this
% \everypar inserted inside the group % ~~~v {\bf \the\everypar Opes} ... % ~~~~~~~~~~~~~~~~~~~~~^ % Setting of \everypar are discarded again when leaving the group and \parshape is lost.
You have to explicitly start a new paragraph before opening a group. The easiest way to do this is
\dontleavehmode{\bf Oeps} ...
Now the \everypar
tokens are inserted directly after \dontleavehmode
outside the group and the problem goes away.
Syntax
Assignments
Spaces before commas or before the closing ]
are not ignored in ConTeXt. That is a common pitfall and leads to errors that can be confusing for beginner, especially those coming from LaTeX, where this is the default behaviour. Formatting your keys like this might look nice but leads to spurious spaces:
\getparameters[test] [ foo=bar , hello=world ] “\testfoo” “\testhello”
Instead it is recommended to adhere to the style that is used in the ConTeXt source to avoid problems with trailing spaces:
\getparameters[test] [foo=bar, hello=world] “\testfoo” “\testhello”
In the most common form of key-value type arguments, ConTeXt will accept trailing commas or even empty items. For example, the following code shows this tolerance for the command \definehighlight.
\definehighlight [dontmiss] [ color=red, ,, %% empty option: do nothing style=bold, %% trailing delimiter ]
This is the syntax accepted e.g. by the majority of setups and
\getparameters
.
(For the parser code cf. syst-aux.mkiv.)
There are, however, exceptions to this rule. A known case where
options are processed in a less tolerant fashion is
\setuplabeltext.
[4]
Thus the following snippet will not compile, forcing ConTeXt to fail
with a cryptic Argument of ...
error message.
\setuplabeltext [Nomen=nomen, Est=est, Omen=est,] %% <= fails! \setuplabeltext [Nomen=nomen, Est=est, Omen=omen] %% <= works \starttext \labeltext{Nomen} \labeltext{Est} \labeltext{Omen} \stoptext
(A similar exception concerning \definepalet has been migrated to the standard argument model but may still show the earlier behavior in not so recent installations. [5])
Treacherous Dimensions
At some places dimension-lookalikes are expected but they do not behave exactly as in TEX per se because they are evaluated differently. A very common example is the command \setupbodyfont that is possibly called, albeit implicitly, in every production document. Its argument, the font size, although it may look like an ordinary dimension expression, will not have the same result if it has zeros prepended or decimal places are specified.
Suppose you want to set the main font to a very large size:
\setupbodyfont[42pt] \starttext foobar \stoptext
this works out well as long as you do not mistake the expression 42pt to be a real dimension.
In TEX dimensions (which are really just integers) are treated the same irrespective of leading or trailing zeros used in the variable assignment. Thus the following are all equivalent:
\newdimen\fortytwo\fortytwo=42pt \newdimen\fortytoo\fortytoo=042pt \newdimen\fortytww\fortytww=42.00pt \starttext \the\fortytwo\ \ifnum\fortytwo=\fortytoo\m{\top}\else\m{\bot}\fi\par \the\fortytoo\ \ifnum\fortytwo=\fortytww\m{\top}\else\m{\bot}\fi\par \the\fortytww\ \ifnum\fortytoo=\fortytww\m{\top}\else\m{\bot}\fi\par \stoptext
However, this does not hold for the Context commands
\setupbodyfont and \switchtobodyfont.
With the latter macros, only the pure-integer specification
(42pt
) can be used reliably, everything else, even though it
denotates the same TEX dimension, will result in a warning:
fonts > bodyfont 42.0pt is defined (can better be done global)
Additionally, if the code in question relies on font switching a lot (e. g. Lua snippets that calculcate font sizes from floating point numbers), there will be a huge perfomance penalty because everytime a font switch occurs, the font will be reloaded entirely. The reason for this is that the process of defining a font for the main text is accompanied by a myriad of secondary definitions for different relative font sizes (\tfx, \tfa and the likes) and shapes – the creation of the body font environment. If the “size” requested by \setupbodyfont cannot be found in the internal table, this environment will be rebuilt on the spot.
It is also not possible to catch these cases by predefining the corresponding bodyfont environments by placing \definebodyfontenvironment statements in the preamble. So if you have, say:
\definebodyfontenvironment[42.0pt] \definebodyfontenvironment[042pt] \definebodyfontenvironment[042.0pt] \starttext \setupbodyfont[42.0pt] foo bar \setupbodyfont[042pt] foo bar \setupbodyfont[042.0pt] foo bar \stoptext
the warning and slowdown will occur regardless. The only real option is to serve \setupbodyfont and the likes natural integers only.
Alternatively you can always employ raw font definitions, if there isn’t any need for the environment in the first place:
\starttext \definedfont[file:iwona-regular.otf at 42.0pt] foo bar \definedfont[file:iwona-regular.otf at 042pt] foo bar \definedfont[file:iwona-regular.otf at 042.0pt] foo bar \stoptext
Here the dimensions are real.
For further information see this and this thread on the mailing list.
Multipass
In some circumstances, portions of code are evaluated two or more times. This can be disruptive in contexts where the order of actions is important.
Trialtypesetting
Often the size of elements must be calculated prior to determining the optimal placements. Probably the most common example are tables: In order to align cells correctly the dimensions of later parts of the document must already be determined before anything is typeset. The stage during which this takes place is called *trial typesetting*.
The system mode trialtypesetting allows fine-grained control over what code should be executed during what stage. For instance, the naive definition of a macro that increments and prints a counter register will behave erratically in tables:
\def \inccount {% \incrementnumber [somecount]% \getnumber [somecount]% } \definenumber [somecount] \setnumber [somecount] [42] \starttext before \inccount \startplacetable[location=here] \bTABLE \bTR \bTD \inccount \eTD \bTD \inccount \eTD \eTR \eTABLE \stopplacetable after \inccount \stoptext
To bypass the extra evaluation, wrap the incrementation part in an
\iftrialtypesetting
conditional.
\def \inccount {% \iftrialtypesetting \else \incrementnumber [somecount]% \fi \getnumber [somecount]% } \definenumber [somecount] \setnumber [somecount] [42] \starttext before \inccount \startplacetable[location=here] \bTABLE \bTR \bTD \inccount \eTD \bTD \inccount \eTD \eTR \eTABLE \stopplacetable after \inccount \stoptext
Note that annoying as it may appear, the trial typesetting phase is
essential for certain features to work, so take extra care when
omitting it.
In the example above the number itself must be present as placeholder
during the first pass even though it has not been updated at this
point.
\def \inccount {% \iftrialtypesetting \else \incrementnumber [somecount]% \getnumber [somecount]% <= wrong! \fi }
Tables
In addition to trial typesetting Context also knows a table state:
\def \tablecheck {\ifintable In table. \else Outside table. \fi} \starttext \tablecheck \startplacetable[location=here] \bTABLE \bTR \bTD \tablecheck \eTD \bTD \tablecheck \eTD \eTR \eTABLE \stopplacetable \tablecheck %% decrement \stoptext
Metapost
As with TeX, Metapost sometimes requires multiple passes, especially when processing text. In below snippet, the Metapost tracer reveals that the code is actually evaluated twice:
\enabletrackers[metapost.showlog] \starttext \startMPcode show "This gets printed twice."; label (btex Some label text etex, (0,0)); \stopMPcode \stoptext
NB removing the label
statement will result in the second
pass being omitted.
In MetaFun - MetaPost in ConTeXt, the default Metapost format in Context, the booleans
mfun_first_run
and mfun_trial_run
allow
detecting the individual stages:
\enabletrackers[metapost.showlog] \starttext \startMPcode if mfun_trial_run : show "This gets printed during the trial pass."; else : show "This gets printed during the final pass."; fi; label (btex Some label text etex, (0,0)); \stopMPcode \stoptext