%D \module
%D   [       file=buff-ver, % was core-ver
%D        version=2000.05.09,
%D          title=\CONTEXT\ Buffer Macros,
%D       subtitle=Verbatim,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

% check after-first and before-last breaks

\writestatus{loading}{ConTeXt Buffer Macros / Verbatim}

\registerctxluafile{buff-ver}{autosuffix}

\unprotect

\startcontextdefinitioncode

\definesystemattribute[verbatimline][public]

\appendtoks
    \c_attr_verbatimline\attributeunsetvalue
\to \everyforgetall

%D Initializations.

\installcorenamespace{typinglines}
\installcorenamespace{typingspace}

\newtoks\everyinitializeverbatim

\appendtoks
    \expand\everyresettypesetting
    \resetfontfeature
    \resetcharacterspacing
    \resetbreakpoints
    \nohyphencollapsing
    % we figured this out when discussions the math manual:
    \parpasses\zerocount
    \noexpansion
    \noprotrusion
    % so far
\to \everyinitializeverbatim

\permanent\protected\def\setverbatimspaceskip % to be checked: must happen after font switch
  {\spaceskip\scaledfontcharwd\font`x\relax
   \xspaceskip\spaceskip}

\defcsname\??typinglines\v!no        \endcsname{\buff_verbatim_ignore_hyphens}
\defcsname\??typinglines\v!normal    \endcsname{\buff_verbatim_ignore_hyphens}
\defcsname\??typinglines\v!yes       \endcsname{\buff_verbatim_obey_breakpoints}
\defcsname\??typinglines\v!hyphenated\endcsname{\buff_verbatim_obey_hyphens}

\defcsname\??typingspace\v!on        \endcsname{\enforced\let\obeyedspace\specialcontrolspace}
\defcsname\??typingspace\v!stretch   \endcsname{\enforced\let\obeyedspace\specialstretchedspace}
\letcsname\??typingspace\v!normal    \endcsname\donothing
\defcsname\??typingspace\v!fixed     \endcsname{\enforced\let\obeyedspace\specialfixedspace}
\defcsname\??typingspace\v!character \endcsname{\enforced\chardef\obeyedspace\spaceasciicode}

\protected\def\buff_verbatim_obey_hyphens
  {}

\protected\def\buff_verbatim_obey_breakpoints
  {\nohyphens
   \veryraggedright}

\protected\def\buff_verbatim_ignore_hyphens
  {\nohyphens}

\lettonothing\p_buff_option

\def\buff_verbatim_initialize_type_one
  {\enforced\let\obeylines\ignorelines
   \edef\p_buff_option{\typeparameter\c!option}%
   \ifx\p_buff_option\v!none
     \usetypestyleandcolor\c!style\c!color
   \orelse\ifempty\p_buff_option
     \usetypestyleandcolor\c!style\c!color
   \else
     \usetypestyleparameter\c!style % no color
   \fi
   \setcatcodetable\vrbcatcodes}

\def\buff_verbatim_initialize_type_two
  {\spaceskip.5\emwidth\relax
   \enforced\let\obeyedspace\specialobeyedspace
   \enforced\let\controlspace\specialcontrolspace
   \begincsname\??typinglines\typeparameter\c!lines\endcsname
   \begincsname\??typingspace\typeparameter\c!space\endcsname
   \relax\expand\everyinitializeverbatim\relax
   \usesetupsparameter\typeparameter\relax}

\permanent\protected\def\doinitializeverbatim % for use elsewhere .. temp hack (see lxml-ini)
  {\buff_verbatim_initialize_type_one
   \buff_verbatim_initialize_type_two}

\let\buff_verbatim_set_line_margin\relax

\def\buff_verbatim_set_line_margin_indeed % we could expand this once
  {\hskip\doifelseoddpage\d_buff_lines_odd_margin\d_buff_lines_even_margin\relax}

\newconditional\c_buff_lines_as_paragraph

\newdimension\d_buff_lines_even_margin
\newdimension\d_buff_lines_odd_margin

\def\buff_verbatim_initialize_typing_one
  {\usebodyfontparameter\typingparameter
   \d_buff_lines_odd_margin {\typingparameter\c!oddmargin }%
   \d_buff_lines_even_margin{\typingparameter\c!evenmargin}%
   \ifzerodim\d_buff_lines_odd_margin\else
     \let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed
   \fi
   \ifzerodim\d_buff_lines_even_margin\else
     \let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed
   \fi
   \ifrelax\buff_verbatim_set_line_margin
     \doadaptleftskip{\typingparameter\c!margin}%
   \fi
   \edef\p_buff_option{\typingparameter\c!option}%
   \ifx\p_buff_option\v!none
     \usetypingstyleandcolor\c!style\c!color
   \orelse\ifempty\p_buff_option
     \usetypingstyleandcolor\c!style\c!color
   \else
     \usetypingstyleparameter\c!style % no color !
   \fi
 % \usealignparameter\typingparameter
   \hbadnessmode\overfullbadnessmodecode % we don't care about underfull and tight can't happen
   \edef\p_align{\typingparameter\c!align}%
   \unless\ifconditional\c_buff_lines_as_paragraph
     \dousealignparameter\p_align
   \orelse\ifx\p_align\v!hangleft
     \dousealignparameter{\v!hangleft range}%
   \orelse\ifx\p_align\v!hangright
     \dousealignparameter{\v!hangright range}%
   \else
     \dousealignparameter\p_align
   \fi}

\def\buff_verbatim_initialize_typing_two
  {\spaceskip.5\emwidth\relax
   \enforced\let\obeyedspace\specialobeyedspace
   \enforced\let\controlspace\specialcontrolspace
   \begincsname\??typinglines\typingparameter\c!lines\endcsname
   \begincsname\??typingspace\typingparameter\c!space\endcsname
   \relax\expand\everyinitializeverbatim\relax
   \usesetupsparameter\typingparameter\relax}

%D \macros
%D   {definetype,setuptype}
%D
%D Specific inline verbatim commands can be defined with the following command.

\installcorenamespace{type}

\installcommandhandler \??type {type} \??type

\appendtoks
    \frozen\instance\protected\edefcsname\currenttype\endcsname{\buff_verbatim_type{\currenttype}}%
\to \everydefinetype

\appendtoks
   \buff_verbatim_initialize_visualizer{\typeparameter\c!option}%
\to \everysetuptype

%D \macros
%D   {definetyping,setuptyping}
%D
%D For most users the standard \type {\start}||\type {\stop}||pair will suffice, but
%D for documentation purposes the next definition command can be of use:
%D
%D \starttyping
%D \definetyping[extratyping][margin=3em]
%D
%D \startextratyping
%D these extra ones are indented by 1 em
%D \stopextratyping
%D \stoptyping
%D
%D The definitions default to the standard typing values.

\installcorenamespace{typing}

\installcommandhandler \??typing {typing} \??typing

\appendtoks
    \frozen\protected\instance\edefcsname\e!start\currenttyping\endcsname{\buff_verbatim_typing_start{\currenttyping}{\currenttyping}}%
    \frozen\protected\instance\edefcsname\e!stop \currenttyping\endcsname{\buff_verbatim_typing_stop}%
    \ifempty\currenttypingparent
      \expanded{\definelinenumbering[\currenttyping]}%
    \else
      \expanded{\definelinenumbering[\currenttyping][\currenttypingparent]}%
    \fi
\to \everydefinetyping

\appendtoks
   \buff_verbatim_initialize_visualizer{\typingparameter\c!option}% we can check at the tex end
\to \everysetuptyping

\def\buff_verbatim_initialize_visualizer#1%
  {\ifproductionrun\clf_loadvisualizer{#1}\fi}

\permanent\protected\def\doifelsevisualizer#1%
  {\clf_doifelsevisualizer{#1}}

\aliased\let\doifvisualizerelse\doifelsevisualizer

%D Verbatim command are very sensitive to argument processing, which is a direct
%D result of the \CATCODES\ being fixed at reading time.
%D
%D Typesetting inline verbatim can be accomplished by \type {\type}, which in this
%D sentence was typeset by saying just \type {\type {\type}}, which in turn was
%D typeset by \unknown. Using the normal grouping characters \type {{}} is the most
%D natural way of using this command.
%D
%D A second, more or less redundant, alternative is delimiting the argument with an
%D own character. This method was implemented in the context of a publication in the
%D \MAPS, where this way of delimiting is recognized by \LATEX\ users.
%D
%D The third, more original alternative, is the one using \type {<<} and \type {>>}
%D as delimiters. This alternative can be used in situations where slanted
%D typeseting is needed.
%D
%D \macros
%D   {type}
%D
%D We define \type {\type} as a protected command. This command has several
%D invocations: grouped, wirt boundary characters, and with font switches.
%D
%D \starttyping
%D normal: \par \type{xx<<..xx..<<xx <<xx>> >>..>>xx} \par \type<<....>> \par \type<<..<<xx>>..>> \par
%D normal: \par \type{xx<..xx..<xx <slanted> >..>xx} \par \type{<....>} \par \type{<..<xx>..>}
%D \setuptype[option=slanted]
%D slanted: \par \type{xx<<..sl..<<xx <<sl>> xx>>..sl..>>xx} \par \type<<..xx..>> \par \type<<..<<sl>>..>> \par
%D slanted: \par \type{xx<<..sl..<xx <sl> xx>..sl..>>xx} \par \type<<..xx..>> \par \type<<..<sl>..>> \par
%D \setuptype[option=none]
%D none: \par \type{xx<<..xx..<<xx <<xx>> >>..>>xx} \par \type<<....>> \par \type<<..<<xx>>..>> \par
%D \stoptyping
%D
%D When writing the manual to \CONTEXT\ and documenting this source we needed to
%D typeset \type {<<} and \type {>>}. Because we wanted to do this in the natural
%D way, we've adapted the original definition a bit. This implementation went
%D through several live cycles. The final implementation looks a bit further and
%D treats the lone \type {<<} and \type {>>} a bit different. The \type {\null}
%D prevents ligatures, which unfortunately turn up in Lucida fonts.
%D
%D The following lines show what happens when we set \type {option=commands}.
%D
%D \startbuffer
%D \starttyping
%D test//test test/BTEX \footnote{test test test}/ETEX test
%D test//test test/BTEX \footnote{test test test}/ETEX  test
%D test test test/BTEX \bf(nota bene)/ETEX test
%D test test test /BTEX \bf(nota bene)/ETEX  test
%D \stoptyping
%D \stopbuffer
%D
%D % \bgroup\setuptyping[option=commands]\getbuffer\egroup
%D
%D this was keyed in as:
%D
%D \typebuffer

% Beware, the command is supposed to do something like \framed and not manipulate
% content i.e. it gets no argument but something b/egrouped instead:

\def\buff_verbatim_left_of_type
  {\typeparameter\c!left
   \typeparameter\c!command\bgroup}

\def\buff_verbatim_right_of_type
  {\egroup
   \typeparameter\c!right}

\permanent\protected\def\type{\buff_verbatim_type\empty}
\permanent\protected\def\typ {\buff_verbatim_typ \empty}

\protected\def\buff_verbatim_type#1%
  {\dontleavehmode
   \bgroup
   \cdef\currenttype{#1}%
   \buff_verbatim_type_indeed}

\def\buff_verbatim_typ#1%
  {\dontleavehmode
   \bgroup
   \cdef\currenttype{#1}%
   \lettypeparameter\c!lines\v!hyphenated
   \enforced\let\specialobeyedspace\specialstretchedspace
   \buff_verbatim_type_indeed}

\tolerant\def\buff_verbatim_type_indeed[#S#1]%
  {\ifarguments\or\setupcurrenttype[#1]\fi
   \buff_verbatim_left_of_type
   \futureexpand\bgroup\buff_verbatim_type_a\buff_verbatim_type_one}

\def\buff_verbatim_type_one
  {\catcode\lessthanasciicode\othercatcode % old precaution
   \catcode\morethanasciicode\othercatcode % old precaution
   \futureexpandis<\buff_verbatim_type_b\buff_verbatim_type_c}

\def\buff_verbatim_type_three
  {\if\next<%
     \expandafter\buff_verbatim_type_b
   \else
     \expandafter\buff_verbatim_type_c
   \fi}

\def\buff_verbatim_type_a
  {\buff_verbatim_initialize_type_one
   \setcatcodetable\tpacatcodes
   \buff_verbatim_type_normal}

\def\buff_verbatim_type_b#1%
  {\buff_verbatim_initialize_type_one
   \setcatcodetable\tpbcatcodes
   \buff_verbatim_type_nested}

\def\buff_verbatim_type_c#1%
  {\buff_verbatim_initialize_type_one
   \setcatcodetable\vrbcatcodes
   \def\next##1#1{\buff_verbatim_type_normal{##1}}%
   \next}

\def\buff_verbatim_type_normal#1%
  {\buff_verbatim_initialize_type_two
   \dostarttaggedchained\t!verbatim\currenttype\currenttype\??type
   \clf_type
     data    {\protecteddetokenize{#1}}%
     tab     {\typeparameter\c!tab}%
     method  {\p_buff_option}%
     compact {\typeparameter\c!compact}% % none | all | last (all needed in tabulate etc for manuals)
     escape  {\typeparameter\c!escape}%  % new but rather useless imo (escaping in general is not used much)
   % nature  {inline}% is default
   \relax
   \dostoptagged
   \buff_verbatim_right_of_type
   \egroup}

\def\buff_verbatim_type_nested#1%
  {\buff_verbatim_initialize_type_two
   \dostarttaggedchained\t!verbatim\currenttype\currenttype\??type
   \clf_type
     data   {\detokenize{#1}}%
%      data    {\protecteddetokenize{#1}}%
     tab    {\typeparameter\c!tab}%
     method {\p_buff_option}% % extra visualizer (maybe: nested,\typeparameter\c!option)
     escape {\typeparameter\c!escape}%  % new but rather useless imo (escaping in general is not used much)
   % nature {inline}% is default
     method {nested}%
   \relax
   \dostoptagged
   \buff_verbatim_right_of_type
   \egroup
   \gobbleoneargument} % grab last >

%D The \type {compact} option can come in handy in the case of inline argument passing
%D
%D \starttyping
%D \definetype[TeXcodeA][option=TEX]
%D \definetype[TeXcodeB][option=TEX,compact=all]
%D \definetype[TeXcodeC][option=TEX,compact=absolute]
%D
%D \def\argA#1{\TeXcodeA{{#1}}}
%D \def\argB#1{\TeXcodeB{{#1}}}
%D \def\argC#1{\TeXcodeC{{#1}}}
%D \stoptyping

%D \macros
%D   {obeyhyphens,obeybreakpoints}
%D
%D Although it's not clear from the macros, one character trait of this macros,
%D which are build on top of the support module, is that they don't hyphenate. We
%D therefore offer the alternative \type{\typ}. The current implementation works all
%D right, but a decent hyphenation support of \type{\tt} text will be implemented
%D soon.

\permanent\protected\def\specialfixedspace     {\kern\interwordspace\relax}
\permanent\protected\def\specialobeyedspace    {\hskip\interwordspace\relax} % better than spaceskip
\permanent\protected\def\specialstretchedspace {\hskip.5\interwordspace\s!plus.125\interwordspace\relax} % \interwordstretch can be zero
\permanent\protected\def\specialcontrolspace   {\normalcontrolspace\allowbreak} % uses fallback

\permanent\protected\def\explicitfixedspace    {\asciispacechar}
\permanent\protected\def\explicitobeyedspace   {\asciispacechar\allowbreak}
\permanent\protected\def\explicitstretchedspace{\asciispacechar\hskip\zeropoint\s!plus.125\interwordspace\relax}%
\permanent\protected\def\explicitcontrolspace  {\optionalcontrolspace\allowbreak} % uses asciispace

\appendtoks
    \enforced\protected\def\obeyedspace{\hskip\zeroskip\relax\asciispacechar\hskip\zeroskip\relax}%
\to \everyenableelements

\permanent\protected\def\obeyhyphens
  {\enforced\let\obeyedspace \specialobeyedspace % maybe \specialstretchedspace
   \enforced\let\controlspace\specialcontrolspace
   \spaceskip.25\emwidth\relax} % hm a bit of stretch !

\permanent\protected\def\obeybreakpoints
  {\ignorehyphens
   \veryraggedright}

\permanent\protected\def\ignorehyphens
  {\nohyphens
   \enforced\let\obeyedspace \specialobeyedspace
   \enforced\let\controlspace\specialcontrolspace
   \spaceskip.5\emwidth\relax}

%D \macros
%D   {tex,arg,mat,dis,astype}
%D
%D Sometimes, for instance when we pass verbatim text as an argument, the fixed
%D \CATCODES\ interfere with our wishes. An experimental implementation of character
%D by character processing of verbatim text did overcome this limitation, but we've
%D decided not to use that slow and sometimes troublesome solution. Instead we stick
%D to some 'old' \CONTEXT\ macros for typesetting typical \TEX\ characters.

\permanent\cdef\lesscharacter    {<} % obsolete
\permanent\cdef\morecharacter    {>} % obsolete

\aliased  \let\texescape        \textbackslash
\aliased  \let\leftargument     \textbraceleft
\aliased  \let\rightargument    \textbraceright
\aliased  \let\inlinemathmarker \textdollar
\permanent\def\displaymathmarker{\textdollar\textdollar}

\def\buff_verbatim_special_type#1#2#% # gobbles spaces
  {\dontleavehmode\bgroup
   \buff_verbatim_initialize_type_one
   \catcode\leftbraceasciicode \begingroupcatcode
   \catcode\rightbraceasciicode\endgroupcatcode
   #1%
   \bgroup % else wrong font for #2
   \aftergroup#2%
   \aftergroup\egroup
   \let\nexttoken}

\mutable\protected\def\tex{\buff_verbatim_special_type\texescape        \relax}
\mutable\protected\def\arg{\buff_verbatim_special_type\leftargument     \rightargument}
\mutable\protected\def\mat{\buff_verbatim_special_type\inlinemathmarker \inlinemathmarker}
\mutable\protected\def\dis{\buff_verbatim_special_type\displaymathmarker\displaymathmarker}

\aliased\let\normaltexttex\tex
\aliased\let\normaltextarg\arg
\aliased\let\normaltextmat\mat
\aliased\let\normaltextdis\dis

\permanent\protected\def\astype
  {\dontleavehmode
   \bgroup\usetypestyleandcolor\c!style\c!color\let\nexttoken}

\permanent\protected\def\asciistr#1% used in some old styles
  {\dontleavehmode\begingroup
   \dostarttaggednodetail\t!verbatim
   \usetypestyleandcolor\c!style\c!color\detokenize{#1}%
   \dostoptagged
   \endgroup}

%D The basic display verbatim commands are defined in an indirect way. As we
%D will see, they are a specific case of a more general mechanism.

\mutable\let\beginofverbatimlines\relax % hooks
\mutable\let\endofverbatimlines  \relax % hooks

\protected\def\buff_verbatim_typing_start#1#2% tricky non standard lookahead
  {\begingroup
   \cdef\currenttyping       {#1}%
   \edef\currenttypingwrapper{#2}%
   \begingroup
   \obeylines % alternatively \future.. could *not* ignore newlines
   \futureexpandis[\buff_verbatim_typing_start_yes\buff_verbatim_typing_start_nop}

\def\buff_verbatim_typing_start_yes[#S#1]%
  {\endgroup
   \ifhastok={#1}%
     \setupcurrenttyping[#1]%
   \orelse\ifcstok{#1}\v!continue
     \lettypingparameter\c!continue\v!yes
   \fi
   \typingparameter\c!before\relax % moved down
   \startpacked[\v!blank]%         % moved down
   \buff_verbatim_setup_keep_together
   \buff_verbatim_setup_line_numbering
   \buff_verbatim_initialize_typing_one
   \expanded{\buff_verbatim_type_block{\e!start\currenttypingwrapper}{\e!stop\currenttypingwrapper}}}

\def\buff_verbatim_typing_start_nop
  {\endgroup
   \typingparameter\c!before\relax
   \startpacked[\v!blank]%
   \buff_verbatim_setup_keep_together
   \buff_verbatim_setup_line_numbering
   \buff_verbatim_initialize_typing_one
   \expanded{\buff_verbatim_type_block{\e!start\currenttypingwrapper}{\e!stop \currenttypingwrapper}}}

%D \start \showmakeup[vpenalty]
%D \starttyping[keeptogether=paragraph]
%D test test
%D test test
%D test test
%D test test
%D \stoptyping
%D \stop

\protected\def\buff_verbatim_setup_keep_together
  {\ifcstok{\typingparameter\c!keeptogether}\v!yes
     \c_buff_lines_as_paragraph \conditionalfalse
     \c_buff_optimize_linebreaks\conditionaltrue
  %\orelse\ifcstok{\typingparameter\c!keeptogether}\v!paragraph
   \orelse\iflastnamedcs\v!paragraph
     \c_buff_lines_as_paragraph \conditionaltrue
     \c_buff_optimize_linebreaks\conditionalfalse
   \else
     \c_buff_lines_as_paragraph \conditionalfalse
     \c_buff_optimize_linebreaks\conditionalfalse
   \fi}

\protected\def\buff_verbatim_type_block#1#2%
  {\expanded{\buff_pickup
     {_typing_}%
     {#1}%
     {#2}%
     {}%
     {\buff_verbatim_type_block_verbatim_indeed{#1}{#2}}%
     \ifcstok{\typingparameter\c!strip}\v!no\zerocount\else\plusone\fi}}

\protected\def\buff_verbatim_type_block_verbatim_indeed#1#2%
  {\buff_verbatim_initialize_typing_two
   \dostarttaggedchained\t!verbatimblock\currenttyping\currenttyping\??typing
   \beginofverbatimlines
   \dostarttaggednodetail\t!verbatimlines
   \clf_typebuffer
     name    {_typing_}%
     strip   {\typingparameter\c!strip}%
     range   {\typingparameter\c!range}%
     tab     {\typingparameter\c!tab}%
     par     {\typingparameter\c!paragraph}%
     method  {\p_buff_option}%
     escape  {\typingparameter\c!escape}%
     nature  {display}%
   \relax
   \dostoptagged
   \endofverbatimlines
   \dostoptagged
   \begincsname#2\endcsname}

\protected\def\buff_verbatim_typing_stop
  {\stoppacked
   \typingparameter\c!after\relax
   \useindentnextparameter\typingparameter
   \endgroup
   \dorechecknextindentation}

\permanent\protected\def\startnamedtyping[#1]%
  {\buff_verbatim_typing_start{#1}\e!namedtyping}

\permanent\let\stopnamedtyping\buff_verbatim_typing_stop

%D Line numbering for files is combined with filtering, while display verbatim has
%D the ability to continue.
%D
%D \starttyping
%D \typefile[numbering=file,start=10,stop=12]{test.tex}
%D
%D \definetyping[code][numbering=line]
%D
%D \starttext
%D \startcode
%D ...
%D ...
%D \stopcode
%D
%D \startcode[start=continue]
%D ...
%D ...
%D \stopcode
%D
%D \startcode[start=10]
%D ...
%D \stopcode
%D \stoptyping

%D Ranges:
%D
%D \starttyping
%D % label:start:one
%D
%D \def\MyMacro
%D   {just an example}
%D
%D % label:stop:one
%D
%D \starttext
%D
%D % \typefile[file][range={3,6}] {whatever.tex}
%D % \typefile[file][range={3,+2}]{whatever.tex}
%D
%D \typefile[file][range={label:start:one,label:stop:one}]{whatever.tex}
%D
%D \stoptext
%D \stoptyping

%D \macros
%D   {typefile}
%D
%D Typesetting files verbatim (for the moment) only supports colorization of \TEX\
%D sources as valid option. The other setup values are inherited from display
%D verbatim. The implementation of \type {\typefile} is straightforward:

% [category] [settings] {name} % for historic reasons, all filenames are {}

\mutable\lettonothing\currenttypingfile
\mutable\lettonothing\currenttypingwrapper

\appendtoks
    \frozen\protected\instance\edefcsname\e!type\currenttyping\v!file\endcsname{\typefile[\currenttyping]}%
\to \everydefinetyping

\permanent\tolerant\protected\def\typefile[#S#1]#*[#S#2]#:#3%
  {\begingroup
   \ifparameter#2\or
     \setuptyping[#1][#2]%
     \buff_verbatim_type_file_checked{#1}{#3}%
   \orelse\ifparameter#1\or
     \ifhastok={#1}%
       \setuptyping[\v!file][#1]%
       \buff_verbatim_type_file_checked\v!file{#3}%
     \else
       \buff_verbatim_type_file_checked{#1}{#3}%
     \fi
   \else
     \buff_verbatim_type_file_checked\v!file{#3}%
   \fi
   \useindentnextparameter\typingparameter % needs checking
   \endgroup
   \dorechecknextindentation} % needs checking

\def\buff_verbatim_type_file_checked#1#2%
  {\doifelsetypingfile{#2}
     {\buff_verbatim_type_file_indeed{#1}\currenttypingfile}
     {\showmessage\m!verbatims1{#2}}}

\permanent\protected\def\doifelsetypingfile#1%
  {\edef\currenttypingfile{\locfilename{#1}}%
   \ifempty\currenttypingfile
     \edef\currenttypingfile{\locfilename{#1.tex}}% downward compatible
   \fi
   \ifempty\currenttypingfile
     \expandafter\secondoftwoarguments
   \else
     \expandafter\firstoftwoarguments
   \fi}

\aliased\let\doiftypingfileelse\doifelsetypingfile

\def\buff_verbatim_type_file_indeed#1#2% category name
  {\cdef\currenttyping{#1}%
   \typingparameter\c!before\relax
   \startpacked[\v!blank]
   \buff_verbatim_setup_keep_together
   \buff_verbatim_setup_line_numbering
   \buff_verbatim_initialize_typing_one
   \buff_verbatim_initialize_typing_two
   \dostarttaggedchained\t!verbatimblock\currenttyping\currenttyping\??typing
   \beginofverbatimlines
   \dostarttaggednodetail\t!verbatimlines
   \clf_typefile
      name   {#2}%
      strip  {\typingparameter\c!strip}%
      range  {\typingparameter\c!range}%
      regime {\currentregime}%
      tab    {\typingparameter\c!tab}%
      method {\p_buff_option}%
      nature {display}%
   \relax
   \dostoptagged
   \endofverbatimlines
   \dostoptagged
   \stoppacked
   \typingparameter\c!after\relax}

%D Line numbering:

\newconditional\verbatimnumberinglines

\permanent\protected\def\beginofverbatimlinenumbering
  {\startlinenumbering
     [\currenttyping]%
     [\c!continue=\typingparameter\c!continue,
        \c!method=\v!type,
         \c!start=\typingparameter\c!start,
          \c!stop=\typingparameter\c!stop, % ?
          \c!step=\typingparameter\c!step]}

\permanent\protected\def\endofverbatimlinenumbering
  {\stoplinenumbering}

\def\buff_verbatim_setup_line_numbering
  {\ifdefined\startlinenumbering
     \edef\p_numbering{\typingparameter\c!numbering}%
     \ifx\p_numbering\v!file
       \setuplinenumbering[\currenttyping][\c!method=\v!file]%
       \verbatimnumberinglines\conditionaltrue
     \orelse\ifx\p_numbering\v!line
       \verbatimnumberinglines\conditionaltrue
     \else
       \verbatimnumberinglines\conditionalfalse
     \fi
     \ifconditional\verbatimnumberinglines
       \enforced\let\beginofverbatimlines\beginofverbatimlinenumbering
       \enforced\let\endofverbatimlines  \endofverbatimlinenumbering
     \fi
   \fi}

%D \macros
%D   {filename}
%D
%D Typesetting filenames in monospaced fonts is possible with
%D
%D \starttyping
%D \filename{here/there/filename.suffix}
%D \stoptyping
%D
%D The definition is not that spectacular.

\permanent\protected\def\filename#1{{\tttf\hyphenatedfilename{#1}}}

%D \macros
%D   {verbatim}
%d
%D And a bonus macro, an unexpanded detokenize:

\permanent\protected\def\verbatim#1{\detokenize{#1}}

%D The setups for display verbatim and file verbatim are shared. One can adapt the
%D extra defined typing environments, but they also default to the values below.
%D Watch the alternative escape character.

% \tttf   gives problems with {\tx \type...}
% \tt\tf  does not adapt to e.g. \bf

\setuptyping
  [\c!before=\blank,
   \c!after=\blank,
  %\c!keeptogether=yes, % this will become default (when tested enough)
  %\c!bodyfont=,
  %\c!color=,
   \c!space=\v!off,
   \c!lines=\v!no,
   \c!page=\v!no,
   \c!tab=\v!yes, % what is this: \s!ascii ?
   \c!option=\v!none,
   \c!text=\v!no,
   \c!style=\tt,
   \c!indentnext=\v!yes,
   \c!margin=\zeropoint,
   \c!evenmargin=\zeropoint,
   \c!oddmargin=\zeropoint,
   \c!blank=\v!line,
  %\c!escape=, % yes | no | {START,STOP} | default when yes: {BTEX,ETEX}
   \c!numbering=\v!no,
  %\c!range=,
   \c!start=1,
  %\c!stop=,
   \c!step=1,
  %\c!continue=,
   \c!strip=\v!no] % auto or number

\definetyping[\v!typing]

% the \zeropoint forces the number to the margin but also works ok in text

\setuplinenumbering[\v!typing][\c!location=\v!left,\c!width=\zeropoint]

\setuptyping       [\v!file]  [\s!parent=\??typing       \v!typing] % we don't want \start..\stop overload
\setuplinenumbering[\v!file]  [\s!parent=\??linenumbering\v!typing]

\setuptyping       [\v!buffer][\s!parent=\??typing       \v!file]   % we don't want \start..\stop overload
\setuplinenumbering[\v!buffer][\s!parent=\??linenumbering\v!file]

%D The setups for inline verbatim default to:

\setuptype
  [\c!space=\v!off,
   \c!lines=\v!no,
  %\c!color=,
   \c!style=\tt,
  %\c!option=\v!normal,
   \c!page=\v!no,
   \c!tab=\v!yes,
   \c!compact=\v!all]

%D Buffers

% [name] [settings] | [name] | [settings]

\permanent\protected\def\typebuffer
  {\begingroup
   \let\currenttyping\v!buffer
   \buff_verbatim_type_buffer}

\permanent\protected\def\typedefinedbuffer[#1]%
  {\buff_verbatim_type_defined_buffer[\v!buffer][\thedefinedbuffer{#1}]}%

% \appendtoks
%     \frozen\instance\protected\edefcsname\e!type\currentbuffer\endcsname
%       {\buff_verbatim_type_defined_buffer[\v!buffer][\currentdefinedbuffer]}%
% \to \everydefinebuffer

\appendtoks
    \frozen\instance\protected\edefcsname\e!type\currentbuffer\endcsname
      {\buff_verbatim_type_defined_buffer[\currentbuffer][\currentdefinedbuffer]}%
\to \everydefinebuffer

\appendtoks % \e!buffer
    \frozen\instance\protected\edefcsname\e!type\currenttyping\v!buffer\endcsname
      {\buff_verbatim_type_buffer_class{\currenttyping}}%
\to \everydefinetyping

\tolerant\protected\def\buff_verbatim_type_buffer[#S#1]#*[#S#2]%
  {\ifarguments
     \buff_verbatim_type_buffer_indeed\currenttyping\empty% []
   \or
     \ifhastok={#1}%
       \setupcurrenttyping[#1]%
       \buff_verbatim_type_buffer_indeed\currenttyping\empty% [settings]
     \else
       \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name]
     \fi
   \or
     \setupcurrenttyping[#2]%
     \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name] [settings]
   \fi
   \useindentnextparameter\typingparameter
   \endgroup
   \dorechecknextindentation}

\protected\def\buff_verbatim_type_buffer_class#1%
  {\begingroup
   \cdef\currenttyping{#1}%
   \buff_verbatim_type_buffer}

\tolerant\protected\def\buff_verbatim_type_defined_buffer[#1]#*[#2]#*[#S#3]% category name settings
  {\begingroup
   \cdef\currenttyping{\namedbufferparameter{#1}\c!category}%
   \ifempty\currenttyping
     \let\currenttyping\v!buffer
   \fi
   \ifhastok={#3}%
     \setupcurrenttyping[#3]%
   \orelse\ifempty{#3}\else
     \cdef\currenttyping{#3}
   \fi
   \buff_verbatim_type_buffer_indeed{\currenttyping}{#2}%
   \useindentnextparameter\typingparameter
   \endgroup
   \dorechecknextindentation}

\protected\def\buff_verbatim_type_buffer_indeed#1#2% category name
  {\cdef\currenttyping{#1}%
   \typingparameter\c!before\relax
   \startpacked[\v!blank]
   \buff_verbatim_setup_keep_together
   \buff_verbatim_setup_line_numbering
   \buff_verbatim_initialize_typing_one
   \buff_verbatim_initialize_typing_two
   \dostarttaggedchained\t!verbatimblock{#1}{#1}\??typing
   \beginofverbatimlines
   \dostarttaggednodetail\t!verbatimlines
   \clf_typebuffer
     name   {#2}%
     strip  {\typingparameter\c!strip}%
     range  {\typingparameter\c!range}%
     regime {\currentregime}%
     tab    {\typingparameter\c!tab}%
     par    {\typingparameter\c!paragraph}%
     method {\p_buff_option}%
     escape {\typingparameter\c!escape}%
     nature {display}%
   \relax
   \dostoptagged
   \endofverbatimlines
   \dostoptagged
   \stoppacked
   \typingparameter\c!after\relax}

\permanent\tolerant\protected\def\typeinlinebuffer[#S#1]#,[#S#2]%
  {\dontleavehmode
   \begingroup
   \enforced\let\setupcurrenttyping\setupcurrenttype % a terrible hack but it saves code
   \lettonothing\currenttype
   \ifparameters
     \buff_verbatim_type_buffer_indeed_inline\currenttyping\empty% []
   \or
     \ifhastok={#1}%
       \setupcurrenttyping[#1]%
       \buff_verbatim_type_buffer_indeed_inline\currenttyping\empty% [settings]
     \else
       \processcommalist[#1]{\buff_verbatim_type_buffer_indeed_inline\currenttyping}% [name]
     \fi
   \or
     \setupcurrenttyping[#2]%
     \processcommalist[#1]{\buff_verbatim_type_buffer_indeed_inline\currenttyping}% [name] [settings]
   \fi
   \endgroup}

\protected\def\buff_verbatim_type_buffer_indeed_inline#1#2% category name
  {\cdef\currenttype{#1}%
   \buff_verbatim_initialize_type_one
   \expand\everyinitializeverbatim % \buff_verbatim_initialize_type_two
   \dostarttaggedchained\t!verbatim\currenttype\currenttype\??type
   \clf_typebuffer
     name   {#2}%
     strip  {\v!yes}%
     regime {\currentregime}%
     method {\p_buff_option}%
     nature {inline}% is default anyway
   \relax
   \dostoptagged}

% get     : before/after of buffer
% typing  : before/after of typing
% process : no before/after (special case anyway)

% the next one is obsolete (bad name and used nowhere) so if it stays
% the name will change

\permanent\tolerant\protected\def\processbuffer[#S#1]#*[#S#2]%
  {\writestatus{nota bene}{\string\processbuffer\space is obsolete}%
   \begingroup
   \ifarguments
     \buff_verbatim_process_indeed\v!buffer\empty% []
   \or
     \ifhastok={#1}%
       \setuptyping[\v!buffer][#1]%
       \buff_verbatim_process_indeed\v!buffer\empty% [settings]
     \else
       \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name]
     \fi
   \or
     \setuptyping[\v!buffer][#2]%
     \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name] [settings]
   \fi
   \endgroup}

\def\buff_verbatim_process_indeed#1#2%
  {\cdef\currenttyping{#1}%
   \clf_processbuffer
     name   {#2}%
     strip  {\typingparameter\c!strip}%
     tab    {\typingparameter\c!tab}%
   % par    {\typingparameter\c!paragraph}%
   % method {\p_buff_option}%
     nature {direct}%
   \relax}

% so far for obsolete

% line numbering, keep broken lines together

\newinteger\nofverbatimlines

% \protected\def\buff_verbatim_begin_of_line
%   {\ifconditional\verbatimnumberinglines
%      \global\advanceby\nofverbatimlines\plusone
%      \c_attr_verbatimline\nofverbatimlines
%    \fi
%    \noindent
%    \buff_verbatim_set_line_margin
%    \expand\everyline % maybe also after starttagged
%    \strut % after starttagged, else break !
%    \dostarttaggednodetail\t!verbatimline}

% \protected\def\buff_verbatim_end_of_line
%   {\dostoptagged
%   %\obeyedline % is actually \par here
%    \ifconditional\c_buff_lines_as_paragraph
%      \parbreak
%    \else
%      \par
%    \fi
%    \ifconditional\verbatimnumberinglines
%      \c_attr_verbatimline\attributeunsetvalue
%    \fi}

% \protected\def\buff_verbatim_end_of_line
%   {\dostoptagged
%   %\obeyedline % is actually \par here
%    \ifconditional\c_buff_lines_as_paragraph
%      \parbreak
%    \else
%      \par
%      \buff_verbatim_inject_breaks % new because now widowpenalties apply to the par
%    \fi
%    \ifconditional\verbatimnumberinglines
%      \c_attr_verbatimline\attributeunsetvalue
%    \fi}

% \protected\def\buff_verbatim_empty_line
%   {\dostoptagged
%    \ifconditional\verbatimnumberinglines
%      \par\strut\par % this will be an option where we use a signal instead of a strut
%    \else
%      \blank[\typingparameter\c!blank]%
%    \fi
%    \dostarttaggednodetail\t!verbatimlines}

% hooks (todo: frozen):

% see (1), which is why \par is needed:
%
% \starttyping
% line 01
% line 02
% .... (add lines)
% line 22
% line 23
% \stoptyping

\newinteger    \c_buff_verbatim_noflines
\newinteger    \c_buff_verbatim_current
\newconditional\c_buff_optimize_linebreaks

\permanent\protected\def\doverbatimspace           {\obeyedspace}

\permanent\protected\def\doinlineverbatimstart     {}
\permanent\protected\def\doinlineverbatimstop      {}
\permanent\protected\def\doinlineverbatimbeginline {}
\permanent\protected\def\doinlineverbatimnewline   {\obeyedspace}
\permanent\protected\def\doinlineverbatimemptyline {\obeyedspace}

% \permanent\protected\def\dodisplayverbatimstart    {\advanceby\c_buff_verbatim_current\plusone
%                                                     \buff_verbatim_begin_of_line}
% \permanent\protected\def\dodisplayverbatimstop     {\buff_verbatim_end_of_line}
% \permanent\protected\def\dodisplayverbatimemptyline{\buff_verbatim_empty_line}
% \permanent\protected\def\dodisplayverbatimbeginline{\advanceby\c_buff_verbatim_current\plusone
%                                                     \buff_verbatim_begin_of_line}
% \permanent\protected\def\dodisplayverbatimnewline  {\buff_verbatim_end_of_line
%                                                     \ifconditional\c_buff_optimize_linebreaks
%                                                       \par % needed see (1), if issue then rely on vbreak
%                                                       \buff_verbatim_inject_breaks
%                                                     \orelse\ifconditional\c_buff_lines_as_paragraph
%                                                         % we need to find a bordercase but no crlf here
%                                                     \else
%                                                       \parbreak
%                                                     \fi}

% \permanent\protected\def\dodisplayverbatimstart    {\starthangrange}
% \permanent\protected\def\dodisplayverbatimemptyline{\stophangrange
%                                                     \blank[\typingparameter\c!blank]%
%                                                     \starthangrange}
% \permanent\protected\def\dodisplayverbatimstop     {\stophangrange}
% \permanent\protected\def\dodisplayverbatimbeginline{\starthangrangestep}
% \permanent\protected\def\dodisplayverbatimnewline  {\stophangrangestep}

%D \starttyping
%D \showmakeup[vpenalty,line,par]
%D
%D \widowpenalties 3 3000 2000 1000
%D \clubpenalties  3   30   20   10
%D
%D % \widowpenalties 3 options \largestspecificationoptioncode 3000 2000 1000
%D % \clubpenalties  3 options \largestspecificationoptioncode   30   20   10
%D
%D \startbuffer
%D test test test test test test and more test test test test test test test and more test
%D test test test test test test and more test test test test test test test and more test
%D
%D test test test test test test and more test test test test test test test and more test
%D test test test test test test and more test test test test test test test and more test
%D \stopbuffer
%D
%D \typebuffer[keeptogether=paragraph,align=hangright]
%D \typebuffer[keeptogether=paragraph,align=hangleft]
%D \stoptyping


% test
%
% \starttyping
% first
% second second
% third third third
% fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth
% fifth
% sixth
% \stoptyping
%
% test
%
% \starttyping
% first
% second second
% third third third
% fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth fourth
% fifth
% sixth sixth sixth sixth sixth sixth sixth sixth sixth sixth sixth sixth sixth sixth sixth sixth sixth sixth sixth sixth sixth
% \stoptyping
%
% test

\permanent\protected\def\dodisplayverbatimstart
  {\advanceby\c_buff_verbatim_current\plusone
   \ifconditional\verbatimnumberinglines
     \global\advanceby\nofverbatimlines\plusone
     \c_attr_verbatimline\nofverbatimlines
   \fi
   \ifconditional\c_buff_lines_as_paragraph
     \buff_verbatim_set_line_margin
     \starthangrange
   \else
     \noindent
     \buff_verbatim_set_line_margin
   \fi
   \expand\everyline % maybe also after starttagged
   \dostarttaggednodetail\t!verbatimline
   \strut}

\permanent\protected\def\dodisplayverbatimstop
  {\dostoptagged
   \ifconditional\c_buff_lines_as_paragraph
     \stophangrange % new because now widowpenalties apply to the par
   \orelse\ifconditional\c_buff_optimize_linebreaks
     \par
     \buff_verbatim_inject_breaks
   \else
     \par
   \fi
   \ifconditional\verbatimnumberinglines
     \c_attr_verbatimline\attributeunsetvalue
   \fi}

\permanent\protected\def\dodisplayverbatimemptyline
  {\dostoptagged
   \ifconditional\c_buff_lines_as_paragraph
     \stophangrange
   \fi
   \ifconditional\verbatimnumberinglines
     \par\strut\par % this will be an option where we use a signal instead of a strut
   \else
     \blank[\typingparameter\c!blank]%
   \fi
   \ifconditional\c_buff_lines_as_paragraph
     \starthangrange
   \fi
   \dostarttaggednodetail\t!verbatimlines}

\permanent\protected\def\dodisplayverbatimbeginline
  {\advanceby\c_buff_verbatim_current\plusone
   \ifconditional\verbatimnumberinglines
     \global\advanceby\nofverbatimlines\plusone
     \c_attr_verbatimline\nofverbatimlines
   \fi
   \ifconditional\c_buff_lines_as_paragraph
     \starthangrangestep
     \buff_verbatim_set_line_margin
   \else
     \noindent
     \buff_verbatim_set_line_margin
   \fi
   \expand\everyline
   \dostarttaggednodetail\t!verbatimline
   \strut}

\permanent\protected\def\dodisplayverbatimnewline
  {\dostoptagged
   \ifconditional\c_buff_lines_as_paragraph
     \stophangrangestep
   \orelse\ifconditional\c_buff_optimize_linebreaks
     \par % needed see (1), if issue then rely on \vbreak or \parbreak
     \buff_verbatim_inject_breaks
   \else
     \par
   \fi
   \ifconditional\verbatimnumberinglines
     \c_attr_verbatimline\attributeunsetvalue
   \fi}

\protected\def\buff_verbatim_inject_breaks % will become obsolete and single widow/club penalty driven
  {\ifnum\c_buff_verbatim_current=\plusone
     \nobreak % \novbreak
   \orelse\ifnum\c_buff_verbatim_noflines=\plusthree
     \nobreak % \novbreak
   \orelse\ifnum\c_buff_verbatim_current={\c_buff_verbatim_noflines-\plusone}%
     \nobreak % \novbreak
   \fi}

\permanent\protected\def\dodisplayverbatiminitialize#1%
  {\forgetparindent % maybe more
   \c_buff_verbatim_noflines#1\relax
   \c_buff_verbatim_current\zerocount}

\loadmarkfile{buff-imp-default}    % preloaded as otherwise spurious spaces inline due to loading
\loadmarkfile{buff-imp-nested}     % preloaded as otherwise spurious spaces inline due to loading
\loadmarkfile{buff-imp-escaped}    % for completeness

%D To be considered:

% \installcorenamespace{visualizer}
%
% \installcommandhandler \??visualizer {visualizer} \??visualizer
%
% \appendtoks
%     \frozen\instanceprotected\edefcsname\currentvisualizer\endcsname{\buff_verbatim_visualize{\currentvisualizer}}%
% \to \everydefinevisualizer
%
% \protected\def\buff_verbatim_visualize#1%
%   {\bgroup
%    \def\currentvisualizer{#1}%
%    \usevisualizerstyleandcolor\c!style\c!color
%    \let\next}

% in footnotes no longer needed as we can preroll

\appendtoks
  % \enforced\def\type#1{\detokenize\expandafter{\csstring#1}}% \protecteddetokenize
    \enforced\def\type#1{\detokenize{#1}}% \protecteddetokenize fails
    \enforced\def\tex #1{\letterbackslash#1}%
\to \everysimplifycommands

\stopcontextdefinitioncode

%D This is \type {\asciimode} without the double comment hackery:

\permanent\protected\def\literalmode{\setcatcodetable\txtcatcodes}

\protect \endinput