diff options
author | Karl Berry <karl@freefriends.org> | 2010-04-03 15:42:12 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2010-04-03 15:42:12 +0000 |
commit | 14b154c49df4af70e973eeafb54e2f31250aff0e (patch) | |
tree | 3d16bd3f92c8dd87c3475e212fca73e37ce370d7 /Master/texmf-dist/tex/latex/nicetext/fifinddo.sty | |
parent | 2a8bfdf220d7f65a85d288b2edef58e46dd9f654 (diff) |
nicetext 0.4 (30mar10)
git-svn-id: svn://tug.org/texlive/trunk@17661 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/nicetext/fifinddo.sty')
-rw-r--r-- | Master/texmf-dist/tex/latex/nicetext/fifinddo.sty | 866 |
1 files changed, 859 insertions, 7 deletions
diff --git a/Master/texmf-dist/tex/latex/nicetext/fifinddo.sty b/Master/texmf-dist/tex/latex/nicetext/fifinddo.sty index 5ae6dab9f0c..456ddd1a67f 100644 --- a/Master/texmf-dist/tex/latex/nicetext/fifinddo.sty +++ b/Master/texmf-dist/tex/latex/nicetext/fifinddo.sty @@ -1,760 +1,1612 @@ %% Macro package `fifinddo.sty' for LaTeX2e, %% FIDO, FIND! + %% copyright (C) 2009 Uwe L\"uck, + %% http://www.contact-ednotes.sty.de.vu + %% -- author-maintained in the sense of LPPL below -- + %% for processing tex(t) files + %% (checking, filtering, converting, substituting, expanding, ...) + -\def\fileversion{0.31} \def\filedate{2010/03/23} + +\def\fileversion{0.4} \def\filedate{2010/03/29} + + %% This file can be redistributed and/or modified under + %% the terms of the LaTeX Project Public License; either + %% version 1.3a of the License, or any later version. + %% The latest version of this license is in + %% + %% http://www.latex-project.org/lppl.txt + %% + %% We did our best to help you, but there is NO WARRANTY. + %% Please report bugs, problems, and suggestions via + %% + %% http://www.contact-ednotes.sty.de.vu + %% + %% For the full documentation, look for `fifinddo.pdf'. + %% Its source starts in `fifinddo.tex'. + %% + %% === Format and package version === + \NeedsTeXFormat{LaTeX2e}[1994/12/01] + % 1994/12/01: \newcommand* etc. + \ProvidesPackage{fifinddo}[\filedate\space v\fileversion\space + filtering TeX(t) files by TeX (UL)] + %% + %% === Category codes === + %% + %% We use the ``underscore" as ``compound identifier." + \catcode`\_=11 %% underscore used in control words + %% + %% |\MakeOther| is a synonym for `\@makeother', needed for matching + %% special characters from the input file. It is exemplified by + %% |\fdPatternCodes| which is the default of |\PatternCodes|. + %% The latter is used in setup macros for reading patterns. + +%% We offer |\SetPatternCodes{<commands>}| + +%% (redefining `\PatternCodes') + +%% and |\ResetPatternCodes| + +%% (for returning to `\fdPatternCodes') + +%% so setup scripts such as 'mdoccorr.cfg' have shorter lines. + \@ifundefined{MakeOther}{\let\MakeOther\@makeother}{} + \newcommand*{\fdPatternCodes}{\MakeOther\&\MakeOther\$} -\newcommand*{\PatternCodes}{} \let\PatternCodes\fdPatternCodes - %% TODO adding/removing + +\newcommand*{\SetPatternCodes}{\def\PatternCodes} + +\newcommand*{\ResetPatternCodes}{\let\PatternCodes\fdPatternCodes} + +\newcommand*{\PatternCodes}{} \ResetPatternCodes + + %% TODO adding/removing; `*' may be wrong 2010/03/29 + +%% + %% It would be bad to have `\MakeOther\%' and `\MakeOther\ ' here in + %% that this may have unexpected, weird effects with arguments of -%% setup macros. Therefore neither `\dospecials' nor `\@sanitize' are + +%% setup macros. (With `\MakeOther\ ' you must not indent within a + +%% setup command, and if you add `\MakeOther\%' the setup command + +%% must stay in one line.) + +%% Therefore neither `\dospecials' nor `\@sanitize' are + %% used. Curly braces remain untouched as default delimiters in setup + %% macros. For matching them, you must use `\MakeOther\{' and + %% `\MakeOther' in your `\PatternCodes', or |\Delimiters| to introduce + %% new ones at the same time, e.g., `\Delimiters\[\]': + \newcommand*{\Delimiters}[2]{% + \MakeOther\{\MakeOther\}\catcode`#1=1\catcode`#2=2\relax} + +%% + %% For replacing strings or for defining other strings of ``other" + %% characters by `\edef', you can use some \LaTeX\ constructs---here + %% are copies |\PercentChar| and |\BackslashChar| of them + %% (do you need more?): + \newcommand*{\PercentChar}{} \let\PercentChar\@percentchar + \newcommand*{\BackslashChar}{} \let\BackslashChar\@backslashcar + %% + %% == File handling == + \newwrite\result_file %% or write to \@mainaux!? + %% |\ResultFile{<output>}| opens (and empties) a file + %% <output> to be written into. + \newcommand*{\ResultFile}[1]{% + \def\result_file_name{#1}% + \immediate\openout\result_file=#1} + %% |\WriteResult{<balanced>}| writes a <balanced> line into + %% <output> (or more lines with `^^J'). + \newcommand*{\WriteResult}[1]{% + \immediate\write\result_file{#1}} + %% |\WriteProvides| writes a `\ProvidesFile' command to the + %% opened <output> file. This should be used when <output> + %% is made as \LaTeXe\ input. + \newcommand*{\WriteProvides}{% + \WriteResult{% + \string\ProvidesFile{\result_file_name}% + [\the\year/\two@digits\month/\two@digits\day\space + automatically generated with fifinddo.sty]}}% + %% |\ProcessFileWith{<input>}{<loop-body>}| opens a file <input> + %% and runs a loop on its lines the main body of which is <loop-body>. + %% When the <loop> starts, a new line of <input> is stored as macro + %% %% <- the <loop> 2010/03/10 + %% |\fdInputLine|. + \newcommand*{\ProcessFileWith}[2]{% + \openin\@inputcheck=#1% + % \ifeof\@inputcheck %% bad `exists?' test + % \PackageError{fifinddo}{File `#1' not here}% + % {Mistyped?}% + % \else + \global\c@fdInputLine=\z@ %% line counter reset + \begingroup + \MakeOther\{\MakeOther\}\@sanitize + %% from docstrip.tex: + % \MakeOther\^^A\MakeOther\^^K%% irrelevant, not LaTeX + \endlinechar\m@ne + %% <- cf. TeXbook "extended keyboards" up-/downarrow + %% -> "math specials", cf. "space specials" + \MakeOther\^^I% ASCII horizontal tab -- guessed!? ^^L!? + %% With v3.1, we support non-ASCII: + \count@=128 + \loop + \ifnum\count@<\@cclvi + \catcode\count@=12 + \advance\count@\@ne + \repeat + \loop \ifeof\@inputcheck \else + \read\@inputcheck to \fdInputLine + \ignorespaces #2% + \repeat + \endgroup + % \fi + \closein\@inputcheck} + %% |\CloseResultFile| closes <output>. + \newcommand*{\CloseResultFile}{\immediate\closeout\result_file} + %% + %% TODO: write EOF for debugging!?---%% 2010/03/18 + %% Peter Wilson's \ctanpkgref{newfile} + %% provides more powerful file handling. + %% % <- TODO relevant? 2009/04/12 + %% -%% \pagebreak %% TODO move theory to fifinddo.tex 2009/04/12 + +%% %% \pagebreak %% removed 2010/03/24 + +%% TODO move theory to fifinddo.tex 2009/04/12 + %% == Basic handling of substring conditionals == + %% \label{sec:theory} + %% === ``Substring Theory" === + %% \begin{flushright}\it + %% I wished I could study string theory,\\ + %% but I only could study substring theory. + %% \end{flushright} + %% A \TeX\ macro, say, `\find' whose parameter text + %% (cf. \TeX book p.~203) + %% starts with `#1<pattern>#2&' stops \TeX\ with an error if it does + %% not find <pattern> and then `&'. Otherwise we have a situation + %% `\find<split1><pattern><split2>&', and `\find' reads <split1> as + %% #1 and <split2> as #2. An important point to note is that <split1> + %% will not contain <pattern>, but possibly <pattern> has more + %% occurrences in <split2>. In this sense, `\find' uses the + %% \emph{first} occurrence of <pattern> it finds in order to delimit #1. + %% Finding the \emph{last} occurrence of <pattern> therefore needs a + %% special idea. + %% + %% In order to use `\find' for a test whether <pattern> is in + %% <target>, we build a ``sandbox" |\find<sand>&|, where <sand> + %% contains <target> \emph{and additionally} <pattern>---as a + %% ``dummy;" so `&' delimits the search and `\find' finds + %% <pattern> either in <target> or somewhere else before `&'. + %% + %% Consider the simple sandbox |\find<target><pattern>&|. + %% We can test #1 and #2 on being empty by `\ifx$#1$' and `\ifx$#2$'. + %% If #2 is empty, <pattern> is \emph{not} in <target>. + %% If #1 is empty at the same time, <target> is empty. + %% If #1 is empty and #2 is not, <pattern> \emph{starts} <target>! + %% This can be used to implement + %% Wikipedia-like lists %% TODO 2009/04/11 + %% and to distinguish package code from comments in 'makedoc'. + %% + %% If #2 is \emph{not} empty, <pattern> occurs in <target>---or this once + %% was \emph{thought}, some time in developping the present package, + %% as well as in the version of 'substr.sty' marked + %% `2005-11-29',\footnote{\url{http://ctan.org/pkg/substr}. + %% 'substr' does not change category codes + %% as 'fifinddo' does + %% and uses \cs{@nil} as delimiter instead of + %% our &&.} try + %% (if that version still is installed)\footnote{The ``feature" has + %% been fixed with v1.2 as of 2009/10/20 of + %% 'substr.sty'.} + %% \[`\IfSubStringInString{<str1><str2><str1>}{<str1><str2>}{YES}{NO}'\] + %% which works \emph{verbatim} as well as considering <str1> and + %% <str2> \emph{placeholders}, e.g., for + %% \begin{center} + %% `\IfSubStringInString{day after day}{day after }{YES}{NO}'\footnote{% + %% Likewise \texttt{t\string\^ete-\string\`a-t\string\^ete} ...}\\ + %% %% <- `e' was missing 2010/03/17 + %% `\IfSubStringInString{AMSTERDAM}{AMSTERD}{YES}{NO}'\\ + %% `\IfSubStringInString{TORONTO}{TORON}{YES}{NO}'\\ + %% `\IfSubStringInString{bonbon}{bon}{YES}{NO}'\footnote{% + %% Polynesian: `aku aku', `rongorongo', `wiki wiki' ...}\\ + %% `\IfSubStringInString{bonobo}{bono}{YES}{NO}' + %% (an ape) + %% \end{center} + %% or `\IfSubStringInString{ionization}{ionizat}{YES}{NO}'.\footnote{% + %% Read 'substr.sty' or try ``normal" things to convince yourself + %% that the syntax indeed is + %% &\IfSubStringInString{<pattern>}{<target>}{<yes>}{<no>}.} + %% Same with \LaTeX's internal `\in@':\footnote{\cs{in@} has been + %% fixed after my warning on Heiko Oberdiek's proposal---at + %% least in the repository.---On 2009/04/21 + %% I learn from Manuel P\'egouri\'e-Gonnard + %% that the first versions of his 'ted' + %% had a similar bug, fixed on v1.05 essentially like here; + %% Steven Segletes confirms that his 'stringstrings' doesn't + %% suffer the problem (returning positions of substrings and + %% numbers of occurrences).} + %% \[`\makeatletter \in@{bonbon}{bon}\ifin@ YES\else NO\fi \makeatother'\] + %% %% \makeatletter \in@{bonbon}{bon}\ifin@ YES\else NO\fi \makeatother + %% %% \IfSubStringInString{ionization}{ionizat}{YES}{NO} + %% + %% In general, the previous approach \emph{fails if and exactly if} + %% <pattern> has a \emph{period} $p$---less than its length---in the sense of that + %% the $p$th token to the right or left of each token in <pattern> + %% is the \emph{same} token. + %% `AMSTERDAM' has a period 8, `day after day' 10, `bonbon' 3, `bonobo' 4. + %% There is a counterexample <target> of length $p$ iff + %% <pattern> has period $p$, namely the first substring of <pattern> + %% having length $p$. If the length of <pattern> exceeds a multiple + %% $mp$ of its period, the first $mp$ tokens of <pattern> form + %% a counterexample <target>. + %% + %% Therefore, a sandbox must have something between <target> and + %% <pattern>.\footnote{Must? Actually, I preferred this solution to + %% other ideas like measuring the length of <split2>.} + %% We choose |\find<target>~<pattern>$&| as standard. + %% The `$' will be used as an argument delimiter to get rid of the dummy + %% <pattern> in <split2>, as well as to decide whether the match was + %% in <target> or in the dummy part of the sandbox. + %% The `$' can be replaced by another tilde `~' in order to + %% test whether <target> \emph{ends} on a <pattern>, defining a macro + %% like `\findatend' whose parameter text starts with `#1<pattern>~#2&'. + %% + %% === Plan for proceeding === + %% When we check a file for several patterns, we seem to need + %% \emph{two} macros for each pattern: one that has the pattern + %% in its parameter text and one that stores the pattern for building + %% the sandbox.\footnote{If it were for the pattern only, the parsing + %% macro might suffice and the macro calling it might extract the + %% pattern from a ``dummy expansion." Somewhat too much for me now; + %% on the other hand the calling macro also hands some ``current" + %% informations to the parsing macro---oh, even this could be + %% handled by a general ``calling" macro \dots} + %% %% TODO 2009/04/15 + %% We use a separate \emph{``name space"} for each of + %% both kinds. The parsing macro and the macro building the sandbox + %% will have a common \emph{``identifier"} by which the user or + %% programmer calls them. Actually, she will usually (first) call + %% the sandbox box builder. The sandbox builder calls the parsing + %% macro. When \emph{all} occurrences of a pattern in the target are + %% looked for, the parser may call itself. + %% + %% Actually, the parsing macro will execute certain actions + %% depending on what it finds in the sandbox, so we call it a + %% \emph{``substring conditional"}. It may read additional arguments + %% after the sandbox that store information gathered before. + %% This is especially useful for designing \emph{``expandable"} + %% chains (sequences) of conditionals where macros cannot store information in + %% macros. The macro setting up the sandbox will initialize such + %% extra arguments at the same time. + %% + %% It may be more efficient \emph{not} to use the following setup + %% macros but to type the macros yourself, just using the following + %% as templates. The setup macros are especially useful with patterns + %% that contain ``special characters," as when you are looking for + %% %% TODO repetition of single right quote not working 2010/03/19 + %% lines that might be package comments. + %% + %% === Meta-Setup === + %% + %% A setup command <setup-cmd> will have the following syntax: + %% \[|<setup-cmd>{<job-id>}[<changes>]{<pattern>}<more-args>|\] + %% <changes> will, in the first instance, be category code changes + %% for reading <pattern> overriding the settings in `\PatternCodes'. + %% They are executed after the latter in a local group. + %% It may be safer to redefine `\PatternCodes' instead + %% of using the optional <changes> argument. + %% + %% A macro + %% \[|\StartFDsetup{<do-setup>}{<job-id>}[<changes>]|\] + %% shared by setup commands + %% may read <job-id> and <changes> for <setup-cmd>. + %% |<do-setup>| will be the macro that reads <pattern> (and more) + %% and processes it. It must contain `\endgroup' to match + %% `\begingroup' from `\FD_prepare_pattern'. + %% <job-id> is stored in a macro |\fdParserId|. + %% The default for <changes> is \emph{nothing}. + \newcommand*{\StartFDsetup}[1]{% + \let\FD_do_setup#1% + \afterassignment\FD_prepare_pattern + \def\fdParserId} + \newcommand*{\FD_prepare_pattern}[1][]{% + \begingroup \PatternCodes #1\FD_do_setup} + %% So <setup-cmd> should be set up about as follows: + %% \begin{quote} + %% `\newcommand*{<setup-cmd>}{\StartFDsetup<do-setup>}'\\ + %% `\newcommand*{<do-setup>}[<args>]{<action>}' + %% \end{quote} + %% <do-setup>'s first argument will be the <pattern> argument + %% of <setup-cmd>. + %% + %% === Setup for conditionals === + %% `substr_cond' is the ``name space" for substring conditionals. + %% A colon separates it from \emph{``job identifiers"} in the actual + %% macro names. + \def\substr_cond{substr_cond:} + %% + %% |\MakeSubstringConditional{<id>}[<changes>]{<pattern>}| + %% starts the definition of a conditional with identifier <id> + %% and pattern <pattern>. <changes> optionally add commands to + %% be executed after `\PatternCodes' in a local group. + %% + \newcommand*{\MakeSubstringConditional} + {\StartFDsetup\mk_substr_cond} + %% + %% `\begingroup' |\mk_substr_cond{<pattern>}| %% TODO!? 2010/03/22 + %% can be directly called by other programmer setup commands when + %% `\fdParserId' and <pattern> have been read. + \def\mk_substr_cond #1{%% #1 pattern string + \endgroup \@namedef{\substr_cond \fdParserId}##1#1##2&} + %% + %% This really is not \LaTeX. We are starting defining a macro + %% `\substr_cond:<id>' in primitive \TeX\ with `\def' in the form + %% \[`\def\substr_cond:<id>#1<pattern>#2&'\] + %% where `\csname' etc. render \lq`:<id>'\rq\ part of the macro name. + %% The user or programmer macro produces the part of the definition + %% until the delimiter `&' to match the sandbox. You have to add + %% (maybe) #3 etc. and the `{<definition text>}' + %% just as with primitive \TeX. + %% + %% === Setup for sandboxes === + %% There was a \emph{question:} will we rather see + %% \emph{string macros} or \emph{strings from macro arguments}? + %% The input file content always comes + %% as `\fdInputLine' first, so we at least \emph{must account} for + %% the possibility of string macros as input. + %% + %% One easy way to apply several checks and substitutions to + %% `\fdInputLine' before the result is written to <output> is + %% `\let\OutputString\fdInputLine' and then let `\OutputString' + %% be to what each job refers as \emph{its} + %% input and output, finally `\WriteResult{\OutputString}'. + %% (`\fdInputLine' might better not be touched, it could be used + %% for a final test whether any change applied for some message on + %% screen, even with an entirely expandable chain of actions.) + %% This way each job, indeed each recursive substitution of a single + %% string must start with expanding `\OutputString'. + %% + %% On the other hand, there is the idea of \emph{``expandable" + %% chains of substitutions}. We may, e.g., define a macro, say, + %% `\manysubstitutions{<macro-name>}', such that + %% `\WriteResult{\manysubstitutions{\fdInputLine}}' + %% writes to <output> the result of applying many expandable + %% substitutions to `\fdInputLine'. + %% Such a macro `\manysubstitutions' may read `\fdInputLine', + %% but it must not redefine any macros. + %% Instead, the substitution macros it calls must read results + %% of previous substitutions as \emph{arguments}. + %% + %% Another aspect: + %% the order of substitutions should be easy to + %% change. Therefore expanding of string macros should rather be + %% controlled by the way a job is \emph{called}, not right here + %% at the \emph{definition} of the job. For this reason, + %% a variant of the sandbox builder expanding some macro was given up. +%% %% <- TODO!? 2010/03/25 + + + %% `setup_substr_cond' is the name space for macros that build + %% sandboxes and initialize arguments for conditional macros. + \def\setup_substr_cond{setup_substr_cond:} + %% \[|\MakeSetupSubstringCondition{<id>}[<changes>]{<pattern>}{<more-args>}|\] + %% % <- TODO allow `%' and ` ' for breaking code lines. + %% ---same <id>, <changes>, <pattern> as for + %% `\MakeSubstringConditional' (this is bad, there may be + %% |\MakeSubstringConditional*{<more-args>}|)---creates the + %% % <- TODO: store args in \Make...Conditional + %% corresponding sandbox, by default without tilde wrap. + %% <more-args> may contain `{#1}' to store the string that was tested, + %% also `{<id>}' for calling repetitions and `{<pattern>}' for screen + %% or log informations. + \newcommand*{\MakeSetupSubstringCondition} + {\StartFDsetup\mk_setup_substr_cond} -%% `\begingroup' |\mk_setup_substr_cond{<pattern>}{<more-args>}| + +%% |\mk_setup_substr_cond{<pattern>}{<more-args>}| + +%% %% without \begingroup 2010/03/29 + %% can be directly called by other programmer setup commands after + %% `\fdParserId' and <pattern> have been read: + \def\mk_setup_substr_cond #1#2{%% #1 pattern string, + %% #2 additional arguments, e.g., `{#1}' to keep tested string + \endgroup + \expandafter \edef + \csname \setup_substr_cond \fdParserId \endcsname ##1{% + \make_not_expanding_cs{\substr_cond \fdParserId}% + %% By `\edef', the name of the substring conditional is stored here + %% as a single token. The rest of the sandbox follows. + ##1\noexpand~#1\dollar_tilde}% + \let\dollar_tilde\sandbox_dollar} + %% If a tilde `~' has been used instead of `$', the default + %% is restored. + \def\sandbox_dollar{$} + \let\dollar_tilde\sandbox_dollar + %% The following general tool |\make_not_expanding_cs| has been used + %% (many definitions in 'latex.ltx' could have used it): %% 2009/04/10 + \def\make_not_expanding_cs#1{% + \expandafter \noexpand \csname #1\endcsname} + %% + %% === Getting rid of the tildes === + %% |\let~\TildeGobbles| can be used to suppress dummy patterns + %% (contained in <split2>) + %% in `\write'ing or with `\edef'. ... will probably become obsolete + %% ... however, it is helpful in that you needn't care + %% whether there is a dummy wrap left at all. (2009/04/13) + \newcommand{\TildeGobbles}{} \def\TildeGobbles#1${} + %% |\RemoveDummyPattern| is used to remove the dummy pattern + %% \emph{immediately}, not waiting for `\write'ing + %% or other ``total" expansion: %% 2009/04/13 + \newcommand{\RemoveDummyPattern}{} \def\RemoveDummyPattern#1~#2${#1} + %% |\RemoveDummyPatternArg<macro>{<arg>}| executes + %% `\RemoveDummyPattern' in the next argument: + \newcommand*{\RemoveDummyPatternArg}[2]{% + \expandafter #1\expandafter {\RemoveDummyPattern #2}} + %% |\RemoveTilde| is used to remove the tilde that separated + %% the dummy pattern from <split1>. + % %% An alternative policy is to pass + % %% <target> (as an argument) to the parsing macro. + \newcommand{\RemoveTilde}{} \def\RemoveTilde#1~{#1} + %% |\RemoveTildeArg<macro>{<arg>}| executes `\RemoveTilde' + %% in the next argument: + \newcommand*{\RemoveTildeArg}[2]{% + \expandafter #1\expandafter {\RemoveTilde #2}} + %% + %% === Calling conditionals === + %% |\ProcessStringWith{<target-string>}{<id>}| builds the sandbox + %% to search <target-string> for the <pattern> associated with the + %% parser-conditional that is identified by <id>, the sandbox then + %% calls the parser. + +%% % Finally, the command \emph{``returns"} the + +%% % result of applying job <id> to <target-string>---in the sense of + +%% % \emph{expanding} to it. %% more precisely 2010/03/25 + +%% %% <- removed again, wrong 2010/03/26 + \newcommand*{\ProcessStringWith}[2]{% + \csname \setup_substr_cond #2\endcsname{#1}} + %% |\ProcessExpandedWith{<string-macro>}{<id>}| does the same but with + %% a \emph{macro} (like `\fdInputLine' or `\OutputString') in which + %% the string to be tested is stored. + +%% %% TODO or \the<tok-reg> 2010/03/25 + \newcommand*{\ProcessExpandedWith}[2]{% + \csname \setup_substr_cond #2\expandafter \endcsname + \expandafter{#1}} + %% I would have preferred the reversed order of arguments which seems + %% to be more natural, but the present is more efficient. + %% Macros with reversed order are currently stored after `\endinput' + %% in section~\ref{sec:pondered}, may be they once return. + %% + %% Anyway, most desired will be |\ProcessInputWith{<id>}| just + %% applying to `\fdInputLine': + \newcommand*{\ProcessInputWith}[1]{% + \csname \setup_substr_cond #1\expandafter \endcsname + \expandafter{\fdInputLine}} + %% (Definition almost copied for efficiency.) + %% TODO: error when undefined 2009/04/07 + %% + %% === Copy jobs === + %% A job identifier <id> may also be considered a mere \emph{hook}, + %% a \emph{placeholder} for a parsing job. What function actually is + %% called may depend on conditions that change while reading the + %% <input> file. %%% On a certain condition, + %% |\CopyFDconditionFromTo{<id1>}{<id2>}| + %% \emph{creates or redefines a sandbox builder} with identifier <id2> + %% that afterwards behaves like the sandbox builder <id1>. + %% So you can store a certain behaviour as <id1> in advance in order + %% once to change the behaviour of <id2> into that of <id1>. + \newcommand*{\CopyFDconditionFromTo}[2]{% + \expandafter \let + \csname \setup_substr_cond #2\expandafter \endcsname + \csname \setup_substr_cond #1\endcsname} + %% (Only the \emph{sandbox} is copied here---what about + %% changing conditionals?) %% TODO + %% + %% An ``almost" example is typesetting documentation from a package + %% file where the ``Legalese" header might be typeset verbatim + %% although it is marked as ``comment." (The present %% 2009/04/07 + %% example changes ``hand-made" macros instead.) + %% + %% This feature could have been placed more below as a ``programming + %% tool." + %% + %% == Programming tools == + %% === Tails of conditionals === + %% \label{sec:tails} + %% When creating complex \emph{expandable} conditionals, + %% this may amount to have primitive `\if' ... `\fi' conditionals + %% nested quite deeply, once perhaps too deep for \TeX's memory. + %% To avoid this, you can apply the common `\expandafter' trick + %% which finishes the current `\if' ... `\fi' before an inside + %% macro is executed (cf. \TeX book p.~219 on ``tail recursion"). + %% + %% Internally tests whether certain strings are present at certain + %% places will be carried out by tests on emptiness or + %% %% onwards) %% !? 2009/12/28 + %% on starting with `~'. E.g., + %% ``#1~=~<split1> empty" indicates that either the <pattern> + %% starts a line or the line is empty altogether (this must be + %% decided by another test). + %% + %% |\IfFDempty{<arg>}{<when-empty>}{<when-not-empty>}| + %% is used to test <arg> on emptyness (without expanding it): + \newcommand*{\IfFDempty}[1]{% + \ifx$#1$\expandafter \@firstoftwo \else + \expandafter \@secondoftwo \fi} + %% |\IfFDinputEmpty{<when-empty>}{<when-not-empty>}| is a variant of + %% the previous to execute <when-empty> if the loop processing <input> + %% finds an empty line---otherwise <when-not-empty>. + \newcommand*{\IfFDinputEmpty}{% + \ifx\fdInputLine\@empty \expandafter \@firstoftwo \else + \expandafter \@secondoftwo \fi} + %% |\IfFDdollar{<arg>}{<when-empty>}{<when-not-empty>}| + %% is another variant, testing <split2> for being `$', + %% main indicator of there is a match anywhere in <target> + %% (as opposed to starting or ending match): + \newcommand*{\IfFDdollar}[1]{% + \ifx$#1\expandafter \@firstoftwo \else + \expandafter \@secondoftwo \fi} + %% It is exemplified and explained in section~\ref{sec:replchain}. + %% (The whole policy requires that `~' remains active in any + %% testing macros here!) + %% + %% However, you might always just type the replacement text + %% (in one line) instead of + %% such an `\If'\,... (for efficiency \dots) + %% + %% If expandability is not desired, you can just chain macros that + %% rework (so re-define) `\OutputString' or so. + %% + %% 2009/04/11: tending towards combining ... + %% Keeping empty input and empty arguments apart is useful in that + %% \emph{one} test of emptiness per input line should suffice---it + %% may be left open whether this should be the first of all tests + %% \dots + %% + %% === Line counter === + %% A \LaTeX\ counter |fdInputLine| may be useful for screen or log + %% messages, moreover you can use it to control processing of the + %% <input> file ``from outside," not dependent on what the parsing + %% macros find. The header of the file might be typeset verbatim, + %% but we may be too lazy to define the ``header" in terms of + %% what is in the file. We just decide that the first ... lines + %% are the ``header," even without counting just trying whether + %% the output is fine. It may be necessary to change that number + %% manually when the header changes. + %% + %% You also can insert lines in <output> + %% which have no counterpart in <input>---if you know what you are + %% doing. With 'makedoc', there is a hook `\EveryComment' that can + %% be used to issue commands ``from outside" at a place where + %% executing the command is safe or appropriate. + \newcounter{fdInputLine} + %% You then must insert |\CountInputLines| in the second argument + %% of `\ProcessFileWith' (or in a macro called from there) + %% so that the counter is stepped. %% TODO!? 2009/04/07 + \newcommand*{\CountInputLines}{\global\advance\c@fdInputLine\@ne} + %% At present %% 2009/04/07 TODO + %% the counter is reset by `\ProcessFileWith', this may change. + %% + %% |\IfInputLine{<relation><number>}{<true>}{<false>}|, when called + %% from the processing loop (second argument of `\ProcessFileWith') + %% issues <true> commands if `\value{fdInputLine}<relation><number>' -%% is true, otherwise <false>. <relation> may usually be just `='. + +%% is true, otherwise <false>. <relation> is one out of + +%% \HardNVerb+<+, `=', `>'. %% 2010/03/24 2010/03/29 + \newcommand*{\IfInputLine}[1]{% + \ifnum\c@fdInputLine#1\relax \expandafter \@firstoftwo + \else \expandafter \@secondoftwo \fi} + %% + %% === The ``identity job" `LEAVE' === + %% \label{sec:LEAVE} + %% The job with identifier |LEAVE| + %% \emph{leaves} an (expandable) chain of jobs + %% (as expandable replacement in section~\ref{sec:replchain}) + %% and \emph{leaves} the processed string without changing it + %% and without the braces enclosing it: + \expandafter \let + \csname \setup_substr_cond LEAVE\endcsname \@firstofone + %% I.e., `\ProcessStringWith{<string>}{LEAVE}' expands to <string> + %% ... \ProcessStringWith{(Indeed!)}{LEAVE} + + %% == Setup for expandable chains of replacements == + %% \label{sec:replchain}%% TODO makedoc: provide less visible label/ref 2009/04/11 + %% By the following means, you can create macros + %% (`\Transform' among them) such that, e.g., + %% \[`\edef\OutputString{\Transform{<string>}}'\] renders `\OutputString' + %% the result of applying a chain (sequence) of stringwise replacements + %% to <string>. + %% You can even write a transformed input <string> to a file + %% without defining anything anything after `\read to'\,.\,.\,. + %% In this case however, you don't get any statistical message + %% about what happened or not. With `\edef\OutputString' you can at + %% least issue some `changed!' or `left!' (maybe `\message{!}' vs.\ + %% `\message{.}'). + %% There is an application in 'makedoc' for ``typographical upgrading" + %% from plain text to \TeX\ input. + %% + %% |\repl_all_chain_expandable| will be the backbone of the + %% replacements. It is called by some parsing macro <parser> + %% and receives from the latter <split1>~=~#1 and <split2>~=~#2. + %% #3 is the result of what happened so far. + \def\repl_all_chain_expandable#1#2#3#4#5#6{% + %% #1, #2 splits, #3 past, #4 substitute, + %% #5 repeat parser, #6 pass to + % \ifx~#2\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi + %% The previous line would be somewhat faster, but let us exemplify + %% `\IfFDdollar' from section~\ref{sec:tails} instead: + \IfFDdollar{#2}% + %% If #2 starts with `$'---with category code 3, ``math shift"!, + %% it \emph{is} `$', due to not reading `$' + %% from input with its standard category code 3 + %% and the sandbox construction (where `$' appears with its standard + %% category code). %% TODO might be explained earlier 2009/04/11 + %% %% or refer to here. + %% And this is the case \emph{exactly} when the <pattern> from + %% <parser> didn't match, again due to the input category codes. + %% Now on \emph{no} match, the sandbox builder #6 is called + %% with target string #3#1 where the last tested string is attached + %% to previous results. The ending `~' is removed, #6 inserts a new + %% wrap for the new dummy pattern. + {\RemoveTildeArg #6{#3#1}}% + %% Otherwise ... the \emph{sandbox builder} <sandbox> + %% (that will be shown below) that called <parser> + %% initialized #5 to be that <parser> itself. (<parser> otherwise + %% wouldn't know who it is.) So <parser> calls itself with another sandbox + %% `#2&'. Note that #2 contains \lq`~<pattern>$'\rq\ due to the initial + %% <sandbox> building. + {#5#2&{#3#1#4}{#4}#5#6}} + %% #4 is the replacement string that <sandbox> passed to <parse>. + %% The first argument after the `&' is previous stuff plus + %% the recently skipped <split1> + %% plus #4 replacing the string <pattern> that was matched. + %% + %% Finally, #5 and #6 again ``recall" <parser> and the sandbox + %% builder to which to change in case of no other match. + %% + %% \pagebreak[3] %% 2010/03/22 + %% % TODO move following up!? 2009/04/11 + %% \[|\MakeExpandableAllReplacer{<id>}[<chng>]{<find>}{<replace>}{<id-next>}|\] + %% creates sandbox and parser with common identifier <id> and search + %% pattern <find>. Each occurrence of <find> will be replaced by + %% <replace>. When <find> is not found, the sandbox builder for + %% <id-next> is called. This may be another replacing macro of the + %% same kind. To return the result without further transformations, + %% call job `LEAVE' (section~\ref{sec:LEAVE}). + %% Optional argument <chng> changes category codes locally + %% for reading <find> and <replace>. + %% %% <- added <cat>, <pattern> -> <find> 2010/03/19 + \newcommand*{\MakeExpandableAllReplacer} + {\StartFDsetup\mk_setup_xpdbl_all_repl} + \newcommand*{\mk_setup_xpdbl_all_repl}[3]{% + %% #1 pattern, #2 substitute, #3 pass to + \endgroup + %% We take pains to call next jobs by single + %% command strings and store them this way, not by `\csname', + %% as `\ProcessStringWith' would do it. `\edef\@tempa' + %% is used for this purpose, but \dots + \edef\@tempa{% + \noexpand\mk_setup_substr_cond{#1}{% + {}{#2}% + \noexpand\noexpand + %% That `\edef\@tempa' must \emph{not expand} the controll + %% words after they have been computed from `\csname' etc. + %% Moreover, expansion of the parser commands + %% must be avoided another time, when `\@tempa' is executed. + \make_not_expanding_cs{\substr_cond\fdParserId}% + \noexpand\noexpand + \make_not_expanding_cs{\setup_substr_cond #3}}}% + %% Those internal setup commands start with `\endgroup' to switch back + %% to standard category codes. We must match them here by + %% `\begingroup'. + \begingroup \@tempa + \begingroup \mk_substr_cond{#1}{% + \repl_all_chain_expandable{##1}{##2}}} + %% The final command is the one that we explained first. %% TODO 2009/04/11 + %% + %% \[|\PrependExpandableAllReplacer{<id>}[<cat>]{<find>}{<replace>}|\] + %% is hoped to be a slight relief in composing replacement chains. + %% It does something like invoking `\MakeExpandableAllReplacer' + %% with <prev-setup-id> for the last <next-id> argument + %% where <prev-setup-id> is the <id> of the job that was set up most + %% recently. If you have adjacent lines + %% \begin{quote} + %% \leavevmode\hbox to 0pt\bgroup + %% `\MakeExpandableAllReplacer{<id-0>}{<find-0>}{<subst-0>}{LEAVE}'% + %% \hss\egroup \\ + %% `\PrependExpandableAllReplacer{<id-1>}{<find-1>}{<subst-1>}'\\ + %% `\PrependExpandableAllReplacer{<id-2>}{<find-2>}{<subst-2>}' + %% \end{quote} + %% and call <id-2>, it will call <id-1>, and the latter will call + %% <id-0>. So you can reorder the chain my moving `\Prepend'... lines. + \newcommand*{\PrependExpandableAllReplacer}{% + \let\fdParserId_before\fdParserId + \StartFDsetup\prep_xpdbl_all_repl} + \newcommand*{\prep_xpdbl_all_repl}[2]{% + \mk_setup_xpdbl_all_repl{#1}{#2}{\fdParserId_before}}% + +%% + +%% %% 2010/03/29: + +%% |\MakeDocCorrectHook{<string>}| belongs to 'makedoc', + +%% but in the meantime ('nicetext' release 0.3) + +%% I have proposed to use it with 'fifinddo' only as well + +%% (running files `fdtxttex.tpl', `fdtxttex.tex'). + +%% Therefore I offer some simplification |\SetCorrectHookJob{<job-id>}| + +%% for defining `\MakeDocCorrectHook' \emph{here.} + +\newcommand*{\SetCorrectHookJob}[1]{% + + \def\MakeDocCorrectHook##1{\ProcessStringWith{##1}{#1}}} + +%% |\SetCorrectHookJobLast| just uses the job that was set up + +%% most recently. + +\newcommand*{\SetCorrectHookJobLast} + + {\SetCorrectHookJob\fdParserId} + %% + %% == Leave package mode == + %% We restore the underscore `_' for math subscripts. + %% (This might better depend on something \dots) %% TODO 2009/04/07 + \catcode`\_=8 %% restores underscore use for subscripts + %% + \endinput + %% \TeX\ ignores the rest of the file when it is \emph{input} + %% ``in the sense of `\input'", as opposed to just reading + %% the file line by line to a macro like `\fdInputLine'. + %% + %% == Pondered == + %% \label{sec:pondered} + %% TODO abbreviated commands (aliases) \MkSubstrCond... + %% TODO \@onlypreamble!? + \newcommand*{\ApplySubstringConditional}[1]{% + %% #1 identifier; text to be searched expected next + \csname setup_substr_cond:#1\endcsname} + \newcommand*{\ApplySubstringConditionalToExpanded}[1]{% 2009/03/31+ + \csname setup_substr_cond:#1\expandafter \endcsname \expandafter} + \newcommand*{\ApplySubstringConditionalToInputString}[1]{% 2009/03/31+ + \csname setup_substr_cond:#1\expandafter \endcsname + \expandafter {\fdInputLine}} + %% TODO or `\OutputString', even `\read' to `\OutputString'!? + % \newcommand*{\ApplySubstringConditionalToExpanded}[2]{% + % %% note: without assignments, robust! + % %% BUT the `\csname ... \expandafter \endcsname' method is faster + % \expandafter \reversed_apply_substr_cond + % \expandafter {#2}{#1}} + % \newcommand*{\reversed_apply_substr_cond}[2]{% + % \ApplySubstringConditional{#2}{#1}} + %% ODER: + % \newcommand*{\expand_attach_arg}[2]{%% 2009/03/31 + % %% #1 command with previous args, TODO cf. LaTeX3 + % \expandafter \attach_arg \expandafter {#1}{#2}} + % %% actually #1 may contain more than one token, + % %% only first expanded + % \newcommand*{\attach_arg}[2]{#2{#1}} + % \newcommand*{\ApplySubstringConditionalToExpanded}[2]{% + % \expandafter \attach_arg \expandafter + % {#2}{\ApplySubstringConditional{#1}}} + %% + %% + %% + %% == VERSION HISTORY == + %% + v0.1 2009/04/03 very first version, tested on morgan.sty + v0.2 2009/04/05 counter fdInputLine, \ProvidesFile moved from + \ProcessFile to \ResultFile, \CopyFD..., + category section first, more sectioning, + suppressing empty code lines before section + titles; discussion, \Delimiters + 2009/04/06 more discussion + 2009/04/07 more discussion, factored \WriteProvides out from + \ResultFile, \ProcessExpandedWith corrected + 2009/04/08 \InputString -> \fdInputline; + removed \ignorespaces + 2009/04/09 \WhenInputLine[2] -> \IfInputline[3], + \ProcessInputWith, typos, + \WriteProvides message `with' + 2009/04/10 \make_not_expanding_cs + DISCOVERED ``IF SUBSTRING" ALGORITHM WRONG + (<str1><str2><str1> in <str1><str2>) + v0.3 2009/04/11 SOME THINGS GIVEN UP EARLIER WILL BE REMOVED, + TO BE STORED IN THE COPY AS OF 2009/04/10 + mainly: sandbox setup (tilde/dollar) + REAL ADDITION: setup for expandable replacing + 2009/04/12 played with `chain' vs. `sequence'; + plain `...', `cf.', `etc.' for `mdcorr.cfg' + 2009/04/13 \RemoveTilde... + 2009/04/15 reworked text, same mistake \in@ + v0.31 2009/04/21f. comments on ted, stringstrings + 2009/12/28 "onwards)" !? "safer", not "more safe" + 2010/03/10 the loop starts + 2010/03/17 corr. t^ete; set up -> setup for + 2010/03/18 TODO EOF, ctan.org/pkg/newfile; non-ASCII + 2010/03/19 extended description of \MakeExpandableAll...; + '' -> " + 2010/03/20 \ctanpkgref + 2010/03/22 \StartFDsetup, \Prepend... + 2010/03/23 URL for `substr.sty' +SENT TO CTAN + + + +v0.4 2010/03/24 removed \pagebreak before "substrings"; + + <relation> with \IfInputLine precisely + + 2010/03/25 todo \ProcessExp... more precisely, etc. + + 2010/03/26 ... was wrong, removed + + 2010/03/29 \SetPatternCodes, \ResetPatternCodes, + + \SetCorrectHookJob, \SetCorrectHookJobLast; + + <relation> with \HardNVerb; + + don't mention \begingroup with + + \mk_setup_substr_cond; renamed v0.4 + + + TODO: cleveref 2010/03/18 + |