\NeedsTeXFormat{LaTeX2e}[1994/12/01] %% \newcommand* etc. \ProvidesPackage{blogexec}[2012/12/20 v0.21 assignments with blog.sty (UL)] %% copyright (C) 2011 Uwe Lueck, %% http://www.contact-ednotes.sty.de.vu %% -- author-maintained in the sense of LPPL below. %% %% This file can be redistributed and/or modified under %% the terms of the LaTeX Project Public License; either %% version 1.3c 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 %% %% == Requirements == %% The \ctanpkgref{dowith} package is needed for managing %% and running lists of macros to be intercepted: \RequirePackage{dowith} %% Admittedly, `\do' and `\@elt' lists (as discussed in `dowith.pdf') %% would be faster than the 'dowith' method, which might be relevant %% here (TODO: how much?). I may abandon 'dowith' later, I just cannot %% afford removing it now (2011/11/05, TODO). %% %% == Processing Source Files == %% With |\BlogInterceptExtra|, 'blog.sty' %% deals with \emph{empty} input lines just like %% \[`\BlogCopyFile[<changes>]{<src-file>}'\] %% does; \emph{otherwise} the content of `\fdInputLine' is copied to %% |\fdOutputCode|. Before the latter is writen to the output file %% <output> (as determined by a recent `\ResultFile{<output>}'), %% |\BlogInterceptions| is run, its purpose is to extract assignment and other %% ``execution" commands and to turn `\fdOutputCode' into an %% expandable macro. We use `\def' because 'blog.sty' may have %% provided a preliminary definition earlier: \def\blog@icl@xtra{% \let\BlogProcessLine\BlogAllowIntercepting \let\BlogInterceptions\AllBlogInterceptions} \def\BlogInterceptExtra{\@ifstar@intercept@hash\blog@icl@xtra} \def\@ifstar@intercept@hash#1{\@ifstar{#1\BlogInterceptHash}#1} %% And this is the default setting (TODO!?): \BlogInterceptExtra %% Below, there are commands for restricted (faster---TODO: relevant? %% or less complex, to reduce danger) %% interception functionality. (Maybe the file should be restructured.) %% |\AllBlogInterceptions| first is nothing: \InitializeListMacro\AllBlogInterceptions %% ---and should become more below. %% %% |\BlogAllowIntercepting| stores the difference to 'blog.sty': \newcommand*{\BlogAllowIntercepting}{% \let\fdOutputCode\fdInputLine \BlogInterceptions %% When, after removing the intercepted command, the line is %% empty, it is \emph{not} written into output: \ifx\fdOutputCode\@empty \else \WriteResult{% \ProcessExpandedWith\fdOutputCode\BlogOutputJob}% %% ... enabling ``ligatures" with 'blog.sty' v0.7. %% 2011/11/21 \fi} %% ... TODO: in 'fifinddo' with something like `\fdInterceptions'? %% %% Especially for storing file-specific macro definitions %% with `\EXECUTE' (below), a parameter character %% (usually hash mark) is needed. %% %% mod. 2011/11/20: %% 'fifinddo.sty' (so far---2011/11/20) %% does not include it with `\BasicNormalCatCodes', %% and 'blog.sty' %% does not include it with `\BlogCodes' %% ---the following |\BlogInterceptHash| does. %% Moreover, |\MakeHashParameter| enables such definitions %% when placed in a source file within the argument of a %% separate(!) `\EXECUTE'. \providecommand*{\MakeHashParameter}{\catcode`\#6 } \def\BlogInterceptHash{% \ToListMacroAdd\BlogCodes\MakeHashParameter \MakeHashParameter} %% TODO: default? 0-arg interception? %% %% == Intercepting Single-Parameter Commands == %% === The General Method === %% Macros to be intercepted that have a single argument will be %% collected in |\blogOneArgInterceptions|: \InitializeListMacro\blogOneArgInterceptions \ToListMacroAdd\AllBlogInterceptions{% \DoWithAllIn\blogTryOneArgCmd \blogOneArgInterceptions} %% Here |\blogTryOneArgCmd{<cmd>}| creates a ``sandbox" for parsing %% in a similar way as 'fifinddo' does it, searching for <cmd>. %% The method there was made thinking of reading files with %% ``plain text" category codes, not aware of 'blog.sty'. %% Maybe this was a mistake, and I will reconsider it. %% There I also introduce a separate sandbox macro %% for each search pattern, thinking of different types of sandboxes. %% This is not done/needed here (strangely, TODO).---The sandbox %% starts with the parsing macro. The latter's name derives from %% <cmd> by prefixing something to its name. %% |\StripEsc| is a little helper for removing the backslash %% from a macro name. \providecommand*{\StripEsc}{\expandafter\@gobble\string} %% Name spaces: %% 2012/08/29 \newcommand*{\blog@x}{\StripEsc\blogx} \newcommand*{\blogTryOneArgCmd}[1]{% \csname \blog@x:\StripEsc#1\expandafter\endcsname \fdOutputCode \@gobble#1\@empty\@nil} %% Here, `\@empty' is the dummy argument for <cmd>---this is what %% must be modified for <cmd> with more than one parameter. %% At present (2011/11/05), that tail starting with `\@gobble' %% may stay at the end of `\fdOutputCode' for each interception per %% `\fdInputLine', until it expands to nothing in the `\write'. %% %% |\MakeBlogOneArgInterception{<cmd>}{<run>}{<write>}| \ \ %% says that when <cmd> is found in `\fdOutputCode', %% <run> should be executed, and `<cmd><arg>' should be replaced %% by <write> in `\fdOutputCode' where <arg> is the argument for %% <cmd> found in `\fdOutputCode'. Let <arc> be <arg> without %% delimiting braces if `<arg>' is `{<arc>}' %% (otherwise `<arc>' is the same as `<arg>'). %% Then use `#2' for referring to <arc> inside <run> and <write>. %% (Sorry, I cannot afford replacing `#2' by a more natural %% placeholder right now.) \begingroup \catcode`\|\z@ |MakeOther|\% %% \z@ 2011/11/22 |@ifdefinable|MakeBlogOneArgInterception{% |gdef|MakeBlogOneArgInterception#1#2#3{% %% First we add <cmd> to `\blogOneArgInterceptions', %% unless it is already there: %% 2011/11/07 |TestListMacroForToken|blogOneArgInterceptions#1% |ifin@ |PackageWarning{blogexec}{Redeclaring |string#1.}% |else |ToListMacroAdd|blogOneArgInterceptions#1% |fi %% Now the parsing macro is defined, together with the actions %% depending on the result: %% %% TODO csnames/namemod.sty 2011/11/22 |@namedef{|blog@x:|StripEsc#1}##1#1##2##3|@nil{% %% #3 will be empty if and only if <cmd> does \emph{not} occur %% in `\fdOutputCode'. A backslash made ``other" will not occur %% in `\fdOutputCode', therefore the following %% `\ifx' becomes true if and only if #3 is empty, i.e., %% <cmd> does \emph{not} occur in `\fdOutputCode': |ifx\##3\% %% In this case we just do nothing. |else %% Otherwise, we apply <run> and <write>: #2% |def|fdOutputCode{##1#3##3}% |fi}% }% }% |endgroup %% %% was single `%' 2011/11/20 %% === &\EXECUTE === %% |\EXECUTE{<run>}| runs <run> and is removed from the %% output line: \MakeBlogOneArgInterception\EXECUTE{#2}{} %% You can \strong{store settings} <set> for processing a source %% file in this file by `\EXECUTE{<set>}' %% (e.g., shorthand macros only useful in this single file). %% You even can switch off the interception functionality %% after running the other settings <set> %% by `\EXECUTE{<set>\BlogCopyLines}'. %% %% `\EXECUTE{<run>}' may be a great relief thinking of pure %% expansion with 'blog.sty'. You may be happy enough with it %% and \emph{restrict} the interception functionality to `\EXECUTE' %% by |\BlogInterceptExecute|. Its definition may be a %% redefinition of the preliminary macro in 'blog.sty'. %% (TODO: option for stopping here, avoid 'dowith'.) \def\blog@icl@exec{% \let\BlogProcessLine\BlogAllowIntercepting \def\BlogInterceptions{\blogTryOneArgCmd\EXECUTE}} \def\BlogInterceptExecute{\@ifstar@intercept@hash\blog@icl@exec} %% %% === &\begin\ and &\end === %% At present (2011/11/06), only |\begin{<env>}| will run %% box 2012/08/28 %% settings. Macros `\<env>' and `\end<env>' will expand %% in the `.html' as with 'blog.sty' alone, not touched here. %% Settings to be \emph{run} must be stored in a macro %% `\blogx.b:<env>'. If this has not been done, only `\relax' %% (from `\csname') will be ``run." \MakeBlogOneArgInterception\begin{% %% Indeed, we have a ``modified selection" from \LaTeX's original `\begin': \@ifundefined{#2}% {\def\@tempa{\@latex@error{Environment #2 undefined}\@eha}}% {\def\@tempa{\def\@currenvir{#2}% % \edef\@currenvline{\on@line}% %% not in source \csname \blog@x.b:#2\endcsname}}% %% \StripEsc->: 2012/08/28 \begingroup \@tempa}{% \csname #2\endcsname} %% % %% TODO single token!? %% rm. 2011/12/15 %% \[|\MakeBlogBeginRun{<env>}<args>{<begin-code>}|\] resembles %% \[`\newenvironment*{<env>}<args>{<begin-code>}{<end-code>}'\] except that %% it does not have `{<end-code>}': \newcommand*{\MakeBlogBeginRun}{\@makeblogbeginrun\newcommand} %% v0.2 allows redefinition by %% \[|\ChangeBlogBeginRun{<env>}<args>{<begin-code>}|\] \newcommand*{\@makeblogbeginrun}[2]{% \expandafter #1\expandafter *% \csname \blog@x.b:#2\endcsname} %% \StripEsc->: 2012/08/28 \newcommand*{\ChangeBlogBeginRun}{\@makeblogbeginrun\renewcommand} %% Moreover, v0.2 allows copying that action by %% \[|\CopyBlogBeginRunTo{<env>}{<enw>}|\] \newcommand*{\CopyBlogBeginRunTo}[2]{% \withcsname \let \blog@x.b:#2\expandafter\endcsname \csname \blog@x.b:#1\endcsname} %% |\end{<env>}|: \MakeBlogOneArgInterception\end{\@checkend{#2}\endgroup}{\end{#2}} % \expandafter\show\csname blogx:end\endcsname %% \[|\BlogInterceptEnvironments|\] restricts interception functionality %% to `\EXECUTE', `\begin', and `\end': \def\blog@icl@envs{% \BlogInterceptExecute \ToListMacroAdd\BlogInterceptions{% \blogTryOneArgCmd\begin\blogTryOneArgCmd\end}} \def\BlogInterceptEnvironments{\@ifstar@intercept@hash\blog@icl@envs} %% TODO: \ 1.~imitate \LaTeX's toggling with `\emph' %% (redefine it in italic environments) %% \ 2.~code indenting (cf.~\ctanpkgref{inputtrc}) %% %% === Skipping Source Code === %% The |{noblog}| environment ``suppresses" \TeX~source %% code in the sense that it does not produce \HTML~code---while %% 'blog.sty''s `{commentlines}' produces an \HTML~comment. \newenvironment*{noblog}{}{} %% 2012/03/04 from ... \MakeBlogBeginRun{noblog}{% \BlogInterceptEnvironments %% 2012/06/22 \let\WriteResult\@gobble} %% %% === A Comfortable Table Environment === %% As an application of |\MakeBlogBeginRun| for 'blog.sty''s %% |{stdallrulestable}|, we provide \lq`|'\rq\ as an active character %% invoking 'blog.sty''s `\endcell' (move to next cell) %% was \cr 2011/11/10 %% and an active character \lq`&'\rq\ for `\figurespace', %% i.e., a Unicode symbol for aligning figures. %% Indeed, we are \emph{not} going back to \LaTeX\ and Plain \TeX\ %% by using `&' for moving to the next cell, I consider the present %% choice more intuitive. \MakeBlogBeginRun{stdallrulestable}{% \MakeActiveDef\|{\endcell}\MakeActiveDef\&{\figurespace}} %% I hope nobody will confuse `&' and `8'. A little drawback may be %% that you now can't use `&' for inserting \acro{HTML} entities. %% However, recall that these settings are restricted to the %% `{stdrulestable}' environment, and that you can use %% `\MakeBlogBeginRun{stdallrulestable}' again for your own choice %% of shorthands. %% (TODO: `\MakeActiveLet') %% %% %% == Intercepting Two-Parameter Macros == %% Here especially I have a macro %% |\labelsection{<label>}{<title>}| \emph{in mind} %% (TODO). %% It could be handled by the one-argument approach %% by storing the first argument and inserting another macro %% that reads the second argument. Therefore I am not sure ... %% (2011/11/04) %% %% == Leaving and HISTORY == \endinput %% \enlargethispage{2\baselineskip} %% 2012/08/28 VERSION HISTORY v0.1 2011/11/04 started; arrived at \EXECUTE 2011/11/05 rm. \blogx@dummy, corrected loop, \BlogInterceptExtra, \BlogInterceptExecute 2011/11/06 \BlogAllowIntercepting, emptiness test with "other" backslash, \begin/\end 2011/11/07 debugging (\catcode... in \@ifdefinable); warning on reusing interceptor, \BlogInterceptEnvironments; doc.: raise interception level in \EXECUTE 2011/11/08 \BlogInterceptHash (understanding needed hours) 2011/11/10 `v0.1' in \Provides..., doc. fix, removing experimental code, doc. all 1-arg interceptions in one section 2011/11/20 \BlogInterceptHash improved 2011/11/20 doc. `%' doubled 2011/11/21 \BlogOutputJob 2011/11/22 TODO + \z@ for \MakeBlogOne... 2011/12/15 rm. TODO v0.2 2012/08/28 \begin/\end revised (\StripEsc wrong) 2012/08/29 \ChangeBlogBeginRun, \CopyBlogBeginRun, \blog@x v0.21 2012/12/20 {noblog}