maml4_tutorial.maml
84.4 KB
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
The MAML4 tutorial
(written in MAML4)
$begin
$define(article)(0)()
$define(tocsec)(1)($par$bold($1)$par)
$define(tocsubsubsec)(1)()
$define(subseclayout)(1)($par$big($bold($1))$par$par)
$input(basis.maml)
$// A counters for the catalog of marks
$pushcounter(markcount)(0)
$// an accumulator for displaying a table of all mark names at the
$// beginning of the catalog section
$accumulator(tabmark)
$define(marklo) $// marl layout
(1)
($addtocounter(markcount)(1)$par$par$bold($countervalue(sec).$countervalue(markcount). $1)$par$par)
$// A colorizer for MAML code
$colorrule(maml)(#$#/#/.*)($darkgreen($1))
$colorrule(maml)((#$[#,#[#]#(#)])|(#$[a-zA-Z#_][0-9a-zA-Z#_]*)|(#$#$))($bold($darkred($1)))
$colorrule(maml)(#$[0-9]+)($magenta($1))
$colorrule(maml)([0-9]+)($sienna($1))
$colorizer(maml)
$// Some layout macros.
$define(p)(0)($par$par)
$define(title)(1)($center($big($big($bold($1)))))
$define(MAML)(0)($bold($rgb(180,0,0)(M)$rgb(0,120,0)(A)$rgb(80,80,80)(M)$rgb(0,0,220)(L)))
$define(em)(1)($italic($1))
$define(textcolor)(0)(100,20,20)
$define(mtt)(1)($tt($colorize(maml)($nolist($1))))
$define(mcode)(1)($code(230,235,220)($colorize(maml)($par$nolist($1)$par$par)))
$define(mcenter)(1)($par$center($colorize(maml)($nolist($1)))$par)
$define(argu)(1)($rgb(0,80,0)($bold($tt(<$1>))))
$define(LaTeX)(0)($latex(\LaTeX))
$define(unsafe)(0)($bold($rgb(220,0,0)(unsafe)))
$define(id)(1)($1)
$define(ptext)(1)($rgb(120,40,40)($1))
$define(fname)(1)($rgb(0,80,50)($tt($1)))
$// A system for displaying names of marks on several columns
$//$pushcounter(catacol)(0)
$//$define(advcol)(0)($if($equals($countervalue(catacol))(3))($setcounter(catacol)(0)$par)($addtocounter(catacol)(1)))
$// Displaying marks in the catalog and accumulating links to them.
$define(mark0)(1)
($append(tabmark)($1)$label($1)$marklo($mtt($$$1)))
$define(mark1)(2)
($append(tabmark)($1)$label($1)$marklo($mtt($$$1$lpar$argu($2)$rpar)))
$define(mark2)(3)
($append(tabmark)($1)$label($1)$marklo($mtt($$$1$lpar$argu($2)$rpar$lpar$argu($3)$rpar)))
$define(mark3)(4)
($append(tabmark)($1)$label($1)$marklo($mtt($$$1$lpar$argu($2)$rpar$lpar$argu($3)$rpar$lpar$argu($4)$rpar)))
$define(mark4)(5)
($append(tabmark)($1)$label($1)$marklo($mtt($$$1$lpar$argu($2)$rpar$lpar$argu($3)$rpar$lpar$argu($4)$rpar$lpar$argu($5)$rpar)))
$/////////////////// Here begins the text //////////////////////////
$title(The $MAML (version 4) Tutorial)
$title(and Reference)
$par$par$par
$MAML (the $em(Minimalist Anubis Markup Language)) is an easy to use tool for writing texts. It provides
commands for using different $bold(font) $italic(styles), $big(font $big(sizes)), $red(colors), for making lists, tables,
sectionning units, inserting images
and
hypertext links, automatically making a table of contents,
and most sorts of things which are useful for writting texts which are agreable to read.
It is also able to automatically produce syntactic colorations. The $MAML
compiler produces HTML and PDF output files from a $MAML source text.
This documentation itself was written in $MAML.$p
Despite its computing capabilities, $MAML is $em(not a programming language). It is a $em(text formating language).
Programming with $MAML is easy provided you write only very short pieces of programs. Making big programs in $MAML
would generate absolutely unreadable source texts (like what happens with $latex(\TeX)). We have managed to present
many (short) examples of $MAML programming in this tutorial, which helps to quickly understand the explanations.$p
The very first version of $MAML was designed for allowing users on a forum to decorate their messages, and was
very rudimentary. This is
why $MAML was called $em(minimalist). This version 4 is now quite far from being $em(minimalist), but the name $MAML
remains (partly because it's funny when pronounced in French and English).
$p
$center($bold(Table of Contents))$par
$tableofcontents
$////////////////////////////////////////////////////////////////////////////////:
$section(howto)(How to use $MAML)
$subsection(ascmdlinetool)(As a command line tool)
$MAML can be used as a command line tool. This tool can work to its full power
only if $mtt(pdflatex) and $mtt(dvipng) are installed on
your system. If they are not, you can still use $MAML, but the mark $mtt($$latex) will not work, and you will not be able
to produce a PDF output. See the Anubis library documentation for more precise explanations.
$par
$par
Assuming that the file $mtt(my_file.maml) contains some $MAML source text,
you just have to issue the command:
$mcode(anbexec maml my_file.maml)
and the $MAML compiler will produce a file named $mtt(my_file.maml.html) that you can view with your favorite browser.
$par
$par
This command line tool has several options that you can discover by typing:
$mcode(anbexec maml)
For example, the option $mtt(-pdf) produces a PDF output.
$p
$subsection(fromyoursource)(From within your Anubis source code)
You may also want to use the $MAML compiler from within your Anubis source code. For example, you may want to use $MAML
on a web site.
In this case, have a look at the Anubis library documentation.
Notice that several $MAML marks are $unsafe for a use on the web. We explain in the library documentation
how to restrict $MAML to safe marks.$p
$subsection(aswebuser)(As a web user)
Since $MAML can be used in a web site (powered for example by the Anubis web server), it is possible to allow web users
(those persons visiting the web site) to write $MAML texts within web pages. In this case, the set of available $MAML
marks is restricted for ensuring the security of the web server.$p
$//////////////////////////////////////////////////////////////////////////
$section(syntax)(The $MAML syntax)
$subsection(beginend)($mtt($$begin), $mtt($$end) and special characters)
When it reads a source text, the $MAML compiler ignores everything until the first occurrence of $ref(begin)($mtt($$begin)). After
this $em(mark), the compiler parses and evaluates the text until it finds $ref(end)($mtt($$end)). Then again, it ignores everything
until the next $mtt($$begin), and so on.$p
Between $mtt($$begin) and $mtt($$end), the compiler considers all characters as neutral (i.e. they represent only
themselves), except the character $mtt($$). This character introduces a so-called $em(mark), which can have so-called
$em(operands). The operands are delimited by pairs of parentheses.
Within an operand, all characters are considered as pure text, except the following:
$list(
$item the character $mtt($$),
$item the left and right parentheses $mtt($lpar) and $mtt($rpar). They are used for delimiting blocks of text.
$item the left and right square brackets $mtt($[) and $mtt($]). They are used for delimiting lists, and within such
lists, the comma $mtt($,) is used for separating the elements of the list. The comma is otherwise neutral.
)
Of course, the possibility exists of inserting these characters as usual neutral characters. It is enough to prefix
them by a $mtt($$). Hence, for example, $mtt($[) marks the beginning of a list, whereas $mtt($$$[) just represents a
left square bracket.$p
The figure below sumarizes the above rules.
$mcode( $em($darkgreen(before $$begin everything is ignored))
$$begin
$em($navy(here, outside any operand of mark, only the character $$ is special))
$$a_mark(... $em($darkred(here, $bold($$ $( $) $[) and $bold($]) are special)) ...)
(... $[ $em($sienna(and here, the comma also is special)) $]
... $$another_mark( $em($darkred(here too, $bold($$ $( $) $[) and $bold($]) are special)) ...) ...
(... $$nolist($em($purple(but here, only $bold($$ $() and $bold($)) are special
even if we are within a list, but brackets
must still be balanced))) ...) )
$$end
$em($darkgreen(here again, everything is ignored))
$$begin
$em($navy(and here, it works again as above after the first $$begin))
$em($black(you can alternate $$begin and $$end any number of times))
$em($black(etc... (and an $$end is required for closing each $$begin))))
$subsection(syntaxmark)(Marks)
This character $mtt($$) indicates
that what follows is a $em(mark). The name of the mark (a non empty sequence of characters among
$mtt($black(A...Za...z0...9))) and the underscore $mtt(_) and not beginning by a digit)
immediatly follows the character $mtt($dollar). The operands
of the mark follow this name, and each one must be delimited by a pair of parentheses. For example, if you
want to render some text in dark red, you can write this, where $mtt(rgb) is the name of the mark (this mark takes two operands):$par
$mcenter($mtt($$rgb(120,0,0)(This text is rendered in dark red.)))
which produces this:
$mcenter($rgb(120,0,0)(This text is rendered in dark red.))
You shall learn below how to write $em(macros) in $MAML using the mark $ref(define)($mtt($$define)),
so that you can actually simplify the writing of the above. For example the name $MAML itself
is produced by the macro $mtt($$MAML) which is defined as follows:
$mcode($$define(MAML)(0) $$// defining the macro $$MAML taking zero operand
($$bold($$rgb(180,0,0)(M)$$rgb(0,120,0)(A)$$rgb(80,80,80)(M)$$rgb(0,0,220)(L))))
$subsection(linecomments)(Line comments)
Notice that you can put $em(line comments) into your $MAML source texts as follows:$p
$center($mtt($$// blah blah blah ...))$par
The mark $mtt($$//) and what follows until the end of the line are ignored by the compiler (but it keep
the new line charaters). This kind of comment can be
put everywhere, including within operands of marks, between the operands of a mark (as shown above) and between
a mark and its first operand.$p
$subsection(balanced)(Parentheses must be balanced)
Each mark accepts a fixed number of operands. Since each operand must be delimited by a pair of parentheses
(which are not part of the operand itself), the
parentheses which are part of the operand (if any) must be balanced, otherwise the $MAML parser will not find the closing
parenthese. Nevertheless, you can still include unbalanced parentheses in an operand provided that you write them
$mtt($$lpar) (left parenthese) and $mtt($$rpar) (right parenthese).$p
$subsection(marknamedelim)(How mark names are delimited)
Also remark that between any two operands of a mark (and between the mark itself and its first operand), you cannot
write anything else than $em(white) characters (i.e. spaces, line-feeds, carriage-returns and tabulators), and line
comments. For example,
$mcode($$rgb(0,0,255)(My text))
is equivalent to
$mcode($$rgb (0,0,255) $$// this make a bright blue
(My Text))
But if you write this: $mtt($$rgb(0,0,255) a (My text)), the compiler will complain that an operand is missing (it
also indicates the path of the file and the line number where this happens).
$par
$par
$em(Remark:) The name of a mark is right delimited by the first character which is not an acceptable character
for such a name. If this character is a space, it is $em(not) discarded (unlike what the $latex(\TeX) compiler
does). Hence for example,
$mtt($$lpar x) (with just one space between $mtt($$lpar) and $mtt(x))
produces $lpar x (with a space between the parenthese and x),
so that it seems that there is no way to obtain $id($lpar)x (with nothing between the parenthese and x).
Actually, there is a simple trick to
obtain the later. Indeed, it is enough to define an $em(identity) macro as follows:
$mcode($$define(id)(1)($$1))
and to write $mtt($$id($$lpar)x).$p
$subsection(definingmarks)(Defining new marks with $mtt($$define))
We already saw examples of use of $mtt($$define) above. It's now time to give precisions about this possibility to
enrich the language with new marks, which is one of the most powerful tools we have at hand.$p
The syntax of $mtt($$define) is as follows:$par
$mcenter($mtt($$define($argu(name))($argu(arity))($argu(value))))
where $argu(name) is the name you want to give to your new mark, $argu(arity) its $em(arity), i.e. the number of
operands it takes, and $argu(value) the value of the mark, which of course depends on the values of it's future operands, which
is the reason why $argu(value) contains so-called $MAML $em(variables) $mtt($$1), $mtt($$2), etc...$p
Notice that if a macro with the same name $argu(name) is already defined, $mtt($$define) does not destroy this
previous definition of $argu(name). It pushes the new definition on a stack of definitions associated to this name. As a
consequence, when you use $mtt($$undefine($argu(name))), the most recent definition of name is poped off this stack (and
forgotten) and the previous one prevails again. See $ref(undefine)($mtt($$undefine)) for some examples.$p
When the $MAML compiler encounters a $mtt($$define($argu(name))($argu(arity))($argu(value))), it doesn't evaluate
(i.e. it doesn't $em(compute)) $argu(name) nor $argu(arity). Consequently, these two operands must be written in their
definitive form.$p
The third operand $argu(value) is only $em(partly evaluated) in the sens that macros are expanded within $argu(value),
but primitive marks are not executed (which is in any case mandatory since operands are not yet known).
This policy has two important consequences:
$list(
$item if $argu(value) contains a call to $argu(name), this call doesn't refer to the macro currently being defined,
but to its previous definition (if any). As a byproduct, this also forbids recursive definitions of macros, so
protecting the $MAML compiler against infinite loops.$p
$item $argu(value) cannot refer to a macro which is not yet defined (there are no forward references in $MAML), so
that the macro always keeps the meaning it has when it is defined, except that the values provided by primitive marks
will be computed only when the macro is used.
)
Nevertheless, you may want, especially if you are defining a customizable style of document for example, to define
macros making use of other macros which can be redefined by the user of your style file. The solution is first of all
to define these other macros conditionally, i.e. as follows:
$mcode($$if($$defined($argu(name)))()($$define($argu(name))(...)(...)))
that is that you provide a $em(default) definition, but only in case your user did not define $argu(name). Of course, this
implies that your user must define $argu(name) $em(before) writing $mtt($$input($argu(your style file))).$p
$subsection(definewithindefine)($mtt($$define) within $mtt($$define))
You may wonder what happens if we write something like:
$mcode($$define(m1)(1)( ... $$define(m2)(1)(... $$1 ...) ... ))
Does this $mtt($$1) represent the operand of $mtt(m1) or the operand of $mtt(m2)$sp?$p
The answer is that it represents
the operand of $mtt(m1) and that the operand of $mtt(m2) is represented by $mtt($$2). More generally, if we have a
$mtt($$define) within a $mtt($$define), the names of the variables of the second (inner) $mtt($$define) are $em(shifted) by the
number of variables of the first (outer) $mtt($$define). As another example, in
$mcode($$define(m1)(2)
($tbgc($_pink)( $argu(zone 1) $$define(m2)(4)
($tbgc($_yellow)( $argu(zone 2) $$define(m3)(3)
($tbgc($_azure)( $argu(zone 3) ))
$argu(zone 2) ))
$argu(zone 1) )))
the valid variables are:
$list(
$item $mtt($$1) to $mtt($$2) in $argu(zone 1)
$item $mtt($$1) to $mtt($$6) in $argu(zone 2)
$item $mtt($$1) to $mtt($$9) in $argu(zone 3)
)
In other words, the variables of an inner $mtt($$define) do not hide the variables of an outer $mtt($$define).$p
As an example, consider the following $MAML code:
$mcode($$define()()($$define()()()))
$subsection(memorymarks)(Marks remember their birth environment)
When you define a new mark with $mtt($$define), you can include in the body of the definition a reference to a counter or to
an accumulator. For example, you can write:
$mcode($$pushcounter(n)(0)
$$define(count)(0)($$addtocounter(n)(1)$$countervalue(n)))
$pushcounter(n)(0)
$define(count)(0)($addtocounter(n)(1)$countervalue(n))
Then if you write $mtt($$count $$count $$count), you get $mtt($count $count $count).$p
Now, what if you write $mtt($$count $$count $$pushcounter(n)(7)$$count)$sp?
$count $count $pushcounter(n)(17)$count
$p
$/////////////////////////////////////////////////////////////////////////
$section(style)(Be stylish)
The primitive $MAML marks are rather basic, and should preferably be used for creating macros.
In other words, it's better to first define (using the $mtt($$define) mark) the concepts you will use in your
text, rather than writing them from scratch at each occurrence. In some sens, defining these concepts is the same as
creating your own style. $p
$subsection(basismaml)(The file $fname(basis.maml))
Notice that a file $fname(basis.maml) exists in $fname(library/doc_tools) which already contains macros of
common usage.
$p
$subsection(styleexample)(An example)
It can be the case that some concept of your discourse has to be emphasized in a particular way, and that
you (arbitrarily) chosed to print it
in red. You should not use $mtt($$rgb(255,0,0)(...)) in the text. You should better first give a name (say $mtt(emph)) to
your concept, and define it near the beginning of the text:
$p
$mtt($$define(emph)(1)($$rgb(255,0,0)($$1)))
$p
and write $mtt($$emph(...)) in the text instead of $mtt($$rgb(255,0,0)(...)).
$p
This will structure your text in a useful semantic way, instead of a non significant way, making it easier
to later update.
It also has the advantage that you can later easily change the layout of the text by modifying
only the values in these $mtt($$define).
$p
$subsection(inputstyle)(Inputting a style file)
The $mtt($$input) mark let you $em(input) a $MAML source at any point of another $MAML source. Hence, you should
define your style in a file (say $mtt(mystyle.maml)) and put an $mtt($$input(mystyle.maml)) after the first $mtt($$begin)
of your source file. Notice that the input file also needs to contain a $mtt($$begin) and an $mtt($$end).$p
$p
$section(tools)(Basic tools)
$MAML is $em(not a programming language). It is a $em(document formatting language). Nevertheless, it provides some
programming capabilities, but only those which are (to our opinion) required for the needs of the layout of the
document. Of course, this set of tools could be enlarged in the future.$p
$subsection(arithmetics)(Elementary arithmetics)
$MAML is able to perform some elementary arithmetic operations on numbers (which are all relative integers). These
operations are:
$list(
$item $box(200)($mtt($$add($argu(m))($argu(n)))) addition of $argu(m) and $argu(n)
$item $box(200)($mtt($$minus($argu(m))($argu(n)))) substraction of $argu(n) from $argu(m)
$item $box(200)($mtt($$opp($argu(m)))) opposite of $argu(m)
$item $box(200)($mtt($$mul($argu(m))($argu(n)))) multiplication of $argu(m) by $argu(n)
$item $box(200)($mtt($$quotient($argu(m))($argu(n)))) quotient of the euclidian division of $argu(m) by $argu(n)
$item $box(200)($mtt($$remainder($argu(m))($argu(n)))) remainder of the euclidian division of $argu(m) by $argu(n)
)
In case of a division by zero, an error message is generated.$p
$//////////////////////////////////////////////////////////////////////////////////
$subsection(booleans)(Booleans and control)
$MAML provides some rudimentary tools for better controling the $MAML compiler. $MAML recognizes the marks $mtt($$true) and
$mtt($$false) as $em(truth values) (aka. $em(booleans)). Other marks also produce booleans, such as
$mtt($$equals($argu(expr 1))($argu(expr 2))) and $mtt($$defined($argu(macro name))).$p
These truth values can be used as $argu(test) in:$p
$center($mtt($$if($argu(test))($argu(if true))($argu(if false))))$par
The value of the above mark is $argu(if true) if $argu(test) is true and $argu(if false) otherwise, and of course
only one of $argu(if true) and $argu(if false) is evaluated.$p
Notice that some logical operators can be defined:
$mcode($$define(and) (2) ($$if($$1)($$2)($$false))
$$define(or) (2) ($$if($$1)($$true)($$2))
$$define(neg) (1) ($$if($$1)($$false)($$true))
$$define(implies) (2) ($$or($$neg($$1))($$2)))
$/////////////////////////////////////////////////////////////////////////////
$subsection(counters)(Counters)
$MAML has a notion of $em(counter). You can create a counter with $mtt($$pushcounter($argu(name))($argu(init))), where
$argu(name) is the name of the new counter, and $argu(init) its initial value (which must be a positive, zero or
negative integer).$p
You can get the value of a counter with $mtt($$countervalue($argu(name))) (giving a character string representing
the value in decimal notation, possibly prefixed by a minus sign).
You can modify the value of a counter with $mtt($$setcounter($argu(name))($argu(value))) and
$mtt($$addtocounter($argu(name))($argu(value))).$p
You can destroy a counter with $mtt($$popcounter($argu(name))).$p
Actually, for each counter name, $MAML manages a stack of counters. Consequently, if you create a new counter with the
same name as an already existing counter, the first counter is not destroyed and
becomes visible again when the second counter is destroyed.$p
As an exemple, consider the following:
$mcode($$pushcounter(n)(0)
$$define(ga)(0)($$addtocounter(n)(1)$$countervalue(n)))
$pushcounter(n)(0)
$define(ga)(0)($addtocounter(n)(1)$countervalue(n))
If we write: $mtt($$ga $$ga $$ga $$ga $$ga $$ga $$ga $$ga $$ga $$ga $$ga $$ga $$ga), we get:$p
$center ($ga $ga $ga $ga $ga $ga $ga $ga $ga $ga $ga $ga $ga)
Continuing that way, we can write:
$mcode($$pushcounter(n)(25)
$$countervalue(n)
$$popcounter(n)
$$countervalue(n))
and we get:
$center(
$pushcounter(n)(25)
$countervalue(n)
$popcounter(n)
$countervalue(n))
(as expected).$p
$subsection(lists)(Lists)
$MAML has a notion of $em(list). In order to create a list (say with three elements $mtt(a), $mtt(b) and $mtt(c)),
you can write $mtt($[a$,b$,c$]). If you write this outside any $MAML operand, you get this:
$p
[a,b,c]
$p
In other words, the square brackets and the comma are just seen as ordinary (neutral) characters (and there is no list
at all in this case). On the contrary, if you write $mtt($$red($[a$,b$,c$])), you get this:
$p
$red([a,b,c])
$p
This is first of all because the square brackets and the comma are recognized as special characters within an operand
(so that we now have an actual list), and because the rendering of a list consists in rendering its element one after the
other without any separator between them. Nevertheless, if we want to render the above list in red with the brackets
and the commas, it is enough to write $mtt($$red($$$[a$$$,b$$$,c$$$])):
$p
$red($[a$,b$,c$])
$p
The square brackets and the comma, everywhere they are recognized as special characters $em(eat) the spaces on both
sides. This means that it is equivalent to write $mtt($$red($[a$,b$,c$])) and to write $mtt($$red( $[ a$, b $, c
$] )). However, be careful because an expression such as $mtt($$red($[a$,b$,c$])) is $em(not) a list
(because it is enclosed into $mtt($$red)) and triggers
an error if written at a place where a list is required.$p
List are useful because they can be manipulated by several primitive marks, such as:
$list(
$item $mtt($ref(reverse)($$reverse)($argu(list)))
$item $mtt($ref(sort)($$sort)($argu(list)))
$item $mtt($ref(length)($$length)($argu(list)))
$item $mtt($ref(sublist)($$sublist)($argu(start))($argu(end))($argu(list)))
$item $mtt($ref(apply)($$apply)($argu(mark name))($argu(list)))
$item $mtt($ref(transpose)($$transpose)($argu(list of lists)))
)
How these primitives marks operate is explained in the $ref(catalog)(catalog).$p
There are circumstances where we want the square brackets and the comma to be considered as ordinary (neutral)
characters. For example, it should be the case for the second operand of
$ref(code)($mtt($$code($argu(color))($argu(computer code)))), and also in some operands of some other primitives.
To simplify the matter and to offer the maximal number of possibilities, primitives such as $mtt($$code) don't care
about that. This is why we propose the primitive $ref(nolist)($mtt($$nolist($argu(text)))) which inhibits the
recognition of the squares brackets and the comma within $argu(text). Hence, $mtt($$code) should be used as follows:
$p
$center($mtt($$code($argu(color))($$nolist($argu(computer code)))))
$par
and you can define a macro for handling this.$p
As an example, consider the following list of words:
$mcode($$define(cities)(0)
($[New York$,Paris$,Berlin$,Moscow$,Casablanca$,Cairo$,Athens$,Rio de Janeiro$]))
$define(cities)(0)([New York,Paris,Berlin,Moscow,Casablanca,Cairo,Athens,Rio de Janeiro])
We can write:
$mcode($$pushcounter(n)(0)
$$define(number)(1)($$addtocounter(n)(1)$$box(20)($$countervalue(n).)$$1$$par)
$$define(a)(1)($$alphabetic($$1))
$$center($$apply(number)($$sort($$apply(a)($$cities)))))
which gives this:
$pushcounter(n)(0)
$define(number)(1)($addtocounter(n)(1)$box(20)($countervalue(n).)$1$par)
$define(a)(1)($alphabetic($1))
$center($apply(number)($sort($apply(a)($cities))))
$p
$subsection(loadadm)(Loading a library of Anubis functions)
It is possible to load a set of Anubis functions that will be automatically transformed into primitive marks. This is
done by the mark $mtt($$loadadm).$p
Such a library is a secondary Anubis module. This module must be generated as follows:
$code($_azure)(
global define MAML_Library
my_maml_library
=
...
)
This library can be loaded from within a $MAML text by $mtt($$loadadm(my_maml_library)). Immediately after this mark,
the new marks defined in the library are available.$p
The type $tt(MAML_Library) is defined in
$fname(doc_tools/maml_library_tools.anubis) together with other required types and some tools.
The type $tt(MAML_Library) is as follows:
$code($_azure)(
public type MAML_Library:
maml_library (List(MAML_Mark)).
)
and the type $tt(MAML_Mark) is as follows:
$code($_azure)(
public type MAML_Mark:
f0 (String name,
(MAML_Tools) -> MAML),
f1 (String name,
(MAML_Tools,MAML) -> MAML),
f2 (String name,
(MAML_Tools,MAML,MAML) -> MAML),
f3 (String name,
(MAML_Tools,MAML,MAML,MAML) -> MAML),
f4 (String name,
(MAML_Tools,MAML,MAML,MAML,MAML) -> MAML),
f5 (String name,
(MAML_Tools,MAML,MAML,MAML,MAML,MAML) -> MAML),
f6 (String name,
(MAML_Tools,MAML,MAML,MAML,MAML,MAML,MAML) -> MAML).
)
so that you can define new marks of all arities from $mtt(0) to $mtt(6). The file
$fname(maml_library_tools.anubis) contains several tools useful for programming $MAML primitives. For example, a
primitive for computing the length of list can be defined as follows:
$code($_azure)(
f1("length",
(MAML_Tools tbox, MAML m1) |->
if is_list(m1) is
{
failure then error(not_a_list(m1)),
success(l) then text(to_decimal(length(l)))
})
)
This produces a $MAML mark whose name is $mtt($$length) accepting a single operand, which must be a list.$p
The functions $tt(is_list) and $tt(not_a_list) are defined in $fname(maml_library_tools.anubis),
whereas $tt(to_decimal) and $tt(length) are standard functions of the Anubis library. The functions
$tt(error) and $tt(text) are the names of two alternatives of the type $tt(MAML). More detailed explanations are given
in $fname(maml_library_tools.anubis), and in the Anubis library documentation.
$p
$/////////////////////////////////////////////////////////////////////////////:
$section(colorize)(Automatic colorization)
$MAML has a simple system for automatic colorization of texts. Within a $MAML source text,
you can define one or several colorizers, and later apply them at will. Actually, by $em(colorization) we mean
something quite general, i.e. not dealing only with colors, as we shall see below.$p
$subsection(createcolorizer)(Creating a colorizer)
In order to create a colorizer, you must:
$list(
$item define one or several $italic(color rules),
$item when done, create the $italic(colorizer).
)
A color rule has the form:$par
$mcenter($mtt($$colorrule($argu(colorizer name))($argu(regular expression))($argu($MAML expression))))
The $argu(colorizer name) of the colorizer must be an ordinary symbol. The $argu(regular expression) must follow the syntax defined in
$fname(library/lexical_analysis/fast_lexer_5.anubis) (see the Anubis library documentation) and $em(is not evaluated), so
that it must be written in its definitive form.
The $argu($MAML expression) can contain the $MAML $em(variable)
$mtt($$1) which is replaced by the token (i.e. the character string recognized by the regular expression)
to be colorized.$par$par
Once the color rules are setup, you can create the colorizer as follows:$par
$mcenter($mtt($$colorizer($argu(colorizer name))))
Then, you can colorize a text:$par
$mcenter($mtt($$colorize($argu(colorizer name))($argu(text))))
$subsection(mycolorizer)(A colorizer example)
As an example, consider the following definition of a colorizer, which is used in this tutorial for colorizing
$MAML code:
$mcode( $$// line comments
$$colorrule(maml)(#$$#/#/.*)($$darkgreen($$1))
$$// mark names (including inhibited characters)
$$colorrule(maml)($black((#$$$[#$,#$[#$]#(#)$])|(#$$$[a-zA-Z#_$]$[0-9a-zA-Z#_$]*)|(#$$#$$)))
($$bold($$darkred($$1)))
$$// MAML variables
$$colorrule(maml)($black(#$$$[0-9$]+))($$magenta($$1))
$$// integers
$$colorrule(maml)($black($[0-9$]+))($$sienna($$1))
$$// creating the colorizer
$$colorizer(maml))
There are plenty of examples of use of this colorizer in this tutorial (including the above definition of the
$mtt(maml) colorizer$sp!), so that you can easily check that the result is coherent with the definition. Notice that
we added a $mtt($$black) around regular expressions above, which explains why digits are not colorized in these expressions.$p
We also used $mtt($$bold) in the above definition, which is not a color per se. Actually any mark can be used, so
that colorizers can also be used for a purpose having nothing to do with colors. Examples are comming below.$p
$subsection(colorizerprecedence)(Primitive marks and colorizers)
You also need to know what happens if the text to be colorized contains $MAML marks.
All macros are expanded before colorization applies, so that macros have no incidence on colorization, but they can be
used within a text to be colorized. $p
Things are different for primitive marks. Indeed, how do you interpret for example
$p
$center($mtt($$colorize(maml)($black(This is $$rgb(120,0,0)(an example) text.))))
$par
It should be clear that $tt($$rgb) in this example should
have precedence over $mtt($$colorize), otherwise it would be useless. So, the behavior of $MAML is that it doesn't
apply a colorizer within the operands of primitive marks (it would be nevertheless meaningless in the case of the operand
$tt(120,0,0) of $tt($$rgb)).$p
As a consequence, the above example gives
$colorize(maml)(This is $rgb(120,0,0)(an example) text.),
not $colorize(maml)(This is an example text.)$p
Nevertheless, you can still colorize within an operand within a text to be colorized. For example,
$p
$center($mtt($$tt($$colorize(maml)($black($$$$bold($$darkgreen($$$$red(text))))))))
$par
produces $tt($colorize(maml)($$bold($darkgreen($$red(text))))), whereas
$p
$center($mtt($$tt($$colorize(maml)($black($$$$bold($$darkgreen($$colorize(maml)($$$$red(text)))))))))
$par
produces $tt($colorize(maml)($$bold($darkgreen($colorize(maml)($$red(text)))))).$p
$subsection(severalcolorizers)(Using several colorizers together)
You can use several colorizers together. Below is another colorizer:
$mcode($$colorrule(funny)([a-e])($$rgb(10,0,130)($$sup($$1)))
$$colorrule(funny)([e-k])($$rgb(150,0,0)($$italic($$1)))
$$colorrule(funny)([l-p])($$rgb(100,100,0)($$big($$1)))
$$colorrule(funny)([p-z])($$rgb(0,100,100)($$sub($$big($$1))))
$$colorizer(funny))
$colorrule(funny)([a-e])($rgb(10,0,130)($sup($1)))
$colorrule(funny)([e-k])($rgb(150,0,0)($italic($1)))
$colorrule(funny)([l-p])($rgb(100,100,0)($big($1)))
$colorrule(funny)([p-z])($rgb(0,100,100)($sub($big($1))))
$colorizer(funny)
If you write:
$mcode($$tt($$colorize(maml)
($$$$bold(Some text $$colorize(funny)(with a piece of funny text) in it.))))
you get $tt($colorize(maml)($$bold(Some text $colorize(funny)(with a piece of funny text) in it.)))$p
$subsection(colorizercall)(Calling a colorizer from within a colorizer)
Using several colorizers together can also help to solve particular colorizing problems, because the above is not the
whole story about $MAML colorizers. Indeed, we have another primitive mark:
$p
$center($mtt($$colorizercall($argu(mode))($argu(colorizer1))($argu(call))($argu(colorizer2))($argu(return))))
$par
which allows to $em(call) a colorizer (here $mtt($argu(colorizer2))) from within another colorizer (here $mtt($argu(colorizer1))).
The operands $mtt($argu(call)) and $mtt($argu(return)), which can be any $MAML expressions expanding into regular expressions, are used
as $em(call) and $em(return) instructions. In other words, when $mtt($argu(colorizer1)) encounters something matching the
regular expression $mtt($argu(call)) it calls $mtt($argu(colorizer2)) which will return when it founds something matching the
regular expression $mtt($argu(return)).$p
The pieces of text matching $mtt($argu(call)) and $mtt($argu(return)) are colorized by $mtt($argu(colorizer1)) or by
$mtt($argu(colorizer2)), depending on the value of $argu(mode). There are four modes:
$list(
$item $mtt(ee) ($em(exclude-exclude)): both $argu(call) and $argu(return) are colorized by $argu(colorizer1),
$item $mtt(ei) ($em(exclude-include)): $argu(call) is colorized $argu(colorizer1) and $argu(return) by $argu(colorizer2),
$item $mtt(ie) ($em(include-exclude)): $argu(call) is colorized $argu(colorizer2) and $argu(return) by $argu(colorizer1),
$item $mtt(ii) ($em(include-include)): both $argu(call) and $argu(return) are colorized by $argu(colorizer2).
)
$subsection(colorcallexample)(A colorizer call example)
Consider the case of an Anubis source text, such as:
$ptext($code(255,255,255)($nolist(
A function for computing the length of a list:
public define Int
length
(
List($$T) l
) =
if l is
{
[ ] then 0,
[h . t] then 1 + length(t)
}.
Blah blah blah ...
)))
This example contains a $em(paragraph) defining a function, which is surrounded by so-called $em(off-paragraph
comments). In order to colorize this text we need to be able to detect the beginning and the end of Anubis paragraphs.
This is not possible if we use only color rules as defined by $mtt($$colorrule), but it becomes possible if we also use
$mtt($$colorizercall).$p
Indeed, we first define two colorizers, say $mtt(off) for off-paragraph comments and $mtt(in) for paragraphs.$p
In this example, we deliberately chosed to have a head of case of the form $ptext($nolist([h . t])) in the conditional,
because it also contains an $em(end dot) (a dot followed by a space or a linefeed) which must not be confused
with the end dot closing the paragraph.$p
In order to colorize the paragraph itself, we need something like:
$p
$center($mtt($$colorizercall(ii)(off)(#npublic)(in)(#.[# #r#n])))
$par
However, if we do that, the colorization of the paragraph will end at the end dot which is within the square brackets.
In order to avoid this, we must add another call:
$p
$center($mtt($$colorizercall(ii)(in)(#$[)(in)(#$])))
$par
(the sharp character, i.e. the escape character for regular expressions,
in front of the square brackets is necessary since square brackets are special characters
in regular expressions).
That way, the colorizer $mtt(in) will call itself when it reads an opening square bracket and return (to itself) when it reads the
corresponding closing square bracket.$p
However, with these two call rules, the colorization is still not correct because when the opening bracket of $mtt([h .
t]) is seen the colorizer $mtt(in) calls itself, and the second instance of $mtt(in) returns on the end dot so that the
first instance of $mtt(in) returns on the closing bracket, and the $mtt(off) colorizer is active again at this
closing bracket. The solution is to define two distinct $mtt(in) colorizers, as shown below.$par
$mcode($$colorrule(off)(.)($$darkgreen($$1))
$$colorrule(in1)(.)($$darkred($$1))
$$colorrule(in2)(.)($$rgb(0,100,100)($$1))
$$colorrule(in1)(#npublic[# #r#n]+define)($$tbgc(220,220,0)($$rgb(0,0,100)($$bold($$1))))
$$colorrule(in1)(#.[# #r#n])($$tbgc(220,220,0)($$rgb(0,0,100)($$bold($$1))))
$$colorizercall(ii)(off)(#npublic[# #r#n]+define)(in1)(#.[# #r#n])
$$colorizercall(ii)(in1)(#$[)(in2)(#$])
$$colorizercall(ii)(in2)(#$[)(in2)(#$])
$$colorizer(in1)
$$colorizer(in2)
$$colorizer(off))
$colorrule(off)(.)($darkgreen($1))
$colorrule(in1)(.)($darkred($1))
$colorrule(in2)(.)($rgb(0,100,100)($1))
$colorrule(in1)(#npublic[# #r#n]+define)($tbgc(220,220,0)($rgb(0,0,100)($bold($1))))
$colorrule(in1)(#.[# #r#n])($tbgc(220,220,0)($rgb(0,0,100)($bold($1))))
$colorizercall(ii)(off)(#npublic[# #r#n]+define)(in1)(#.[# #r#n])
$colorizercall(ii)(in1)(#[)(in2)(#])
$colorizercall(ii)(in2)(#[)(in2)(#])
$colorizer(in1)
$colorizer(in2)
$colorizer(off)
(we put a different color for $mtt(in1) and $mtt(in2) texts for showing where $mtt(in1) calls $mtt(in2) and where $mtt(in2)
returns).
Now, if we write $mtt($$code($$_ivory)($$colorize(off)($argu(the above example text)))), we get:
$code($_ivory)($colorize(off)($nolist(
A function for computing the length of a list:
public define Int
length
(
List($$T) l
) =
if l is
{
[ ] then 0,
[h . t] then 1 + length(t)
}.
Blah blah blah ...
)))
and more generally, this works for any depth of square brackets nesting.$p
$subsection(noncolor)(A non colorizing example.)
As said above, colorizers are more general than just a tool for colorizing text. For example, they can be used,
to some extent, for $em(parsing) a text.$p
Assume that we have a text which is in CSV (comma separated values) format. Such texts are very common since every
database system is able to export its tables in this format. Below is an example of such a datum.
$mcode($$define(mycsvtable)(0)
(Ford,Max,32,New York
Jackson,Niel,64,Los Angeles
Kennedy,Justin,25,New York
Obama,Barack,55,Washington
Smith,John,24,Baltimore
Trump,Donald,70,New York))
$define(mycsvtable)(0)
(Ford,Max,32,New York
Jackson,Niel,64,Los Angeles
Kennedy,Justin,25,New York
Obama,Barack,55,Washington
Smith,John,24,Baltimore
Trump,Donald,70,New York)
In this piece of text, the lines of the table are separated by linefeeds and the values in a line are separated by
commas. For simplicity, we assume that the values contain no comma and no linefeed. In a realistic situation, we would
have to enhance our example for handling (for example) commas which are within a pair of parentheses. This kind of
enhancement would require some $mtt($$colorizercall).$p
We define the following colorizer.
$mcode( $$// a counter for columns
$$pushcounter(col)(0)
$$// a counter for lines
$$pushcounter(line)(0)
$$// we count one column when we see a comma
$$colorrule(display)(#,)($$addtocounter(col)(1))
$$// we count one line and reset the column counter when we see a linefeed
$$// and at the same time we introduce some space and the line number on
$$// the left of the line
$$colorrule(display)(#n)
($$addtocounter(line)(1)$$par$$box(40)($$countervalue(line))$$setcounter(col)(0))
$$// detect values and colorize them differently depending on the column number
$$colorrule(display)($[^#n#$,$]*)($$if($$equals(2)($$countervalue(col)))
($$box(40)($$red($$1)))
($$if($$equals(0)($$countervalue(col)))
($$box(100)($$bold($$1)))
($$box(100)($$1))))
$$// create the colorizer
$$colorizer(display))
$pushcounter(col)(0)
$pushcounter(line)(0)
$colorrule(display)(#,)($addtocounter(col)(1))
$colorrule(display)(#n)($addtocounter(line)(1)$par$box(40)($countervalue(line))$setcounter(col)(0))
$colorrule(display)([^#n#,]*)($if($equals(2)($countervalue(col)))
($box(40)($red($1)))($if($equals(0)($countervalue(col)))($box(100)($bold($1)))($box(100)($1))))
$colorizer(display)
If we write
$mcode($$colorize(display)(
$$mycsvtable))
we obtain:
$par
$colorize(display)(
$mycsvtable)
$p
Notice that thanks to the counter $mtt(col), we can perform a different treatment on each column.
Also remark that the first line of
the table has a number in front of it because we added a linefeed in front of $mtt($$mycsvtable) within the second operand of
$mtt($$colorize).
$p
Now, we want to get this same text in the form of a list of lines, where each line is itself a list of values.
To this end, we define another $em(colorizer).
$mcode( $$// an accumulator for holding the final result
$$accumulator(table)
$$// an accumulator which is reinitialized at each line
$$accumulator(line)
$$// without the line below, the commas would appear on the page
$$colorrule(parsecsv)(#$,)()
$$// the role for recording a complete line
$$colorrule(parsecsv)(#n)($$append(table)($$content(line))$$accumulator(line))
$$// the rule for recording a value
$$colorrule(parsecsv)($[^#n#$,$]+)($$append(line)($$1))
$$// make the colorizer
$$colorizer(parsecsv)
$$// and compute our list of lists
$$colorize(parsecsv)($$mycsvtable
))
$accumulator(table)
$accumulator(line)
$colorrule(parsecsv)(#,)()
$colorrule(parsecsv)(#n)($append(table)($content(line))$accumulator(line))
$colorrule(parsecsv)([^#n#,]+)($append(line)($1))
$colorizer(parsecsv)
$colorize(parsecsv)($mycsvtable
)
Despite the fact that we wrote $mtt($$colorize), this doesn't produce any output because
the regular expressions capture everything in the text and the values in the color
rules contain only marks which produce side effects but no output.$p
So, we expect that the accumulator $mtt(table) contains our list of lists.
To check that, we define:
$mcode($$define(putbox)(1)($$tbgc($$_azure)($$box(75)($$1)) )
$$define(putpar)(1)($$apply(putbox)($$1)$$par))
$define(putbox)(1)($tbgc($_azure)($box(75)($1)) )
$define(putpar)(1)($apply(putbox)($1)$par)
and write $mtt($$apply(putpar)($$content(table))), which produces
$p
$apply(putpar)($content(table))
$par
and $mtt($$apply(putpar)($$transpose($$content(table)))), which produces
$p
$apply(putpar)($transpose($content(table)))
$par
This last manipulation makes even more obvious the fact that we actually got our table in the form of
a list of lists.
$p
$///////////////////////////////////////////////////////////////////////////////////////////
$section(tips)(Tips and tricks)
If your text needs to display some computer code, it can be the case (depending on the programming language)
that this code uses dollar characters. This is the case of Anubis for example, since dollars are used by
type parameters. These dollars can make a problem since the dollar is also the escape character of $MAML.$par$par
You can of course double the dollars in the computer text examples, but there are situations where we don't want to
do this, or just cannot do this. This is the case for example in the Anubis library, since some files are at the
same time $MAML files (compilable by $MAML), and Anubis file (compilable by $mtt(anubis)). In this case, we cannot
change anything to the text, and in particular, we cannot double the dollars. $par$par
A solution, assuming for example that there are two type parameters $mtt($$T) and $mtt($$U) in the Anubis text, is to
define two macros:
$mcode($$define(T)(0)($$$$T)
$$define(U)(0)($$$$U))
so that the $MAML compiler will not be disturbed by these type parameters, which is rendered correctly.
Since this doesn't change anything in the
Anubis text itself (the above $mtt($$define) should be outside any Anubis paragraph), this doesn't change anything from the point
of view of the Anubis compiler. This trick can of course be applied to other programming languages.$p
$subsection(guidelinesweb)(Guidelines for using $MAML on the web)
Using $MAML on the web requires some care in order not to put your web server into an unsecure situation.$p
Using $MAML on the web means allowing your web users to write
$MAML texts within a JavaScript text editor or within a $tt(<textarea>) HTML object for example. When the web user
clicks on the $bold(submit) button (or whatever plays this role), a piece of $MAML text arrives on the server. It would
be dangerous to compile it directly because the web user could for example get confidential files by using $mtt($$input)
or put viruses on your server by using $mtt($$output), and probably destroy your server by many other means.$p
This is the reason why the incoming text must be wrapped into another $MAML text before being submitted to the $MAML
compiler. We have adopted a very simple and flexible way of insuring your web server security as far as $MAML is
concerned. Indeed, we have the primitive mark $mtt($$noprimitive) which forbids the direct use of a primitive mark
(except $ref(noprimitive)(a small number of them) which are not dangerous) for
the rest of the text. Hence, if you append $mtt($$noprimitive) in front of the incomming text, any call to a primitive in
this text is rejected. Notice that the marks comming from a library loaded by $mtt($$loadadm) are still allowed
after $mtt($$noprimitive), so that you should not load any library containing some dangerous stuff. If you want to
forbid the marks from the libraries as well, use $mtt($$nolibrary). The marks comming from the libraries can then only
be used through your macros, just as what happens for primitives.$p
Nevertheless, $MAML can't do much without using primitives (and possibly library marks),
but it will use them only though the macros you define
yourself in the preambule of the wrapper text, and of course before $mtt($$noprimitive) and $mtt($$nolibrary),
otherwise your macros
could not do much. Now, its up to you to define the
macros your web users are allowed to write down. Depending on how you do that, your server is more or less in danger.
For example if you define:
$mcode($$define(out)(2)($$output($$1)($$2)))
your web users will be able to use $mtt($$output). Hence, you must $em(filter) the use of primitives with your macros.
For example, if you want to give access to a (probably registered) user to a personal directory, you can provide macros
such as:
$mcode( $$// define an error message
$$define(msg)(0)(Only letters, digits and underscore allowed in file names)
$$// create a colorizer for restricting the usage of file names
$$colorrule(checkfilename)([a-zA-Z0-9_]+)($$1)
$$// forbid anything else
$$colorrule(checkfilename)(.)($$error($$msg))
$$colorrule(checkfilename)(#n)($$error($$msg))
$$colorizer(checkfilename)
$$// define two macros for your web users
$$define(output)(2)($$output($argu(userpath)/$$colorize(checkfilename)($$1))($$2))
$$define(input)(1)($$input($argu(userpath)/$$colorize(checkfilename)($$1))))
Of course, $argu(userpath) is a path that you generate on the fly when you create the wrapper text
for your web user.$p
Be sure that you prefectly understand the meaning of regular expressions before doing this. For example, if you allow
the dot in file names, the web user could write two consecutive dots in a file name, which means the parent directory,
and so on.
$p
Designing a safe set of macros for the web is not as easy as it may seem. We have one such paranoid
set already defined in $fname(doc_tools/maml_web_macros.maml).$p
$subsection(commonerrors)(Common errors)
Below are most of the errors the author made himself during the writting of this tutorial, plus some errors he did not
make but which are likely to happen.
$list(
$item Thinking that $mtt($$tbgc($$_red)($$box(100)())) produces a red rectangle of the given width
(with no text at all into it).
This actually produces a white rectangle. In order
to get this red rectangle, you need to write $mtt($$tbgc($$_red)($$box(100)($$sp))) (recall that $mtt($$sp) is
the so-called $em(non breakable space)).$p
$item Using $mtt($$blahblah) instead of $mtt($$$$blahblah), i.e. forgetting to double the dollar when we want to render a dollar
character (or the contrary).$p
$item Writing $tt(#$$//.*) instead of $tt(#$$#/#/.*) as a regular expression in order to colorize $MAML line comments.
Of course, the first form $em(is seen) as the beginning of a line comment, and the final result is quite surprising.$p
$item Forgetting to shift variable names in case of a $mtt($$define) within a $mtt($$define).
)
$/////////////////////////////////////////////////////////////////////////////////
$section(toolsbasis)(Tools available in $fname(basis.maml))
This $MAML file provides some tools of common usage. In order to use these tools, you must write
$center($mtt($$input(basis.maml)))$par
after the first $mtt($$begin), but some tools require that you define a macro before this $mtt($$input).$p
Some of the macros defined in this file can be redefined easily from within your source text. If this is not enough for
your needs, you still have the possibility to use a customized copy of $fname(basis.maml).$p
$subsection(colors)(Colors)
The file $fname(basis.maml) provides a small selection of colors in the form of macros taking zero operand. These macros are to be used
within the first operand of $mtt($$rgb), $mtt($$code) and $mtt($$tbgc), i.e. at a place where a color value in the
form $mtt(r,g,b) is expected.$p
$pushcounter(colorcnt)(0)
$define(sc)(2)($box(20)()$box(100)($$_$1)$tbgc($2)($sp$sp$sp$sp$sp$sp$sp$sp$sp$sp)$box(20)()$//
$if($equals(2)($countervalue(colorcnt)))($setcounter(colorcnt)(0)$par)($addtocounter(colorcnt)(1)))
$sc(azure)($_azure)
$sc(black)($_black)
$sc(blue)($_blue)
$sc(caramel)($_caramel)
$sc(chocolate)($_chocolate)
$sc(cyan)($_cyan)
$sc(darkgreen)($_darkgreen)
$sc(gold)($_gold)
$sc(green)($_green)
$sc(grey)($_grey)
$sc(ivory)($_ivory)
$sc(lavender)($_lavender)
$sc(magenta)($_magenta)
$sc(navy)($_navy)
$sc(orange)($_orange)
$sc(pink)($_pink)
$sc(purple)($_purple)
$sc(red)($_red)
$sc(darkred)($_darkred)
$sc(salmon)($_salmon)
$sc(sienna)($_sienna)
$sc(turquoise)($_turquoise)
$sc(white)($_white)
$sc(yellow)($_yellow)
$undefine(sc)
$p
The file also provide macros with the same name, but without the leading underscore,
taking one operand for directly colorizing texts. For example $mtt($$red(...)) is
equivalent to $mtt($$rgb($$_red)(...)).$p
$subsection(stylearticle)(The style $mtt(article))
This $em(style) provides definitions for the marks $mtt($$section), $mtt($$subsection) and $mtt($$subsubsection) (which
are not primitive marks), and also defines a mark $mtt($$tableofcontents).$p
$subsubsection(_)(How to use it)
In order to use this style, you must write:$p
$center($mtt($$define(article)(0)()))$par
$em(before) $mtt($$input(basis.maml)), because the style is conditionned by a $mtt($$if($$defined(article))...)
within $fname(basis.maml).$p
The marks $mtt($$section), $mtt($$subsection) and $mtt($$subsubsection) take two operands. The first one must be a
symbol
which is the symbolic name you want to give to the section (it is used
for generating internal links, but you can also refer to the section with a $ref(ref)($mtt($$ref(...)(...)))).
The second one is the title of the section.$p
The mark
$mtt($$tableofcontents) produces a table of contents and can be written anywhere because it contains a
$ref(postpone)($mtt($$postpone)),
so that it provides a complete table of contents regardless of its position in your source text.$p
$subsubsection(_)(Customizing $mtt(article))
The lines of the table of contents are displayed by the marks $mtt($$tocsec),
$mtt($$tocsubsec) and $mtt($$tocsubsubsec). If you are not satisfied with the layout provided by these marks, you can
define your own versions, provided that you write your definitions $em(before) $mtt($$input(basis.maml)). These marks take only one
operand which is the line to be displayed. For example, you can define:$par
$mcenter($mtt($$define(tocsec)(1)($$par$$bold($$1)$$par)))
This will replace the default definition provided by $fname(basis.maml). This may be useful for example to redefine
$mtt($$tocsubsubsec) if you have
subsubsections in your text and don't want them to appear in the table of contents.$p
The same is true for the marks $mtt($$seclayout), $mtt($$subseclayout) and $mtt($$subsubseclayout), which define the
layout of the section titles themselves. These marks take one operand which is the title itself.$p
$subsection(book)(The style $mtt(book))
This style is the same as article, except that it also has a notion of chapter. Hence, it also defines the mark
$mtt($$chapter($argu(symbolic name))($argu(title))), and you can redefine the marks
$mtt($$tocchap($argu(title))) and $mtt($$chaplayout($argu(title))).$p
$////////////////////////////////////////////////////////////////////////////:
$section(catalog)(The catalog of $MAML marks)
Below is a description of the $postpone($countervalue(markcount)) primitive $MAML marks.$p
$// Produce a table of contents on 4 columns for the catalog
$define(putboxmark)(1)($box(130)($ref($1)($mtt($$$1))))
$define(displaymarkgroup)(1)($apply(putboxmark)($1)$par)
$postpone($center($apply(displaymarkgroup)($transpose($groupby
($if($equals(0)($remainder($countervalue(markcount))(4)))
($quotient($countervalue(markcount))(4))
($add(1)($quotient($countervalue(markcount))(4))))($content(tabmark))))))
$mark1(accumulator)(name)
This mark creates a $em(variable) named $argu(name) called an $em(accumulator).
The content of an accumulator is always a list, and this list is empty when the accumulator is created. With the mark
$mtt($$append), you can add content to the accumulator. Each use of $mtt($$append) adds an element to the end of the list
contained in the accumulator. At any time, you can get the content of the accumulator with $mtt($$content).$p
An accumulator cannot be destroyed, but it can be reinitialized. Indeed, $mtt($$accumulator($argu(name))) empties the
accumulator if it already exists, and puts the empty list in it. Unlike counters and macros, there is no stack associated to an
accumulator name. For example:
$mcode($$accumulator(acc)
$$append(acc)(A)
$$append(acc)(B)
$$content(acc)
$$par
$$accumulator(acc)
$$append(acc)(C)
$$content(acc))
produces:
$p
$accumulator(acc)
$append(acc)(A)
$append(acc)(B)
$content(acc)
$par
$accumulator(acc)
$append(acc)(C)
$content(acc)
$p
Accumulators can be used in conjunction with $ref(postpone)($mtt($$postpone)) for constructing
tables of content and indexes.
See also $ref(append)($mtt($$append)) and $ref(content)($mtt($$content)).
$mark2(addtocounter)(name)(value)
This marks adds $argu(value) to the most recent instance of the counter whose name is $argu(name).
$mark2(append)(name)(text)
This mark appends $argu(text) at the end of the content of the $ref(accumulator)(accumulator) $argu(name). More
precisely, since the content of an accumulator is a list, the new content of the accumulator is the list obtained
by adding $argu(text) as the last element of this list.
See also $ref(accumulator)($mtt($$accumulator)) and $ref(content)($mtt($$content)).
$mark2(apply)(name)(list)
This mark applies the macro whose name is $argu(name) to all elements of the list $argu(list). This creates a new list
of the same length. If $argu(list) is not a list, the result is the same as if it was a one element list.$p
Notice that the first operand is the name of the macro to applied, but $em(without the leading $mtt($$)). In other words, this
operand is not the macro to apply but only its name. The corresponding macro must take just one operand. If not, an
error message is generated.$p
Furthermore, the macro to be applied must take a unique operand, and notice that $argu(name) cannot be the name of
a primitive mark. It $em(must) be the name of a macro. Hence, if you want to apply a primitive mark, you must first
define an equivalent macro.$p
As an example, consider the following:
$mcode($$define(mylist)(0)($[a$,b$,c$,d$])
$$mylist$$par
$$define(a)(1)(<$$red($$1)>)
$$apply(a)($$mylist))
which produces:$p
$define(mylist)(0)([a,b,c,d])
$mylist$par
$define(a)(1)(<$red($1)>)
$apply(a)($mylist)
$p
See also $ref(box)($mtt($$box)) for a more sophisticated example.
$mark0(begin) This mark is looked for by $MAML before it parses anything (even within a file refered to by
$mtt($$input)). When $mtt($$begin) is found, $MAML parses the text until it
encounters the mark $mtt($$end). After this mark, $MAML continues ignoring everything until the next $mtt($$begin),
etc... $par$par
Notice that this mecanism can also be used for inserting a comment:
$mcode($$end
... your comment ...
$$begin)
$mark1(big)(text) Prints its operand $argu(text) bigger. This mark can be nested. For example,
$list(
$item $box(200)($mtt($$big(text))) produces $big(text)
$item $box(200)($mtt($$big($$big(text)))) produces $big($big(text))
$item $box(200)($mtt($$big($$big($$big(text))))) produces $big($big($big(text)))
)
$mark1(bold)(text) The operand is rendered in $bold(bold).
$mark2(box)(width)(text) This mark puts $argu(text) into an invisible box of width $argu(width). The text is left aligned
within the box. This mark can be used for simulating tabulators. For example,
$mcode($$define(tableline)(4)($$box(50)($$1) $$box(50)($$2) $$box(30)($$red($$3)) $$4 $$par)
$$tableline(Smith)(John)(24)(Baltimore)
$$tableline(Ford) (Max) (32)(New York))
produces:$par$par
$define(tableline)(4)($box(50)($1) $box(50)($2) $box(30)($red($3)) $4 $par)
$tableline(Smith)(John)(24)(Baltimore)
$tableline(Ford) (Max) (32)(New York)
$par
$label(colortableexample)
As an example, here is something more sophisticated. We construct a table similar to the table above,
but we want it to be automatically sorted by the last names (first column) and to be in pajama stripes,
in other words, so that odd numbered lines
are shown on a different background color than even numbered lines. It is clear that the background color
cannot be decided before the list is sorted, so that, after the list is sorted, we have to apply a macro
to each element of the list. This is why we need to use the primitive mark $ref(apply)($mtt($$apply)).
$mcode( $$// we first create a counter that we use as a flag
$$// (taking the values 0 and 1 only)
$$pushcounter(flag)(0)
$$// we define a color depending on the value of the flag
$$// and flipflopping the flag at each use
$$define(linecolor)(0)
($$if($$equals(0)($$countervalue(flag)))
($$setcounter(flag)(1)$$_lavender)
($$setcounter(flag)(0)$$_ivory))
$$// define the layout of a line of the table, and put an '$$alphabetic' in order
$$// to tell MAML how to sort lines
$$define(tableline)(4)
($$box(80)($$alphabetic($$1))$$box(80)($$2)$$box(50)($$red($$3))$$box(80)($$4)$$par)
$$// define a macro for putting a backgroud color behind a line
$$define(putbg)(1)($$tbgc($$linecolor)($$1))
$$// sort the lines and apply this macro to each line
$$center($$apply(putbg)($$sort(
$[$$tableline(Smith)(John)(24)(Baltimore)$,
$$tableline(Ford) (Max) (32)(New York)$,
$$tableline(Jackson)(Niel)(64)(Los Angeles)$,
$$tableline(Kennedy) (Justin) (25)(New York)$,
$$tableline(Trump)(Donald)(70)(New York)$,
$$tableline(Obama) (Barack)(55)(Washington)$]
))))
$pushcounter(flag)(0)
$define(linecolor)(0)($if($equals(0)($countervalue(flag)))($setcounter(flag)(1)$_lavender)($setcounter(flag)(0)$_ivory))
$define(tableline)(4)($box(80)($alphabetic($1))$box(80)($2)$box(50)($red($3))$box(80)($4)$par)
$define(putbg)(1)($tbgc($linecolor)($1))
$center($apply(putbg)($sort(
[$tableline(Smith)(John)(24)(Baltimore),
$tableline(Ford) (Max) (32)(New York),
$tableline(Jackson)(Niel)(64)(Los Angeles),
$tableline(Kennedy) (Justin) (25)(New York),
$tableline(Trump)(Donald)(70)(New York),
$tableline(Obama) (Barack)(55)(Washington)])))
$p
The macro $mtt($$pajamatable) defined in $fname(basis.maml) realises such a table and accepts the data in the form of a
list of lists.
$mark1(center)(text) This mark horizontally centers the $argu(text) in the page. For example,
$mtt($$center(centered text)) produces:$par
$mcenter(centered text)
$mark2(code)(background color)(text) This marks is for writing computer code.
The $argu(text) operand is formated using a fixed width
(typewriter) font, spaces and newlines are taken into account, so that the result has essentially the same layout as the
original. Nevertheless, $MAML marks are allowed within $argu(text), but some of them, such as $mtt($$list),
can produce incoherent results. For example,
$par
$mcode($$define(T)(0)($$$$T) $$// so that MAML is not troubled by $$T
$$code($$_lavender)($$nolist($black(
define Int
length
(
List($$T) l
) =
if l is
{
[ ] then 0, // the list is empty
[h . t] then 1+length(t)
}.)
$$undefine(T))))
produces:
$define(T)(0)($$T)
$code($_lavender)($nolist(define Int
length
(
List($T) l
) =
if l is
{
[ ] then 0, // the list is empty
[h . t] then 1+length(t)
}.))
$undefine(T)
(You can also use a $ref(colorize)(colorizer) for colorizing the code.)
$par$par
See also $ref(tt)($mtt($$tt(...))) and $ref(verbatim)($mtt($$verbatim(...)))
$mark2(colorize)(name)(text) See $ref(colorize)(Automatic colorization).
$mark1(colorizer)(name) See $ref(colorize)(Automatic colorization).
$mark4(colorizercall)(name)(regexpr)(name)(regexpr) See $ref(colorize)(Automatic colorization).
$mark3(colorrule)(name)(regexpr)(text) See $ref(colorize)(Automatic colorization).
$mark1(content)(name)
The value of this mark is the content of the $ref(accumulator)(accumulator) $argu(name). Recall that this content
is a list. See also $ref(accumulator)($mtt($$accumulator)) and $ref(append)($mtt($$append)).
$mark1(countervalue)(name)
This mark produces the value of the counter $argu(name) in decimal notation. See $ref(counters)(Counters).
$mark3(define)(name)(number of operands)(value)
This mark let you define new marks (i.e. $em(macros)). It takes three operands. The first operand $argu(name)
is the name of the new mark. If it is
already in use, the new definition masks the previous one until you use an $ref(undefine)($mtt($$undefine($argu(name)))).
The name must be made only of letters $mtt(A...Z) and $mtt(a...z), decimal digits $mtt(0...9) and
the underscore character, and must
not begin by a digit. The second operand $argu(number of operands) is the number of operands your new mark will accept.
It must
be a positive or zero integer. The last operand $argu(value) is the value of the mark. This is a $MAML text, and it can
contain marks of the form $mtt($$1), $mtt($$2), $mtt($$3), ... (called $MAML $em(variables)) which represent the operands
of the mark, and which will later be replaced by the actual operands when the mark is used in the text.$p
$mtt($$define) doesn't allow to define recursive macros. Nevertheless,
see $ref(undefine)($mtt($$undefine)) where more explanations are given on the behavior of $mtt($$define).
$mark1(defined)(name)
This mark has a boolean value which is $em(true) if a macro is defined with name $argu(name) and $em(false)
otherwise.
$mark0(end) This mark indicates that the $MAML compiler should stop parsing until the next $mtt($$begin) (or the end
of file). See $ref(begin)($mtt($$begin)).
$mark2(equals)(expr 1)(expr 2)
This mark has a boolean value which is $em(true) if $argu(expr 1) and $argu(expr 2) are equal. By $em(equal), we
mean identical after $argu(expr 1) and $argu(expr 2) are computed.
$mark1(error)(text)
This mark produces an error message. This is useful when you write macros whose operands must satisfy a particular
property. The operand $argu(text) is the text of the message. This text can contain the $MAML mark $mtt($$position)
(taking no operand)
which will be replaced by the position (file path + line number + column number) in the source text where your macro
is used.
$mark0(false) This mark represents the truth value $em(false).
$mark2(groupby)(n)(list)
This mark accepts a positive non zero integer $argu(n) as its first operand and a list $argu(list)
as its second operand. The result is a
list of lists, where all lists, except possibly the last one, have length $argu(n). For example,
$mcode($$define(putbox)(1)($$box(20)(($$1)))
$$define(putpar)(1)($$1$$par)
$$apply(putpar)($$groupby(4)($$apply(putbox)($nolist([a,b,c,d,e,f,g,h,i,j])))))
produces:$p
$define(putbox)(1)($box(20)(($1)))
$define(putpar)(1)($1$par)
$apply(putpar)($groupby(4)($apply(putbox)([a,b,c,d,e,f,g,h,i,j])))
$p
$em(Remark): This is typically used for displaying a list of items on several columns. In this case, we also have to
$ref(transpose)(transpose) the list since the actual flow of rendering is by lines, not by columns. But then, the number
to be given as the first operand of $mtt($$groupby) is not so obvious. Indeed, if the length of the list is divisible by
the wanted number of columns, the quotient is the right answer, but if not, we must add $mtt(1) to this quotient,
otherwise we shall have one column too many.
$mark3(if)(test)(if true)(if false)
This mark represents $argu(if true) if $argu(test) is true, and $argu(if false) otherwise. Only one of
$argu(if true) and $argu(if false) is evaluated.
$mark1(ifhtml)(text) The operand $argu(text) is present in the HTML output, but not in the $LaTeX nor in the PDF
output.
$mark1(ifpdf)(text) The operand $argu(text) is present in the $LaTeX and in the PDF
output, but not in the HTML output.
$mark2(image)(width)(file path)
This mark inserts an image in the text. The operand $argu(width) is the width the image will have
when displayed (in pixels in the case of HTML, and points in the case of $LaTeX), and $argu(file path) is the path of the file
containing the image. For example,
$mcode($$center($$image($$ifpdf(100)$$ifhtml(200))($$id($$thisfilepath)/cows.jpg)))
produces:
$mcenter($image($ifpdf(100)$ifhtml(200))($id($thisfilepath)/cows.jpg))
Remark the presence of $mtt($$id($$thisfilepath)/) before the name of the file (which is here assumed to be
in the same directory as the maml file containing the above expression). The mark $mtt($$thisfilepath) gives
the absolute path of the file it is written into. Also, because we need to glue this path to the name of the image
file, we use the macro $mtt($$id) defined by $mtt($$define(id)(1)($$1)). $p
At the same time, you remark that the width of the image doesn't need to be given lexically and
can be computed using $MAML marks.
$mark1(input)(file name)
This mark let you insert the content of another $MAML file. This other file could for example contain your own $MAML
macros.$par$par
Notice that the input file also needs to have a $mtt($$begin) and an $mtt($$end).
In other words, when told to read another file by
$mtt($$input) the $MAML compiler ignores everything in this other file until it finds a $mtt($$begin).
$par$par
This mark can be $unsafe on the web, except if you filter the operand. See the Anubis library documentation.
$mark1(italic)(text) Prints its operand $argu(text) in $italic(italic).
$mark0(item) Marks the begining of an $em(item) within a $ref(list)($mtt($$list))
$mark1(label)(tag) This mark defines a $em(label) in the text, in other words, a position where to jump.
This is to be used in conjunction with $ref(ref)($mtt($$ref)).
$mark1(latex)(formula) This mark allows to include math formulas to be formated by $LaTeX.
For example,
$mcenter($mcode($$latex($dollar$$\int_0^\infty\frac{dx}{1+x^2}$dollar$dollar)))
is rendered as:
$latex($$\int_0^\infty\frac{dx}{1+x^2}$$)
This mark should not be used for big pieces of $LaTeX
text. It is mainly intended for math formulas, especially for HTML output where the formula is rendered
as a PNG image with transparent background.
$par$par
You can use $mtt($$latex) in the text. The result is correctly aligned with the text. For example,$par
$mcenter($mcode(the polynomial $$latex($black($$X^2+X+1$$)) is of degree 2))
is rendered as:
$mcenter(the polynomial $latex($X^2+X+1$) is of degree 2)
Unfortunatly, $latex(\TeX) is $unsafe as explained in $tlink(this document)(http://cseweb.ucsd.edu/~hovav/dist/texhack.pdf).
Hence, you should forbid this mark for a web usage, except if you add a filter in order to reject all $LaTeX
commands which don't belong to a given list of safe commands. This list doesn't need to be very long since the
$mtt($$latex) mark is mainly used for inserting math formulas. See the Anubis library documentation to learn how
to install this list of safe $LaTeX commands.
$mark1(length)(list)
This mark returns the number of elements in its operand which is supposed to be a list. If the operand is not a list,
the result is $mtt(1) if the operand is not empty (i.e. if it contains at least one character), and $mtt(0) if it is
empty.
$mark1(list)(items) This mark allows to create a list (not in the sens of $MAML $ref(lists)(lists),
but as a sequence of indented items in the output).
The operand $argu(items) must be a sequence of $em(items),
i.e. texts which are all prefixed by the mark $ref(item)($mtt($$item)).$par$par
Example:
$mcode($$list(
$$item Boys: $$list( $$item John $$item Max)
$$item Girls: $$list($$item Julie $$item Geraldine $$item Sophia)))
produces:
$list(
$item Boys: $list( $item John $item Max)
$item Girls: $list($item Julie $item Geraldine $item Sophia))
$mark1(loadadm)(module name)
This mark loads the secondary Anubis module whose path is given. The Anubis type of this module must be
$tt(MAML_Library) as explained in the section $ref(loadadm)(Loading a library of Anubis functions).$p
Of course, this results in an error if the module is either not found, of another type, compiled with another version
of Anubis, etc... If the loading succeeds the Anubis functions defined in the library become automatically new $MAML
marks.
$mark0(lpar) This mark inserts a left (opening) parenthese into the text. You must use $mtt($$lpar) and/or
$mtt($$rpar) (or alternatively $mtt($$$() and $mtt($$$))) if you want to introduce unbalanced parentheses
within an operand of a mark.
$mark2(mailto)(address)(text) This marks, which appears as $argu(text),
creates a link which is supposed, in the HTML case, to open your mail agent in order to let you
send an email to the indicated $argu(address). In the PDF case, the $argu(address) is just indicated between parentheses
beside $argu(text).
For example,$par
$mcenter($mtt($$blue($$mailto(XZ32@planet.mars)(the martian)))) produces:
$blue($mailto(XZ32@planet.mars)(the martian))$ifhtml( (you can try it)).
$mark1(nolist)(text)
This mark inhibits the recognition of the square brackets and the comma as list delimitors within $argu(text). See
$ref(lists)(Lists).
$mark0(noprimitive)
This mark disables the use of all primitive marks until the end of the document, except for the marks
$mtt($$alphabetic), $mtt($$colorize), $mtt($$define), $mtt($$if) and $mtt($$undefine). Hence, after $mtt($$noprimitive),
only the
macros, the marks listed above and the marks coming from a library via
$mtt($$loadadm) are allowed. This can be used for securing the usage of $MAML by web users,
since the macros you define before $mtt($$noprimitive) can filter their operands. See
$ref(guidelinesweb)(the guidelines for the web).
$mark1(note)(text) This mark produces a footnote containing $argu(text).
In the case of $LaTeX/PDF this is a usual
footnote.$ifpdf($note(Like this one.)) In the case of HTML, this is a popup which appears at the bottom of the browser's window when the mouse
passes over this indication : $ifhtml($note(Here is the note !))$ifpdf(($sup(note))).$ifhtml( Try it !)
$mark2(nth)(n)(list)
This mark extracts the $argu(n)$sup(th) element of the list $argu(list). It generates an error if this element doesn't
exist. Numbering begins at zero.
$mark2(output)(file path)(text) This mark does not produce anything in the resulting HTML or PDF files, but outputs
$argu(text) (without any modification) into the file $argu(file path).
$par
$par
$mtt($$output) can be very $unsafe for the web. In any case it is not very useful on the web because web pages offer
other ways of uploading files. So, the best is just to forbid it.
$mark0(par) This marks generates a line break. You can use several $mtt($$par) in order to make some
vertical space in your text.
$par$par
$em(Warning:) The MAML parser doesn't take newline characters into account (they are just read as spaces). Hence,
using $mtt($$par) is often necessary. You can also define a macro inserting several such newlines. For example:
$mcode($$define(p)(0)($$par$$par))
$mark1(popcounter)(name)
This mark destroys the most recent counter whose name is $argu(name).
$mark1(postpone)(text)
The $MAML text $argu(text) is evaluated only after the entire $MAML source is parsed and evaluated (including the
sources obtained via $mtt($$input)).
On the contrary, everything not within a $mtt($$postpone) is
evaluated at the moment it is parsed. The mark $mtt($$postpone) is typically used in conjunction with $mtt($$accumulator),
$mtt($$append) and $mtt($$content) for creating a table of contents at the beginning of a document. This is how
the table of contents at the beginning of this tutorial was made.$p
As another easy example, the sentence $em(Below is a description of the $postpone($countervalue(markcount))
primitive $MAML marks.) that you can find just after the section title $ref(catalog)(The catalog of $MAML marks) contains a
$mtt($$postpone($$countervalue(markcount))) producing the number $postpone($countervalue(markcount)) (where
$mtt(markcount) is the name of the counter used for numbering the marks in this catalog).
$mark2(pushcounter)(name)(init)
This mark creates a new counter under the name $argu(name), with $argu(init) as its initial value. See
$ref(counters)(Counters).
$mark2(ref)(tag)(text)
This mark creates an internal hyperlink. When clicked upon, this moves the text
to the position of the $ref(label)($mtt($$label)) (this is a $mtt($$ref) !) with the same tag name.
$mark1(reverse)(list)
This mark return its operand (assumed to be a list), but in reverse order. If the operand is not a list, an error
message is generated.
$mark2(rgb)(color)(text) This mark sets the color of characters in $argu(text) to $argu(color), where
$argu(color) has the form of three integers separated by commas, representing the intensities of red, green and blue.
These numbers must be between 0 and 255. For example,$par
$mcenter($mtt($$rgb(255,0,0)(the text)))
produces:
$mcenter($rgb(255,0,0)(the text))
See also $ref(colors)(the predefined colors).
$mark0(rpar) This mark inserts a right (closing) parenthese into the text. You must use $mtt($$lpar) and/or
$mtt($$rpar) (or alternatively $mtt($$$() and $mtt($$$))) if you want to introduce unbalanced parentheses within
an operand of a mark.
$mark2(setcounter)(name)(value)
This mark puts the value $argu(value) in the most recent counter whose name is $argu(name). See $ref(counters)(Counters).
$mark1(sort)(list)
This marks performs a quick sorting of its operand which is supposed to be a list. If the operand is not a list, an
error message is generated.$p
The sorting is always alphabetic, but it can be relative to any part of the elements in the list. In order to
designate which part of an element of the list must be used for comparison, put the special mark
$mtt($$alphabetic($argu(part))) around this part.$p
At the rendering stage $mtt($$alphabetic($argu(part))) is just replaced by $mtt($argu(part)). See $ref(box)($mtt($$box))
for an example.
$mark0(sp) This mark (space) produces an unbreakable space (translated into $tt( ) in HTML and $tt(~) in $latex(\LaTeX)).
$mark1(sub)(text) This mark lowers $argu(text) and renders it in a smaller size. For example, $mtt(x$$sub(1))
produces x$sub(1).
$mark3(sublist)(start)(end)(list)
The third operand of this mark is supposed to be a list. If it's not a list, an error message is generated.$p
If it is a list, the result is the sublist beginning at element number $argu(start) (included) and finishing at
element number $argu(end) (not included). Notice that numbering begins at $mtt(0), not $mtt(1).
If the value of $argu(start) or $argu(end) is out of bounds, this value is
replaced by the actual bound which is $mtt(0) for $argu(start) and the length of the list for $argu(end). For example,
$mcode($$sublist(-3)(4)($nolist([a,b,c,d,e,f,g,h,i,j,k]))$$par
$$sublist(0)(4)($nolist([a,b,c,d,e,f,g,h,i,j,k]))$$par
$$sublist(1)(4)($nolist([a,b,c,d,e,f,g,h,i,j,k])))
produces:$p
$sublist(-3)(4)([a,b,c,d,e,f,g,h,i,j,k])$par
$sublist(0)(4)([a,b,c,d,e,f,g,h,i,j,k])$par
$sublist(1)(4)([a,b,c,d,e,f,g,h,i,j,k])
$mark1(sup)(text) This mark raises $argu(text) and renders it in a smaller size. For example, $mtt(x$$sup(1))
produces x$sup(1).
$mark2(tbgc)(color)(text) This mark ($em(text background color)) shows $argu(text) over a background of color
$argu(color). For example, $mtt($$tbgc($$_lavender)(Some text.))
produces: $tbgc($_lavender)(Some text.)
$par$par
This is valuable for short texts. For long texts, $ref(code)($mtt($$code(...))) may be more
appropriate.
$mark0(thisfilepath)
This marks provides the absolute path of the file it is written into.$p
$mtt($$thisfilepath) is $unsafe for the web, because it can reveal an absolute path of your web server. You should forbid
it.
$mark2(tlink)(text)(url) This mark creates an hypertext link targeting the $argu(url), and shown as the clickable
$argu(text) (which can also be an image). For example,
$mcode($$tlink(Visit
$$big($$blue(G)$$red(o)$$yellow(o)$$blue(g)$$green(l)$$red(e)))
(http://www.google.com))
produces
$tlink(Visit
$big($blue(G)$red(o)$yellow(o)$blue(g)$green(l)$red(e)))(http://www.google.com)$ifhtml( (that
you can click upon)).
$mark1(transpose)(list of lists)
This mark $em(transposes) (somehow as in mathematics) a list of lists considered as a $em(matrix). As an example,
we define:
$mcode($$define(mylist)(0)($[$[a$,b$]$,$[c$,d$,e$]$,$[f$,g$]$])
$$define(addbox)(1)($$box(16)($$1))
$$define(separ)(1)($$apply(addbox)($$1)$$par))
$define(mylist)(0)([[a,b],[c,d,e],[f,g]])
$define(addbox)(1)($box(16)($1))
$define(separ)(1)($apply(addbox)($1)$par)
Now, if we write $mtt($$apply(separ)($$mylist)), we obtain:
$p
$apply(separ)($mylist)
$par
and if we write $mtt($$apply(separ)($$transpose($$mylist))), we obtain:
$p
$apply(separ)($transpose($mylist))
$par
Notice that if a line of the matrix is shorter than a subsequent line, $mtt($$transpose) automatically inserts $em(empty)
(invisible) elements in the
transposed matrix so that items which are in the same $em(line) in the original matrix are in the same $em(column) in the
transposed matrix.$p
This is useful (in conjunction with $ref(sublist)($mtt($$sublist))) and some $ref(arithmetics)(arithmetics)
for example for displaying a list of items on several columns, with the first group of elements in the first
column (not the first line), the next group of elements in the second column, and so on. This can be used for example
for automatically producing an index on several columns. This is also used in this tutorial for displaying the list
of all marks on four columns $ref(catalog)(at the beginning of this section).$p
Below is a simple example. We want to sort a list of words in alphabetic order and to present them on two columns.
$mcode( $$// define a list of words
$$define(words)(0)
($[We$,want$,to$,sort$,a$,list$,of$,words$,and$,
to$,present$,them$,in$,alphabetic$,order$,on$,two$,columns$]))
$define(words)(0)
([We,want,to,sort,a,list,of,words,and,to,present,them,in,alphabetic,order,on,two,columns])
We prepare the sorting of the list by applying a $mtt($$box(120)) and a $mtt($$alphabetic) to all elements.
$mcode($$define(a)(1)($$box(120)($$alphabetic($$1))) $$// because $$apply accepts only macros
$$define(sortedwords)(0)($$sort($$apply(a)($$words))))
$define(a)(1)($box(120)($alphabetic($1)))
$define(sortedwords)(0)($sort($apply(a)($words)))
so that $mtt($$sortedwords) looks like this:
$p
$sortedwords
$p
Now, we compute the length of this list, divide it by $mtt(2) and add 1 if the remainder is not zero,
so that we can cut our list in two lists
of almost the same length (the first one with possibly one element more than the second one).
$mcode($$define(halflen)(0)($$add($$quotient($$length($$sortedwords))(2))
($$if($$equals(0)($$remainder($$length($$sortedwords))(2)))(0)(1)))
$$define(column1)(0)($$sublist(0)($$halflen)($$sortedwords))
$$define(column2)(0)($$sublist($$halflen)($$length($$sortedwords))($$sortedwords)))
$define(halflen)(0)($add($quotient($length($sortedwords))(2))
($if($equals(0)($remainder($length($sortedwords))(2)))(0)(1)))
$define(column1)(0)($sublist(0)($halflen)($sortedwords))
$define(column2)(0)($sublist($halflen)($length($sortedwords))($sortedwords))
Finally, we can get the wanted result by writing:
$define(putpar)(1)($1$par)
$mcode($$define(putpar)(1)($$1$$par)
$$center($$apply(putpar)($$transpose($[$$column1$,$$column2$]))))
$center($apply(putpar)($transpose([$column1,$column2])))
$p
$mark0(true) This mark represents the truth value $em(true).
$mark1(tt)(text) This mark renders $argu(text) in fixed width (typewriter) font. It is similar to
$ref(code)($mtt($$code(...))), with the difference that $argu(text) is put inline instead of as a separate block.
For example, $mtt($$red($$tt(This)) is $$code(220,220,220)(an) example.)
produces: $red($tt(This)) is $code(220,220,220)(an) example.
$par$par
See also $ref(code)($mtt($$code(...))) and $ref(verbatim)($mtt($$verbatim(...))).
$mark1(undefine)(name) This mark allows to $em(undefine) a macro previously defined by $ref(define)($mtt($$define)).
Actually, it removes only the last definition of the macro whose name is given, so that the previous definition of
this same mark name (if any) is working again.
If no macro with name $argu(name) exists, nothing happens. $par$par
Example:
$mcode($$define(emph)(1)($$italic($$1))
$$emph(text1)$$par
$$define(emph)(2)($$bold($$1):$$red($$2))
$$emph(text2a)(text2b)$$par
$$undefine(emph)
$$emph(text3))
produces:$par$par
$define(emph)(1)($italic($1))
$emph(text1)$par
$define(emph)(2)($bold($1):$red($2))
$emph(text2a)(text2b)$par
$undefine(emph)
$emph(text3)
$par$par
As a consequence, a $MAML text can safely be embedded into another $MAML text using $mtt($$input), provided
that you $em(undefine) the macros defined in the embedded text at the end of the embedded text. $p
As told in $ref(define)($mtt($$define)), $mtt($$define) doesn't allow recursion. However, if a macro with the same
name is already defined, any usage of this macro name in the body of the new definition refers to the previous
definition. For example,
$mcode($$define(bu)(1)($$italic($$1))
$$bu(Some text.)$$par
$$define(bu)(2)($$rgb(120,0,0)($$bu($$1) $$2))
$$bu(Text1)(Text2)) produces:$par$par
$define(bu)(1)($italic($1))
$bu(Some text.)$par
$define(bu)(2)($rgb(120,0,0)($bu($1) $2))
$bu(Text1)(Text2)$par
$mark1(verbatim)(text) This marks reproduces its content without any change with two exceptions.
Indeed, $MAML marks within
$argu(text) are not interpreted, except the two marks $mtt($$lpar) and $mtt($$rpar), which allows you
to produce unbalanced parentheses in $argu(text) despite the fact that actual parentheses $em(must) be
balanced in $argu(text). Example:
$par
$mcode($$verbatim(In this ($$italic(text))(), ((parentheses) are) $$rpar$$rpar$$lpar balanced.))
produces:
$p
$verbatim(In this ($italic(text))(), ((parentheses) are) $rpar$rpar$lpar balanced.)
$p
Nevertheless, colors are applied if $mtt($$verbatim(...)) is within a $mtt($$rgb(...)(...)). Indeed,
$mcode($$rgb(255,0,0)($$verbatim(Red verbatim text))) produces:
$rgb(255,0,0)($verbatim(Red verbatim text))
On the contrary, $mcode($$colorize(maml)($$verbatim(Red verbatim text))) produces:
$colorize(maml)($verbatim(Red verbatim text))
because $mtt($$verbatim) is not a macro.
$par
$par
See also $ref(code)($mtt($$code(...))) and $ref(tt)($mtt($$tt(...))).
$p$p
$center($big($big($big($big($colorize(funny)(Enjoy !))))))
$ifhtml($par$par$par$par$par$par$par$par)
$end