summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/xpeek/xpeek.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2012-08-17 22:49:00 +0000
committerKarl Berry <karl@freefriends.org>2012-08-17 22:49:00 +0000
commit1993479d9cf72029f3156e0f44657df711deb319 (patch)
tree2322b7820cfb6f5cd9dd7dd7f77d0747510ba2ed /Master/texmf-dist/source/latex/xpeek/xpeek.dtx
parent03efb6dbd755ff22b128511a02ccd0940ac572c3 (diff)
xpeek (17aug12)
git-svn-id: svn://tug.org/texlive/trunk@27442 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/xpeek/xpeek.dtx')
-rw-r--r--Master/texmf-dist/source/latex/xpeek/xpeek.dtx312
1 files changed, 215 insertions, 97 deletions
diff --git a/Master/texmf-dist/source/latex/xpeek/xpeek.dtx b/Master/texmf-dist/source/latex/xpeek/xpeek.dtx
index 5eca346e2bc..007ca4e6e7d 100644
--- a/Master/texmf-dist/source/latex/xpeek/xpeek.dtx
+++ b/Master/texmf-dist/source/latex/xpeek/xpeek.dtx
@@ -3,17 +3,10 @@
% !TeX encoding = utf-8
% !TeX spellcheck = en_US
%<*internal>
-\iffalse
-%</internal>
-%<*internal>
-\fi
-\def\nameofplainTeX{plain}
-\ifx\fmtname\nameofplainTeX\else
- \expandafter\begingroup
-\fi
+\begingroup
%</internal>
%<*install>
-\input l3docstrip.tex
+\input{l3docstrip.tex}
\keepsilent
\askforoverwritefalse
\preamble
@@ -37,24 +30,31 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
----------------------------------------------------------------
\endpreamble
+\declarepreamble\minimalpreamble
+\endpreamble
\postamble
\endpostamble
\usedir{tex/latex/xpeek}
\generate{
\file{\jobname.sty}{\from{\jobname.dtx}{package}}
}
+\nopreamble\nopostamble
+\generate{
+ \file{\jobname.tests}{\from{\jobname.dtx}{tests}}
+}
+\generate{
+ \file{\jobname-test.tex}{\from{\jobname.dtx}{testsuite,tests}}
+}
%</install>
%<install>\endbatchfile
%<*internal>
+\usepreamble\minimalpreamble
+\usepostamble\defaultpostamble
\usedir{source/latex/xpeek}
\generate{
\file{\jobname.ins}{\from{\jobname.dtx}{install}}
}
-\ifx\fmtname\nameofplainTeX
- \expandafter\endbatchfile
-\else
- \expandafter\endgroup
-\fi
+\endgroup
%</internal>
%<*driver>
\pdfobjcompresslevel=0
@@ -63,6 +63,7 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
\usepackage{xpeek}
\usepackage{xspace}
\usepackage[all]{foreign}
+\usepackage{qstest}
^^A Set up formatting options
@@ -79,6 +80,14 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
}
\xspaceaddexceptions{”}
+^^A Define indented verbatim environment
+\DefineVerbatimEnvironment{IVerbatim}{Verbatim}%
+ {xleftmargin=2.5\rmemwidth, gobble=4}
+\newlength\rmemwidth
+\AtBeginDocument{
+ \setlength\rmemwidth{\fontdimen6\font}
+}
+
^^A Enable line continuations in `syntax` environments
\NewDocumentCommand \fixsyntaxlines {}
{\def\^^M{\unskip\space\ignorespaces}}
@@ -96,15 +105,23 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
% \DoNotIndex
% {
% \ProvidesExplPackage, \RequirePackage, \NewDocumentCommand,
+% \ExplSyntaxOn, \ExplSyntaxOff
+% \documentclass, \usepackage,
+% \begin, \end,
+% \xspace,
% \bool_new:N, \bool_set_true:N, \bool_set_false:N, \bool_if:NTF,
+% \hbox_set:Nn, \box_wd:N, \l_tmpa_box, \l_tmpb_box,
% \cs_new_protected:Npn,
+% \dim_use:N,
% \peek_after:Nw,
% \prg_new_protected_conditional:Npnn,
% \prg_return_true:, \prg_return_false:,
-% \tl_new:N, \tl_clear:N, \tl_set:Nn,
+% \tl_new:N, \tl_clear:N, \tl_const:Nn, \tl_set:Nn,
% \tl_put_right:Nn,
% \tl_map_inline:Nn, \tl_map_break:,
+% \c_empty_tl,
% \token_if_eq_charcode:NNT,
+% \xsp, \c_xsp_exceptions_tl,
% }
%
% \NewDocumentCommand \releasenote {}
@@ -157,17 +174,31 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
% Table~\ref{tab:itcor} compares the use of \cs{textit}
% against using the font-switch command \cs{itshape}
% with \& without explicit italic correction.
-% \begin{table}\centering
-% \begin{tabular}{lll}
-% |\textit{half}hearted| & \textit{half}hearted & (correct)\\
-% |{\itshape half}hearted| & {\itshape half}hearted & (overlap)\\
-% |{\itshape half\/}hearted| & {\itshape half\/}hearted & (correct)\\
+% \begin{table}[hbp]\centering
+% \begin{tabular}{|lll|}
+% \hline
+% |{\itshape half}hearted| &
+% {\itshape half}hearted &
+% (overlap)\\
+% |{\itshape half\/}hearted| &
+% {\itshape half\/}hearted &
+% (correct)\\
+% |\textit{half}hearted| &
+% \textit{half}hearted &
+% (correctly including italic correction)\\
% ^^A There’s a bug in the package `trace` which breaks suppression
% ^^A of italic correction; see latex3/svn-mirror#96 for details.
% ^^A As a temporary work-around, include `\nocorr` where needed.
-% |by \textit{half}.| & by \textit{half\nocorr}. & (correct)\\
-% |by {\itshape half}.| & by {\itshape half}. & (correct)\\
-% |by {\itshape half\/}.| & by {\itshape half\/}. & (too wide)\\
+% |by {\itshape half}.| &
+% by {\itshape half}. &
+% (correct)\\
+% |by {\itshape half\/}.| &
+% by {\itshape half\/}. &
+% (too wide)\\
+% |by \textit{half}.| &
+% by \textit{half\nocorr}. &
+% (correctly omitting italic correction)\\
+% \hline
% \end{tabular}
% \caption{Automatic italic correction with \cs{textit}}
% \label{tab:itcor}
@@ -177,24 +208,22 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
%
% It is, unfortunately, not hard to confuse \cs{textit}.
% As an example, consider the following code:
-% \begin{quote}
-% |\NewDocumentCommand \naif {} {\textit{na\"\i f}}|\\
-% …\\
-% |He was a true \naif.|
-% \end{quote}
+% \begin{IVerbatim}
+% \NewDocumentCommand \naif {} {\textit{na\"\i f}}
+% He was a true \naif.
+% \end{IVerbatim}
% This yields
% \begin{quote}
% \NewDocumentCommand \naif {} {\textit{na\"\i f\nocorr}}
% He was a true \naif.
% \end{quote}
% So far, so good.
-%
% But using this macro in middle of a sentence
% may produce results the naïve user does not expect.
% For example, try
-% \begin{quote}
-% |He was such a \naif he expected this example to work.|
-% \end{quote}
+% \begin{IVerbatim}
+% He was such a \naif he expected this example to work.
+% \end{IVerbatim}
% yielding
% \begin{quote}
% \NewDocumentCommand \naif {} {\textit{na\"\i f}}
@@ -213,11 +242,10 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
% will mention the \pkg{xspace} package.
% This is the sort of use-case it was developed for, after all,
% so let’s try it:
-% \begin{quote}
-% |\NewDocumentCommand \naif {} {\textit{na\"\i f}\xspace}|\\
-% …\\
-% |He was such a \naif he expected this example to work.|
-% \end{quote}
+% \begin{IVerbatim}
+% \NewDocumentCommand \naif {} {\textit{na\"\i f}\xspace}
+% He was such a \naif he expected this example to work.
+% \end{IVerbatim}
% This produces
% \begin{quote}
% \NewDocumentCommand \naif {} {\textit{na\"\i f}\xspace}
@@ -228,9 +256,9 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
% But you see, there’s a kinda hitch.^^A
% \footnote{Cue Malcolm Reynolds: “Don’t complicate things.”}
% Recall the first time we used the macro:
-% \begin{quote}
-% |He was a true \naif.|
-% \end{quote}
+% \begin{IVerbatim}
+% He was a true \naif.
+% \end{IVerbatim}
% Now it yields this:
% \begin{quote}
% \NewDocumentCommand \naif {} {\textit{na\"\i f}\xspace}
@@ -276,8 +304,8 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
%
% \begin{variable}{\g_xpeek_matchlist_tl, \g_xpeek_ignorelist_tl}
% \begin{syntax}
-% \cs{tl_gput_right:Nn} \cs{g_xpeek_\meta{list}_tl} \marg{tokens}
-% \cs{tl_gremove_all:Nn} \cs{g_xpeek_\meta{list}_tl} \marg{tokens}
+% \cs{tl_gput_right:Nn} \cs{g_xpeek_\meta{list}_tl} \Arg{tokens}
+% \cs{tl_gremove_all:Nn} \cs{g_xpeek_\meta{list}_tl} \Arg{tokens}
% \end{syntax}
% These two token-lists are the heart of \pkg{xpeek}.
%
@@ -291,9 +319,9 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
% if \LaTeX’s \cs{textit} had an ignore-list
% and the token \cs{xspace} were in that list,
% then the definition
-% \begin{quote}
-% |\NewDocumentCommand \naif {} {\textit{na\"\i f}\xspace}|
-% \end{quote}
+% \begin{IVerbatim}[gobble=6]
+% \NewDocumentCommand \naif {} {\textit{na\"\i f}\xspace}
+% \end{IVerbatim}
% from the example above
% would have worked properly:
% \cs{textit} would have ignored the \cs{xspace},
@@ -308,11 +336,11 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
%
% \begin{function}{\xpeek_after:nw}
% \begin{syntax}
-% \cs{xpeek_after:nw} \marg{code} \meta{token}
+% \cs{xpeek_after:nw} \Arg{code} \meta{token}
% \end{syntax}
% Similar to \pkg{expl3}’s \cs{peek_after:Nw},
% this sets the test variable \cs{l_peek_token} to \meta{token}
-% then executes the \marg{code}.
+% then executes the \Arg{code}.
% The \meta{token} remains in the input stream.
% \end{function}
%
@@ -320,24 +348,24 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
%
% \begin{function}{\xpeek_collect_do:nn}
% \begin{syntax}\fixsyntaxlines
-% \cs{xpeek_collect_do:nn} \marg{ignore-list} \marg{operation} \
+% \cs{xpeek_collect_do:nn} \Arg{ignore-list} \Arg{operation} \
% \meta{the rest of the input-stream}
% \end{syntax}
% This collects all leading tokens in the input stream
% which are in the ignore-list,
% and passes them as an argument to the operation.
% For example, the invocation
-% \begin{quote}
-% |\xpeek_collect_do:nn { abc } { \foo \bar } caada|
-% \end{quote}
+% \begin{IVerbatim}[gobble=6]
+% \xpeek_collect_do:nn { abc } { \foo \bar } caada
+% \end{IVerbatim}
% will collect the leading “\texttt{caa}” from the input stream
% and pass those tokens as an argument to
% the operation “|\foo \bar|”.
% \Ie, the code above is equivalent to this:
-% \begin{quote}
-% |\foo \bar { caa } da|
-% \end{quote}
-% (Note that it’s \cs{bar} \emph{within} the \marg{operation}
+% \begin{IVerbatim}[gobble=6]
+% \foo \bar { caa } da
+% \end{IVerbatim}
+% (Note that it’s \cs{bar} \emph{within} the \Arg{operation}
% that gets the collected tokens as an argument.)
% \end{function}
%
@@ -346,16 +374,16 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
% \begin{function}{\xpeek_if_in:NNTF}
% \begin{syntax}\fixsyntaxlines
% \cs{xpeek_if_in:NNTF} \cs{\meta{haystack}} \cs{\meta{needle}} \
-% \marg{true-code} \marg{false-code}
+% \Arg{true-code} \Arg{false-code}
% \end{syntax}
% Among the variants of \cs{tl_if_in:Nn(TF)} defined in \pkg{expl3},
% the form \cs{tl_if_in:NNTF} is missing.
% But that’s the form needed in this package,
% in constructions like this:
-% \begin{quote}
-% |\xpeek_if_in:NNTF \g_xpeek_matchlist_tl \l_peek_token|\\
-% | |\marg{true-code} \marg{false-code}
-% \end{quote}
+% \begin{IVerbatim}[gobble=6, commandchars=+\[\]]
+% \xpeek_if_in:NNTF \g_xpeek_matchlist_tl \l_peek_token
+% +marg[true-code] +marg[false-code]
+% \end{IVerbatim}
% So we define it ourselves.
% \end{function}
%
@@ -365,52 +393,59 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
% here’s an example of using the \pkg{xpeek} facilities
% to implement correct automatic italic correction \ala \cs{textit}.
%
-% Set the match-list equal to \LaTeX’s default \cs{nocorrlist}.
-% Only \cs{xspace} is needed in the ignore-list:
-% \begin{quote}
-% |\tl_gset:Nn \g_xpeek_matchlist_tl { , . }|\\
-% |\tl_gset:Nn \g_xpeek_ignorelist_tl { \xspace }|
-% \end{quote}
+% We set the match-list equal to \LaTeX’s default \cs{nocorrlist};
+% as mentioned above, \cs{xspace} needs to be in the ignore-list:
+% \begin{IVerbatim}
+% \tl_gset:Nn \g_xpeek_matchlist_tl { , . }
+% \tl_gset:Nn \g_xpeek_ignorelist_tl { \xspace }
+% \end{IVerbatim}
% (Note that this does not require \cs{xspace} to be defined;
-% it merely ensure that if it is defined,
-% the macro will work correctly.)
+% it merely ensure that
+% the macro will work correctly
+% if it is defined.)
%
-% Declare the new italicization command \cs{xit}.
+% Next, we declare the new italicization command \cs{xit}.
% It calls \cs{xpeek_collect_do:nn} to collect
% any instances of \cs{xspace} that might follow the invocation.
-% The \marg{code} argument to \cs{xpeek_collect_do:nn}
-% is where the italicization happens.
-% Before that ends, though,
-% the code checks whether \cs{l_peek_token} is in the ignore-list
-% and includes italic correction, or not, appropriately.
-% The last command within the \marg{code}
+% These are saved, but ignored for the time being.
+%
+% It’s within the \Arg{code} argument to \cs{xpeek_collect_do:nn},
+% between \cs{group_begin:} and \cs{group_end:},
+% that the italicization happens.
+% Before we return to the default font, though,
+% the code checks whether \cs{l_peek_token} is in the ignore-list;
+% it then decides whether to include italic correction.
+%
+% Recall next that the last command within the \Arg{code}
% is what will get the collected tokens as an argument.
% Since we want to keep \cs{xspace} if it’s there,
% we finish up the code with \cs{use:n},
% which simply puts its argument into the input stream.
-% \begin{quote}
-% |\NewDocumentCommand \xit {m}|\\
-% | {|\\
-% | \xpeek_collect_do:nn \g_xpeek_ignorelist_tl|\\
-% | {|\\
-% | \group_begin:|\\
-% | \itshape #1|\\
-% | \xpeek_if_in:NNTF \g_xpeek_matchlist_tl \l_peek_token|\\
-% | { } { \/ }|\\
-% | \group_end:|\\
-% | \use:n|\\
-% | }|\\
-% | }|\\
-% \end{quote}
+%
+% Here’s the code:
+% \begin{IVerbatim}
+% \NewDocumentCommand \xit {m}
+% {
+% \xpeek_collect_do:nn \g_xpeek_ignorelist_tl
+% {
+% \group_begin:
+% \itshape #1
+% \xpeek_if_in:NNTF \g_xpeek_matchlist_tl \l_peek_token
+% { } { \/ }
+% \group_end:
+% \use:n
+% }
+% }
+% \end{IVerbatim}
%
% Finally, define the command we tried to make work in the introduction,
-% and see whether we’ve made it work.
-% \begin{quote}
-% |\NewDocumentCommand \naif {} {\xit{na\"\i f}\xspace}|\\
-% |He was a true \naif.|\\
-% |He was such a \naif he expected this example to work.|
-% \end{quote}
-% After all this, the code above yields this result:
+% and see whether we’ve made it work:
+% \begin{IVerbatim}
+% \NewDocumentCommand \naif {} {\xit{na\"\i f}\xspace}
+% He was a true \naif.
+% He was such a \naif he expected this example to work.
+% \end{IVerbatim}
+% The code above yields this result:
% \begin{quote}
% \ExplSyntaxOn
% \tl_gset:Nn \g_xpeek_matchlist_tl { , . }
@@ -454,7 +489,7 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
%
% \begin{macrocode}
\ProvidesExplPackage
- {xpeek} {2012/08/09} {0.1}
+ {xpeek} {2012/08/15} {0.2}
{Define commands that peek ahead in the input stream}
% \end{macrocode}
%
@@ -575,6 +610,89 @@ Joel C. Salomon ‹joelcsalomon@gmail.com›.
%</package>
% \end{macrocode}
%
+% \section{Test Suite}
+%
+% \changes{Version 0.2}{2012/08/15}{Added test-suite}
+%
+% ^^A Reset line numbers in code listings
+% \makeatletter
+% \c@CodelineNo 0
+% \makeatother
+%
+% The test suite below is run automatically
+% when this document is produced.
+% It can also be run separately by executing
+% \begin{IVerbatim}[commandchars=+\[\]]
+% latex +jobname-test
+% \end{IVerbatim}
+% at the command prompt.
+%
+% \input{\jobname.tests}
+%
+% \begin{macrocode}
+%<testsuite>\documentclass{article}
+%<testsuite>\usepackage{xparse, expl3, xpeek, qstest}
+%<testsuite>\begin{document}
+%<*tests>
+% \end{macrocode}
+%
+% \subsection{Set-Up: Wrapping \cs{Expect}}
+%
+% \begin{macro}[internal]{\ExpectIdenticalWidths}
+% Since the commands \pkg{xpeek} helps produce are not expandable,
+% directly comparing their outputs is not feasible.
+% Instead, typeset two versions into boxes
+% and have \pkg{qstest} compare these boxes’ widths.
+% (Thanks to Heiko Oberdiek for this technique;
+% see \url{http://tex.stackexchange.com/q/67192/2966}.)
+% \begin{macrocode}
+\ExplSyntaxOn
+\NewDocumentCommand \ExpectIdenticalWidths { m m }
+ {
+ \hbox_set:Nn \l_tmpa_box {#1}
+ \hbox_set:Nn \l_tmpb_box {#2}
+ \Expect
+ * {\dim_use:N \box_wd:N \l_tmpa_box}
+ * {\dim_use:N \box_wd:N \l_tmpb_box}
+ }
+\ExplSyntaxOff
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Emulating \cs{xspace}}
+%
+% Define a simple analogue to \cs{xspace}.
+% \begin{macrocode}
+\ExplSyntaxOn
+\tl_const:Nn \c_xsp_exceptions_tl { ,;:.!? }
+\NewDocumentCommand \xsp {}
+ {
+ \xpeek_collect_do:nn \c_empty_tl
+ {
+ \xpeek_if_in:NNTF \c_xsp_exceptions_tl \l_peek_token
+ { } { ~ }
+ }
+ }
+\ExplSyntaxOff
+% \end{macrocode}
+% Test \cs{xsp}, ensuring that it is space-factor–agnostic.
+% \begin{macrocode}
+\begin{qstest}{Emulating \xspace}{xpeek}
+ \ExpectIdenticalWidths{foo bar}{foo\xsp bar}
+ \ExpectIdenticalWidths{foo. bar}{foo\xsp. bar}
+ \ExpectIdenticalWidths{FOO. bar}{FOO\xsp. bar}
+ \ExpectIdenticalWidths{foo. bar}{foo.\xsp bar}
+ \ExpectIdenticalWidths{FOO. bar}{FOO.\xsp bar}
+\end{qstest}
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</tests>
+%<testsuite>\end{document}
+% \end{macrocode}
+% N.B\@. The stand-alone test-suite will not produce any output,
+% only a log file.
+%
% \end{implementation}
%
% \PrintChanges