diff options
Diffstat (limited to 'doc/context/sources/general/manuals/cld/cld-verbatim.tex')
-rw-r--r-- | doc/context/sources/general/manuals/cld/cld-verbatim.tex | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/doc/context/sources/general/manuals/cld/cld-verbatim.tex b/doc/context/sources/general/manuals/cld/cld-verbatim.tex new file mode 100644 index 000000000..2007f7d73 --- /dev/null +++ b/doc/context/sources/general/manuals/cld/cld-verbatim.tex @@ -0,0 +1,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 |