Hi,

Among the 'can they be made better' candidates in the engine are \vadjust and \local[left|right]box primitives that are not really used in context (okay, vadjust is used in mkii).

The \vadjust vertical injector can be illustrated with

\starttext
    \ignorespaces\input tufte \removeunwantedspaces
    we want a break before this line \vadjust pre {\break}%
    \ignorespaces\input tufte \removeunwantedspaces

    \page

    \ignorespaces\input tufte \removeunwantedspaces
    we want seperate lines now \leftparbox{\vadjust post {\break}}%
    \ignorespaces\input tufte \removeunwantedspaces
    \resetleftparbox{}
\stoptext

It's a signal that injects something in a vertical list without interupting the horizontal text flow. One can inject before (pre) or after (post which is default). New is that we can also influence the order: after vs before preceding \vadjust in the same line. Also new is that deeply nested adjustments can migrate (so the hole los: marks, inserts and vadjust are now in sync) which is demonstrated with the next example:

\starttext
    \showstruts
    \input tufte \removeunwantedspaces\space
    \localleftbox  par {%
       \hbox to 0pt{%
          \llap{L}%
          \vadjust{\strut\blackrule[width=1cm,color=red]}%
          \hbox{\vadjust pre{\strut\blackrule[width=1cm,color=green]}}%
       }\hss
    }%
    \localrightbox par {}%
    \input tufte \removeunwantedspaces\space
    \vadjust pre    {\strut BEFORE 1}%
    \vadjust pre    {\strut BEFORE 2}%
    \vadjust before {\strut AFTER  1}%
    \vadjust before {\strut AFTER  2}%
    \ignorespaces
    \input tufte
\stoptext

Indeed it looks bad (ugly) but it illustrates the idea. What makes vadjust sort of useless for content is that it messes up spacing (but if there is real demand and usage i can sort that out at some point, maybe some new options or so). Thsi example also brings us to local boxes:

\showframe

\starttext

\showmakeup[hbox]

\startnarrower[2*left] \raggedleft
{\localleftbox par {L1}\input tufte  \par}
\stopnarrower
\blank

\startnarrower[2*middle] \raggedcenter
{\localrightbox par {R1}\input tufte  \par}
\stopnarrower
\blank

\stoptext

New is the par keyword that forces the setting to be applied from the first line downards (fyio: these commands, when display set registers, when inline they set registers and inject a node). Watch out: one needs to use grouping in order not to bleed into other mechanisms.

Also new is that we can query the content of these registers using \the, as in:

