1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% latex.mp Parametrizable latex labels for metapost
%% Copyright (c) 2003 JL Diaz
%% based on an idea taken from Metafun, by Hans Hagen
%
% This program may be distributed and/or modified under the conditions
% of the LaTeX Project Public License, either version 1.2 of this
% license or (at your option) any later version. The latest version
% of this license is in http://www.latex-project.org/lppl.txt and
% version 1.2 or later is part of all distributions of LaTeX version
% 1999/12/01 or later.
%
% This program consists of the file latex.mp
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% For the impatient: Jump to "USAGE"
%
% Introduction: The problem
%
% Let us suppose that you need to typeset several labels of the form
% $x_1$, $x_2$, ... $x_{10}$. Since each label is a formula, the
% construction btex/etex is required to typeset it through TeX (or
% LaTeX). So, the straighforward solution is:
%
% label(btex $x_1$ etex, (1u,0u));
% label(btex $x_2$ etex, (2u,0u));
% ...
% label(btex $x_{10}$ etex, (10u,0u));
%
% This repeated structure is inviting us to convert it into a for
% loop. A naive attempt would be:
%
% for i=1 upto 10:
% label (btex $x_{i}$ etex, (i*u, 0));
% endfor;
%
% Unfortunately the above would produce ten times the same label
% $x_{i}$, because i is not evaluated in this context as a variable.
%
% A second, more clever attempt would be:
%
% for i=1 upto 10:
% label("btex $x_{" & decimal i & "}$ etex", (i*u, 0));
% endfor;
%
% where we are making use of the string concatenation operator (&),
% and the "decimal" operator, which produces an string whith the
% decimal representation of its argument. This way, the macro label
% will receive successively as first argument the strings: "btex
% $x_{1}$ etex", "btex $x_{2}$ etex", end so on.
%
% This solution does not work either, because label is receiving a
% string, instead of a picture (which is the result of a proper
% btex/etex construction). When a string is received, label simply
% outputs that string, without calling TeX (LaTeX) for formatting it.
%
% Metapost provides a way of "executing" the code which is stored in
% a string, it is the scantokens primitive. So, it appears that a
% modification of the label primitive would be possible, which
% applies the scantokens primitive on the string which it receives as
% parameter. Unfortunately this does not work either, because the way
% in which btex/etex works procludes it use as argument of
% scantokens.
%
% So, apparently, there is not an easy solution to the problem of
% passing arguments to the etex/btex construct.
%
% The solution
%
% Since the construct btex/etex can only be used at the "top level"
% of a source file, and not embedded in any string, the only way to
% achieve the desired result is to store the string "btex ... etex"
% in an external temporal file, and input back that file.
%
% This solution is implemented in the macro package "TEX.mp" which is
% part of the standard metapost distribution. Using this package, the
% problem of printing the ten labels $x_1$ .. $x_{10}$ becomes simple:
%
% for i=0 upto 10:
% label(TEX("$x_{" & decimal i & "}$", (u*i,0));
% endfor;
%
% The macro TEX receives an string as argument, and uses TeX to
% typeset it. This is achieved, as already explained, by creating a
% new string which encapsulated the given argument into a btex/etex
% pair, writing this new string in an external file, and inputting
% that file back.
%
% This approach has two main drawbacks:
%
% 1) An external file is created, and processed each time TEX is
% used. This is very inefficient, and the slowdown is noticeable if
% TEX is used often.
%
% 2) If we want to use latex istead of tex, the TEX macro will not
% work, because the external file created through this macro does
% not include the verbatimtex header required to initialize latex.
%
% Metafun approach: a clever solution
%
% In the excelent macro package Metafun (by Hans Hagens), a nice
% solution is found to the first problem. Instead of writing the
% auxiliar file and inputting it again, what is wrote is an auxiliar
% metapost program which defines a serie of picture variables, each
% one with the result of a btex/etex pair. In the first run of
% metapost, this auxiliar file is write-only. In the second run, the
% file is read at the beginning, so all picture variables get
% defined. In this second run, each time the TEX macro is called, it
% checks if the corresponding picture variable is already defined,
% and in this case it simply returns its value.
%
% This approach is much more efficient, since a single externa file
% is produced and processed, no matter how much the TEX macro is
% called. The only drawback is that two metapost runs are required.
%
% latex.mp: my solution
%
% I liked very much the metafun solution, but I did not want to use
% the whole Metafun package only to obtain this
% functionality. Moreover, metafun relies in a set of external
% scripts, which decide to input or not the external file, depending
% on the existence of that file. I would prefer do not require perl
% nor any other scripting language. Only metapost.
%
% This is why I wrote "latex.mp". It implements the idea in the
% metafun package, but it does not require any external script in
% order to check the existence of the auxiliar file.
%
% ================================================================
%
% USAGE
%
% input "latex";
% initlatex(...);
% ...
%
% latex("string to be formatted by latex");
% % Returns a picture which can be used in a label
%
% The initlatex macro writes a latex header in an auxiliar file. You
% do not need to call this macro if you use TeX as typesetting engine.
%
% On the other hand, if you want to use LaTeX as typesetting engine,
% you need to call this macro before the first beginfig(). The macro
% requires a mandatory argument, which is a string with adittional
% macro commands to be placed before the "\begin{document}". For
% example:
%
% initlatex("\usepackage[latin1]{inputenc}\usepackage{amsmath}");
%
% If you do not need any aditional package, you can use "" as
% argument.
%
% You can use the latex macro in any place where a picture is
% expected, as in the first argument of a label comand. For example:
%
% for i=0 upto 10:
% label(latex("$x_{$ & decimal i & "}$", (u*i,0));
% endfor;
%
% In order to correctly obtain the labels which use the latex macro,
% you need to process your source file twice through metapost. The
% first run all labels will show as "[?]", but the second run they
% will have the correct value.
%
% IMPORTANT:
%
% If the text passed to the latex macro contains errors, latex will be
% unable to complete its run. This will make impossible to run mpost
% on the source, even if the errors are corrected, until you delete
% the auxiliar file (which has .mpt extension)
%
%
%================================================================
% Implementation
%
numeric NumPic; % Total number of times that latex() macro has been
% called
picture LaTeXPic[]; % Picture array which stores the result of each
% latex macro call. This array is filled when the
% axiliar file is read.
string LaTeXsetup; % additional packages and macro definitions for latex
% Initialization
NumPic:=0;
LaTeXsetup:="\documentclass{article}";
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Entry point
%
% The auxiliar file is read, but only if it exists
%
if readfrom(jobname&".mpt") <> EOF:
scantokens ("input "&jobname & ".mpt");
fi;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% initlatex()
%
% By calling this function, the user can specify aditional packages and
% macro definitions to the be used by latex.
%
% For example:
%
% initlatex("\usepackage[latin1]{inputenc}\usepackage{amsmath}");
%
% The global variable LaTeXsetup is also provided, mainly for third
% party libraries which require to define their own macros. The
% programmers of these libraries should append their own material to
% the LaTeXsetup variable, by using the & operator. For example:
%
% LaTeXsetup:=LaTeXsetup & "\def\TO{\Longrightarrow}";
%
def initlatex primary s =
write "verbatimtex" to jobname & ".mpt";
write "%&latex" to jobname & ".mpt";
write LaTeXsetup to jobname & ".mpt";
write s to jobname & ".mpt";
write "\begin{document}" to jobname & ".mpt";
write "etex" to jobname & ".mpt";
enddef;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% latex()
%
% This macro receives a string, and returns a picture which contains
% the result of running the string by latex. The result can be used
% whenever a picture argument is expected, as for example in a label.
vardef latex@#(expr txt) =
NumPic := NumPic + 1 ;
if string txt :
write "% figure " & decimal charcode & " : " & char(10) &
"LaTeXPic[" & decimal NumPic & "] := btex " &
txt & " etex ;" to jobname & ".mpt" ;
if unknown LaTeXPic[NumPic] :
thelabel@#("[??]",origin)
else :
thelabel@#(LaTeXPic[NumPic],origin)
fi
else :
thelabel@#(txt,origin)
fi
enddef ;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% EOF
|