diff options
author | Karl Berry <karl@freefriends.org> | 2012-08-17 22:49:00 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2012-08-17 22:49:00 +0000 |
commit | 1993479d9cf72029f3156e0f44657df711deb319 (patch) | |
tree | 2322b7820cfb6f5cd9dd7dd7f77d0747510ba2ed /Master/texmf-dist/source/latex/xpeek/xpeek.dtx | |
parent | 03efb6dbd755ff22b128511a02ccd0940ac572c3 (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.dtx | 312 |
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 |