\dorecurse{10}{
    \showboxes
    \localleftbox{\ruledhbox {\smallinfofont\setstrut\strut[L #1.0]}}%
\localleftbox{\ruledhbox {\smallinfofont\setstrut\strut[L #1.1]}\the\localleftbox}% \localleftbox{\ruledhbox {\smallinfofont\setstrut\strut[L #1.2]}\the\localleftbox}% \localleftbox{\ruledhbox {\smallinfofont\setstrut\strut[L #1.3]}\the\localleftbox}%
    %
\localrightbox{\ruledhbox {\smallinfofont\setstrut\strut[R #1.0]}}%

\localrightbox{\the\localrightbox\ruledhbox{\smallinfofont\setstrut\strut[R #1.1]}}%

\localrightbox{\the\localrightbox\ruledhbox{\smallinfofont\setstrut\strut[R #1.2]}}%
    \localrightbox{\the\localrightbox\ruledhbox{\smallinfofont[R #1.3]}}%
    % \localrightbox{}%
    \samplefile{tufte}
}

Flushing permits us to append and prepend but it's still ugly so that is why we now have a new interface (context layer on top of engine):

\dorecurse{10}{
    \showboxes
    %
    \resetleftparbox
    \resetrightparbox
    %
    \prependleftparbox {\ruledhbox{\smallinfofont\setstrut\strut[L #1.0]}}%
    \prependleftparbox {\ruledhbox{\smallinfofont\setstrut\strut[L #1.1]}}%
    \prependleftparbox {\ruledhbox{\smallinfofont\setstrut\strut[L #1.2]}}%
    \prependleftparbox {\ruledhbox{\smallinfofont\setstrut\strut[L #1.3]}}%
    %
    \appendrightparbox{\ruledhbox{\smallinfofont\setstrut\strut[R #1.0]}}%
    \appendrightparbox{\ruledhbox{\smallinfofont\setstrut\strut[R #1.1]}}%
    \appendrightparbox{\ruledhbox{\smallinfofont\setstrut\strut[R #1.2]}}%
    \appendrightparbox{\ruledhbox{\smallinfofont[R #1.3]}}%
    %
    \samplefile{tufte}
}

But as this is not really user friendly, there is more: a mechanism for hooking in handlers.

\definelocalboxes
  [linenumber]
  [command=\LeftNumber,
   location=left,
   width=3em,
   style=\bs,
   color=darkred]

\definelocalboxes
  [linenumbertwo]
  [linenumber]
  [command=\RightNumber,
   location=right,
   width=6em,
   style=\bf,
   color=darkgreen]

\definelocalboxes
  [linetext]
  [command=\LeftText,
   location=lefttext,
   style=\bs,
   color=darkblue]

\definelocalboxes
  [linetexttwo]
  [linetext]
  [command=\RightText,
   location=righttext,
   style=\bf,
   color=darkgray]

% just using the content

% \protected\def\LeftNumber {\hbox to \localboxesparameter{width}{\strut\box\localboxcontentbox\hss)}} % \protected\def\RightNumber{\hbox to \localboxesparameter{width}{\strut(\hss\box\localboxcontentbox)}}

% using the provided line number:

% \def\LineNumberL{\the\localboxlinenumber}
% \def\LineNumberR{\the\localboxlinenumber}

% using a tex counter

% \newcount\MyLineNumberL
% \newcount\MyLineNumberR
% \def\LineNumberL{\global\advance\MyLineNumberL\plusone\the\MyLineNumberL}
% \def\LineNumberR{\global\advance\MyLineNumberR\plusone\the\MyLineNumberR}

% using proper counters

\definecounter[MyLineNumberL]
\definecounter[MyLineNumberR]

\setupcounter[MyLineNumberL][numberconversion=characters]
\setupcounter[MyLineNumberR][numberconversion=romannumerals]

\def\LineNumberL{\incrementcounter[MyLineNumberL]\convertedcounter[MyLineNumberL]}
\def\LineNumberR{\incrementcounter[MyLineNumberR]\convertedcounter[MyLineNumberR]}

\protected\def\LeftNumber {\hbox to \localboxesparameter{width}{\strut(\LineNumberL\hss)}} \protected\def\RightNumber{\hbox to \localboxesparameter{width}{\strut(\hss\LineNumberR)}}

\protected\def\LeftText #1{#1\quad}
\protected\def\RightText#1{\quad#1}

\showframe

\starttext

\start
    \localbox[linenumber]{}%
    \localbox[linenumbertwo]{}%
    \localbox[linetext]{L}%
    \startlocalbox[linetexttwo]
        R
    \stoplocalbox
    \dorecurse{100}{
        \samplefile{tufte}
        \par
    }
\stop

If you play a bit with these low level mechanism the luametatex / context combination now permits weird applications (which for sure some of you will (ab)use). The above example shows how to implement line numbers (there are drawbacks compared to the existing mechanisms) and other stuff in the margins and text edges but the most important aspect is that when the content in these boxes has width, it will be taken into account in the par builder because that is what this is about: these local boxes are taken into acount when breaking lines. When the handlers kick in, you have

\localboxattribute         : more for internal use
\localboxlinenumber        : as the par builder sees it
\localboxwidth             : the local box width
\localboxoffset            : the total distance to the edge
\localboxleftskip          : the effective leftskip
\localboxrightskip         : the effective rightskip
\localboxlefthang          : the current shape related value
\localboxrighthang         : the current shape related value
\localboxindent            : only first line
\localboxparfillleftskip   : effective value (onky last line)
\localboxparfillrightskip  : effective value (only last line)
\localboxovershoot         : overfull compensation

most of these relate to normalized lines and as such there is plenty to play with. Others can be seen in the examples.

I might add some more control to both these 'injection' mechanism because directly out of the (pdftex/omega/luatex) they are not that useful (which is probably also why we don't use them.) These are cheap extensions so they don't really influence runtime much, so .. when not used ... no harm done. I really have no clue how useful this is.

I need to ponder this usage:

\definelocalboxes
  [linetextA]
  [command=\LeftTextA,
   location=lefttext,
   style=\bs,
   color=darkblue]

\protected\def\LeftTextA#1{\llap{#1}\quad}

\definelocalboxes
  [linetextB]
  [command=\LeftTextB,
   location=left,
   style=\bs,
   color=darkgreen]

\protected\def\LeftTextB{\llap{\unhbox\localboxcontentbox}\quad}

\starttext

\dorecurse{10}{some text #1 }
\leftparbox {\red \bf keyword}HERE\leftparbox{}
\dorecurse{10}{some text #1 }
\blank

{\dorecurse{10}{some text #1 }
\leftparbox {\red \bf keyword}test
\dorecurse{10}{some text #1 }}
\blank

{\dorecurse{10}{some text #1 }
\localbox[linetextA]{keyword}HERE
\dorecurse{10}{some text #1 }}

{\dorecurse{10}{some text #1 }
\localbox[linetextB]{keyword}HERE
\dorecurse{10}{some text #1 }}

{\dorecurse{10}{some text #1 }
\localbox[linetextB]{keyword 1}HERE1
\dorecurse{10}{some text #1 }
\localbox[linetextB]{keyword 2}HERE2
\dorecurse{10}{some text #1 }}

\stoptext

so there's always so echallenge left.

Hans

-----------------------------------------------------------------
                                          Hans Hagen | PRAGMA ADE
              Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
       tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
-----------------------------------------------------------------
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the 
Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

Reply via email to