diff options
Diffstat (limited to 'doc/context/sources/general/manuals/lowlevel/lowlevel-paragraphs.tex')
-rw-r--r-- | doc/context/sources/general/manuals/lowlevel/lowlevel-paragraphs.tex | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/doc/context/sources/general/manuals/lowlevel/lowlevel-paragraphs.tex b/doc/context/sources/general/manuals/lowlevel/lowlevel-paragraphs.tex new file mode 100644 index 000000000..a7a7fddf3 --- /dev/null +++ b/doc/context/sources/general/manuals/lowlevel/lowlevel-paragraphs.tex @@ -0,0 +1,423 @@ +% language=us + +\environment lowlevel-style + +\startdocument + [title=paragraphs, + color=middlecyan] + +\startsection[title=Introduction] + +This manual is mostly discussing a few wrappers around low level \TEX\ features. +Its writing is triggered by an update to the \METAFUN\ and \LUAMETAFUN\ manuals +where we mess a bit with shapes. It gave a good reason to also cover some more +paragraph related topics but it might take a while to complete. Remind me if you +feel that takes too much time. + +\stopsection + +\startsection[title=Properties] + +A paragraph is just a collection of lines that result from one input line that +got broken. This process of breaking into lines is influenced by quite some +parameters. In traditional \TEX\ and also in \LUAMETATEX\ by default the values +that are in effect when the end of the paragraph is met are used. So, when you +change them in a group and then ends the paragraph after the group, the values +you've set in the group are not used. + +However, in \LUAMETATEX\ we can optionally store them with the paragraph. When +that happens the values current at the start are frozen. You can still overload +them but that has to be done explicitly then. The advantage is that grouping no +longer interferes with the line break algorithm. The magic primitive is \type +{\snapshotpar}. + +\starttabulate +\NC \type {\hsize} \NC \NC \NR +\NC \type {\leftskip} \NC \NC \NR +\NC \type {\rightskip} \NC \NC \NR +\NC \type {\hangindent} \NC \NC \NR +\NC \type {\hangafter} \NC \NC \NR +\NC \type {\parindent} \NC \NC \NR +\NC \type {\parfillleftskip} \NC \NC \NR +\NC \type {\parfillrightskip} \NC \NC \NR +\NC \type {\adjustspacing} \NC \NC \NR +\NC \type {\protrudechars} \NC \NC \NR +\NC \type {\pretolerance} \NC \NC \NR +\NC \type {\tolerance} \NC \NC \NR +\NC \type {\emergencystretch} \NC \NC \NR +\NC \type {\looseness} \NC \NC \NR +\NC \type {\lastlinefit} \NC \NC \NR +\NC \type {\linepenalty} \NC \NC \NR +\NC \type {\interlinepenalty} \NC \NC \NR +\NC \type {\clubpenalty} \NC \NC \NR +\NC \type {\widowpenalty} \NC \NC \NR +\NC \type {\displaywidowpenalty} \NC \NC \NR +\NC \type {\brokenpenalty} \NC \NC \NR +\NC \type {\adjdemerits} \NC \NC \NR +\NC \type {\doublehyphendemerits} \NC \NC \NR +\NC \type {\finalhyphendemerits} \NC \NC \NR +\NC \type {\parshape} \NC \NC \NR +\NC \type {\interlinepenalties} \NC \NC \NR +\NC \type {\clubpenalties} \NC \NC \NR +\NC \type {\widowpenalties} \NC \NC \NR +\NC \type {\displaywidowpenalties} \NC \NC \NR +\NC \type {\baselineskip} \NC \NC \NR +\NC \type {\lineskip} \NC \NC \NR +\NC \type {\lineskiplimit} \NC \NC \NR +\NC \type {\adjustspacingstep} \NC \NC \NR +\NC \type {\adjustspacingshrink} \NC \NC \NR +\NC \type {\adjustspacingstretch} \NC \NC \NR +\NC \type {\hyphenationmode} \NC \NC \NR +\stoptabulate + +There are more paragraph related parameters than in for instance \PDFTEX\ and +\LUATEX\ and these are (to be) explained in the \LUAMETATEX\ manual. You can +imagine that keeping this around with the paragraph adds some extra overhead to +the machinery but most users won't notice that because is is compensated by gains +elsewhere. + +In \LMTX\ taking these snapshots is turned on by default and because it thereby +fundamentally influences the par builder, users can run into compatibility issues +but in practice there has been no complaints (and this feature has been in use +quite a while before this document was written). One reason for users not +noticing is that one of the big benefits is probably handled by tricks mentioned on the +mailing list. Imagine that you have this: + +\starttyping[option=TEX] +{\bf watch out:} here is some text +\stoptyping + +In this small example the result will be as expected. But what if something magic +with the start of a paragraph is done? Like this: + +\starttyping[option=TEX] +\placefigure[left]{A cow!}{\externalfigure[cow.pdf]} + +{\bf watch out:} here is some text ... of course much more is needed to + get a flow around the figure! +\stoptyping + +The figure will hang at the left side of the paragraph but it is put there when +the text starts and that happens inside the bold group. It means that the +properties we set in order to get the shape around the figure are lost as soon as +we're at \quote{\type {here is some text}} and definitely is wrong when the +paragraph ends and the par builder has to use them to get the shape right. We get +text overlapping the figure. A trick to overcome this is: + +\starttyping[option=TEX] +\dontleavehmode {\bf watch out:} here is some text ... of course much + more is needed to get a flow around the figure! +\stoptyping + +where the first macro makes sure we already start a paragraph before the group is +entered (using a \type {\strut} also works). It's not nice and I bet users have +been bitten by this and by now know the tricks. But, with snapshots such fuzzy +hacks are not needed any more! The same is true with this: + +\starttyping[option=TEX] +{\leftskip 1em some text \par} +\stoptyping + +where we had to explicitly end the paragraph inside the group in order to retain +the skip. I suppose that users normally use the high level environments so they +never had to worry about this. It's also why users probably won't notice that +this new mechanism has been active for a while. Actually, when you now change a +parameter inside the paragraph will not be applied (unless you prefix it with +\type {\frozen}) but no one did that anyway. + +{\em todo: freeze categories, overloading, turning on and off, etc} + +\stopsection + +\startsection[title=Wraping up] + +In \CONTEXT\ \LMTX\ we have a mechanism to exercise macros (or content) before a +paragraph ends. This is implemented using the \type {\wrapuppar} primitive. The +to be wrapped up material is bound to the current paragraph which in order to +get this done has to be started when this primitive is used. + +Although the high level interface has been around for a while it still needs a +bit more testing (read: use cases are needed). In the few cases where we already +use it application can be different because again it relates to snapshots. This +because in the past we had to use tricks that also influenced the user interface +of some macros (which made them less natural as one would expect). So the +question is: where do we apply it in old mechanisms and where not. + +{\em todo: accumulation, interference, where applied, limitations} + +% \vbox {vbox : \wrapuppar{1}test\par x\wrapuppar{2}test}\blank +% \vtop {vtop : \wrapuppar{1}test\par x\wrapuppar{2}test}\blank +% \vcenter{vcenter : \wrapuppar{1}test\par x\wrapuppar{2}test}\blank +% $$x = \vcenter{vcenter : \wrapuppar{1}test\par x\wrapuppar{2}test}$$\blank +% x\vadjust{vadjust : \wrapuppar{1}test\par x\wrapuppar{2}test}x\blank + +\stopsection + +\startsection[title=Shapes] + +In \CONTEXT\ we don't use \type {\parshape} a lot. It is used in for instance +side floats but even then not in all cases. It's more meant for special +applications. This means that in \MKII\ and \MKIV\ we don't have some high level +interface. However, when \METAFUN\ got upgraded to \LUAMETAFUN, and the manual +also needed an update, one of the examples in that manual that used shapes also +got done differently (read: nicer). And that triggered the arrival of a new high +level shape mechanism. + +One important property of the \type {\parshape} mechanism is that it works per +paragraph. You define a shape in terms of a left margin and width of a line. The +shape has a fixed number of such pairs and when there is more content, the last one +is used for the rest of the lines. When the paragraph is finished, the shape is +forgotten. + +{\em Not discussed here is a variant that will end up in \LUAMETATEX\ that works +with the progression, i.e.\ takes the height of the content so far into account. +This is somewhat tricky because for that to work vertical skips need to be +frozen, which is no real big deal but has to be done careful in the code.} + +The high level interface is a follow up on the example in the \METAFUN\ manual and +uses shapes that carry over to the next paragraph. In addition we can cycle over +a shape. In this interface shapes are defined using keyword. Here are some +examples: + +\starttyping[option=TEX] +\startparagraphshape[test] + left 1mm right 1mm + left 5mm right 5mm +\stopparagraphshape +\stoptyping + +This shape has only two entries so the first line will have a 1mm margin while +later lines will get 5mm margins. This translates into a \type {\parshape} like: + +\starttyping[option=TEX] +\parshape 2 + 1mm \dimexpr\hsize-1mm\relax + 5mm \dimexpr\hsize-5mm\relax +\stoptyping + +Watch the number \type {2}: it tells how many specification lines follow. As you +see, we need to calculate the width. + +\starttyping[option=TEX] +\startparagraphshape[test] + left 1mm right 1mm + left 5mm right 5mm + repeat +\stopparagraphshape +\stoptyping + +This variant will alternate between 1mm and 5mm margins. The repeating feature is +translated as follows. Maybe at some point I will introduce a few more options. + +\starttyping[option=TEX] +\parshape 2 options 1 + 1mm \dimexpr\hsize-1mm\relax + 5mm \dimexpr\hsize-5mm\relax +\stoptyping + +A shape can have some repetition, and we can save keystrokes by copying the last +entry. The resulting \type {\parshape} becomes rather long. + +\starttyping[option=TEX] +\startparagraphshape[test] + left 1mm right 1mm + left 2mm right 2mm + left 3mm right 3mm + copy 8 + left 4mm right 4mm + left 5mm right 5mm + left 5mm hsize 10cm +\stopparagraphshape +\stoptyping + +Also watch the \type {hsize} keyword: we don't calculate the hsize from the \type +{left} and \type {right} values but explicitly set it. + +\starttyping[option=TEX] +\startparagraphshape[test] + left 1mm right 1mm + right 3mm + left 5mm right 5mm + repeat +\stopparagraphshape +\stoptyping + +When a \type {right} keywords comes first the \type {left} is assumed to be zero. +In the examples that follow we will use a couple of definitions: + +\startbuffer[setup] +\startparagraphshape[test] + both 1mm both 2mm both 3mm both 4mm both 5mm both 6mm + both 7mm both 6mm both 5mm both 4mm both 3mm both 2mm +\stopparagraphshape +\stopbuffer + +\startbuffer[setup-repeat] +\startparagraphshape[test-repeat] + both 1mm both 2mm both 3mm both 4mm both 5mm both 6mm + both 7mm both 6mm both 5mm both 4mm both 3mm both 2mm + repeat +\stopparagraphshape +\stopbuffer + +\typebuffer[setup,setup-repeat][option=TEX] + +The last one could also be defines as: + +\starttyping[option=TEX] +\startparagraphshape[test-repeat] + \rawparagraphshape{test} repeat +\stopparagraphshape +\stoptyping + +In the previous code we already introduced the \type {repeat} option. This will +make the shape repeat at the engine level when the shape runs out of specified +lines. In the application of a shape definition we can specify a \type {method} +to be used and that determine if the next paragraph will start where we left off +and discard afterwards (\type {shift}) or that we move the discarded lines up +front so that we never run out of lines (\type {cycle}). It sounds complicated +but just keep in mind that \type {repeat} is part of the \type {\parshape} and +act within a paragraph while \type {shift} and \type {cycle} are applied when a +new paragraph is started. + +\startbuffer[demo] +\startshapedparagraph[list=test] + \dorecurse{8}{\showparagraphshape\samplefile{tufte} \par} +\stopshapedparagraph +\stopbuffer + +\startbuffer[demo-repeat] +\startshapedparagraph[list=test-repeat] + \dorecurse{8}{\showparagraphshape\samplefile{tufte} \par} +\stopshapedparagraph +\stopbuffer + +In \in {figure} [fig:shape:discard] you see the following applied: + +\typebuffer[demo,demo-repeat][option=TEX] + +\startplacefigure[title=Discarded shaping,reference=fig:shape:discard] +\startcombination[nx=2,ny=2] + {\typesetbuffer[setup,demo][page=1,width=.4\textwidth,frame=on]} {discard, finite shape, page 1} + {\typesetbuffer[setup,demo][page=2,width=.4\textwidth,frame=on]} {discard, finite shape, page 2} + {\typesetbuffer[setup-repeat,demo-repeat][page=1,width=.4\textwidth,frame=on]} {discard, repeat in shape, page 1} + {\typesetbuffer[setup-repeat,demo-repeat][page=2,width=.4\textwidth,frame=on]} {discard, repeat in shape, page 2} +\stopcombination +\stopplacefigure + +In \in {figure} [fig:shape:shift] we use this instead: + +\startbuffer[demo] +\startshapedparagraph[list=test,method=shift] + \dorecurse{8}{\showparagraphshape\samplefile{tufte} \par} +\stopshapedparagraph +\stopbuffer + +\startbuffer[demo-shift] +\startshapedparagraph[list=test-repeat,method=shift] + \dorecurse{8}{\showparagraphshape\samplefile{tufte} \par} +\stopshapedparagraph +\stopbuffer + +\typebuffer[demo,demo-repeat][option=TEX] + +\startplacefigure[title=Shifted shaping,,reference=fig:shape:shift] +\startcombination[nx=2,ny=2] + {\typesetbuffer[setup,demo][page=1,width=.4\textwidth,frame=on]} {shift, finite shape, page 1} + {\typesetbuffer[setup,demo][page=2,width=.4\textwidth,frame=on]} {shift, finite shape, page 2} + {\typesetbuffer[setup-repeat,demo-shift][page=1,width=.4\textwidth,frame=on]} {shift, repeat in shape, page 1} + {\typesetbuffer[setup-repeat,demo-shift][page=2,width=.4\textwidth,frame=on]} {shift, repeat in shape, page 2} +\stopcombination +\stopplacefigure + +Finally, in \in {figure} [fig:shape:cycle] we use: + +\startbuffer[demo] +\startshapedparagraph[list=test,method=cycle] + \dorecurse{8}{\showparagraphshape\samplefile{tufte} \par} +\stopshapedparagraph +\stopbuffer + +\startbuffer[demo-cycle] +\startshapedparagraph[list=test-repeat,method=cycle] + \dorecurse{8}{\showparagraphshape\samplefile{tufte} \par} +\stopshapedparagraph +\stopbuffer + +\typebuffer[demo,demo-repeat][option=TEX] + +\startplacefigure[title=Cycled shaping,reference=fig:shape:cycle] +\startcombination[nx=2,ny=2] + {\typesetbuffer[setup,demo][page=1,width=.4\textwidth,frame=on]} {cycle, finite shape, page 1} + {\typesetbuffer[setup,demo][page=2,width=.4\textwidth,frame=on]} {cycle, finite shape, page 2} + {\typesetbuffer[setup-repeat,demo-cycle][page=1,width=.4\textwidth,frame=on]} {cycle, repeat in shape, page 1} + {\typesetbuffer[setup-repeat,demo-cycle][page=2,width=.4\textwidth,frame=on]} {cycle, repeat in shape, page 2} +\stopcombination +\stopplacefigure + +These examples are probably too small to see the details but you can run them +yourself or zoom in on the details. In the margin we show the values used. Here +is a simple example of (non) poetry. There are other environments that can be +used instead but this makes a good example anyway. + +\startbuffer +\startparagraphshape[test] + left 0em right 0em + left 1em right 0em + repeat +\stopparagraphshape + +\startshapedparagraph[list=test,method=cycle] + verse line 1.1\crlf verse line 2.1\crlf + verse line 3.1\crlf verse line 4.1\par + verse line 1.2\crlf verse line 2.2\crlf + verse line 3.2\crlf verse line 4.2\crlf + verse line 5.2\crlf verse line 6.2\par +\stopshapedparagraph +\stopbuffer + +\typebuffer[option=TEX] + +\getbuffer + +{\em todo: move the new (still in {\em \type {meta-imp-txt.mkxl})} code into the +core and integrate it in {\em \type {\startshapedparagraph}} as method {\em \type +{mp}} in which case the list is a list of graphics.} + +\starttyping[option=TEX] +\startshapedparagraph[list={test 1,test 2,test 3,test 4},method=mp] + ..... +\stopshapedparagraph +\stoptyping + +{\em So methods then become kind of plugins.} + +A mechanism like this is often never completely automatic in the sense that you +need to keep an eye on the results. Depending on user demands more features can +be added. With weird shapes you might want to set up the alignment to be \type +{tolerant} and have some \type {stretch}. + +\stopsection + +% \startsection[title=Linebreaks] +\startsection[title=Modes] + +% \ruledvbox{1\ifhmode\writestatus{!}{HMODE 1}\fi} % hsize +% \ruledvbox{\hbox{\strut 2}\ifhmode\writestatus{!}{HMODE 2}\fi} % fit +% \ruledvbox{\hbox{\strut 3}\hbox{\strut 3}\ifhmode\writestatus{!}{HMODE 3}\fi} % fit +% \ruledvbox{\hbox{\strut 4}4\ifhmode\writestatus{!}{HMODE 4}\fi} % hsize +% \ruledvbox{\hbox{\strut 5}5\hbox{\strut 5}\ifhmode\writestatus{!}{HMODE 5}\fi} % hsize +% \ruledvbox{6\hbox{\strut 6}\ifhmode\writestatus{!}{HMODE 6}\fi} % hsize + +{\em todo: some of the side effects of so called modes} + +\stopsection + +\startsection[title=Normalization] + +{\em todo: users don't need to bother about this but it might be interesting anyway} + +\stopsection + +\stopdocument + |