Open main menu

Changes

1,650 bytes added ,  10:11, 16 December 2021
Add hints on bracket usage; c&p from the list: https://www.mail-archive.com/ntg-context@ntg.nl/msg87937.html
< [[Main Page]]= Programming Topics =
== Using variables ConTeXt Features ==* [[Modes]]: Conditional processing of text* [[Setups]]: An alternative to macros for storing chunks of code
== Commands and Arguments ==* [[System Macros]] (''Recommended reading''. Topics: temporary variables, expansion control, argument grabbing and handling, definitions and assignments, branches and decisions, cases, comma separated lists, assignments and parameters, user interaction.)* [[Programming in LuaTeX]] (Topic: alleviating the more cumbersome sides of TeX programming.)* [[Commands with KeyVal arguments|Commands with Key=Value arguments]]: (Topic: things like <texcodecode>\setvariablescommand[namespacethiskey=thatvalue]</code>.) * [[keyCommands with optional arguments]]: (Topic: one or more optional arguments within brackets.) == Module Parameters ==value* [[Module Parameters]]: Passing parameters to modules. == Programming Techniques ==* [[Processing Lists]]: Processing lists of values* [[Counters]]: Manipulating counters in context* [[Expressions]]: Evaluating expressions of type number, dimen, glue or muglue* [[Executesystemcommand]]: process contents of an environment by another program* Loops and expansion [http://randomdeterminism.wordpress.com/2009/03/05/tex-programming-the-past-the-present-and-the-future/ (blog post)] == Debugging ==\getvariable{namespace}{key}* [[Console Mode]]: Using ConTeXt on keyboard input directly, rather than loading a <tt>.tex</texcodett>file. = Use of brackets = One must '''not''' confuse with the LaTeX convention where "mandatory"arguments are contained in curly braces and brackets indicate"optional" arguments.
== Defining new commands ==Curly braces not only give grouping but generally'''Special characters are used for objects to be typeset, as for \in command names'''{Figure}{a} [fig:ref].
Some commands have special characters in their namesFor new users, it is worth repeating here that TeX normally does not consider to arguments within bracescan be either a comma-separated list of words OR a comma-separatedletters: <tt>@</tt>list of keyword=value pairs, <tt>!</tt> and <tt>?</tt>BUT NOT A MIXTURE OF BOTH. Generally, aBefore and after the use or definition of such protected commands in your input fileskeyword=value exists for all words, the catcode of these for example \cite[authoryear][ref]characters has to be changed. This is done by <cmd>unprotect</cmd> and <cmd>protect</cmd>:\cite[alternative=authoryear,reference=ref]
<texcode>values can be grouped using curly braces, as in\unprotect\def\!testcite[alternative=authoryear,lefttext={{alfasee } ,}][ref1,ref2] where the\protect lefttext is associated with the first cite reference (and none with the</texcode>second). This can be tricky but is in fact rather straight-forward.
The newly defined command <tt>\!test</tt> can of course only be called upon when we are in the <cmd>unprotect</cmd>ed state, otherwise TeX reads the command <tt>\!</tt>, followed by the word <tt>test</tt> (and probably complains loudly about not being in math mode). These protection/unprotection commands can be nested. When the nesting becomes deeper than one level, the system reports the current protection level. It is a good habit to always start your macro files with <cmd>unprotect</cmd> and end them with <cmd>protect</cmd>.= Using variables =
'''See also''':There are several ways to handle variables in ConTeXt.The recommended and easiest method is to use the[[Commands with KeyVal arguments|Commands with Key=Value arguments]], <tt>\setvariables</tt> and <tt>\getvariable</tt> macros.[[Commands Doing it this way you also avoid to get in conflict with optional arguments]]>already defined stuff (as variables use their own namespace).
== Processing lists of values ==To store variables, you can use the <tt>\setvariables</tt>=== Processing a comma-separated list of values ===macro.
Suppose you defined a command like this one somewhere in your document:
<texcode>
% stores value in variable namespace:key\defsetvariables[namespace][key=value]% stores the expanded value\IHaveTo#1#2{I have to #1 on #2.setevariables[namespace][key=value]% global\par}setgvariables[namespace][key=value]% global and expanded value\setxvariables[namespace][key=value]
</texcode>
 Use <tt>\getvariable</tt> to process a variable. Reading an undefinedvariable results in the <tt>\empty</tt> token. This is not a serious problem,as long as you expect text only.But be warned: the compilation process breaks, if you expect a dimensionor number. So callingbetter take care, that you define your variables, before you use them. 
<texcode>
% gets value of the variable namespace:key\IHaveTogetvariable{tidy upnamespace}{Mondaykey}
</texcode>
Will print out
I have to tidy up on Monday.
But sometimes you have To avoid problems, also pay attention to repeat some task more than oncethe following: You can set several variables (same namespace) at the same time. In this case you can define a new So the command:<texcodett>\def\MyMumOrderedMeTo[#1]#2% {\processcommalist[#1]{\IHaveTo{#2}}}setvariables</texcodett>logically uses the '''plural''' formCallingand works with '''square brackets'''.<texcode>\MyMumOrderedMeTo[Monday,WednesdayOn the other hand you can only process one variable at the same time,Saturday]{tidy up}</texcode>sowill spare you some typing <itt>(however not tidying up!)\getvariable</itt>:uses the '''singular''' form and works with '''braces'''.
I have OK, here comes a simple example. Let's say, that we want to tidy up on Monday. I have to tidy up on Wednesday.variable I have to tidy up on Saturdayspace before and after a letter macro called <tt>\Opening</tt>.
In case a command <tt>\IHaveTo</tt> is already defined in a slightly different way:
<texcode>
\long\def\IHaveTo[Opening#1]#2{I have to #2 on #1.\par}%</texcode>you can define <tt> \MyMumOrderedMeTo</tt> asgetvariable{Letter:opening}{before}<texcode> \defnoindent{\MyMumOrderedMeTo[begstrut#1]#2%\endstrut} {\begingroup \def\processitem##1getvariable{\IHaveTo[##1]Letter:opening}{#2}after}% \processcommalist[#1]\processitem \endgroup}
</texcode>
=== Processing By using variables in your macros, you can separate the layout definition,so that your macros get much more flexible.Just ensure, that all variables are set, before you use them! In this example we want to have a dash-separated list blank line in front of values ===the opening, andtwo blank lines right after it. The value for the second key containssquare brackets, so it must be enclosed in braces.
Sometimes you have more work to do than just that borring stuff at home. And as it is quite important as well, you don't want to loose your time enumerating all of the tasks. Being able to do something like
<texcode>
\IHaveToDoTheTaskssetvariables[1-4Letter:opening] [before=\blank,7 after={\blank[2*big]},9-11 ]{until tomorrow}
</texcode>
may sound like a good idea.
Suppose you already defined:You can now save this style setup (among others) in a separate file andinclude it at the start of your document (before <texcodett>\def\IHaveToDoTheTask[#1]#2{The task #1 has to be done #2.\par}Opening</texcodett>isdefined or at least used).
You have to define some macros first (thanks to Taco!)And don't forget:<texcode>% a few auxiliary core macros '''Ensure that all variables are needed to uncompress the list.%% \uncompresslist is the twin of the already existing \compresslist% which works in the other direction (syst-new)%\unprotectset before you use them!'''
% I guess this function is already available but couldnt find it...== CLD ==%\def\apptomacHow to pass variable from TeX to Lua and vice versa? See [[CLD_passing_variables#1#2% {\ifx#1\empty\def#1{#2}\else \@EA\def\@EA#1\@EA{#1,#2}\fi}Variables|CLD passing variables]].
% the next macro does this:%% \itemwithdash<<9-11>>- => \dorecurse {<<1+11-9>>}% {\apptomac\uncompressedlist<<9-1+\recurselevel>>}%% (the 1+ and -1 are needed to solve a counter offset.)\def\itemwithdash#1-#2-% {\@EA\dorecurse\@EA {\the\numexpr 1+#2-#1\relax}% {\@EA\apptomac\@EA\uncompressedlist\@EA {\the\numexpr #1-1+\recurselevel\relax}}}%Defining new commands =
% top level. The result will be == Special characters in \uncompressedlist\def\uncompresslist[#1]% {\def\uncompressedlist{}% \def\processitem##1% {\doifinstringelse{-}{##1} {\itemwithdash##1-} {\apptomac\uncompressedlist{##1}}}% \processcommalist[#1]\processitem }command names ==
\protectSome commands have special characters in their names, that TeX normally does not consider to be letters: <tt>@</tt>, <tt>!</tt> and <tt>?</texcodett>. Before and after the use or definition of such protected commands in your input files, the catcode of these characters has to be changed. This is done by {{cmd|unprotect}} and {{cmd|protect}}:
And then you're ready to define
<texcode>
\def\IHaveToDoTheTasks[#1]#2%unprotect {\begingroup def\uncompresslist[#1]% <= Yeah! \def\processitem##1test{\IHaveToDoTheTask[##1]{#2}alfa}% \processcommacommand[\uncompressedlist]\processitem \endgroup}protect
</texcode>
Guess whatThe newly defined command <tt>\! Your test</tt> can of course only be called upon when we are in the {{cmd|unprotect}}ed state, otherwise TeX reads the command <tt>\IHaveToDoTheTasks[1-4!</tt>,7,9-11]{until tomorrow}followed by the word <tt>test</tt> resulted (and probably complains loudly about not being in: The task 1 has to be done until tomorrowmath mode). The task 2 has to These protection/unprotection commands can be done until tomorrownested. The task 3 has to be done until tomorrowWhen the nesting becomes deeper than one level, the system reports the current protection level. The task 4 has It is a good habit to be done until tomorrow. The task 7 has to be done until tomorrow. The task 9 has to be done until tomorrow. The task 10 has to be done until tomorrow. The task 11 has to be done until tomorrowalways start your macro files with {{cmd|unprotect}} and end them with {{cmd|protect}}.
So - what are you still waiting for? Go back to work and do them right away!
=Passing verbatim text as macro parameter == Comments ===Resulted from thread [http://archive.contextgarden.net/thread/20050704.151237.f815d89d.html] and will be used in some modules such as [[RawSteps]]. It would be nice if processing dash-separated lists of values would make it into the ConTeXt core.
 == Passing (For passing text to LuaTex verbatim text as macro parameter ==, see the [[Programming_in_LuaTeX#Manipulating_verbatim_text_for_dummies|Programming in LuaTeX]] article on this wiki.)
In case you want to write macros that should handle verbatim text,
\framed{\obeyspaces{A gap from here to there!}}
</texcode>
 
<context>
\framed{\obeyspaces{A gap from here to there!}}
</context>
But if you pass this text as a parameter for your own macro
<texcode>
\def\TextWithSpaces#1{\framed{\obeyspaces#1}}%
\TextWithSpaces{A gap from here to there!}
</texcode>
<context>
\def\TextWithSpaces#1{\framed{\obeyspaces#1}}%
\TextWithSpaces{A gap from here to there!}
</texcodecontext>
the additional spaces are '''ignored'''.
The cause for this behavior is, that This happens because the category code changeis not yet in effect whenstill has no effect herethe argument is parsed, and the spaces are removed during parsing. The To keepthe spaces, the catcode change must be done, '''before''' youpass the parameterargument is parsed.
Here is a two-part solution for the problem (''suggested by Taco Hoekwater''):
\def\doTextWithSpaces #1{#1\egroup}
</texcode>
 
Both of these produce the desired result:
 
<context>
\def \TextWithSpaces {\framed\bgroup\obeyspaces\doTextWithSpaces}
\def\doTextWithSpaces #1{#1\egroup}
 
\TextWithSpaces{A gap from here to there!}
</context>
 
[[Category:Programming and Databases]]
[[Category:Tools]]
57

edits