teepee 0.15.7 → 0.15.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/teepee/commander-mixins/boolean.rb +147 -0
- data/lib/teepee/commander-mixins/control.rb +189 -0
- data/lib/teepee/commander-mixins/formatting.rb +206 -0
- data/lib/teepee/commander-mixins/mathematics.rb +296 -0
- data/lib/teepee/commander-mixins/thinking-bicycle-models.rb +134 -0
- data/lib/teepee/commander.rb +13 -759
- metadata +7 -2
@@ -0,0 +1,296 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# -*- mode: Ruby -*-
|
3
|
+
|
4
|
+
# Copyright © 2013-2016, Christopher Mark Gore,
|
5
|
+
# Soli Deo Gloria,
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
# 2317 South River Road, Saint Charles, Missouri 63303 USA.
|
9
|
+
# Web: http://cgore.com
|
10
|
+
# Email: cgore@cgore.com
|
11
|
+
#
|
12
|
+
# Redistribution and use in source and binary forms, with or without
|
13
|
+
# modification, are permitted provided that the following conditions are met:
|
14
|
+
#
|
15
|
+
# * Redistributions of source code must retain the above copyright
|
16
|
+
# notice, this list of conditions and the following disclaimer.
|
17
|
+
#
|
18
|
+
# * Redistributions in binary form must reproduce the above copyright
|
19
|
+
# notice, this list of conditions and the following disclaimer in the
|
20
|
+
# documentation and/or other materials provided with the distribution.
|
21
|
+
#
|
22
|
+
# * Neither the name of Christopher Mark Gore nor the names of other
|
23
|
+
# contributors may be used to endorse or promote products derived from
|
24
|
+
# this software without specific prior written permission.
|
25
|
+
#
|
26
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
27
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
28
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
29
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
30
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
31
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
32
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
33
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
34
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
35
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
36
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
37
|
+
|
38
|
+
|
39
|
+
module Teepee
|
40
|
+
module CommanderMixins
|
41
|
+
module Mathematics
|
42
|
+
def numeric? *numbers
|
43
|
+
numbers.all? {|number| number.kind_of? Numeric}
|
44
|
+
end
|
45
|
+
|
46
|
+
def non_numeric_error nan
|
47
|
+
command_error "The value \"#{nan}\" is not a number."
|
48
|
+
end
|
49
|
+
|
50
|
+
def ensure_numeric number
|
51
|
+
if number.kind_of? Complex
|
52
|
+
command_error "Complex numbers are not yet supported."
|
53
|
+
elsif not number.kind_of? Numeric
|
54
|
+
command_error "Non-numeric result."
|
55
|
+
else
|
56
|
+
number
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def number_from_word word
|
61
|
+
begin
|
62
|
+
word.to_number
|
63
|
+
rescue ArgumentError, NoMethodError
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_numbers words
|
69
|
+
words.map {|word| number_from_word word}.reject &:nil?
|
70
|
+
end
|
71
|
+
|
72
|
+
def + numbers
|
73
|
+
ensure_numeric to_numbers(numbers).inject 0, :+
|
74
|
+
end
|
75
|
+
|
76
|
+
def - numbers
|
77
|
+
numbers = to_numbers numbers
|
78
|
+
if numbers.length == 1
|
79
|
+
ensure_numeric -numbers.first
|
80
|
+
else
|
81
|
+
ensure_numeric numbers.reduce :-
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def * numbers
|
86
|
+
ensure_numeric to_numbers(numbers).inject 1, :*
|
87
|
+
end
|
88
|
+
|
89
|
+
def / numbers
|
90
|
+
numbers = to_numbers numbers
|
91
|
+
if numbers.length == 1
|
92
|
+
ensure_numeric 1 / numbers.first
|
93
|
+
else
|
94
|
+
ensure_numeric numbers.reduce :/
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def ** numbers
|
99
|
+
ensure_numeric to_numbers(numbers).reduce :**
|
100
|
+
end
|
101
|
+
|
102
|
+
def % numbers
|
103
|
+
to_numbers(numbers).inject { |base, percent| base*percent/100.0 }
|
104
|
+
end
|
105
|
+
|
106
|
+
def add_percentage numbers
|
107
|
+
to_numbers(numbers).inject {|base, percent| base * (1+percent/100.0) }
|
108
|
+
end
|
109
|
+
|
110
|
+
def subtract_percentage numbers
|
111
|
+
to_numbers(numbers).inject {|base, percent| base * (1-percent/100.0) }
|
112
|
+
end
|
113
|
+
|
114
|
+
def percent_total numbers
|
115
|
+
to_numbers(numbers).inject {|total, part| Float(part)/Float(total)*100.0 }
|
116
|
+
end
|
117
|
+
|
118
|
+
def acos angle
|
119
|
+
ensure_numeric Math.acos angle.to_number
|
120
|
+
end
|
121
|
+
|
122
|
+
def acosh angle
|
123
|
+
ensure_numeric Math.acosh angle.to_number
|
124
|
+
end
|
125
|
+
|
126
|
+
def asin angle
|
127
|
+
ensure_numeric Math.asin angle.to_number
|
128
|
+
end
|
129
|
+
|
130
|
+
def asinh angle
|
131
|
+
ensure_numeric Math.asinh angle.to_number
|
132
|
+
end
|
133
|
+
|
134
|
+
def atan angle
|
135
|
+
ensure_numeric Math.atan angle.to_number
|
136
|
+
end
|
137
|
+
|
138
|
+
def atanh angle
|
139
|
+
ensure_numeric Math.atanh angle.to_number
|
140
|
+
end
|
141
|
+
|
142
|
+
def ceiling number
|
143
|
+
ensure_numeric number.to_number.ceil
|
144
|
+
end
|
145
|
+
|
146
|
+
def cos angle
|
147
|
+
ensure_numeric Math.cos angle.to_number
|
148
|
+
end
|
149
|
+
|
150
|
+
def cosh angle
|
151
|
+
ensure_numeric Math.cosh angle.to_number
|
152
|
+
end
|
153
|
+
|
154
|
+
def degrees2radians degrees
|
155
|
+
ensure_numeric degrees.to_number * Math::PI / 180.0
|
156
|
+
end
|
157
|
+
|
158
|
+
def e
|
159
|
+
Math::E
|
160
|
+
end
|
161
|
+
|
162
|
+
def erf number
|
163
|
+
ensure_numeric Math.erf number.to_number
|
164
|
+
end
|
165
|
+
|
166
|
+
def erfc number
|
167
|
+
ensure_numeric Math.erfc number.to_number
|
168
|
+
end
|
169
|
+
|
170
|
+
def floor number
|
171
|
+
ensure_numeric number.to_number.floor
|
172
|
+
end
|
173
|
+
|
174
|
+
def gamma number
|
175
|
+
ensure_numeric Math.gamma number.to_number
|
176
|
+
end
|
177
|
+
|
178
|
+
def greater_than numbers
|
179
|
+
if numbers.empty?
|
180
|
+
true_constant
|
181
|
+
elsif numbers.length == 1
|
182
|
+
true_constant
|
183
|
+
else
|
184
|
+
numbers[0].to_number > numbers[1].to_number and greater_than numbers.rest
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def greater_than_or_equal numbers
|
189
|
+
if numbers.empty?
|
190
|
+
true_constant
|
191
|
+
elsif numbers.length == 1
|
192
|
+
true_constant
|
193
|
+
else
|
194
|
+
numbers[0].to_number >= numbers[1].to_number and greater_than_or_equal numbers.rest
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def i
|
199
|
+
command_error "Complex numbers are not yet supported."
|
200
|
+
end
|
201
|
+
|
202
|
+
def hypot numbers
|
203
|
+
ensure_numeric Math.sqrt to_numbers(numbers).map {|n| n**2}
|
204
|
+
end
|
205
|
+
|
206
|
+
def ld number
|
207
|
+
ensure_numeric Math.log2 number.to_number
|
208
|
+
end
|
209
|
+
|
210
|
+
def ldexp fraction, exponent
|
211
|
+
ensure_numeric Math.ldexp fraction.to_number, exponent.to_number
|
212
|
+
end
|
213
|
+
|
214
|
+
def less_than numbers
|
215
|
+
if numbers.empty?
|
216
|
+
true_constant
|
217
|
+
elsif numbers.length == 1
|
218
|
+
true_constant
|
219
|
+
else
|
220
|
+
numbers[0].to_number < numbers[1].to_number and less_than numbers.rest
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def less_than_or_equal numbers
|
225
|
+
if numbers.empty?
|
226
|
+
true_constant
|
227
|
+
elsif numbers.length == 1
|
228
|
+
true_constant
|
229
|
+
else
|
230
|
+
numbers[0].to_number <= numbers[1].to_number and less_than_or_equal numbers.rest
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def lgamma number
|
235
|
+
ensure_numeric Math::lgamma(number.to_number).first
|
236
|
+
end
|
237
|
+
|
238
|
+
def ln number
|
239
|
+
ensure_numeric Math.log number.to_number
|
240
|
+
end
|
241
|
+
|
242
|
+
def log base, number
|
243
|
+
if number.nil?
|
244
|
+
number, base = base, number
|
245
|
+
ensure_numeric Math.log10 number.to_number # default to log base 10
|
246
|
+
else
|
247
|
+
ensure_numeric Math.log number.to_number, base.to_number
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def log10 number
|
252
|
+
ensure_numeric Math.log10 number.to_number
|
253
|
+
end
|
254
|
+
|
255
|
+
def mod numbers
|
256
|
+
ensure_numeric to_numbers(numbers).reduce :%
|
257
|
+
end
|
258
|
+
|
259
|
+
def pi
|
260
|
+
Math::PI
|
261
|
+
end
|
262
|
+
|
263
|
+
def radians2degrees radians
|
264
|
+
ensure_numeric(radians.to_number * 180.0 / Math::PI)
|
265
|
+
end
|
266
|
+
|
267
|
+
def round number, precision = nil, *_
|
268
|
+
if precision.nil? or precision.to_number.nil?
|
269
|
+
ensure_numeric number.to_number.round
|
270
|
+
else
|
271
|
+
ensure_numeric number.to_number.round precision.to_number
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def sin angle
|
276
|
+
ensure_numeric Math.sin angle.to_number
|
277
|
+
end
|
278
|
+
|
279
|
+
def sinh angle
|
280
|
+
ensure_numeric Math.sinh angle.to_number
|
281
|
+
end
|
282
|
+
|
283
|
+
def sqrt number
|
284
|
+
ensure_numeric Math.sqrt number.to_number
|
285
|
+
end
|
286
|
+
|
287
|
+
def tan angle
|
288
|
+
ensure_numeric Math.tan angle.to_number
|
289
|
+
end
|
290
|
+
|
291
|
+
def tanh angle
|
292
|
+
ensure_numeric Math.tanh angle.to_number
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# -*- mode: Ruby -*-
|
3
|
+
|
4
|
+
# Copyright © 2013-2016, Christopher Mark Gore,
|
5
|
+
# Soli Deo Gloria,
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
# 2317 South River Road, Saint Charles, Missouri 63303 USA.
|
9
|
+
# Web: http://cgore.com
|
10
|
+
# Email: cgore@cgore.com
|
11
|
+
#
|
12
|
+
# Redistribution and use in source and binary forms, with or without
|
13
|
+
# modification, are permitted provided that the following conditions are met:
|
14
|
+
#
|
15
|
+
# * Redistributions of source code must retain the above copyright
|
16
|
+
# notice, this list of conditions and the following disclaimer.
|
17
|
+
#
|
18
|
+
# * Redistributions in binary form must reproduce the above copyright
|
19
|
+
# notice, this list of conditions and the following disclaimer in the
|
20
|
+
# documentation and/or other materials provided with the distribution.
|
21
|
+
#
|
22
|
+
# * Neither the name of Christopher Mark Gore nor the names of other
|
23
|
+
# contributors may be used to endorse or promote products derived from
|
24
|
+
# this software without specific prior written permission.
|
25
|
+
#
|
26
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
27
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
28
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
29
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
30
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
31
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
32
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
33
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
34
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
35
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
36
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
37
|
+
|
38
|
+
|
39
|
+
module Teepee
|
40
|
+
module CommanderMixins
|
41
|
+
module ThinkingBicycleModels
|
42
|
+
def tb_href target, string
|
43
|
+
%{<a href="#{TB_COM}/#{target}">#{string}</a>}
|
44
|
+
end
|
45
|
+
|
46
|
+
def id_command_handler(id,
|
47
|
+
klass,
|
48
|
+
singular = klass.to_s.camelcase_to_snakecase,
|
49
|
+
plural = singular.pluralize,
|
50
|
+
partial = "#{plural}/inline",
|
51
|
+
view="")
|
52
|
+
if not id
|
53
|
+
command_error "#{singular}_id: error: no #{singular} ID specified"
|
54
|
+
elsif not id.to_s =~ /\A[0-9]+\z/
|
55
|
+
command_error "#{singular}_id: error: invalid #{singular} ID specified"
|
56
|
+
else
|
57
|
+
tb_href "#{plural}/#{id.to_s}/#{view}", "#{klass.to_s} ##{id.to_s}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def bookmarks_folder_id id
|
62
|
+
id_command_handler id, :Folder, "folder", "folders", "folders/bookmarks_inline", "bookmarks"
|
63
|
+
end
|
64
|
+
|
65
|
+
def folder_id id
|
66
|
+
id_command_handler id, :Folder
|
67
|
+
end
|
68
|
+
|
69
|
+
def forum_id id
|
70
|
+
id_command_handler id, :Forum
|
71
|
+
end
|
72
|
+
|
73
|
+
def image expressions
|
74
|
+
expressions = strip expressions
|
75
|
+
uri, *alt_text = expressions
|
76
|
+
uri = ERB::Util.html_escape uri.to_html
|
77
|
+
if not valid_uri? uri
|
78
|
+
command_error "Not a valid URI for the image."
|
79
|
+
else
|
80
|
+
if alt_text.empty?
|
81
|
+
html_tag :img, nil, {src: uri}
|
82
|
+
else
|
83
|
+
html_tag :img, nil, {src: uri, alt: alt_text.map(&:to_html).join.strip}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def keyword_id id
|
89
|
+
id_command_handler id, :Keyword
|
90
|
+
end
|
91
|
+
|
92
|
+
def link expressions
|
93
|
+
expressions = strip expressions
|
94
|
+
uri, *desc = expressions
|
95
|
+
uri = ERB::Util.html_escape uri.to_html
|
96
|
+
if not valid_uri? uri
|
97
|
+
command_error "Not a valid URI."
|
98
|
+
else
|
99
|
+
desc = [uri] if desc.empty?
|
100
|
+
html_tag :a, desc, {href: uri}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def link_id id
|
105
|
+
id_command_handler id, :Link
|
106
|
+
end
|
107
|
+
|
108
|
+
def mailto email_address
|
109
|
+
email_address = email_address.to_html
|
110
|
+
if valid_email_address? email_address
|
111
|
+
html_tag :a, [email_address], {href: "mailto:#{email_address}"}
|
112
|
+
else
|
113
|
+
command_error "I'm not sure that's a valid email address."
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def note_id id
|
118
|
+
id_command_handler id, :Note
|
119
|
+
end
|
120
|
+
|
121
|
+
def tag_id id
|
122
|
+
id_command_handler id, :Tag
|
123
|
+
end
|
124
|
+
|
125
|
+
def user user
|
126
|
+
if not user
|
127
|
+
command_error "user: error: no user specified"
|
128
|
+
else
|
129
|
+
tb_href "users/#{user}", user.to_html
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/lib/teepee/commander.rb
CHANGED
@@ -35,8 +35,20 @@
|
|
35
35
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
36
36
|
# POSSIBILITY OF SUCH DAMAGE.
|
37
37
|
|
38
|
+
require 'teepee/commander-mixins/boolean'
|
39
|
+
require 'teepee/commander-mixins/control'
|
40
|
+
require 'teepee/commander-mixins/formatting'
|
41
|
+
require 'teepee/commander-mixins/mathematics'
|
42
|
+
require 'teepee/commander-mixins/thinking-bicycle-models'
|
43
|
+
|
38
44
|
module Teepee
|
39
45
|
class Commander
|
46
|
+
include CommanderMixins::Boolean
|
47
|
+
include CommanderMixins::Control
|
48
|
+
include CommanderMixins::Formatting
|
49
|
+
include CommanderMixins::Mathematics
|
50
|
+
include CommanderMixins::ThinkingBicycleModels
|
51
|
+
|
40
52
|
attr_accessor :parser
|
41
53
|
|
42
54
|
def initialize params
|
@@ -61,73 +73,6 @@ module Teepee
|
|
61
73
|
command_error "The variable \"#{variable}\" is not defined."
|
62
74
|
end
|
63
75
|
|
64
|
-
def numeric? *numbers
|
65
|
-
numbers.all? {|number| number.kind_of? Numeric}
|
66
|
-
end
|
67
|
-
|
68
|
-
def non_numeric_error nan
|
69
|
-
command_error "The value \"#{nan}\" is not a number."
|
70
|
-
end
|
71
|
-
|
72
|
-
def ensure_numeric number
|
73
|
-
if number.kind_of? Complex
|
74
|
-
command_error "Complex numbers are not yet supported."
|
75
|
-
elsif not number.kind_of? Numeric
|
76
|
-
command_error "Non-numeric result."
|
77
|
-
else
|
78
|
-
number
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def ensure_boolean boolean
|
83
|
-
if boolean.to_html == "true" or boolean.to_html == "false"
|
84
|
-
boolean
|
85
|
-
else
|
86
|
-
command_error "Non-boolean value."
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def html_tag tag, expressions, attribs=nil
|
91
|
-
opening_tag = if attribs
|
92
|
-
attribs_string = attribs.map {|k,v| %{#{k}="#{v}"}}.join " "
|
93
|
-
if expressions.nil?
|
94
|
-
"<#{tag} #{attribs_string}/>"
|
95
|
-
else
|
96
|
-
"<#{tag} #{attribs_string}>"
|
97
|
-
end
|
98
|
-
else
|
99
|
-
if expressions.nil?
|
100
|
-
"<#{tag}/>"
|
101
|
-
else
|
102
|
-
"<#{tag}>"
|
103
|
-
end
|
104
|
-
end
|
105
|
-
if expressions.nil?
|
106
|
-
opening_tag
|
107
|
-
else
|
108
|
-
opening_tag + expressions.map(&:to_html).join.strip + "</#{tag}>"
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def tb_href target, string
|
113
|
-
%{<a href="#{TB_COM}/#{target}">#{string}</a>}
|
114
|
-
end
|
115
|
-
|
116
|
-
def id_command_handler(id,
|
117
|
-
klass,
|
118
|
-
singular = klass.to_s.camelcase_to_snakecase,
|
119
|
-
plural = singular.pluralize,
|
120
|
-
partial = "#{plural}/inline",
|
121
|
-
view="")
|
122
|
-
if not id
|
123
|
-
command_error "#{singular}_id: error: no #{singular} ID specified"
|
124
|
-
elsif not id.to_s =~ /\A[0-9]+\z/
|
125
|
-
command_error "#{singular}_id: error: invalid #{singular} ID specified"
|
126
|
-
else
|
127
|
-
tb_href "#{plural}/#{id.to_s}/#{view}", "#{klass.to_s} ##{id.to_s}"
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
76
|
def left_strip expressions
|
132
77
|
while expressions.first.kind_of? WhitespaceToken
|
133
78
|
expressions.shift
|
@@ -147,109 +92,13 @@ module Teepee
|
|
147
92
|
end
|
148
93
|
|
149
94
|
def valid_email_address? email_address
|
150
|
-
email_address =~ /\A[[:graph:]]+@[\w.]+\z/
|
151
|
-
end
|
152
|
-
|
153
|
-
def true_constant? expression
|
154
|
-
expression.to_html == "true"
|
155
|
-
end
|
156
|
-
|
157
|
-
def false_constant? expression
|
158
|
-
expression.to_html == "false"
|
95
|
+
email_address =~ /\A[[:graph:]]+@[\w._-]+\z/
|
159
96
|
end
|
160
97
|
|
161
98
|
def pipe? expression
|
162
99
|
expression.is_a? PipeToken
|
163
100
|
end
|
164
101
|
|
165
|
-
def number_from_word word
|
166
|
-
begin
|
167
|
-
word.to_number
|
168
|
-
rescue ArgumentError, NoMethodError
|
169
|
-
nil
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def to_numbers words
|
174
|
-
words.map {|word| number_from_word word}.reject &:nil?
|
175
|
-
end
|
176
|
-
|
177
|
-
#----------------------------------------------------------------------------
|
178
|
-
|
179
|
-
def + numbers
|
180
|
-
ensure_numeric to_numbers(numbers).inject 0, :+
|
181
|
-
end
|
182
|
-
|
183
|
-
def - numbers
|
184
|
-
numbers = to_numbers numbers
|
185
|
-
if numbers.length == 1
|
186
|
-
ensure_numeric -numbers.first
|
187
|
-
else
|
188
|
-
ensure_numeric numbers.reduce :-
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
def * numbers
|
193
|
-
ensure_numeric to_numbers(numbers).inject 1, :*
|
194
|
-
end
|
195
|
-
|
196
|
-
def / numbers
|
197
|
-
numbers = to_numbers numbers
|
198
|
-
if numbers.length == 1
|
199
|
-
ensure_numeric 1 / numbers.first
|
200
|
-
else
|
201
|
-
ensure_numeric numbers.reduce :/
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
def ** numbers
|
206
|
-
ensure_numeric to_numbers(numbers).reduce :**
|
207
|
-
end
|
208
|
-
|
209
|
-
def % numbers
|
210
|
-
to_numbers(numbers).inject { |base, percent| base*percent/100.0 }
|
211
|
-
end
|
212
|
-
|
213
|
-
def add_percentage numbers
|
214
|
-
to_numbers(numbers).inject {|base, percent| base * (1+percent/100.0) }
|
215
|
-
end
|
216
|
-
|
217
|
-
def subtract_percentage numbers
|
218
|
-
to_numbers(numbers).inject {|base, percent| base * (1-percent/100.0) }
|
219
|
-
end
|
220
|
-
|
221
|
-
def percent_total numbers
|
222
|
-
to_numbers(numbers).inject {|total, part| Float(part)/Float(total)*100.0 }
|
223
|
-
end
|
224
|
-
|
225
|
-
def acos angle
|
226
|
-
ensure_numeric Math.acos angle.to_number
|
227
|
-
end
|
228
|
-
|
229
|
-
def acosh angle
|
230
|
-
ensure_numeric Math.acosh angle.to_number
|
231
|
-
end
|
232
|
-
|
233
|
-
def asin angle
|
234
|
-
ensure_numeric Math.asin angle.to_number
|
235
|
-
end
|
236
|
-
|
237
|
-
def asinh angle
|
238
|
-
ensure_numeric Math.asinh angle.to_number
|
239
|
-
end
|
240
|
-
|
241
|
-
def atan angle
|
242
|
-
ensure_numeric Math.atan angle.to_number
|
243
|
-
end
|
244
|
-
|
245
|
-
def atanh angle
|
246
|
-
ensure_numeric Math.atanh angle.to_number
|
247
|
-
end
|
248
|
-
|
249
|
-
def b expressions
|
250
|
-
html_tag :b, expressions
|
251
|
-
end
|
252
|
-
|
253
102
|
def backquote
|
254
103
|
"`"
|
255
104
|
end
|
@@ -258,375 +107,10 @@ module Teepee
|
|
258
107
|
"\\"
|
259
108
|
end
|
260
109
|
|
261
|
-
def big expressions
|
262
|
-
html_tag :big, expressions
|
263
|
-
end
|
264
|
-
|
265
|
-
def bookmarks_folder_id id
|
266
|
-
id_command_handler id, :Folder, "folder", "folders", "folders/bookmarks_inline", "bookmarks"
|
267
|
-
end
|
268
|
-
|
269
|
-
def boolean_and booleans
|
270
|
-
if booleans.empty?
|
271
|
-
return true_constant
|
272
|
-
end
|
273
|
-
b = booleans.first.to_html
|
274
|
-
if false_constant? b
|
275
|
-
false_constant
|
276
|
-
elsif true_constant? b or booleans.first.kind_of? WhitespaceToken
|
277
|
-
boolean_and booleans[1..-1]
|
278
|
-
else
|
279
|
-
command_error "Not a boolean value #{booleans.first}"
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
def boolean_nand booleans
|
284
|
-
boolean_not boolean_and booleans
|
285
|
-
end
|
286
|
-
|
287
|
-
def boolean_nor booleans
|
288
|
-
boolean_not boolean_or booleans
|
289
|
-
end
|
290
|
-
|
291
|
-
def boolean_not boolean
|
292
|
-
boolean = boolean.to_html
|
293
|
-
if true_constant? boolean
|
294
|
-
false_constant
|
295
|
-
elsif false_constant? boolean
|
296
|
-
true_constant
|
297
|
-
else
|
298
|
-
command_error "Not a boolean value"
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
def boolean_or booleans
|
303
|
-
if booleans.empty?
|
304
|
-
return false_constant
|
305
|
-
end
|
306
|
-
b = booleans.first.to_html
|
307
|
-
if true_constant? b
|
308
|
-
true_constant
|
309
|
-
elsif false_constant? b or booleans.first.kind_of? WhitespaceToken
|
310
|
-
boolean_or booleans[1..-1]
|
311
|
-
else
|
312
|
-
command_error "Not a boolean value"
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
def boolean_xnor booleans
|
317
|
-
boolean_not boolean_xor booleans
|
318
|
-
end
|
319
|
-
|
320
|
-
def boolean_xor booleans
|
321
|
-
# There are two schools of thought as to what a multi-variable XOR is.
|
322
|
-
# 1. Chained XORs, giving a parity check.
|
323
|
-
# 2. 'Exclusively' one true for ALL inputs.
|
324
|
-
# I'm going with the second: one and only one true, the rest false.
|
325
|
-
# It seems therefore that the zero-argument version should be false then.
|
326
|
-
if booleans.empty?
|
327
|
-
false_constant
|
328
|
-
else
|
329
|
-
any_trues = false
|
330
|
-
booleans.each do |boolean|
|
331
|
-
if true_constant? boolean
|
332
|
-
if any_trues
|
333
|
-
return false_constant
|
334
|
-
else
|
335
|
-
any_trues = true
|
336
|
-
end
|
337
|
-
elsif false_constant? boolean
|
338
|
-
# do nothing
|
339
|
-
elsif boolean.kind_of? WhitespaceToken
|
340
|
-
# do nothing
|
341
|
-
else
|
342
|
-
return command_error "Not a boolean value"
|
343
|
-
end
|
344
|
-
end
|
345
|
-
return any_trues.to_html
|
346
|
-
end
|
347
|
-
end
|
348
|
-
|
349
|
-
def br
|
350
|
-
html_tag :br, nil
|
351
|
-
end
|
352
|
-
|
353
|
-
def case_operator expressions
|
354
|
-
value, _, *rest = strip expressions
|
355
|
-
if value and not rest.empty?
|
356
|
-
def cond_helper value, expressions
|
357
|
-
test_value, _, form, *rest = strip expressions
|
358
|
-
if equal [value.to_html, test_value.to_html]
|
359
|
-
form
|
360
|
-
elsif not rest.empty?
|
361
|
-
cond_helper value, rest
|
362
|
-
end
|
363
|
-
end
|
364
|
-
cond_helper value, rest
|
365
|
-
end
|
366
|
-
end
|
367
|
-
|
368
|
-
def ceiling number
|
369
|
-
ensure_numeric number.to_number.ceil
|
370
|
-
end
|
371
|
-
|
372
|
-
def comment expressions
|
373
|
-
nil
|
374
|
-
end
|
375
|
-
|
376
|
-
def cond_operator expressions
|
377
|
-
conditional, _, form, *rest = strip expressions
|
378
|
-
if true_constant? conditional.to_html
|
379
|
-
form
|
380
|
-
elsif not rest.empty?
|
381
|
-
cond_operator rest
|
382
|
-
end
|
383
|
-
end
|
384
|
-
|
385
|
-
def cos angle
|
386
|
-
ensure_numeric Math.cos angle.to_number
|
387
|
-
end
|
388
|
-
|
389
|
-
def cosh angle
|
390
|
-
ensure_numeric Math.cosh angle.to_number
|
391
|
-
end
|
392
|
-
|
393
|
-
def decrement variable
|
394
|
-
return variable_not_defined_error variable if not is_defined? variable
|
395
|
-
old_value = get_operator(variable).to_number
|
396
|
-
return non_numeric_error old_value if not numeric? old_value
|
397
|
-
@parser.variables[variable.to_html] = old_value - 1
|
398
|
-
end
|
399
|
-
|
400
|
-
def define expressions
|
401
|
-
variable, _, value = expressions
|
402
|
-
k = variable.to_html
|
403
|
-
v = value.to_html
|
404
|
-
@parser.variables[k] = v
|
405
|
-
get_operator k
|
406
|
-
end
|
407
|
-
|
408
|
-
def is_defined? variables
|
409
|
-
if not variables.is_a? Array
|
410
|
-
return is_defined? [variables]
|
411
|
-
elsif Set.new(variables.map(&:to_html)).subset? Set.new(@parser.variables.keys)
|
412
|
-
true_constant
|
413
|
-
else
|
414
|
-
false_constant
|
415
|
-
end
|
416
|
-
end
|
417
|
-
|
418
|
-
def degrees2radians degrees
|
419
|
-
ensure_numeric degrees.to_number * Math::PI / 180.0
|
420
|
-
end
|
421
|
-
|
422
|
-
def del expressions
|
423
|
-
html_tag :del, expressions
|
424
|
-
end
|
425
|
-
|
426
110
|
def dollar
|
427
111
|
"$"
|
428
112
|
end
|
429
113
|
|
430
|
-
def dotimes expressions
|
431
|
-
n = expressions.first.to_number
|
432
|
-
return "" if n.nil? or n < 1
|
433
|
-
span_operator expressions[1..-1] * n
|
434
|
-
end
|
435
|
-
|
436
|
-
def e
|
437
|
-
Math::E
|
438
|
-
end
|
439
|
-
|
440
|
-
def equal expressions
|
441
|
-
if expressions.empty?
|
442
|
-
true_constant
|
443
|
-
elsif expressions.length == 1
|
444
|
-
true_constant
|
445
|
-
else
|
446
|
-
expressions[0].to_html == expressions[1].to_html and equal expressions.rest
|
447
|
-
end
|
448
|
-
end
|
449
|
-
|
450
|
-
def enumerate expressions
|
451
|
-
html_tag :ol, expressions
|
452
|
-
end
|
453
|
-
|
454
|
-
def enumerate_numeric expressions
|
455
|
-
html_tag :ol, expressions, {type: "1"}
|
456
|
-
end
|
457
|
-
|
458
|
-
def enumerate_uppercase expressions
|
459
|
-
html_tag :ol, expressions, {type: "A"}
|
460
|
-
end
|
461
|
-
|
462
|
-
def enumerate_lowercase expressions
|
463
|
-
html_tag :ol, expressions, {type: "a"}
|
464
|
-
end
|
465
|
-
|
466
|
-
def enumerate_roman_uppercase expressions
|
467
|
-
html_tag :ol, expressions, {type: "I"}
|
468
|
-
end
|
469
|
-
|
470
|
-
def enumerate_roman_lowercase expressions
|
471
|
-
html_tag :ol, expressions, {type: "i"}
|
472
|
-
end
|
473
|
-
|
474
|
-
def erf number
|
475
|
-
ensure_numeric Math.erf number.to_number
|
476
|
-
end
|
477
|
-
|
478
|
-
def erfc number
|
479
|
-
ensure_numeric Math.erfc number.to_number
|
480
|
-
end
|
481
|
-
|
482
|
-
def false_constant
|
483
|
-
"false"
|
484
|
-
end
|
485
|
-
|
486
|
-
def floor number
|
487
|
-
ensure_numeric number.to_number.floor
|
488
|
-
end
|
489
|
-
|
490
|
-
def folder_id id
|
491
|
-
id_command_handler id, :Folder
|
492
|
-
end
|
493
|
-
|
494
|
-
def forum_id id
|
495
|
-
id_command_handler id, :Forum
|
496
|
-
end
|
497
|
-
|
498
|
-
def gamma number
|
499
|
-
ensure_numeric Math.gamma number.to_number
|
500
|
-
end
|
501
|
-
|
502
|
-
def get_operator variable
|
503
|
-
@parser.variables[variable.to_html].to_html
|
504
|
-
end
|
505
|
-
|
506
|
-
def greater_than numbers
|
507
|
-
if numbers.empty?
|
508
|
-
true_constant
|
509
|
-
elsif numbers.length == 1
|
510
|
-
true_constant
|
511
|
-
else
|
512
|
-
numbers[0].to_number > numbers[1].to_number and greater_than numbers.rest
|
513
|
-
end
|
514
|
-
end
|
515
|
-
|
516
|
-
def greater_than_or_equal numbers
|
517
|
-
if numbers.empty?
|
518
|
-
true_constant
|
519
|
-
elsif numbers.length == 1
|
520
|
-
true_constant
|
521
|
-
else
|
522
|
-
numbers[0].to_number >= numbers[1].to_number and greater_than_or_equal numbers.rest
|
523
|
-
end
|
524
|
-
end
|
525
|
-
|
526
|
-
def h1 expressions
|
527
|
-
html_tag :h1, expressions
|
528
|
-
end
|
529
|
-
|
530
|
-
def h2 expressions
|
531
|
-
html_tag :h2, expressions
|
532
|
-
end
|
533
|
-
|
534
|
-
def h3 expressions
|
535
|
-
html_tag :h3, expressions
|
536
|
-
end
|
537
|
-
|
538
|
-
def h4 expressions
|
539
|
-
html_tag :h4, expressions
|
540
|
-
end
|
541
|
-
|
542
|
-
def h5 expressions
|
543
|
-
html_tag :h5, expressions
|
544
|
-
end
|
545
|
-
|
546
|
-
def h6 expressions
|
547
|
-
html_tag :h6, expressions
|
548
|
-
end
|
549
|
-
|
550
|
-
def i
|
551
|
-
command_error "Complex numbers are not yet supported."
|
552
|
-
end
|
553
|
-
|
554
|
-
def if_operator expressions
|
555
|
-
expressions = strip expressions
|
556
|
-
conditional, _, true_clause, _, false_clause = expressions
|
557
|
-
if true_constant? conditional.to_html
|
558
|
-
true_clause.to_html
|
559
|
-
elsif false_clause
|
560
|
-
false_clause.to_html
|
561
|
-
end
|
562
|
-
end
|
563
|
-
|
564
|
-
def image expressions
|
565
|
-
expressions = strip expressions
|
566
|
-
uri, *alt_text = expressions
|
567
|
-
uri = ERB::Util.html_escape uri.to_html
|
568
|
-
if not valid_uri? uri
|
569
|
-
command_error "Not a valid URI for the image."
|
570
|
-
else
|
571
|
-
if alt_text.empty?
|
572
|
-
html_tag :img, nil, {src: uri}
|
573
|
-
else
|
574
|
-
html_tag :img, nil, {src: uri, alt: alt_text.map(&:to_html).join.strip}
|
575
|
-
end
|
576
|
-
end
|
577
|
-
end
|
578
|
-
|
579
|
-
def increment variable
|
580
|
-
return variable_not_defined_error variable if not is_defined? variable
|
581
|
-
old_value = get_operator(variable).to_number
|
582
|
-
return non_numeric_error old_value if not numeric? old_value
|
583
|
-
@parser.variables[variable.to_html] = old_value + 1
|
584
|
-
end
|
585
|
-
|
586
|
-
def it expressions
|
587
|
-
html_tag :i, expressions
|
588
|
-
end
|
589
|
-
|
590
|
-
def item expressions
|
591
|
-
html_tag :li, expressions
|
592
|
-
end
|
593
|
-
|
594
|
-
def itemize expressions
|
595
|
-
html_tag :ul, expressions
|
596
|
-
end
|
597
|
-
|
598
|
-
def itemize_disc expressions
|
599
|
-
html_tag :ul, expressions, {style: "list-style-type:disc"}
|
600
|
-
end
|
601
|
-
|
602
|
-
def itemize_circle expressions
|
603
|
-
html_tag :ul, expressions, {style: "list-style-type:circle"}
|
604
|
-
end
|
605
|
-
|
606
|
-
def itemize_square expressions
|
607
|
-
html_tag :ul, expressions, {style: "list-style-type:square"}
|
608
|
-
end
|
609
|
-
|
610
|
-
def itemize_none expressions
|
611
|
-
html_tag :ul, expressions, {style: "list-style-type:none"}
|
612
|
-
end
|
613
|
-
|
614
|
-
def hypot numbers
|
615
|
-
ensure_numeric Math.sqrt to_numbers(numbers).map {|n| n**2}
|
616
|
-
end
|
617
|
-
|
618
|
-
def keyword_id id
|
619
|
-
id_command_handler id, :Keyword
|
620
|
-
end
|
621
|
-
|
622
|
-
def ld number
|
623
|
-
ensure_numeric Math.log2 number.to_number
|
624
|
-
end
|
625
|
-
|
626
|
-
def ldexp fraction, exponent
|
627
|
-
ensure_numeric Math.ldexp fraction.to_number, exponent.to_number
|
628
|
-
end
|
629
|
-
|
630
114
|
def left_brace
|
631
115
|
"{"
|
632
116
|
end
|
@@ -635,123 +119,10 @@ module Teepee
|
|
635
119
|
"["
|
636
120
|
end
|
637
121
|
|
638
|
-
def less_than numbers
|
639
|
-
if numbers.empty?
|
640
|
-
true_constant
|
641
|
-
elsif numbers.length == 1
|
642
|
-
true_constant
|
643
|
-
else
|
644
|
-
numbers[0].to_number < numbers[1].to_number and less_than numbers.rest
|
645
|
-
end
|
646
|
-
end
|
647
|
-
|
648
|
-
def less_than_or_equal numbers
|
649
|
-
if numbers.empty?
|
650
|
-
true_constant
|
651
|
-
elsif numbers.length == 1
|
652
|
-
true_constant
|
653
|
-
else
|
654
|
-
numbers[0].to_number <= numbers[1].to_number and less_than_or_equal numbers.rest
|
655
|
-
end
|
656
|
-
end
|
657
|
-
|
658
|
-
def lgamma number
|
659
|
-
ensure_numeric Math::lgamma(number.to_number).first
|
660
|
-
end
|
661
|
-
|
662
|
-
def link expressions
|
663
|
-
expressions = strip expressions
|
664
|
-
uri, *desc = expressions
|
665
|
-
uri = ERB::Util.html_escape uri.to_html
|
666
|
-
if not valid_uri? uri
|
667
|
-
command_error "Not a valid URI."
|
668
|
-
else
|
669
|
-
desc = [uri] if desc.empty?
|
670
|
-
html_tag :a, desc, {href: uri}
|
671
|
-
end
|
672
|
-
end
|
673
|
-
|
674
|
-
def link_id id
|
675
|
-
id_command_handler id, :Link
|
676
|
-
end
|
677
|
-
|
678
|
-
def ln number
|
679
|
-
ensure_numeric Math.log number.to_number
|
680
|
-
end
|
681
|
-
|
682
|
-
def log base, number
|
683
|
-
if number.nil?
|
684
|
-
number, base = base, number
|
685
|
-
ensure_numeric Math.log10 number.to_number # default to log base 10
|
686
|
-
else
|
687
|
-
ensure_numeric Math.log number.to_number, base.to_number
|
688
|
-
end
|
689
|
-
end
|
690
|
-
|
691
|
-
def log10 number
|
692
|
-
ensure_numeric Math.log10 number.to_number
|
693
|
-
end
|
694
|
-
|
695
|
-
def mailto email_address
|
696
|
-
email_address = email_address.to_html
|
697
|
-
if valid_email_address? email_address
|
698
|
-
html_tag :a, [email_address], {href: "mailto:#{email_address}"}
|
699
|
-
else
|
700
|
-
command_error "I'm not sure that's a valid email address."
|
701
|
-
end
|
702
|
-
end
|
703
|
-
|
704
|
-
def mod numbers
|
705
|
-
ensure_numeric to_numbers(numbers).reduce :%
|
706
|
-
end
|
707
|
-
|
708
|
-
def nbsp count
|
709
|
-
if count and count.to_number and count.to_number > 0
|
710
|
-
" " * count.to_number
|
711
|
-
else
|
712
|
-
" "
|
713
|
-
end
|
714
|
-
end
|
715
|
-
|
716
|
-
def not_equal numbers
|
717
|
-
if numbers.empty?
|
718
|
-
true_constant
|
719
|
-
elsif numbers.length == 1
|
720
|
-
true_constant
|
721
|
-
else
|
722
|
-
numbers[0].to_number != numbers[1].to_number and equal numbers.rest
|
723
|
-
end
|
724
|
-
end
|
725
|
-
|
726
|
-
def note_id id
|
727
|
-
id_command_handler id, :Note
|
728
|
-
end
|
729
|
-
|
730
|
-
def pi
|
731
|
-
Math::PI
|
732
|
-
end
|
733
|
-
|
734
122
|
def pipe
|
735
123
|
"|"
|
736
124
|
end
|
737
125
|
|
738
|
-
def prog1_operator expressions
|
739
|
-
expressions.map(&:to_html).first
|
740
|
-
end
|
741
|
-
|
742
|
-
def progn_operator expressions
|
743
|
-
expressions.map(&:to_html).last
|
744
|
-
end
|
745
|
-
|
746
|
-
def prognil expressions
|
747
|
-
expressions.map(&:to_html)
|
748
|
-
""
|
749
|
-
end
|
750
|
-
|
751
|
-
def radians2degrees radians
|
752
|
-
ensure_numeric(radians.to_number * 180.0 / Math::PI)
|
753
|
-
end
|
754
|
-
|
755
126
|
def right_brace
|
756
127
|
"}"
|
757
128
|
end
|
@@ -760,129 +131,12 @@ module Teepee
|
|
760
131
|
"]"
|
761
132
|
end
|
762
133
|
|
763
|
-
def round number, precision = nil, *_
|
764
|
-
if precision.nil? or precision.to_number.nil?
|
765
|
-
ensure_numeric number.to_number.round
|
766
|
-
else
|
767
|
-
ensure_numeric number.to_number.round precision.to_number
|
768
|
-
end
|
769
|
-
end
|
770
|
-
|
771
|
-
def sin angle
|
772
|
-
ensure_numeric Math.sin angle.to_number
|
773
|
-
end
|
774
|
-
|
775
|
-
def sinh angle
|
776
|
-
ensure_numeric Math.sinh angle.to_number
|
777
|
-
end
|
778
|
-
|
779
|
-
def small expressions
|
780
|
-
html_tag :small, expressions
|
781
|
-
end
|
782
|
-
|
783
134
|
def squiggle
|
784
135
|
"~"
|
785
136
|
end
|
786
137
|
|
787
|
-
def sqrt number
|
788
|
-
ensure_numeric Math.sqrt number.to_number
|
789
|
-
end
|
790
|
-
|
791
138
|
def space
|
792
139
|
" "
|
793
140
|
end
|
794
|
-
|
795
|
-
def span_operator expressions
|
796
|
-
html_tag :span, expressions
|
797
|
-
end
|
798
|
-
|
799
|
-
def sub expressions
|
800
|
-
html_tag :sub, expressions
|
801
|
-
end
|
802
|
-
|
803
|
-
def sup expressions
|
804
|
-
html_tag :sup, expressions
|
805
|
-
end
|
806
|
-
|
807
|
-
def table expressions
|
808
|
-
html_tag :table, expressions
|
809
|
-
end
|
810
|
-
|
811
|
-
def table_data expressions
|
812
|
-
html_tag :td, expressions
|
813
|
-
end
|
814
|
-
|
815
|
-
def table_header expressions
|
816
|
-
html_tag :th, expressions
|
817
|
-
end
|
818
|
-
|
819
|
-
def table_row expressions
|
820
|
-
html_tag :tr, expressions
|
821
|
-
end
|
822
|
-
|
823
|
-
def tag_id id
|
824
|
-
id_command_handler id, :Tag
|
825
|
-
end
|
826
|
-
|
827
|
-
def tan angle
|
828
|
-
ensure_numeric Math.tan angle.to_number
|
829
|
-
end
|
830
|
-
|
831
|
-
def tanh angle
|
832
|
-
ensure_numeric Math.tanh angle.to_number
|
833
|
-
end
|
834
|
-
|
835
|
-
def true_constant
|
836
|
-
"true"
|
837
|
-
end
|
838
|
-
|
839
|
-
def tt expressions
|
840
|
-
html_tag :tt, expressions
|
841
|
-
end
|
842
|
-
|
843
|
-
def u expressions
|
844
|
-
html_tag :u, expressions
|
845
|
-
end
|
846
|
-
|
847
|
-
def undefine expressions
|
848
|
-
expressions.each do |expression|
|
849
|
-
@parser.variables.delete expression.to_html
|
850
|
-
end
|
851
|
-
""
|
852
|
-
end
|
853
|
-
|
854
|
-
def unless_operator expressions
|
855
|
-
expressions = strip expressions
|
856
|
-
conditional = expressions.first
|
857
|
-
expressions = strip expressions.rest
|
858
|
-
if false_constant? conditional.to_html
|
859
|
-
if expressions.length <= 1
|
860
|
-
expressions.first
|
861
|
-
else
|
862
|
-
span_operator expressions
|
863
|
-
end
|
864
|
-
end
|
865
|
-
end
|
866
|
-
|
867
|
-
def user user
|
868
|
-
if not user
|
869
|
-
command_error "user: error: no user specified"
|
870
|
-
else
|
871
|
-
tb_href "users/#{user}", user.to_html
|
872
|
-
end
|
873
|
-
end
|
874
|
-
|
875
|
-
def when_operator expressions
|
876
|
-
expressions = strip expressions
|
877
|
-
conditional = expressions.first
|
878
|
-
expressions = strip expressions.rest
|
879
|
-
if true_constant? conditional.to_html
|
880
|
-
if expressions.length <= 1
|
881
|
-
expressions.first
|
882
|
-
else
|
883
|
-
span_operator expressions
|
884
|
-
end
|
885
|
-
end
|
886
|
-
end
|
887
141
|
end
|
888
142
|
end
|