% language=us runpath=texruns:manuals/cld

\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

