summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/cld/cld-verbatim.tex
blob: 2007f7d733d79fe2d10eb26052127987bb2ba504 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
% language=uk

\startcomponent cld-verbatim

\environment cld-environment

\startchapter[title=Verbatim]

\startsection[title=Introduction]

\index{verbatim}

If you are familiar with traditional \TEX, you know that some characters have
special meanings. For instance a \type {$} starts and ends inline math mode:

\starttyping
$e=mc^2$
\stoptyping

If we want to typeset math from the \LUA\ end, we can say:

\starttyping
context.mathematics("e=mc^2")
\stoptyping

This is in fact:

\starttyping
\mathematics{e=mc^2}
\stoptyping

However, if we want to typeset a dollar and use the \type {ctxcatcodes} regime,
we need to explicitly access that character using \type {\char} or use a command
that expands into the character with catcode other.

One step further is that we typeset all characters as they are and this is called
verbatim. In that mode all characters are tokens without any special meaning.

\stopsection

\startsection[title=Special treatment]

The formula in the introduction can be typeset verbatim as follows:

\startbuffer
context.verbatim("$e=mc^2$")
\stopbuffer

\typebuffer

This gives:

\ctxluabuffer

You can also do things like this:

\startbuffer
context.verbatim.bold("$e=mc^2$")
\stopbuffer

\typebuffer

Which gives:

\ctxluabuffer

So, within the \type {verbatim} namespace, each command gets its arguments
verbatim.

\startbuffer
context.verbatim.inframed({ offset = "0pt" }, "$e=mc^2$")
\stopbuffer

\typebuffer

Here we get: \ctxluabuffer. So, settings and alike are processed as if the user
had used a regular \type {context.inframed} but the content comes out verbose.

If you wonder why verbatim is needed as we also have the \type {type} function
(macro) the answer is that it is faster, easier to key in, and sometimes the only
way to get the desired result.

\stopsection

\startsection[title=Multiple lines]

Currently we have to deal with linebreaks in a special way. This is due to the
way \TEX\ deals with linebreaks. In fact, when we print something to \TEX, the
text after a \type {\n} is simply ignored.

For this reason we have a few helpers. If you want to put something in a buffer,
you cannot use the regular buffer functions unless you make sure that they are
not overwritten while you're still at the \LUA\ end.

\starttyping
context.tobuffer("temp",str)
context.getbuffer("temp")
\stoptyping

