Avoid pointless empty spaces in README and other generated files
[conteq.git] / conteq.dtx
1 % \iffalse meta-comment
2 % !TEX program  = pdfLaTeX
3 %<*internal>
4 \iffalse
5 %</internal>
6 %<*readme>
7 ----------------------------------------------------------------
8 conteq --- continued equalities
9 E-mail: mail@joachim-breitner.de
10 Source repository: http://git.nomeata.de/?p=conteq.git
11 Source repository mirror: https://github.com/nomeata/conteq
12 Released under the LaTeX Project Public License v1.3c or later
13 See http://www.latex-project.org/lppl.txt
14 ----------------------------------------------------------------
15
16 This package allows you to write an continued equality such as
17
18     \begin{conteq}
19     e^{\pi\cdot i} \\
20     = -1 & Euler's formula \\
21     < 0 & this is an inequality \\ 
22     < \sqrt 3 \\
23     = \int e^{-x^2} dx & this is due to Gauss.
24     \end{conteq}
25
26 in a declarative manner and easily switch between various layouts afterwards.
27 %</readme>
28 %<*internal>
29 \fi
30 \def\nameofplainTeX{plain}
31 \ifx\fmtname\nameofplainTeX\else
32   \expandafter\begingroup
33 \fi
34 %</internal>
35 %<*install>
36 \input docstrip.tex
37 \keepsilent
38 \askforoverwritefalse
39 \preamble
40 ----------------------------------------------------------------
41 conteq --- continued equalities
42 E-mail: mail@joachim-breitner.de
43 Released under the LaTeX Project Public License v1.3c or later
44 See http://www.latex-project.org/lppl.txt
45 ----------------------------------------------------------------
46
47 \endpreamble
48 \postamble
49
50 Copyright (C) 2013,2015 by Joachim Breitner <mail@joachim-breitner.de>
51
52 This work may be distributed and/or modified under the
53 conditions of the LaTeX Project Public License (LPPL), either
54 version 1.3c of this license or (at your option) any later
55 version.  The latest version of this license is in the file:
56
57 http://www.latex-project.org/lppl.txt
58
59 This work is "maintained" (as per LPPL maintenance status) by
60 Joachim Breitner.
61
62 This work consists of the file  conteq.dtx
63 and the derived files           conteq.ins,
64                                 conteq.pdf and
65                                 conteq.sty.
66
67 \endpostamble
68 \usedir{tex/latex/conteq}
69 \generate{
70   \file{\jobname.sty}{\from{\jobname.dtx}{package}
71                       \from{\jobname.dtx}{layouts}}
72 }
73 %</install>
74 %<install>\endbatchfile
75 %<*internal>
76 \generate{
77   \file{\jobname.ins}{\from{\jobname.dtx}{install}}
78 }
79 \nopreamble\nopostamble
80 \generate{
81   \file{README.txt}{\from{\jobname.dtx}{readme}}
82 }
83 \ifx\fmtname\nameofplainTeX
84   \expandafter\endbatchfile
85 \else
86   \expandafter\endgroup
87 \fi
88 %</internal>
89 %<package>\NeedsTeXFormat{LaTeX2e}
90 %<package>\RequirePackage{expl3}[2012/07/02]
91 %<package>\ProvidesExplPackage
92 %<package>  {conteq}              % Package name
93 %<package>  {2015/07/17}          % Release date
94 %<package>  {0.1.1}                 % Release version
95 %<package>  {Various layouts for continued equalities} % Description
96 %
97 %<*driver>
98 \documentclass[full]{l3doc}
99 \usepackage[T1]{fontenc}
100 \usepackage{lmodern}
101 \usepackage{conteq}
102 %\usepackage[numbered]{hypdoc}
103 \EnableCrossrefs
104 \CodelineIndex
105 \RecordChanges
106 \begin{document}
107   \DocInput{\jobname.dtx}
108 \end{document}
109 %</driver>
110 % \fi
111 %
112 % \GetFileInfo{\jobname.sty}
113 %
114 % \CheckSum{175}
115 %
116 %
117 %\title{^^A
118 %  \textsf{conteq} --- continued equalities\thanks{^^A
119 %    This file describes version \fileversion, last revised \filedate.^^A
120 %  }^^A
121 %}
122 %\author{Joachim Breitner\thanks{E-mail: mail@joachim-breitner.de}}
123 %
124 %\date{Released \filedate}
125 %
126 %\maketitle
127 %
128 %\changes{0.1.1}{2015/07/17}{Stop using deprecated expl3 macros}
129 %\changes{0.1}{2013/05/23}{Converted to DTX file}
130 %
131 %
132 % \section{Introduction}
133 %
134 % There are various ways to layout an continued equality that spans multiple lines and has explanations along some steps. Often, the best layout is not clear beforehand, as it depends on the sizes of the various elements, or implementing it adds too much noise to the actual formulas. This package provides an environment for continued equalities (or inequalities) that allows you to easily define and switch layouts.
135 %
136 % \section{Usage}
137 %
138 % \DescribeEnv{conteq}
139 % Our running example is the following continued equality:
140
141 % \begin{verbatim}
142 % \begin{conteq}
143 % e^{\pi\cdot i} \\
144 % = -1 & Euler's formula \\
145 % < 0 & this is an inequality \\ 
146 % < \sqrt 3 \\
147 % = \int e^{-x^2} dx & this is due to Gauss.
148 % \end{conteq}
149 % \end{verbatim}
150 %
151 % As you can see, the expressions of the continued equality are separated by |\\|, with equality signs (or other relations) at the beginning of all lines but the first. Some equalities also have explanations.
152
153 % The result of the above code is
154 % \begin{conteq}
155 % e^{\pi\cdot i} \\
156 % = -1 & Euler's formula \\
157 % < 0 & this is an inequality \\ 
158 % < \sqrt 3 \\
159 % = \int e^{-x^2} dx & this is due to Gauss.
160 % \end{conteq}
161 %
162 % The expressions are typeset in math mode, while the explanation is assumed to be regular text. The curly braces around the explanations come from the default |\ConteqExplStyle|.
163 %
164 % There are other layouts available, which you select with an optional parameter to |\begin{conteq}|, e.g.
165 % \begin{verbatim}
166 % \begin{conteq}[explline]
167 % [..]
168 % \end{conteq}
169 % \end{verbatim}
170 %
171 % The layouts defined by |conteq| are:
172 %
173 % \paragraph{plain} The default layout, shown above.
174 %
175 % \paragraph{explline} A layout that puts the explanations below the right-hand side of the equalty it is explaining. To be used when the explanations and righ-hand sides are long.
176 % \begin{conteq}[explline]
177 % e^{\pi\cdot i} \\
178 % = -1 & Euler's formula \\
179 % < 0 & this is an inequality \\ 
180 % < \sqrt 3 \\
181 % = \int e^{-x^2} dx & this is due to Gauss.
182 % \end{conteq}
183
184 %
185 % \paragraph{headline} Like plain, but the first expression is also vertically aligned with the right-hand sides.
186 % \begin{conteq}[headline]
187 % e^{\pi\cdot i} \\
188 % = -1 & Euler's formula \\
189 % < 0 & this is an inequality \\ 
190 % < \sqrt 3 \\
191 % = \int e^{-x^2} dx & this is due to Gauss.
192 % \end{conteq}
193 %
194 % \paragraph{onecolumn} A combination of \textbf{explline} and \textbf{headline} that puts everything in one column, for maximum space efficiency.
195 % \begin{conteq}[onecolumn]
196 % e^{\pi\cdot i} \\
197 % = -1 & Euler's formula \\
198 % < 0 & this is an inequality \\ 
199 % < \sqrt 3 \\
200 % = \int e^{-x^2} dx & this is due to Gauss.
201 % \end{conteq}
202 %
203 % \paragraph{oneline} A layout, more for demonstrational purposes, that ignores the explanations and puts everything in one line.
204 % \begin{conteq}[oneline]
205 % e^{\pi\cdot i} \\
206 % = -1 & Euler's formula \\
207 % < 0 & this is an inequality \\ 
208 % < \sqrt 3 \\
209 % = \int e^{-x^2} dx & this is due to Gauss.
210 % \end{conteq}
211 %
212 % \DescribeMacro{\ConteqSetDefaultLayout} You can change the default layout using |\ConteqSetDefaultLayout|\marg{layout}
213 %
214 % \section{Defining layouts}
215 %
216 % \DescribeMacro{\ConteqDefineLayout}
217 % To define a new layout you use |\ConteqDefineLayout|, which takes seven arguments:
218 % \begin{enumerate}
219 % \item The name of the layout,
220 % \item What to put before the continued equalities,
221 % \item the left-hand side of the first equality,
222 % \item the right-hand side of equalities without explanation,
223 % \item the right-hand side of equalities with explanation,
224 % \item the line separator and
225 % \item what to put after the continued equalities.
226 % \end{enumerate}
227 %
228 % For example the existing layouts are defined using
229 % \iffalse
230 %<*layouts>
231 % \fi
232 %    \begin{macrocode}
233
234 \ConteqDefineLayout
235     {plain}
236     {\begin{align*}}
237     { #1 }
238     { & #1 }
239     { & #1 && #2 }
240     { \\ }
241     {\end{align*}}
242 \ConteqSetDefaultLayout{plain}
243
244 \ConteqDefineLayout
245     {explline}
246     {\begin{align*}}
247     { #1 }
248     { & #1 }
249     { & #1 \\ & \mathrel{\phantom{=}} #2 }
250     { \\ }
251     {\end{align*}}
252
253 \ConteqDefineLayout
254     {headline}
255     {\begin{align*}}
256     { &\mathrel{\phantom{=}} #1 \\ }
257     { & #1 }
258     { & #1 && #2 }
259     { \\ }
260     {\end{align*}}
261  
262 \ConteqDefineLayout
263     {onecolumn}
264     {\begin{align*}}
265     { &\mathrel{\phantom{=}} #1 \\ }
266     { & #1 }
267     { & #1 \\ & \mathrel{\phantom{=}} #2 }
268     { \\ }
269     {\end{align*}}
270
271 \ConteqDefineLayout
272     {oneline}
273     {\[}
274     { #1 }
275     { #1 }
276     { #1 }
277     {}
278     {\]}
279
280 %    \end{macrocode}
281 %
282 % \section{Changing the explanation style}
283 %
284 % \DescribeMacro{\ConteqExplStyle}
285 % The explanation is formatted using the macro |\ConteqExplStyle|\marg{explanation}, which is by default defined as
286 %    \begin{macrocode}
287 \newcommand{\ConteqExplStyle}[1]{\{~#1~\}}
288 %    \end{macrocode}
289 %
290 % To change the style, simply redefine this macro using, for example:
291 % \begin{verbatim}
292 % \renewcommand{\ConteqExplStyle}{\textit{-- #1}}
293 % \end{verbatim}
294 %
295 %
296 % \section{Future work}
297 %
298 % This package is, at the time of writing, very new, so please le me know about problems you are having or features you are missing.
299 %
300 % One feature that I am considering is an auto-selection of layouts, so when you specify |\begin{conteq}[plain,explline,onecolumn]...\end{conteq}|, it will analyze the table and select, from your list of layouts, the first one that is ``ok'', where ``ok'' would be some layout-specific heuristic taking the size of the expressions and explanations as well as the current |\linewidth| into account. If you think that this would be useful to you, please let me know.
301 %
302 % You can follow the package's development at \url{http://git.nomeata.de/?p=conteq.git} or the mirror at \url{https://github.com/nomeata/conteq}.
303 %
304 % \iffalse
305 %</layouts>
306 % \fi
307 %
308 %\StopEventually{^^A
309 %  \PrintChanges
310 %  \PrintIndex
311 %}
312 %
313 %
314 %
315 % \section{Implementation}
316 %
317 % \iffalse
318 %<*package>
319 % \fi
320 %
321 % \subsection{Package loading}
322
323 %    \begin{macrocode}
324 \RequirePackage{amsmath}
325 \RequirePackage{environ}
326 %    \end{macrocode}
327 %
328 % \subsection{Defining Messages}
329 %
330 %    \begin{macrocode}
331 \msg_new:nnn
332     { conteq }
333     { empty }
334     { Empty~conteq~environment~\msg_line_context: }
335
336 \msg_new:nnn
337     { conteq }
338     { ignoreddata }
339     { Ignored~text~\msg_line_context: }
340
341 \msg_new:nnn
342     { conteq }
343     { undefined layout }
344     { Undefined~layout~``#1''~\msg_line_context: }
345 %    \end{macrocode}
346
347 % \subsection{Declaring local variables}
348 %
349 %    \begin{macrocode}
350 \tl_new:N \l__conteq_default_layout_tl
351 \tl_new:N \l__conteq_layout_tl
352 \tl_new:N \l__conteq_body_tl
353 \tl_new:N \l__conteq_lines_seq
354 \tl_new:N \l__conteq_cells_seq
355 \tl_new:N \l__conteq_head_tl
356 \tl_new:N \l__conteq_lastline_tl
357 \tl_new:N \l__conteq_rhs_tl
358 \tl_new:N \l__conteq_expl_tl
359 \tl_new:N \l__conteq_result_tl
360 %    \end{macrocode}
361
362 % \subsection{Layouts}
363 %
364 % \begin{macro}{\ConteqSetDefaultLayout}
365 % The code to set the default layout.
366 %    \begin{macrocode}
367 \cs_new_protected:Nn \__conteq_set_default_layout:n
368   {
369     \tl_set:Nn \l__conteq_default_layout_tl {#1}
370   }
371 \cs_new_eq:NN \ConteqSetDefaultLayout \__conteq_set_default_layout:n
372 %    \end{macrocode}
373 % \end{macro}
374 %
375 % \begin{macro}{\ConteqDefineLayout}
376 % The code to define new layouts.
377 %    \begin{macrocode}
378 \tl_const:Nn \c__conteq_prefix_tl { __conteq_layouts }
379
380 \cs_new_protected:Nn \__conteq_define_layout:nnnnnnn
381   {
382     \cs_new_protected:cn { \c__conteq_prefix_tl _ #1 _begin: } { #2 }
383     \cs_new_protected:cn { \c__conteq_prefix_tl _ #1_lhs:n } { #3 }
384     \cs_new_protected:cn { \c__conteq_prefix_tl _ #1_rhs_only:n } { #4 }
385     \cs_new_protected:cn { \c__conteq_prefix_tl _ #1_rhs_expl:nn } { #5 }
386     \cs_new_protected:cn { \c__conteq_prefix_tl _ #1_nl: } { #6 }
387     \cs_new_protected:cn { \c__conteq_prefix_tl _ #1_end: } { #7 }
388   }
389 \cs_new_eq:NN \ConteqDefineLayout \__conteq_define_layout:nnnnnnn
390 %    \end{macrocode}
391 % \end{macro}
392 %
393 % \subsection{Expansion utility function}
394
395 % \begin{macro}{\__conteq_args_once:Nn, \__conteq_args_once:NV, \__conteq_args_once:Nnn, \__conteq_args_once:NVV}
396 % For ease of debugging(?) we construct a token list that contains exactly the tokens that a programmer would enter to create the layout manually. For that we need some fine-grained control over expansion.
397 %
398 %    \begin{macrocode}
399 \cs_new:Npn \__conteq_args_once:Nn #1#2
400   {
401    \exp_not:o { #1 {#2} }
402   }
403 \cs_generate_variant:Nn \__conteq_args_once:Nn { NV }
404
405 \cs_new:Npn \__conteq_args_once:Nnn #1#2#3
406   {
407    \exp_not:o { #1 { #2 }{ #3 } }
408   }
409 \cs_generate_variant:Nn \__conteq_args_once:Nnn { NVV }
410 %    \end{macrocode}
411 % \end{macro}
412 %
413 % \subsection{Main code}
414 %
415 % \begin{macro}{\__conteq_print_line:nn}
416 % This macro splits and prints one line of the table. The second argument is either |\\| or, for the last line of the table, empty.
417 %    \begin{macrocode}
418 \cs_new_protected:Npn \__conteq_print_line:Nnn #1#2#3
419   {
420     \seq_set_split:Nnn \l__conteq_cells_seq { & } { #2 }
421     \seq_pop_left:NN \l__conteq_cells_seq \l__conteq_rhs_tl
422     \tl_clear:N \l__conteq_expl_tl
423     \seq_if_empty:NF \l__conteq_cells_seq
424       {
425         \seq_pop_left:NN \l__conteq_cells_seq \l__conteq_expl_tl
426       }
427     \tl_if_blank:VTF \l__conteq_expl_tl
428       {
429         \tl_put_right:Nx #1
430           {
431             \__conteq_args_once:NV \__conteq_rhs_only:n \l__conteq_rhs_tl
432           }
433       }
434       {
435         \tl_set:Nx \l_tmpa_tl { \exp_not:N \text { \exp_not:N \ConteqExplStyle { \exp_not:V \l__conteq_expl_tl } } }
436         \tl_put_right:Nx #1
437           {
438             \__conteq_args_once:NVV \__conteq_rhs_expl:nn \l__conteq_rhs_tl \l_tmpa_tl
439           }
440       }
441       \seq_if_empty:NF \l__conteq_cells_seq
442         {
443           \msg_warning:nn{conteq}{ignoreddata}
444         }
445     \tl_put_right:Nn #1 {#3}
446   }
447 \cs_generate_variant:Nn \__conteq_print_line:Nnn { Nno, NVn }
448 %    \end{macrocode}
449 % \end{macro}
450
451 %
452 % \begin{environment}{conteq}
453 %
454 % The main environment of the package.
455 %    \begin{macrocode}
456 \NewEnviron{ conteq }[1][ \l__conteq_default_layout_tl ]{
457   \tl_set:NV \l__conteq_body_tl \BODY
458   
459   \tl_if_blank:oT \l__conteq_body_tl
460     {
461       \msg_warning:nn{conteq}{empty}
462     }
463 %    \end{macrocode}
464
465 % Figure out the layout to use\ldots
466 %    \begin{macrocode}
467   \tl_set:Nn \l__conteq_layout_tl { #1 }
468 %    \end{macrocode}
469 % and set the various functions accordingly, if the layout exists.
470 %    \begin{macrocode}
471   \cs_if_exist:cTF { \c__conteq_prefix_tl _ \l__conteq_layout_tl _ begin: }
472     {
473       \clist_map_inline:nn{ begin:, lhs:n,rhs_only:n, rhs_expl:nn, nl:, end: }
474         {
475           \cs_set_eq:cc { __conteq_ ##1 }{ \c__conteq_prefix_tl _ \l__conteq_layout_tl _ ##1 }
476         }
477     }{
478       \msg_critical:nnx{conteq}{undefined layout}{\l__conteq_layout_tl}
479     }
480 %    \end{macrocode}
481
482 % Split the body into individual lines.
483 %    \begin{macrocode}
484   \seq_set_split:NnV \l__conteq_lines_seq { \\ } \l__conteq_body_tl
485
486   \tl_clear:N \l__conteq_result_tl
487 %    \end{macrocode}
488
489 % If there is only one line, simply print it.
490 %    \begin{macrocode}
491
492   \int_case:nnF { \seq_count:N \l__conteq_lines_seq }
493     {
494       {1}
495         {
496           \tl_put_right:Nx \l__conteq_result_tl { \exp_not:o \__conteq_begin: }
497           \tl_put_right:NV \l__conteq_result_tl \l__conteq_body_tl
498           \tl_put_right:Nx \l__conteq_result_tl { \exp_not:o \__conteq_end: }
499         }
500     }
501     {
502 %    \end{macrocode}
503
504 % Otherwise extract the head and the last line, and print each line using |\__conteq_print_line:nn|
505 %    \begin{macrocode}
506       \seq_pop_left:NN \l__conteq_lines_seq \l__conteq_head_tl
507       \seq_pop_right:NN \l__conteq_lines_seq \l__conteq_lastline_tl
508
509       \tl_put_right:Nx \l__conteq_result_tl { \exp_not:o \__conteq_begin: }
510       \tl_put_right:Nx \l__conteq_result_tl
511         {
512           \__conteq_args_once:NV \__conteq_lhs:n \l__conteq_head_tl
513         }
514       \seq_map_inline:Nn \l__conteq_lines_seq
515         {
516           \__conteq_print_line:Nno \l__conteq_result_tl { ##1 } { \__conteq_nl: }
517         }
518       \__conteq_print_line:NVn \l__conteq_result_tl \l__conteq_lastline_tl {} 
519       \tl_put_right:Nx \l__conteq_result_tl { \exp_not:o \__conteq_end: }
520     }
521     % Use this for debugging
522     %\tl_show:N \l__conteq_result_tl
523     \tl_use:N \l__conteq_result_tl
524   }
525 %    \end{macrocode}
526 %\end{environment}
527 %
528 %    \begin{macrocode}
529 \endinput
530 %    \end{macrocode}
531
532 %
533 % \iffalse
534 %</package>
535 % \fi
536 %
537 % \Finale
538 \endinput