%D \module %D [ file=typo-lbx, %D version=2021.10.10, %D title=\CONTEXT\ Typesetting Macros, %D subtitle=Local Boxes, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \writestatus{loading}{ConTeXt Typesetting Macros / Local Boxes} % This time the usual musical timestamp is: New Scary Goldings ft. John Scofield % MonoNeon & Louis Cole (late October 2021) (plus the playlist in loop mode) and % further improved after watching Cory Wong's LIVE IN MPLS (9 FEB 2019) concert. % maybe: \iflocalbox 0/1/2 \registerctxluafile{typo-lbx}{autosuffix} %D The advantage is that it's deal with in the par builder which has some advantages %D but when used in complex situation there can be side effects. Therefore is should %D be considered a somewhat low level mechanism on top of which one can write more %D mechanisms that provide more rendering control. Also, keep in mind that combining %D many instances at the same time add some complizity. Therefore, for the moment it's %D a playground. \unprotect \def\typo_localboxes_reset {\localleftbox {}% no index here, works grouped \localrightbox {}% \localmiddlebox{}} \appendtoks \typo_localboxes_reset \to\everyforgetall \definesystemattribute[localboxesmark][public] %D We used to pass arguments but there might be many so ... \newbox\localboxcontentbox \installcorenamespace{localboxes} \installcorenamespace{localboxesattribute} \installcorenamespace{localboxesnamespace} \installcorenamespace{localboxeslocations} \installcorenamespace{localboxesresetters} \installcommandhandler \??localboxes {localboxes} \??localboxes \setuplocalboxes [\c!command=\localboxcontent, \c!width=\zeropoint, \c!location=\v!left, \c!distance=\zeropoint] \newinteger\c_typo_localboxes \newinteger\c_typo_localboxes_index \appendtoks \global\advanceby\c_typo_localboxes\plusone \global\expandafter\integerdef\csname\??localboxesattribute\currentlocalboxes\endcsname\c_typo_localboxes \gletcsname\??localboxesnamespace\number\c_typo_localboxes\endcsname\currentlocalboxes \to \everydefinelocalboxes %D The optional argument forces setting the \quote {whole} paragraph properties (which is needed %D when the assignment happens after e.g.\ \type {\everypar} but is also meant for the first %D line. %D Todo: reserve index 1 for this: \def\typo_paragraphs_l#1{\localleftbox \ifcstok{#1}\v!global par\fi} \def\typo_paragraphs_r#1{\localrightbox \ifcstok{#1}\v!global par\fi} \def\typo_paragraphs_m#1{\localmiddlebox\ifcstok{#1}\v!global par\fi} \permanent\tolerant\protected\def\leftparbox [#1]{\typo_paragraphs_l{#1}\bgroup\enforced\let\leftparbox \relax\let\next} \permanent\tolerant\protected\def\rightparbox [#1]{\typo_paragraphs_r{#1}\bgroup\enforced\let\rightparbox\relax\let\next} \permanent\tolerant\protected\def\middleparbox[#1]{\typo_paragraphs_m{#1}\bgroup\enforced\let\rightparbox\relax\let\next} % called back: \permanent\protected\def\localboxcontent {\box\localboxcontentbox} \permanent\protected\def\localboxcommand {\ifcsname\??localboxesnamespace\number\localboxindex\endcsname %\edef\currentlocalboxes{\lastnamedcs}% \expandafter\let\expandafter\currentlocalboxes\lastnamedcs \setbox\localboxcontentbox\hbox {\uselocalboxesstyleandcolor\c!style\c!color % sometimes redundant \localboxesparameter\c!command}% \fi} %D We don't group because we set the local boxes. Also, watch out: by injecting the %D existing local box we create nested ones. This is handled in the callback but if %D really needed one can do something like (do we need a primitive?): \mutable\lettonothing\currentlocalboxeslocation \def\typo_localboxes_localbox {\ifx\currentlocalboxeslocation\v!right \localrightbox \orelse\ifx\currentlocalboxeslocation\v!left \localleftbox \else \localmiddlebox \fi} \def\typo_localboxes_zero#1#2#3% {\ifcsname\??localboxesattribute#2\endcsname \c_typo_localboxes_index\lastnamedcs \edef\currentlocalboxes{#2}% \edef\currentlocalboxeslocation{#1}% \typo_localboxes_localbox index \c_typo_localboxes_index \bgroup \hpack \ifcstok{\localboxesparameter\c!repeat}\v!no attr \localboxesmarkattribute \localboxmarkonce\c_typo_localboxes_index\relax \fi to \zeropoint \bgroup \uselocalboxesstyleandcolor\c!style\c!color \hbox{#3}% \hss \egroup \egroup \fi} \def\typo_localboxes_asis#1#2#3% {\ifcsname\??localboxesattribute#2\endcsname \c_typo_localboxes_index\lastnamedcs \edef\currentlocalboxes{#2}% \edef\currentlocalboxeslocation{#1}% \typo_localboxes_localbox index \c_typo_localboxes_index \bgroup \hpack \ifcstok{\localboxesparameter\c!repeat}\v!no attr \localboxesmarkattribute \localboxmarkonce\c_typo_localboxes_index\relax \fi % todo: use width if dimension, use distance if given \bgroup \uselocalboxesstyleandcolor\c!style\c!color \hbox{#3}% no \hss \egroup \egroup \fi} \defcsname\??localboxeslocations\v!left \endcsname{\typo_localboxes_zero\v!left } \defcsname\??localboxeslocations\v!right \endcsname{\typo_localboxes_zero\v!right } \defcsname\??localboxeslocations\v!lefttext \endcsname{\typo_localboxes_asis\v!left } \defcsname\??localboxeslocations\v!righttext\endcsname{\typo_localboxes_asis\v!right } \defcsname\??localboxeslocations\v!middle \endcsname{\typo_localboxes_asis\v!middle} \letcsname\??localboxesresetters\v!left \endcsname\v!left \letcsname\??localboxesresetters\v!right \endcsname\v!right \letcsname\??localboxesresetters\v!lefttext \endcsname\v!left \letcsname\??localboxesresetters\v!righttext\endcsname\v!right \letcsname\??localboxesresetters\v!middle \endcsname\v!middle \permanent\tolerant\protected\def\resetlocalbox[#1]% {\ifcsname\??localboxesattribute#1\endcsname \c_typo_localboxes_index\lastnamedcs \edef\currentlocalboxes{#1}% \ifcsname\??localboxesresetters\localboxesparameter\c!location\endcsname \edef\currentlocalboxeslocation{\lastnamedcs}% \typo_localboxes_localbox index \c_typo_localboxes_index {}% \fi \fi} \def\typo_localboxes_box#1% {\dowithnextboxcontent {\edef\currentlocalboxes{#1}% \uselocalboxesstyleandcolor\c!style\c!color} {\ifcsname\??localboxeslocations\namedlocalboxesparameter{#1}\c!location\endcsname \expandafter\lastnamedcs \else \csname\??localboxeslocations\v!left\expandafter\endcsname \fi{#1}{\unhbox\nextbox}}} \permanent\tolerant\protected\def\localbox[#1]% {\typo_localboxes_box{#1}\hbox} \permanent\tolerant\protected\def\startlocalbox[#1]% {\dowithnextbox {\ifcsname\??localboxeslocations\namedlocalboxesparameter{#1}\c!location\endcsname \expandafter\lastnamedcs \else \csname\??localboxeslocations\v!left\expandafter\endcsname \fi{#1}{\unhbox\nextbox}}% \hbox\bgroup \edef\currentlocalboxes{#1}% \uselocalboxesstyleandcolor\c!style\c!color \enforced\def\stoplocalbox{\removeunwantedspaces\egroup}% \ignorespaces} \aliased\let\stoplocalbox\donothing \permanent\tolerant\protected\def\startlocalboxrange[#1]% {\globalpushmacro\stoplocalboxrange \ifcsname\??localboxeslocations\namedlocalboxesparameter{#1}\c!location\endcsname \lastnamedcs{#1}{}% \fi} \permanent\protected\def\stoplocalboxrange {\globalpopmacro\stoplocalboxrange}% % using left and right with left lagging behind: % % \permanent\protected\def\localmarginlefttext#1% % {\setbox\localboxcontentbox\hpack % {\unhbox\localboxcontentbox % \setbox\localboxcontentbox\lastbox % \unhbox\localboxcontentbox}% % \hpack xoffset -\dimexpr % #1 % +\localboxprogress % +\localboxleftoffset % +\wd\localboxcontentbox % +\localboxesparameter\c!distance % \relax{\box\localboxcontentbox}} % % \permanent\protected\def\localmarginrighttext#1% % {\hpack xoffset \dimexpr % #1 % +\localboxrightoffset % +\localboxlocalwidth % -\localboxprogress % +\localboxesparameter\c!distance % \relax{\box\localboxcontentbox}} % using middle: \permanent\protected\def\localmarginlefttext#1% {\ifzeropt\localboxesparameter\c!width\relax % a but ugly hack ... for now \setbox\localboxcontentbox\hpack {\unhbox\localboxcontentbox \setbox\localboxcontentbox\lastbox \unhbox\localboxcontentbox}% \fi \hpack xoffset \dimexpr -#1 -\localboxprogress -\wd\localboxcontentbox -\localboxesparameter\c!distance \relax{\box\localboxcontentbox}} \permanent\protected\def\localmarginrighttext#1% {\hpack xoffset \dimexpr #1 +\localboxlinewidth -\localboxprogress +\localboxesparameter\c!distance \relax{\box\localboxcontentbox}} % todo: use generic one above \permanent\protected\def\localmargintext[#1]#2% {\dontleavehmode \ifcsname\??localboxesattribute#1\endcsname \c_typo_localboxes_index\lastnamedcs \edef\currentlocalboxes{#1}% \edef\currentlocalboxeslocation{\localboxesparameter\c!location}% \ifx\currentlocalboxeslocation\v!right\localrightbox\orelse\ifx\currentlocalboxeslocation\v!left\localleftbox\else\localmiddlebox\fi index \c_typo_localboxes_index \bgroup \hpack \ifcstok{\localboxesparameter\c!repeat}\v!no attr \localboxesmarkattribute \localboxmarkonce\c_typo_localboxes_index\relax \fi to \zeropoint \bgroup \uselocalboxesstyleandcolor\c!style\c!color \hbox{#2}% \hss \egroup \egroup \fi} \definelocalboxes [\v!leftmargin] [\c!command=\localmarginlefttext\zeropoint, \c!repeat=\v!no, \c!distance=\leftmargindistance, % \c!location=\v!left] \c!location=\v!middle] \definelocalboxes [\v!rightmargin] [\c!command=\localmarginrighttext\zeropoint, \c!repeat=\v!no, \c!distance=\rightmargindistance, % \c!location=\v!right] \c!location=\v!middle] \definelocalboxes [\v!leftedge] [\c!command=\localmarginlefttext\leftmargintotal, \c!repeat=\v!no, \c!distance=\leftedgedistance, % \c!location=\v!left] \c!location=\v!middle] \definelocalboxes [\v!rightedge] [\c!command=\localmarginrighttext\rightmargintotal, \c!repeat=\v!no, \c!distance=\rightedgedistance, % \c!location=\v!right] \c!location=\v!middle] %D Here is an example of usage: %D \starttyping %D \definelocalboxes %D [linenumber] %D [command=\LeftNumber,location=left,width=3em,style=\bs,color=darkred] %D %D \definelocalboxes %D [linenumbertwo] [linenumber] %D [command=\RightNumber,location=right,width=6em,style=\bf,color=darkgreen] %D %D \definelocalboxes %D [linetext] %D [command=\LeftText,location=lefttext,style=\bs,color=darkblue] %D %D \definelocalboxes %D [linetexttwo] [linetext] %D [command=\RightText,location=righttext,style=\bf,color=darkgray] %D %D % \def\LineNumberL{\the\localboxlinenumber} %D % \def\LineNumberR{\the\localboxlinenumber} %D %D % \newinteger\MyLineNumberL %D % \newinteger\MyLineNumberR %D % \def\LineNumberL{\global\advanceby\MyLineNumberL\plusone\the\MyLineNumberL} %D % \def\LineNumberR{\global\advanceby\MyLineNumberR\plusone\the\MyLineNumberR} %D %D \definecounter[MyLineNumberL] %D \definecounter[MyLineNumberR] %D %D \setupcounter[MyLineNumberL][numberconversion=characters] %D \setupcounter[MyLineNumberR][numberconversion=romannumerals] %D %D \def\LineNumberL{\incrementcounter[MyLineNumberL]\convertedcounter[MyLineNumberL]} %D \def\LineNumberR{\incrementcounter[MyLineNumberR]\convertedcounter[MyLineNumberR]} %D %D \protected\def\LeftNumber {\hbox to \localboxesparameter{width}{\strut(\LineNumberL\hss)}} %D \protected\def\RightNumber{\hbox to \localboxesparameter{width}{\strut(\hss\LineNumberR)}} %D %D % \protected\def\LeftNumber {\hbox to \localboxesparameter{width}{\strut\box\localboxcontentbox\hss)}} %D % \protected\def\RightNumber{\hbox to \localboxesparameter{width}{\strut(\hss\box\localboxcontentbox)}} %D %D \protected\def\LeftText {\localboxcontentbox\quad} %D \protected\def\RightText{\quad\localboxcontentbox} %D %D \start %D \localbox[linenumber]{}% %D \localbox[linenumbertwo]{}% %D \localbox[linetext]{L}% %D \startlocalbox[linetexttwo] %D R %D \stoplocalbox %D \dorecurse{100}{ %D \samplefile{tufte} %D \par %D } %D \stop %D \stoptyping \protect \endinput