Another helper is the following. It splits the string into lines and feeds them
piecewise using the \type {context} function and in the process adds a space at
the end of the line (as this is what \TEX\ normally does.

\starttyping
context.tolines(str)
\stoptyping

Catcodes can get in the way when you pipe something to \TEX\ that itself changes
the catcodes. This happens for instance when you write buffers that themselves
have buffers or have code that changes the line endings as with \type
{startlines}. In that case you need to feed back the content as if it were a
file. This is done with:

\starttyping
context.viafile(str)
\stoptyping

The string can contain newlines. The string is written to a virtual file that is
input. Currently names looks like \type {virtual://virtualfile.1} but future
versions might have a different name part, so best use the variable instead.
After all, you don't know the current number in advance anyway.

\stopsection

\startsection[title=Pretty printing]

In \CONTEXT\ \MKII\ there have always been pretty printing options. We needed it
for manuals and it was also handy to print sources in the same colors as the
editor uses. Most of those pretty printers work in a line|-|by|-|line basis, but
some are more complex, especially when comments or strings can span multiple
lines.

When the first versions of \LUATEX\ showed up, rewriting the \MKII\ code to use
\LUA\ was a nice exercise and the code was not that bad, but when \LPEG\ showed
up, I put it on the agenda to reimplement them again.

We only ship a few pretty printers. Users normally have their own preferences and
it's not easy to make general purpose pretty printers. This is why the new
framework is a bit more flexible and permits users to kick in their own code.

Pretty printing involves more than coloring some characters or words:

\startitemize[packed]
\startitem spaces should honoured and can be visualized \stopitem
\startitem newlines and empty lins need to be honoured as well \stopitem
\startitem optionally lines have to be numbered but \stopitem
\startitem wrapped around lines should not be numbered \stopitem
\stopitemize

It's not much fun to deal with these matters each time that you write a pretty
printer. This is why we can start with an existing one like the default pretty
printer. We show several variants of doing the same. We start with a simple clone
of the default parser. \footnote {In the meantime the lexer of the \SCITE\ editor
that I used also provides a mechanism for using \LPEG\ based lexers. Although in
the pretty printing code we need a more liberal one I might backport the lexers I
wrote for editing \TEX, \METAPOST, \LUA, \CLD, \XML\ and \PDF\ as a variant for
the ones we use in \MKIV\ now. That way we get similar colorschemes which might
be handy sometimes.}

\startbuffer
local P, V = lpeg.P, lpeg.V

local grammar = visualizers.newgrammar("default", {
  pattern    = V("default:pattern"),
  visualizer = V("pattern")^1
} )

local parser = P(grammar)

visualizers.register("test-0", { parser = parser })
\stopbuffer

\typebuffer \ctxluabuffer

We distinguish between grammars (tables with rules), parsers (a grammar turned
into an \LPEG\ expression), and handlers (collections of functions that can be
applied. All three are registered under a name and the verbatim commands can
refer to that name.

\startbuffer
\starttyping[option=test-0,color=]
Test 123,
test 456 and
test 789!
\stoptyping
\stopbuffer

\typebuffer

Nothing special happens here. We just get straightforward verbatim.

\getbuffer

Next we are going to color digits. We collect as many as possible in a row, so
that we minimize the calls to the colorizer.

\startbuffer
local patterns, P, V = lpeg.patterns, lpeg.P, lpeg.V

local function colorize(s)
  context.color{"darkred"}
  visualizers.writeargument(s)
end

local grammar = visualizers.newgrammar("default", {
  digit      = patterns.digit^1 / colorize,
  pattern    = V("digit") + V("default:pattern"),
  visualizer = V("pattern")^1
} )

local parser = P(grammar)

visualizers.register("test-1", { parser = parser })
\stopbuffer

\typebuffer \ctxluabuffer

Watch how we define a new rule for the digits and overload the pattern rule. We
can refer to the default rule by using a prefix. This is needed when we define a
rule with the same name.

\startbuffer
\starttyping[option=test-1,color=]
Test 123,
test 456 and
test 789!
\stoptyping
\stopbuffer

\typebuffer

This time the digits get colored.

\getbuffer

In a similar way we can colorize letters. As with the previous example, we use
\CONTEXT\ commands at the \LUA\ end.

\startluacode
local patterns, P, V = lpeg.patterns, lpeg.P, lpeg.V

local function colorize_lowercase(s)
  context.color{"darkgreen"}
  visualizers.writeargument(s)
end
local function colorize_uppercase(s)
  context.color{"darkblue"}
  visualizers.writeargument(s)
end

local grammar = visualizers.newgrammar("default", {

  lowercase = patterns.lowercase^1 / colorize_lowercase,
  uppercase = patterns.uppercase^1 / colorize_uppercase,

  pattern =
      V("lowercase")
    + V("uppercase")
    + V("default:pattern"),

  visualizer = V("pattern")^1

} )

local parser = P(grammar)

visualizers.register("test-2", { parser = parser })
\stopluacode

\startbuffer
\starttyping[option=test-2,color=]
Test 123,
test 456 and
test 789!
\stoptyping
\stopbuffer

\typebuffer

Again we get some coloring.

\getbuffer

It will be clear that the amount of rules and functions is larger when we use a
more complex parser. It is for this reason that we can group functions in
handlers. We can also make a pretty printer configurable by defining handlers at
the \TEX\ end.

\startbuffer
\definestartstop
  [MyDigit]
  [style=bold,color=darkred]

\definestartstop
  [MyLowercase]
  [style=bold,color=darkgreen]

\definestartstop
  [MyUppercase]
  [style=bold,color=darkblue]
\stopbuffer

\typebuffer \getbuffer

The \LUA\ code now looks different. Watch out: we need an indirect call to for
instance \type {MyDigit} because a second argument can be passed: the settings
for this environment and you don't want that get passed to \type {MyDigit} and
friends.

\startluacode
local patterns, P, V = lpeg.patterns, lpeg.P, lpeg.V
local pattern = visualizers.pattern
local verbatim = context.verbatim

local MyDigit     = verbatim.MyDigit
local MyLowercase = verbatim.MyLowercase
local MyUppercase = verbatim.MyUppercase

-- local handler = newhandler("default, {
--   digit     = function(s) MyDigit    (s) end,
--   lowercase = function(s) MyLowercase(s) end,
--   uppercase = function(s) MyUppercase(s) end,
-- } )

local handler = {
  digit     = function(s) MyDigit    (s) end,
  lowercase = function(s) MyLowercase(s) end,
  uppercase = function(s) MyUppercase(s) end,
}

local grammar = visualizers.newgrammar("default", {

  digit     = pattern(handler,"digit",     patterns.digit    ^1),
  lowercase = pattern(handler,"lowercase", patterns.lowercase^1),
  uppercase = pattern(handler,"uppercase", patterns.uppercase^1),

  pattern =
      V("lowercase")
    + V("uppercase")
    + V("digit")
    + V("default:pattern"),

  visualizer = V("pattern")^1

} )

local parser = P(grammar)

visualizers.register("test-3", { parser = parser, handler = handler })
\stopluacode

\startbuffer
\starttyping[option=test-3,color=]
Test 123,
test 456 and
test 789!
\stoptyping
\stopbuffer

\typebuffer

We get digits, upper- and lowercase characters colored:

\getbuffer

You can also use parsers that don't use \LPEG:

\startbuffer
local function parser(s)
  visualizers.write("["..s.."]")
end

visualizers.register("test-4", { parser = parser })
\stopbuffer

\typebuffer \ctxluabuffer

\startbuffer
\starttyping[option=test-4,space=on,color=darkred]
Test 123,
test 456 and
test 789!
\stoptyping
\stopbuffer

\typebuffer

The function \type {visualizer.write} takes care of spaces and newlines.

\getbuffer

We have a few more helpers:

\starttabulate[|||]
\NC \type{visualizers.write}          \NC interprets the argument and applies methods \NC \NR
\NC \type{visualizers.writenewline}   \NC goes to the next line (similar to \type {\par} \NC \NR
\NC \type{visualizers.writeemptyline} \NC inserts an empty line (similer to \type {\blank} \NC \NR
\NC \type{visualizers.writespace}     \NC inserts a (visible) space \NC \NR
\NC \type{visualizers.writedefault}   \NC writes the argument verbatim without interpretation \NC \NR
\stoptabulate

These mechanism have quite some overhead in terms of function calls. In the worst
case each token needs a (nested) call. However, doing all this at the \TEX\ end
also comes at a price. So, in practice this approach is more flexible but without
too large a penalty.

In all these examples we typeset the text verbose: what is keyed in normally
comes out (either or not with colors), so spaces stay spaces and linebreaks are
kept.

\startbuffer
local function parser(s)
  local s = string.gsub(s,"show","demonstrate")
  local s = string.gsub(s,"'re"," are")
  context(s)
end

visualizers.register("test-5", { parser = parser })
\stopbuffer

\typebuffer \ctxluabuffer

\startbuffer
\starttyping[option=test-5,color=darkred,style=]
This is just some text to show what we can do with this mechanism. In
spite of what you might think we're not bound to verbose text.
\stoptyping
\stopbuffer

We can apply this visualizer as follows:

\typebuffer

This time the text gets properly aligned:

\getbuffer

It often makes sense to use a buffer:

\startbuffer
\startbuffer[demo]
This is just some text to show what we can do with this mechanism. In
spite of what you might think we're not bound to verbose text.
\stopbuffer
\stopbuffer

\typebuffer \getbuffer

Instead of processing the buffer in verbatim mode you can then
process it directly:

\startbuffer
\setuptyping[file][option=test-5,color=darkred,style=]
\ctxluabuffer[demo]
\stopbuffer

\typebuffer

Which gives:

\start \getbuffer \stop

In this case, the space is a normal space and not the fixed verbatim space, which
looks better.

\stopsection

\stopchapter

\stopcomponent