ecmascript-mkiv.tex /size: 11 Kb    last modification: 2023-12-21 09:43
1% language=us runpath=texruns:manuals/libraries
2
3% author    : Hans Hagen
4% copyright : ConTeXt Development Team
5% license   : Creative Commons Attribution ShareAlike 4.0 International
6% reference : pragma-ade.nl | contextgarden.net | texlive (related) distributions
7% origin    : the ConTeXt distribution
8%
9% comment   : Because this manual is distributed with TeX distributions it comes with a rather
10%             liberal license. We try to adapt these documents to upgrades in the (sub)systems
11%             that they describe. Using parts of the content otherwise can therefore conflict
12%             with existing functionality and we cannot be held responsible for that. Many of
13%             the manuals contain characteristic graphics and personal notes or examples that
14%             make no sense when used out-of-context.
15%
16% comment   : Some chapters might have been published in TugBoat, the NTG Maps, the ConTeXt
17%             Group journal or otherwise. Thanks to the editors for corrections. Also thanks
18%             to users for testing, feedback and corrections.
19
20% for now:
21
22\usemodule[article-basic]
23\usemodule[abbreviations-smallcaps]
24\usemodule[scite]
25\usemodule[ecmascript]
26
27\definecolor
28  [maincolor]
29  [r=.4]
30
31\definecolor
32  [extracolor]
33  [g=.4]
34
35\setupbodyfont
36  [11pt]
37
38\setuptype
39  [color=maincolor]
40
41% \setuptyping
42%   [color=maincolor]
43
44\definefontsynonym
45  [TitlePageMono]
46  [file:lmmonoproplt10-bold*default]
47
48\setuphead
49  [color=maincolor]
50
51\usesymbols
52  [cc]
53
54\setupinteraction
55  [hidden]
56
57\loadfontgoodies[lm]
58
59\startdocument
60  [metadata:author=Hans Hagen,
61   metadata:title=ecmascript in context lmtx,
62   author=Hans Hagen,
63   affiliation=PRAGMA ADE,
64   location=Hasselt NL,
65   title=\ECNASCRIPT\ in \CONTEXT\ \LMTX,
66   support=www.contextgarden.net,
67   website=www.pragma-ade.nl]
68
69\starttext
70
71\startMPpage
72    StartPage;
73
74        fill Page withcolor "darkgreen";
75
76        draw textext.lrt("\tttf ECMA")
77            xsized .75PaperWidth
78            shifted ulcorner (Page enlarged -15mm )
79            withcolor "white" ;
80
81        draw textext.llft("\tttf SCRIPT")
82            xsized .50PaperWidth
83            shifted urcorner (Page enlarged -15mm topenlarged -70mm)
84            withcolor "white" ;
85
86        draw textext.llft("\tttf in context lmtx")
87            xsized .50PaperWidth
88            shifted urcorner (Page enlarged -15mm topenlarged -110mm)
89            withcolor "white" ;
90
91        draw textext.llft("\tttf using the optional mujs library")
92            xsized .50PaperWidth
93            shifted lrcorner (Page enlarged -15mm bottomenlarged -10mm)
94            withcolor "white" ;
95
96    StopPage;
97\stopMPpage
98
99\dontcomplain
100
101% \startsubject[title=Contents]
102%
103% \placelist[section][alternative=a]
104%
105% \stopsubject
106
107\startsection[title=Introduction]
108
109When you use \CONTEXT\ there is no way around noticing that the \LUA\ scripting
110language is an important component. When we progressed from \LUATEX\ to
111\LUAMETATEX\ did didn't change. I like that language a lot! Among the reasons are
112that it reminds me of \PASCAL, that it's clean, fast and well maintained. There
113is no huge infrastructure involved, nor lots of libraries and therefore
114dependencies.
115
116So why bother about another scripting language? One can argue that because of the
117World Wide Web one should use \JAVASCRIPT\ instead. It might make sense from a
118commercial point of view, or for some promotional reason. But that all makes
119little sense in the perspective of \CONTEXT. But, when I was playing with
120optional libraries in \LUAMETATEX,
121
122On and off I wonder if I should spend some time on adding \LUA\ annotation
123support to the open source mupdf viewer. After all, it has some basic
124\JAVASCRIPT\ support (but currently not enough, for instance it lacks control
125over widgets and layers and such.) However, then I noticed that the related
126\JAVASCRIPT\ code was actually an independent library and looking at the header
127files it looked quite a bit like the \LUA\ interface. So, just for the fun of it I
128gave it a try, and when doing so, I realized that having support for \JAVASCRIPT,
129or actually \ECMASCRIPT, because that is what it is, could make users who are
130afraid of \LUA\ willing to play with simple scripting in \CONTEXT. Of course,
131after a while they will figure out that \LUA\ is the real deal.
132
133Therefore, instead of sticking to an experiment, I decided to make support for
134the \type {mujs} library an option. After all, every now and they we need
135something new to play with. But be warned: it's an optional thing. The
136interpreter is not embedded in the binary and is loaded on demand (when present).
137In spite of that performance is quite okay.
138
139\stopsection
140
141\startsection[title=A few examples]
142
143Because the provided interface is pretty limited, a few simple examples will do.
144There are plenty of tutorials on the Internet. The main thing to keep in mind is
145that an \ECMASCRIPT\ interpreter is normally pretty limited when it comes to
146communicating with its environment. For instance, the main application provides
147way to print something (to a console) or read from files. So, commands that
148relate to this are specific for \LUAMETATEX. Before anything can be done you need
149to load the (\type {mujs}) library, which is done with:
150
151\starttyping
152\usemodule[ecmascript]
153\stoptyping
154
155You can write a message to the log (or an output pane or console) with the \type
156{console} function, one that normally is present in a \JAVASCRIPT\ (\ECMASCRIPT)
157environment:
158
159\starttyping
160\ecmacode {console("Example Three!")}
161\stoptyping
162
163Printing something to the \TEX\ engine is done with this command:
164
165\startbuffer
166\ecmacode {texprint("Just a {\\bf short} sentence.")}
167\stopbuffer
168
169\typebuffer[option=TEX]
170
171This produces:
172
173\getbuffer
174
175and is comparable with the \type {tex.print} (which prints lines) function at the
176\LUA\ end. This means that there is also \type {texsprint} (which accumulates
177parts into lines). In practice one will probably always use that one.
178
179When there are two arguments, the first argument has to be a number and sets the
180so called catcode table to be used.
181
182\startbuffer
183\ecmacode {texprint(catcodes.vrb,"Just a {\\bf short} sentence.")}
184\stopbuffer
185
186\typebuffer[option=TEX]
187
188This results in a verbatim print: {\tttf \inlinebuffer} The backslash is just that,
189a backslash and not a trigger for a \TEX\ command.
190
191You can do pretty much everything with these print commands. Take for instance the
192following example:
193
194\startbuffer
195\startecmacode
196  console("We're doing some MetaPost!");
197  texsprint(
198      "\\startMPcode "
199    + 'fill fullsquare xyscaled (6cm,1cm) withcolor "darkred";'
200    + 'fill fullsquare xyscaled (4cm,1cm) withcolor "darkgreen";'
201    + 'fill fullsquare xyscaled (2cm,1cm) withcolor "darkblue";'
202    + "\\stopMPcode "
203  );
204\stopecmacode
205\stopbuffer
206
207\typebuffer[option=TEX]
208
209This produces:
210
211\startlinecorrection
212\getbuffer
213\stoplinecorrection
214
215in \LUA\ we can do this:
216
217\startbuffer
218\startluacode
219  context.startMPcode()
220    context('fill fullsquare xyscaled (6cm,1cm) withcolor "middlecyan";')
221    context('fill fullsquare xyscaled (4cm,1cm) withcolor "middlemagenta";')
222    context('fill fullsquare xyscaled (2cm,1cm) withcolor "middleyellow";')
223  context.stopMPcode()
224\stopluacode
225\stopbuffer
226
227\typebuffer[option=TEX]
228
229The result is the same but the code to produce it looks more like \CONTEXT, if
230only because way more built in features are provided. It makes no sense to do
231the same with another scripting language.
232
233\startlinecorrection
234\getbuffer
235\stoplinecorrection
236
237As mentioned, reading from files is to be provided by the main program and indeed
238we do have some basic interface. Actually we delegate all to the \LUA\ end by
239using a callback mechanism but users won't see these details. It suffices to know
240that file lookups are done the same way as in the main program because we use the
241same resolvers. One can (in the spirit of \ECMASCRIPT) open a file by creating a
242new file object. After that one can read from the file and, when done, close it.
243
244\startbuffer
245\startecmacode
246  var f = File("ecmascript-mkiv.tex","r");
247  var l = f.read("*a");
248  f.close();
249  texprint(
250      "This file has "
251    + l.length // or: l.length.toString()
252    + " bytes!"
253  )
254\stopecmacode
255\stopbuffer
256
257\typebuffer[option=TEX]
258
259Which reports that: \quotation {\inlinebuffer} The arguments to the \type {read}
260method are the same as in \LUA, so for instance \type {*a} reads the whole file,
261\type {*l} a single line, and a number will read that many bytes. There is
262currently no support for writing as I see no need for it (yet).
263
264You can load an external file too.
265
266\startluacode
267io.savedata("ecmascript-demo-001.js",[[
268function filesize(name) {
269    var f = File(name,"r");
270    if (f != undefined) {
271        var l = f.read("*a");
272        f.close();
273        return l.length;
274    } else {
275        return 0;
276    }
277}
278]])
279\stopluacode
280
281\startbuffer
282\ecmafile{ecmascript-demo-001.js}
283\stopbuffer
284
285\typebuffer[option=TEX] \getbuffer
286
287This file defines a function:
288
289\typefile{ecmascript-demo-001.js}
290
291We use this as follows:
292
293\startbuffer
294\startecmacode
295  texsprint(
296      "This file has "
297    + filesize("ecmascript-mkiv.tex")
298    + " bytes!"
299  )
300\stopecmacode
301\stopbuffer
302
303\typebuffer[option=TEX]
304
305The result is the same as before: \quotation {\inlinebuffer} but by using a
306predefined function we save ourselves some typing. Actually, a more efficient
307variant is this:
308
309\starttyping
310function filesize(name) {
311    var f = File(name,"r");
312    if (f != undefined) {
313        var l = f.seek("end");
314        f.close();
315        return l;
316    } else {
317        return 0;
318    }
319}
320\stoptyping
321
322As with the \type {read} method, the \type {seek} method behaves the same as
323its \LUA\ counterpart, which is a good reason to have a look at the \LUA\
324manual.
325
326If you want you want also access the \ECMASCRIPT\ interpreter from the \LUA\ end,
327not that it makes much sense, but maybe you have a lot of complex code that you
328don't want to rewrite. Here is an example:
329
330\startbuffer
331\startluacode
332  optional.loaded.mujs.execute [[
333    var MyMax = 10; // an example of persistence
334  ]]
335
336  optional.loaded.mujs.execute [[
337    texsprint("\\startpacked");
338    for (var i = 1; i <= MyMax; i++) {
339      texprint(
340        "Here is some rather dumb math test: "
341      + Math.sqrt(i/MyMax)
342      + "!\\par"
343      );
344    }
345    texsprint("\\stoppacked");
346  ]]
347\stopluacode
348\stopbuffer
349
350\typebuffer[option=TEX]
351
352This assumes that you have loaded the module \type {ecmascript} which does the
353necessary preparations. Watch the different ways to add comment and also watch
354how we need to escape the \CONTEXT\ commands. Of course the syntax of both
355languages is different too.
356
357\getbuffer
358
359For now there is not much more to tell. I might add a few features (and more
360examples). And the low level optional interface is not yet declared stable but as
361we wrap it in higher level commands no one will notice changes at that end.
362
363\stopsection
364
365\startsection[title=Extensions]
366
367To summarize, for printing to \TEX\ we have:
368
369\starttyping
370texsprint([catcodetableid,]string|number)
371\stoptyping
372
373and
374
375\starttyping
376texprint(catcodetableid,]string|number)
377\stoptyping
378
379and for printing to the console:
380
381\starttyping
382console(string|number)
383\stoptyping
384
385A file is opened with:
386
387\starttyping
388var f = File.new(filename[,mode])
389\stoptyping
390
391and the returned file object has the methods:
392
393\starttyping
394var str = f:read([string|number])
395var pos = f:seek(whence[,offset])
396\stoptyping
397
398There is a predefined table \type {catcodes} with sybolic entries
399for:
400
401\starttabulate
402\NC \type {tex} \NC regular \TEX\ catcode regime       \NC \NR
403\NC \type {ctx} \NC standard \CONTEXT\ catcode regime  \NC \NR
404\NC \type {vrb} \NC verbatim catcode regime            \NC \NR
405\NC \type {prt} \NC protected \CONTEXT\ catcode regime \NC \NR
406\stoptabulate
407
408\stopsection
409
410\startsection[title=Colofon]
411
412\starttabulate[|B|p|]
413\NC author  \NC \documentvariable{author}, \documentvariable{affiliation}, \documentvariable{location} \NC \NR
414\NC version \NC \currentdate \NC \NR
415\NC website \NC \documentvariable{website} \endash\ \documentvariable{support} \NC \NR
416\stoptabulate
417
418\stopsection
419
420\stopdocument
421