Changes

Jump to navigation Jump to search
→‎Manipulating verbatim text for dummies: Added comments. Did some mostly-minor rewordings.
Writing macros that manipulate verbatim text involve catcode finesse that only TeX wizards can master.
Consider a simple example. Suppose we want to write an environment <code>\startdedentedtyping</code> ... <code>\stopdedentedtyping</code> that removes the indentation of the first line from every line. Thus, the output of...
<texcode>
\startdedentedtyping
#include &lt;stdio.h&gt; void main() { print("Hello world \n") ; }
\stopdedentedtyping
</texcode>
... should be the same as the output of...
<texcode>
\stoptyping
</texcode>
... even though the leading whitespace is different.
'''Note''' the difference in whitespace at the beginning of each line. I don't even know how to write an environment that will remove the leading spaces but leave other spaces untouched. On the other hand, once we capture the contents of the environment, removing the leading indent or ''dedenting'' the content in lua Lua is easy. Here is a lua Lua function that uses lpeg.
<texcode>
\startluacode
-- Initialise a userdata namespace to keep our own functions in.
-- That way, we won't interfere with anything ConTeXt keeps in
-- the global namespace.
userdata = userdata or {}
 
function userdata.dedentedtyping(content)
local newline = lpeg.P("\n\r") + lpeg.P("\r\n") + lpeg.P("\n") + lpeg.P("\r")
local splitter = lpeg.Ct(lpeg.splitat(newline))
local lines = lpeg.match(splitter, content)
end
\stopluacode</texcode>
The only hard part is capturing the content of the environment and passing it to luaLua. As explained in [[Inside_ConTeXt#Passing_verbatim_text_as_macro_parameter|Inside ConText]], the trick to capturing the content of an environment verbatim is to ensure that spaces and newlines have a catcode that makes them significant. This is done using <code>\obeyspaces</code> and <code>\obeylines</code>. Using that trick, we can write this macro as
<texcode>\unprotect
A more robust solution is to use ConTeXt's built in support for buffers. Using buffers, the above macro can be written as
<texcode>% Create an environment that stores everything % between \startdedentedtyping and \stopdedentedtyping % in a buffer named 'dedentedtyping'.\def\startdedentedtyping {\dostartbuffer [dedentedtyping] [startdedentedtyping] [stopdedentedtyping]}
% On closing the dedentedtyping environment, call the LuaTeX
% function dedentedtyping(), and pass it the contents of
% the buffer called 'dedentedtyping'
\def\stopdedentedtyping
{\ctxlua{ userdata.dedentedtyping( buffers.content('dedentedtyping') ) }}</texcode>Unlike MkII, where the contents of a buffer were written to an external file, in MkIV buffers are stored in memory. Thus, with luatex LuaTeX is really simple to manipulate verbatim text: write the text manipulating code in lua and pass the contents of the environment to Lua; use Lua functions to do the lua function using bufferstext-manipulation; and in Lua call <code>context.something()</code> functions to produce the ConTeXt code you want.
= Conclusion =

Navigation menu