The problem has three aspects:
Aspect 1:
\scantokens
pretends to write things unexpanded to external text file and then to input that external text file whereby the content of that external text file gets tokenized under the current category-code-régime.
+v
-arguments encode line-endings as ^^M
-characters of category-code 12(other)=carriage-return-characters of category-code 12(other) while at the time of carrying out \scantokens
the value of the integer-parameter \newlinechar
still denotes the character ^^J
=the linefeed-character.
You need to make sure that \newlinechar
's value denotes the ^^M
-character=the carriage-return-character at the time when \scantokens
does its faking of unexpanded-writing things to external file.
Aspect 2:
In case code is in a single line, there must be a linebreak between the call to \begin{LTXexample}[...]
and the first line of code.
There must also be a linebreak between the last line of code and \end{LTXexample}
.
So you need a routine for detecting whether the code sequence is enclosed by linebreaks or not.
This can be implemented in the same way as checks for leading and trailing spaces. Instead about space-tokens it is about ^^M
-character-tokens of category-code 12(other)=carriage-return-character-tokens of category-code 12(other), that's all.
Detecting leading and trailing spaces is discussed in Michael Downes' Around-the-Bend-answer 15. (Exercise 15 is about writing macros for trimming leading and trailing spaces from macro arguments.)
Peter Wilson created a nicely formatted pdf-file with all Around-the-Bend-exercises and -answers.
Aspect 3:
The treatment of indenting of lines.
The argument of \LTXIO
can contain several lines of code.
How shall indenting of such code be treated?
In the example below, such indenting is left as is.
\documentclass{article}
\usepackage{xparse}
\usepackage{showexpl}
\makeatletter
%%=============================================================================
%% Work around showexpl's weird overriding of xleftmargim/xrightmargin in case
%% of having no codeline-numbers -- that weirdness is in \SX@codeInput.
%%=============================================================================
\lst@Key{nocodelinenumbers}{false}[true]{%
\lstKV@SwitchCases{#1}{%
false:\\%
true:\long\def\lst@PlaceNumber{}%
}{\PackageError{Listings}{nocodelinenumbers #1 unknown}\@ehc}%
}%
%%=============================================================================
%% Check whether argument is empty:
%%=============================================================================
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\if\relax\detokenize{#1}\relax
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{\@firstoftwo{\expandafter}{} \@firstoftwo}%
{\@firstoftwo{\expandafter}{} \@secondoftwo}%
}%
%%=============================================================================
%% Exchange arguments
%%=============================================================================
\newcommand\UD@Exchange[2]{#2#1}%
\begingroup
% Dummy-definition, will be overridden. Is used only to get ^^M of
% category code 12(other) as #1 and verbatimized calls as #2 and #3
% into subsequent definition-texts:
\NewDocumentCommand\UD@CheckWhetherLeadingEndl{+m+v+v}{%
\endgroup
%%===========================================================================
%% Check whether_verbatimized_ argument starts with a endline-character
%%===========================================================================
%% \UD@CheckWhetherLeadingEndl{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% endline-charactern>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a endline-character>}%
\newcommand\UD@CheckWhetherLeadingEndl[1]{%
\UD@@CheckWhetherLeadingEndl\UD@SelDom##1\UD@SelDom#1\UD@@SelDom
}%
\@ifdefinable\UD@@CheckWhetherLeadingEndl{%
\long\def\UD@@CheckWhetherLeadingEndl##1\UD@SelDom#1##2\UD@@SelDom{%
\UD@CheckWhetherNull{##2}{\@secondoftwo}{\@firstoftwo}%
}%
}%
%%===========================================================================
%% Check whether _verbatimized_ argument ends with a endline-character
%%===========================================================================
%% \UD@CheckWhetherTrailingEndl{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s last token is a
%% endline-charactern>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s last token is not
%% a endline-character>}%
\newcommand\UD@CheckWhetherTrailingEndl[1]{%
\UD@@CheckWhetherTrailingEndl##1\UD@SelDom#1\UD@SelDom\UD@@SelDom
}%
\@ifdefinable\UD@@CheckWhetherTrailingEndl{%
\long\def\UD@@CheckWhetherTrailingEndl##1#1\UD@SelDom##2\UD@@SelDom{%
\UD@CheckWhetherNull{##2}{\@secondoftwo}{\@firstoftwo}%
}%
}%
%%===========================================================================
%% \LTXIO
%%===========================================================================
\newcommand*\LTXIO{%
\begingroup
% Make sure endline-chars yield linebreaks when \scantokens
% does its fake-writing-part:
\newlinechar=`\^^M %
% Make sure horizontal tabs won't cause problems when LTXIO reads its
% +v-argument:
\@makeother\^^I%
\InnerLTXIO
}%
\NewDocumentCommand{\InnerLTXIO}{+v}{%
\scantokens\expandafter{%
\romannumeral0%
\UD@CheckWhetherLeadingEndl{##1}{%
\UD@CheckWhetherTrailingEndl{##1}{%
\UD@Exchange{##1}%
}{%
\UD@Exchange{##1#1}%
}%
}{%
\UD@CheckWhetherTrailingEndl{##1}{%
\UD@Exchange{#1##1}%
}{%
\UD@Exchange{#1##1#1}%
}%
}%
{ \endgroup#2}%
#3%
}%
}%
}%
%%-----------------------------------------------------------------------------
%% Now let's change the catcode of ^^M and then call the dummy-definition
%% of \UD@CheckWhetherLeadingEndl so that it can fetch the catcode-12-^^M
%% and the verbatim-phrases for closing the group and overriding itself
%% and defining all those macros where that catcode-12-^^M and those
%% verbatimized phrases are needed:
\catcode`\^^M=12 %
\UD@CheckWhetherLeadingEndl%
{^^M}%
{\begin{LTXexample}[pos=b, frame=single, linewidth=\textwidth, xleftmargin=3.4pt,
xrightmargin=3.4pt, basicstyle=\ttfamily, nocodelinenumbers, showspaces=true,
showtabs=true]}%
{\end{LTXexample}}%
\makeatother
\begin{document}
\noindent\textbf{The input}
\begin{verbatim*}
\LTXIO
{
{%
\Huge
another
piece
of
text%
}\\
{\scriptsize another piece of text}
}
\end{verbatim*}
\noindent\textbf{yields:}\vspace*{\partopsep}\vspace*{\topsep}
\LTXIO
{
{%
\Huge
another
piece
of
text%
}\\
{\scriptsize another piece of text}
}
\bigskip
\noindent\null\hrule height 2pt\hfill\null
\bigskip
\noindent\textbf{The input}
\begin{verbatim*}
\LTXIO{{\Huge another piece of text}}
\end{verbatim*}
\noindent\textbf{yields:}\vspace*{\partopsep}\vspace*{\topsep}
\LTXIO{{\Huge another piece of text}}
\end{document}
