% Verbatim facilities.
\newcatcodetable\verbcatcodes{\\\{\}\$\&\#\^\_\~\%=12,\ \^^M=13}

\def\verb#1{%
  \def\ptx@verb##1#1{\ptx@verb_punc{}{##1}\egroup}%
  \bgroup
  \catcodetable\verbcatcodes
  \iffcommand\codefont\codefont
  \ptx@verb
  }

% Hack to prevent French spacing before punctuation. I should find
% something better (attributes marking material to be left alone when
% the French punctuation kicks in in the "kerning" callback).
\def\ptx@verb_punc#1#2{%
  \ifelseif{%
    {\ifcontains:{#2}} {\splitstringat:{#2}{\ptx@verb_glue{#1}:}}
    {\ifcontains;{#2}} {\splitstringat;{#2}{\ptx@verb_glue{#1};}}
    {\ifcontains!{#2}} {\splitstringat!{#2}{\ptx@verb_glue{#1}!}}
    {\ifcontains?{#2}} {\splitstringat?{#2}{\ptx@verb_glue{#1}?}}
     \iftrue           {#1#2}}%
  }
\def\ptx@verb_glue#1#2#3#4{%
  \ptx@verb_punc{#1#3\kern0pt#2}{#4}%
  }

\bgroup
\setcatcodes{\ \^^M=13}%
\gdef {\quitvmode\spacecs}%
\gdef^^M{\quitvmode\par}%
\egroup

\def\tcode#1{{\codefont#1}}
\long\def\com#1{%
  \bgroup
    \codefont
    \string#1%
  \egroup
  \antigobblespace
  }
\freedef\arg{{\codefont\it<#1>}\iffnext\spacechar{\kern.2ex }}
\freedef\barg{{\codefont\char"007B\relax\arg{#1}\char"007D\relax}}
\freedef\oarg{{\codefont[\arg{#1}]}}

\luacode
pitex.verbatims = {}
local function prepare_verbatim (chunk, name)
	return function (str)
    if not str:match("^%s*\noexpand\\" .. chunk .. "/") then
      table.insert(pitex.verbatims[name], str)
      return "%"
    else
      pitex.callback.remove("process_verbatim", "process_input_buffer")
      return "\noexpand\\usecs{ptx@inner_verbatimstop:" .. chunk .. "}"
    end
  end
end

function install_verbatim (chunk, regime, name)
	pitex.verbatims[name] = { regime = regime }
  pitex.callback.process_verbatim = prepare_verbatim(chunk, name)
  pitex.callback.register("process_input_buffer", "process_verbatim")
end

function do_verbatim(name, exec)
	if exec then
    tex.print(pitex.verbatims[name])
  else
    tex.print(pitex.verbatims[name].regime, pitex.verbatims[name])
  end
end
\luacode/

\def\ptx@verbatim_last{}

\def\newverbatim#1{%
  \ifnext[
    {\ptx@newverbatim#1}
    {\ptx@newverbatim#1[\verbcatcodes]}%
  }

\long\def\ptx@newverbatim#1[#2]#3#4{%
  \edef#1{%
    \bgroup\primunexpanded{#3}%
    \bgroup\primunexpanded{\setcatcodes{\^^M=12}}%
    \noexpand\ptx@verbatim{\commandtoname#1}{#2}}%
  \defcs{ptx@inner_verbatimstop:\commandtoname#1}{#4\egroup}%
  }

\bgroup
\setcatcodes{\^^M=12}%
\gdef\ptx@verbatim#1^^M{%
  \egroup%
  \ptx@verbatim_prepare#1\relax%
  }%
\egroup

\def\ptx@verbatim_prepare#1#2{%
  \ifnext[
    {\ptx@verbatim_do{#1}{#2}}
    {\ptx@verbatim_do{#1}{#2}[last]}%
  }

\def\ptx@verbatim_do#1#2[#3]{%
  \gdef\ptx@verbatim_last{#3}%
  \directlua{install_verbatim("#1", \the#2, "#3")}%
  }

\newverbatim\verbatim{}
                     {\codefont\parindent0pt %\hsize=\maxdimen
                      \directlua{pitex.callback.close("french_punctuation", "kerning")}\relax
                      \vskip\baselineskip\printverbatim\relax
                      \directlua{pitex.callback.open("french_punctuation", "kerning")}
                      \vskip\baselineskip\removenextindent}

\def\doverbatim{%
  \ifnext[
    {\ptx@doverbatim{true}}
    {\ptx@doverbatim{true}[\ptx@verbatim_last]}%
  }
\def\printverbatim{%
  \ifnext[
    {\ptx@doverbatim{nil}}
    {\ptx@doverbatim{nil}[\ptx@verbatim_last]}%
  }
\def\ptx@doverbatim#1[#2]{%
  \directlua{do_verbatim("#2", #1)}%
  }
