Is there any difference between defining a variable using \def
and using \define
, when used without a number inside square brackets, e.g. \def\somecommand{\percent}
and \define\somecommand{\percent}
? Can I always use \define
in places where \def
can be used?
[Tex/LaTex] Are \def and \define the same in ConTeXt
contextcontext-mkiv
Related Solutions
I agree with you that exploiting the document structure is a convenient choice for this end: it offers a high degree of configurability and comes with neat extras like list (read: table of contents) building by default. So the following will be a structure based solution, leaving the enumerations based approach to somebody else.
The trick is the ownnumbers key of structure headers.
It allows precise control over the counter mechanism for every head.
Headers that are defined with ownnumbers=yes
take a mandatory first argument by means of which their counter value can be set explicitly.
Counters created by \definecounter
each have their own way key that allows fine-grained control of the reset, or disabling it as required by this question (way=text
).
Once the counters are in place, all that’s left is to suppress placement of the structure title element.
This is done in two parts: First, all headers are defined to be accessed only implicitly.
The user level macros \week
, \activity
and \presentation
are wrappers that at the same time pass the headers their “ownnumbers” and an empty title string.
Second, placement method \activityhead
is defined that chooses the display string from a mapping of labels, ignoring the structure title altogether.
(Coding style is mkiv for consistency as \defineheadplacement
does not support named arguments.)
\unprotect
%% (1) define the base commands. Notice the “ownnumber” key in
%% \base_presentation and \base_activity. This lets us supply an
%% independent numbering scheme.
\definehead [base_week] [chapter]
\definehead [base_activity] [section]
\definehead [base_presentation] [section]
\setuphead [part]
[sectionresetset=default]
\setuphead [base_week]
[number=yes,alternative=activityhead,
sectionsegments=chapter]
\setuphead [base_activity]
[number=yes,alternative=activityhead,
sectionsegments=section,ownnumber=yes,
before={\blank[line]\incrementcounter[activity]},]
\setuphead [base_presentation]
[number=yes,alternative=activityhead,
sectionsegments=section,ownnumber=yes,
before={\blank[line]\incrementcounter[presentation]},]
%% (2) define a placement method for headings that omits the title.
\defineheadplacement[activityhead][vertical]#1#2{%
\labeltext{\currenthead}\hskip\numberheaddistance #1%
}
%% (3) heading text is static so we use labels.
%% The following line is cramped due to an exception in option
%% parsing.
%% Cf. http://archive.contextgarden.net/message/20120611.090327.dd9b1347.en.html
\setuplabeltext[base_week=Week,base_activity=Activity,base_presentation=Presentation]
%% (4a) define counters for use with the “presentation” and “activity”
%% heads.
\definecounter [presentation] [start=0,way=text]
\definecounter [activity] [start=0,way=text]
%% (4b) define a reset trigger for the part structural.
\definestructureresetset [default] [0] [0]
%% (5) define a set of wrappers. These compensate for the fact that you
%% can’t have a simple structure head without the mandatory
%% argument. We start with a plain one.
\define \week{\base_week{}}
%% The “\presentation” and “\activity” macros need special treatment
%% to make it respect the separate counter.
\define \activity{\base_activity {\rawcountervalue[activity]} \empty}
\define\presentation{\base_presentation{\rawcountervalue[presentation]}\empty}
%% (6) side effect: the table of contents needs a placement method on
%% its own in order to conform with the requirements. This step is
%% optional if you don’t care for a toc.
\unexpanded\def\week_list#1#2#3{%
\blank[line]%
{\tfa\word\sc\labeltext{\currentlist}}%
\space#1\hfill#3\par
}
\unexpanded\def\activity_list#1#2#3{%
\hskip\emwidth
\labeltext{\currentlist}%
\space#1\hfill#3\par
}
\setuplist [base_week] [alternative=command,command=\week_list]
\setuplist [base_activity] [alternative=command,command=\activity_list]
\setuplist [base_presentation] [alternative=command,command=\activity_list]
\protect
\starttext
\placelist[base_week, base_activity, base_presentation]\page
\part {My Life ...}
\week
\activity
Dear diary. Today I was pompous and my sister was crazy.
\activity
This is some text.
\activity
This is some text.
\week
\activity
This is some more text.
\presentation
This is some more text.
\activity
This is some more text.
\activity
This is some more text.
\part{... the Exciting Story of a Great Man}
\week
\activity
This is yet some more text.
\presentation
This is yet some more text.
\activity
This is yet some more text.
\stoptext
How can I set ConTeXt to automatically switch fonts when I switch to a different language?
There might be a misconception involved here as to what \language[foo]
actually does. It changes the current hyphenation rules, but is by no means a switch to another script and/or type face.
For this reason your question can be interpreted in (at least) two ways:
- You want to be able to use another script once you did a
\language[...]
. - You want a generic language environment switch.
The first variant is best implemented using font fallbacks and will work even without the \language
command. This can be considered a cheap and easy solution. The second approach might appear more complicated at the first glance, but it integrates neatly with the overall interface and is extensible with other language related features (text direction, transliteration, emphases etc.) if needed.
Below examples will use Russian for demonstration but should work with any defined language.
The Fallback Method: First we need a list of the codepoint ranges for subsitution, in this case the four defined Cyrillic ranges. The first in the list would already cover contemporary Russian but there’s no reason not to be thorough.
- 0x0400:0x04ff Cyrillic
- 0x0500:0x052f Cyrillic Supplement
- 0x2de0:0x2dff Cyrillic Extended A
- 0xa640:0xa69f Cyrillic Extended B
They are predefined in Context so we could refer to them by name. Anyways it does not hurt to address them explicitly.
In the example, we will take the fallback glyphs from Computer Modern Unicode which provide a sufficiently close match for Latin Modern. (The CMU fonts are part of TEX Live.) For each of the four varieties regular, italic, bold, bold italic of the serif type face we need a different fallback, because we want Context to substitute glyphs from the appropriate CMU font. After that the fallbacks are ready for use in our typescript, here under the name mainfont.
\definefontfallback [cyrillic_regular] [name:CMUSerifRoman]
[0x0400:0x04ff,0x0500:0x052f,0x2de0:0x2dff,0xa640:0xa69f] [force=yes]
\definefontfallback [cyrillic_bold] [name:CMUSerifBold]
[0x0400:0x04ff,0x0500:0x052f,0x2de0:0x2dff,0xa640:0xa69f] [force=yes]
\definefontfallback [cyrillic_italic] [name:CMUSerifItalic]
[0x0400:0x04ff,0x0500:0x052f,0x2de0:0x2dff,0xa640:0xa69f] [force=yes]
\definefontfallback [cyrillic_bolditalic] [name:CMUSerifBoldItalic]
[0x0400:0x04ff,0x0500:0x052f,0x2de0:0x2dff,0xa640:0xa69f] [force=yes]
%% Now we hook the fallbacks into their respective type faces.
\starttypescript [serif] [mainfont]
\setups[font:fallback:serif]
\definefontsynonym [Serif] [name:Latin Modern Roman] [fallbacks=cyrillic_regular]
\definefontsynonym [SerifBold] [name:Latin Modern Roman Bold] [fallbacks=cyrillic_bold]
\definefontsynonym [SerifItalic] [name:Latin Modern Roman Italic] [fallbacks=cyrillic_italic]
\definefontsynonym [SerifBoldItalic] [name:Latin Modern Roman Bold Italic] [fallbacks=cyrillic_bolditalic]
\stoptypescript
%% Complete the typescript for all four type faces. Note that we default
%% to the predefined Latin Modern setups for the three other faces.
\starttypescript [mainfont]
\definetypeface [mainfont] [rm] [serif] [mainfont] [default]
\definetypeface [mainfont] [ss] [sans] [latin-modern] [default]
\definetypeface [mainfont] [tt] [mono] [latin-modern] [default]
\definetypeface [mainfont] [mm] [math] [latin-modern] [default]
\stoptypescript
%% Finally, we are ready to activate the typescript.
\setupbodyfont [mainfont,20pt]
\starttext
English {\italic English} {\bold English} {\bolditalic English}
\language[ru] %% does only switch the hyphenation pattern
Маленький мальчик нашел пулемет. Больше в деревне никто не живет. \par
{\italic Маленький мальчик нашел пулемет. Больше в деревне никто не живет.}\par
{\bold Маленький мальчик нашел пулемет. Больше в деревне никто не живет.}\par
{\bolditalic Маленький мальчик нашел пулемет. Больше в деревне никто не живет.}\par
\stoptext
The Macro Method: Just switching the font and hyphenation patterns may suffice for the occasional foreign word, but multilingual typesetting in general will have further requirements, like for instance the different spacing conventions for French. Thus a macro that can be extended on demand is of great value. Below listing gives the skeleton code for a Context-style macro generator \definelazylanguage
, which comes with the companion \setuplazylanguage
. It allows defining commands that, in this basic form, handle both pattern and font switching. All definitions will create (1) an ordinary macro \foo{...}
and (2) the complementing \startfoo
/ \stopfoo
environment. These accept an optional first argument (in brackets, of course) for local setups.
EDIT: Fyi the \installnamespace
and \installcorenamespace
that make this all possible currently reside in mult-aux.mkiv, see there for further documentation.
ANOTHER EDIT: The following snippet has been revised according to a set of fixes Wolfgang just sent to me. (Many thanks!) It does not only correct a grouping bug but also exploits the namespace functionality more efficiently than the previous version.
% macros=mkvi
\unprotect
\installnamespace {lazylanguage}
\installcommandhandler \????lazylanguage {lazylanguage} \????lazylanguage
\appendtoks
\setuevalue {\currentlazylanguage}{\lazylanguage_direct[\currentlazylanguage]}%
\setuevalue{\e!start\currentlazylanguage}{\lazylanguage_start [\currentlazylanguage]}%
\setuevalue{\e!stop \currentlazylanguage}{\lazylanguage_stop }%
\to \everydefinelazylanguage
\unexpanded\def\lazylanguage_direct[#id]%
{\edef\currentlazylanguage{#id}%
\dosingleempty\lazylanguage_direct_indeed}
\def\lazylanguage_direct_indeed[#options]%
{\groupedcommand
{\lazylanguage_start_indeed[#options]}%
\donothing}
\unexpanded\def\lazylanguage_start[#id]%
{\bgroup
\edef\currentlazylanguage{#id}%
\dosingleempty\lazylanguage_start_indeed}
% %% This is the macro that implements the core switching functionality.
\def\lazylanguage_start_indeed[#options]%
{\iffirstargument
\setupcurrentlazylanguage[#options]%
\fi
%% Here would be the place where you can hook further language
%% settings into your command, imitating the pattern of below
%% expressions.
\language[\lazylanguageparameter{patterns}]
\doifsomething{\lazylanguageparameter{bodyfont}}
{\switchtobodyfont[\lazylanguageparameter{bodyfont}]}}
\let\lazylanguage_stop\egroup
\protect
\definelazylanguage [lru]
\setuplazylanguage [lru] [
bodyfont=antykwa,
patterns=ru,
]
\startlru
Маленький мальчик нашел пулемет. Больше в деревне никто не живет. \par
{\italic Маленький мальчик нашел пулемет. Больше в деревне никто не живет.}\par
{\bold Маленький мальчик нашел пулемет. Больше в деревне никто не живет.}\par
{\bolditalic Маленький мальчик нашел пулемет. Больше в деревне никто не живет.}\par
\stoplru
English {\italic English} {\bold English} {\bolditalic English}
\stoptext
Note that the code might look confusing at first but that’s because of the multiple levels of wrapping, so it’s actually a feature =). All you need to understand is that the real action is taking place inside the macro \lazylanguage_start_indeed
, where you can alway hook further parameters according to the following scheme:
\doifsomething{\lazylanguageparameter{<parametername>}}
{\lazylanguageparameter{<parametername>}}%
Just replace the <parametername>
dummy with a key of your choice and you can use it in the setup.
Best Answer
For reference: There are two definitions of
\define
: The first one in syst-aux.mkiv shows the behavior Egreg mentioned in his comment: if the macro is already defined, it leaves it as it is. (A companion,\redefine
allows you to overwrite the current definition of macro regardless of its being in use.) Ironically, this preliminary definition is overwritten without note as soon as the format loads core-sys.mkiv (while\redefine
stays around forever).The actual definition of the
\define
macro as provided by the user interface does not only check for previously defined control sequences of the same name, but also serves as some kind of short notation for mandatory arguments. It has the schemewhere the first argument, a digit, specifies the number of arguments the new macro is going to accept. Obviously this can result in shorter definitions. For comparison, the selector
requires some less typing with the
\define
macro:Thus these definitions may result in more readable code -- which is always a good thing when writing TEX.
Unfortunately the
\define
wrapper takes away a good deal of the expressiveness of plain\def
’s. In Context, you will have noticed, macros taking optional arguments are commonplace with respect to the user inteface. For example you simply can’t replace the second\def
inition in below snippet with an equivalent expression using\define
:That’s because with
\define
you can’t specify the argument delimiters (here: brackets) necessary for optional arguments, so basically your macros are limited to taking mandatory (braced) arguments only. For the same reason there is no way to define cheap\{start|stop}something
environments either:(The user interface for this is
\definestartstop
(cf. core-sys.mkiv), anyways.)Finally, nowadays the most important drawback of
\define
is that it does not allow for mkvi-style arguments. There is simply no way to refer to a parameter by its name if you can’t assign it one in the first place.So if you want to do some serious macro writing, you will soon learn to avoid
\define
, while it is safe for less complex tasks.