summaryrefslogtreecommitdiff
path: root/macros/luatex/optex/if-macros.opm
blob: 5e56503bd87b2a998b7dcf658cab0643ede0fde2 (plain)
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
%% This is part of OpTeX project, see http://petr.olsak.net/optex

\_codedecl \newif {Special if-macros, is-macros and loops <2020-02-27>} % preloaded in format

   \_doc ----------------------------
   The `\newif` macro works like in plain \TeX. It means that
   after `\newif\ifxxx` you can use `\xxxtrue` or
   `\xxxfalse` to set the boolean value and use `\ifxxx true\else false\fi`
   to test this value. The defalut value is false.

   The macro `\_newifi` enables to declare `\_ifxxx` and to use `\_xxxtrue` and
   `\_xxxfalse`. This means that it is usable for _prefixed macros.
   \_cod ----------------------------

\_def\_newif #1{\_ea\_newifA \_string #1\_relax#1}
\_ea\_def \_ea\_newifA \_string\if #1\_relax#2{%
   \_sdef{#1true}{\_let#2=\_iftrue}%
   \_sdef{#1false}{\_let#2=\_iffalse}%
   \_let#2=\_iffalse
}
\_def\_newifi #1{\_ea\_newifiA \string#1\_relax#1}
\_ea\_def \_ea\_newifiA \string\_if #1\_relax#2{%
   \_sdef{_#1true}{\_let#2=\_iftrue}%
   \_sdef{_#1false}{\_let#2=\_iffalse}%
   \_let#2=\_iffalse
}

   \_doc ----------------------------
   The `\loop <codeA> \ifsomething <codeB> \repeat` loops `<codeA> <codeB>`
   until `\ifsomething` is false. Then `<codeB>` is not executed and loop is
   finished. This works like in plain \TeX, but implementation is soewhat
   better (you can use `\else` clause after the `\ifsomething`).

   There are public version `\loop...\repeat` and private version
   `\_loop...\_repeat`. You canot mix both versions in one loop. 
   \_cod ----------------------------

\_def \_loop #1\_repeat{\_def\_body{#1}\_iterate}
\_def \loop #1\repeat{\_def\_body{#1}\_iterate}
\_let \_repeat=\_fi % this makes \loop...\if...\repeat skippable
\_let \repeat=\_fi
\_def \_iterate {\_body \_ea \_iterate \_fi}

   \_doc ----------------------------
   The macro `\isnextchar <char>{<codeA>}{<codeB>}` executes `<codeA>` if next
   character is equal to <char>. Else the `<codeB>` is executed. The macro is
   not expandable.
   \_cod ----------------------------

\_long\_def\_isnextchar#1#2#3{\_begingroup\_toks0={\_endgroup#2}\_toks1={\_endgroup#3}%
   \_let\_tmp=#1\_futurelet\_next\_isnextcharA
}
\_def\_isnextcharA{\_the\_toks\_ifx\_tmp\_next0\_else1\_fi\_space}

   \_doc ----------------------------
   The macro `\isempty{<text>}\iftrue <codeA>\else <codeB>\fi` executes <codeA>
   if <text> is empty and <codeB> if it is non-empty. You can use
   `\isempty{<text>}\iffalse <codeB>\else <codeA>\fi` too. This macro is
   expandable. 

   There are a collection of macros with commnon syntax:
   `\issomething<params>\iftrue` or `\issomething<params>\iffalse`.
   The `\iftrue` or `\iffalse` is a part of this syntax because we need to keep
   skippable nested `\if` conditions.

   We read this `\iftrue` or `\iffalse` into unseparated parameter and repeat
   it because we need to remove an optional space before this command.
   \_cod ----------------------------

\_def \_isempty #1#2{\_ea\_ifx\_ea\_relax\_detokenize{#1}\_relax 
    \_else \_ea\_unless \_fi #2}
\_def \_isnoempty #1#2{\_ea\_ifx\_ea\_relax\_detokenize{#1}\_relax 
    \_ea\_unless \_fi #2}
\_def \_istoksempty #1{\_ea\_isempty\_ea{\_the#1}}

   \_doc ----------------------------
   `\isequal{<textA>}{<textB>}\iftrue` is true if the <textA> and <textB> are
   equal, only from strings point of view, category codes are ignored.
   The macro is expandable.
   \_cod ----------------------------

\_def\_isequal#1#2#3{\_directlua{%
   if "\_luaescapestring{\_detokenize{#1}}"=="\_luaescapestring{\_detokenize{#2}}" 
   then else tex.print("\_nbb unless") end}#3}

   \_doc ----------------------------
   `\ismacro\macro{text}\iftrue` is true if macro is defined as {<text>}.
   Category codes are ignored in this testing. The macro is expandable.
   \_cod ----------------------------

\_def\_ismacro#1{\_ea\_isequal\_ea{#1}}

   \_doc ----------------------------
   `\isinlist\list{<text>}\iftrue` is true if the
   `<text>` is included the macro body of the `\list`. 
   The catogory code are relevant here. THe macro is not expandable.
   \_cod ----------------------------

\_def\_isdefined #1#2{\_ifcsname #1\_endcsname \_else \_ea\_unless \_fi #2}

   \_doc ----------------------------
   `\isdefined{<csname>}\iftrue` is true if `\<csname>` is defined.
   \_cod ----------------------------

\_long\_def\_isinlist#1#2{\_begingroup 
   \_long\_def\_tmp##1#2##2\_end/_{\_endgroup\_isnoempty{##2}}%
   \_ea\_tmp#1\_endlistsep#2\_end/_%
}

   \_doc ----------------------------
   `\isfile{<filename>}\iftrue` is true if the file <filename> exists and are
   readable by \TeX.
   \_cod \_fin ----------------------

\_newread \_testin

\_def\_isfile #1{%
   \_openin\_testin ={#1}\_relax
   \_ifeof\_testin \_ea\_unless
   \_else \_closein\_testin
   \_fi
}

\_public
   \newif \isnextchar \isempty \isequal \ismacro \isdefined \isinlist \isfile ;

\_endcode