teepee 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,89 @@
1
+ # -*- coding: utf-8 -*-
2
+ # -*- mode: Ruby -*-
3
+
4
+ # Copyright © 2013-2015, 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
+ require 'active_support/all'
39
+ require 'monkey-patch'
40
+
41
+ require 'teepee/constants'
42
+ require 'teepee/errors'
43
+ require 'teepee/commander'
44
+
45
+ include ERB::Util
46
+
47
+ module Teepee
48
+ class ActionableCommander < Commander
49
+ def initialize action_view, controller
50
+ @action_view = action_view
51
+ @controller = controller
52
+ end
53
+
54
+ def id_command_handler(id,
55
+ klass,
56
+ singular = klass.to_s.camelcase_to_snakecase,
57
+ plural = singular.pluralize,
58
+ partial = "#{plural}/inline",
59
+ view="")
60
+ if not id
61
+ command_error "#{singular}_id: error: no #{singular} ID specified"
62
+ elsif not id.to_s =~ /\A[0-9]+\z/
63
+ command_error "#{singular}_id: error: invalid #{singular} ID specified"
64
+ else
65
+ thing = klass.find Integer(id.to_s)
66
+ if thing
67
+ @@action_view.render partial: partial,
68
+ locals: {singular.to_sym => thing}
69
+ else
70
+ command_error "unknown #{singular} ID #{id.to_s}"
71
+ end
72
+ end
73
+ end
74
+
75
+ def user user
76
+ if not user
77
+ command_error "user: error: no user specified"
78
+ else
79
+ the_user = User.smart_find user.to_s
80
+ if the_user
81
+ @action_view.render partial: 'users/name_link',
82
+ locals: {the_user: the_user}
83
+ else
84
+ command_error "unknown user #{user.to_s}"
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,268 @@
1
+ # -*- coding: utf-8 -*-
2
+ # -*- mode: Ruby -*-
3
+
4
+ # Copyright © 2013-2015, 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
+ require 'active_support/all'
39
+ require 'monkey-patch'
40
+
41
+ require 'teepee/constants'
42
+ require 'teepee/errors'
43
+ require 'teepee/parser-node'
44
+ require 'teepee/commander'
45
+ require 'teepee/actionable-commander'
46
+
47
+ module Teepee
48
+ class CommandParser < ParserNode
49
+ attr_reader :command, :expressions
50
+
51
+ def initialize(command, expressions)
52
+ raise ArgumentError if not command.is_a? WordToken
53
+ @command = command
54
+ raise ArgumentError if not expressions.is_a? Array
55
+ expressions.each do |expression|
56
+ raise ArgumentError if not expression.kind_of? ParserNode
57
+ end
58
+ @expressions = expressions
59
+ end
60
+
61
+ def command_error(message)
62
+ %{<span style="color: red">[#{message}]</span>}
63
+ end
64
+
65
+ def to_html
66
+ case command.word
67
+ when "backslash", "bslash"
68
+ @@commander.backslash
69
+ when "left-brace",
70
+ "left_brace",
71
+ "leftbrace",
72
+ "lbrace",
73
+ "opening-brace",
74
+ "opening_brace",
75
+ "openingbrace",
76
+ "obrace"
77
+ @@commander.left_brace
78
+ when "right-brace",
79
+ "right_brace",
80
+ "rightbrace",
81
+ "rbrace",
82
+ "closing-brace",
83
+ "closing_brace",
84
+ "closingbrace",
85
+ "cbrace"
86
+ @@commander.right_brace
87
+ when "br", "newline"
88
+ @@commander.br
89
+ when "bold", "b", "textbf"
90
+ @@commander.b expressions
91
+ when "del",
92
+ "s",
93
+ "strike",
94
+ "strikethrough",
95
+ "strikeout"
96
+ @@commander.del expressions
97
+ when "i"
98
+ @@commander.i
99
+ when "italic",
100
+ "textit",
101
+ "it"
102
+ @@commander.it expressions
103
+ when "underline",
104
+ "u"
105
+ @@commander.u expressions
106
+ when "tt",
107
+ "texttt",
108
+ "teletype",
109
+ "typewriter"
110
+ @@commander.tt expressions
111
+ when "small"
112
+ @@commander.small expressions
113
+ when "big"
114
+ @@commander.big expressions
115
+ when "subscript",
116
+ "sub"
117
+ @@commander.sub expressions
118
+ when "superscript",
119
+ "sup"
120
+ @@commander.sup expressions
121
+ when "user",
122
+ "user-id",
123
+ "user_id"
124
+ @@commander.user first_word_token
125
+ when "link-id",
126
+ "link_id"
127
+ @@commander.link_id first_word_token
128
+ when "keyword-id",
129
+ "keyword_id"
130
+ @@commander.keyword_id first_word_token
131
+ when "tag-id",
132
+ "tag_id"
133
+ @@commander.tag_id first_word_token
134
+ when "forum-id",
135
+ "forum_id"
136
+ @@commander.forum_id first_word_token
137
+ when "folder-id",
138
+ "folder_id"
139
+ @@commander.folder_id first_word_token
140
+ when "bookmarks-folder-id",
141
+ "bookmarks_folder_id",
142
+ "bookmarks_folder-id",
143
+ "bookmarks-folder_id",
144
+ "bookmark-folder-id",
145
+ "bookmark_folder_id",
146
+ "bookmark_folder-id",
147
+ "bookmark-folder_id"
148
+ @@commander.bookmarks_folder_id first_word_token
149
+ when "pi"
150
+ @@commander.pi
151
+ when "e"
152
+ @@commander.e
153
+ when "+"
154
+ @@commander.+ *numbers_from_expressions
155
+ when "-"
156
+ @@commander.- *numbers_from_expressions
157
+ when "*"
158
+ @@commander.* *numbers_from_expressions
159
+ when "/"
160
+ @@commander./ *numbers_from_expressions
161
+ when "%"
162
+ @@commander.% *numbers_from_expressions
163
+ when "^", "**"
164
+ @@commander.** *numbers_from_expressions
165
+ when "sin", "cos", "tan",
166
+ "asin", "acos", "atan",
167
+ "sinh", "cosh", "tanh",
168
+ "asinh", "acosh", "atanh",
169
+ "erf", "erfc",
170
+ "gamma", "log10", "sqrt"
171
+ @@commander.send command.word.to_sym, number_from_expression
172
+ when "d2r",
173
+ "deg->rad",
174
+ "degrees->radians"
175
+ @@commander.degrees2radians number_from_expression
176
+ when "r2d",
177
+ "rad->deg",
178
+ "radians->degrees"
179
+ @@commander.radians2degrees number_from_expression
180
+ when "lgamma"
181
+ @@commander.lgamma number_from_expression
182
+ when "ld",
183
+ "log2"
184
+ @@commander.ld number_from_expression
185
+ when "ln"
186
+ @@commander.ln number_from_expression
187
+ when "log"
188
+ base, number = numbers_from_expressions
189
+ @@commander.log base, number
190
+ when "ldexp"
191
+ fraction, exponent = numbers_from_expressions
192
+ @@commander.ldexp fraction, exponent
193
+ when "hypot"
194
+ @@commander.hypot numbers_from_expressions
195
+ else
196
+ command_error "unknown command #{command.to_html}"
197
+ end
198
+ end
199
+
200
+ def html_tag(tag)
201
+ "<#{tag}>" + expressions.map(&:to_html).join + "</#{tag}>"
202
+ end
203
+
204
+ def tb_href(target, string)
205
+ %{<a href="#{TB_COM}/#{target}">#{string}</a>}
206
+ end
207
+
208
+ def first_word_token
209
+ expressions.select {|expr| expr.is_a? WordToken}.first
210
+ end
211
+
212
+ def numbers_from_expressions
213
+ expressions
214
+ .map do |number|
215
+ begin
216
+ Float(number.to_html)
217
+ rescue ArgumentError
218
+ nil
219
+ end
220
+ end.reject &:nil?
221
+ end
222
+
223
+ def number_from_expression
224
+ numbers_from_expressions.first
225
+ end
226
+
227
+ class << self
228
+ @@commander = Commander.new
229
+ @@action_view = nil
230
+ @@controller = nil
231
+
232
+ def parse(tokens)
233
+ expressions = []
234
+ rest = tokens
235
+ backslash, command, left_brace = rest.shift(3)
236
+ right_brace = nil
237
+ raise ParseError if not backslash.is_a? BackslashToken
238
+ raise ParseError if not command.is_a? WordToken
239
+ if not left_brace.is_a? LeftBraceToken # A command with no interior.
240
+ rest.unshift left_brace if not left_brace.is_a? WhitespaceToken
241
+ return [CommandParser.new(command, []), rest]
242
+ end
243
+ while rest.length > 0
244
+ if rest.first.is_a? WordToken
245
+ expressions << rest.shift
246
+ elsif rest.first.is_a? WhitespaceToken
247
+ expressions << rest.shift
248
+ elsif rest.first.is_a? BackslashToken
249
+ result, rest = CommandParser.parse(rest)
250
+ expressions << result
251
+ elsif rest.first.is_a? RightBraceToken
252
+ right_brace = rest.shift
253
+ return [CommandParser.new(command, expressions), rest]
254
+ else
255
+ raise ParseError
256
+ end
257
+ end
258
+ if right_brace.nil? # Allow a forgotten final right brace.
259
+ return [CommandParser.new(command, expressions), rest]
260
+ end
261
+ end
262
+
263
+ def commander= new
264
+ @@commander = new
265
+ end
266
+ end
267
+ end
268
+ end
@@ -0,0 +1,320 @@
1
+ # -*- coding: utf-8 -*-
2
+ # -*- mode: Ruby -*-
3
+
4
+ # Copyright © 2013-2015, 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
+ require 'active_support/all'
39
+ require 'monkey-patch'
40
+
41
+ require 'teepee/constants'
42
+ require 'teepee/errors'
43
+
44
+ include ERB::Util
45
+
46
+ module Teepee
47
+ class Commander
48
+ def command_error message
49
+ %{<span style="color: red">[#{message}]</span>}
50
+ end
51
+
52
+ def command_not_yet_implemented command
53
+ command_error "The command #{command} is not yet implemented."
54
+ end
55
+
56
+ def ensure_numeric number
57
+ if number.kind_of? Complex
58
+ command_error "Complex numbers are not yet supported."
59
+ elsif not number.kind_of? Numeric
60
+ command_error "Non-numeric result."
61
+ else
62
+ number
63
+ end
64
+ end
65
+
66
+ def html_tag tag, expressions
67
+ "<#{tag}>" + expressions.map(&:to_html).join + "</#{tag}>"
68
+ end
69
+
70
+ def tb_href target, string
71
+ %{<a href="#{TB_COM}/#{target}">#{string}</a>}
72
+ end
73
+
74
+ def id_command_handler(id,
75
+ klass,
76
+ singular = klass.to_s.camelcase_to_snakecase,
77
+ plural = singular.pluralize,
78
+ partial = "#{plural}/inline",
79
+ view="")
80
+ if not id
81
+ command_error "#{singular}_id: error: no #{singular} ID specified"
82
+ elsif not id.to_s =~ /\A[0-9]+\z/
83
+ command_error "#{singular}_id: error: invalid #{singular} ID specified"
84
+ else
85
+ tb_href "/#{plural}/#{id.to_s}/#{view}", "#{klass} ##{id.to_s}"
86
+ end
87
+ end
88
+
89
+ #----------------------------------------------------------------------------
90
+
91
+ def + *numbers
92
+ ensure_numeric numbers.inject 0, :+
93
+ end
94
+
95
+ def - *numbers
96
+ if numbers.length == 1
97
+ ensure_numeric -numbers.first
98
+ else
99
+ ensure_numeric numbers.reduce :-
100
+ end
101
+ end
102
+
103
+ def * *numbers
104
+ ensure_numeric numbers.inject 1, :*
105
+ end
106
+
107
+ def / *numbers
108
+ if numbers.length == 1
109
+ ensure_numeric 1 / numbers.first
110
+ else
111
+ ensure_numeric numbers.reduce :/
112
+ end
113
+ end
114
+
115
+ def % *numbers
116
+ ensure_numeric numbers.reduce :%
117
+ end
118
+
119
+ def ** *numbers
120
+ ensure_numeric numbers.reduce :**
121
+ end
122
+
123
+ def acos number
124
+ ensure_numeric Math.acos number
125
+ end
126
+
127
+ def acosh number
128
+ ensure_numeric Math.acosh number
129
+ end
130
+
131
+ def asin number
132
+ ensure_numeric Math.asin number
133
+ end
134
+
135
+ def asinh number
136
+ ensure_numeric Math.asinh number
137
+ end
138
+
139
+ def atan number
140
+ ensure_numeric Math.atan number
141
+ end
142
+
143
+ def atanh number
144
+ ensure_numeric Math.atanh number
145
+ end
146
+
147
+ def b expressions
148
+ html_tag :b, expressions
149
+ end
150
+
151
+ def backslash
152
+ "\\"
153
+ end
154
+
155
+ def big expressions
156
+ html_tag :big, expressions
157
+ end
158
+
159
+ def bookmarks_folder_id id
160
+ id_command_handler id, Folder, "folder", "folders", "folders/bookmarks_inline", "bookmarks"
161
+ end
162
+
163
+ def br
164
+ "\n</br>\n"
165
+ end
166
+
167
+ def cos angle
168
+ ensure_numeric Math.cos angle
169
+ end
170
+
171
+ def cosh number
172
+ ensure_numeric Math.cosh number
173
+ end
174
+
175
+ def degrees2radians degrees
176
+ ensure_numeric degrees * Math::PI / 180.0
177
+ end
178
+
179
+ def del expressions
180
+ html_tag :del, expressions
181
+ end
182
+
183
+ def e
184
+ Math::E
185
+ end
186
+
187
+ def erf number
188
+ ensure_numeric Math.erf number
189
+ end
190
+
191
+ def erfc number
192
+ ensure_numeric Math.erfc number
193
+ end
194
+
195
+ def folder_id id
196
+ id_command_handler id, Folder
197
+ end
198
+
199
+ def forum_id id
200
+ id_command_handler id, Forum
201
+ end
202
+
203
+ def gamma number
204
+ ensure_numeric Math.gamma number
205
+ end
206
+
207
+ def i
208
+ command_error "Complex numbers are not yet supported."
209
+ end
210
+
211
+ def it expressions
212
+ html_tag :i, expressions
213
+ end
214
+
215
+ def hypot numbers
216
+ ensure_numeric Math.sqrt numbers.map {|n| n**2}
217
+ end
218
+
219
+ def ld n
220
+ ensure_numeric Math.log2 n
221
+ end
222
+
223
+ def ldexp fraction, exponent
224
+ ensure_numeric Math.ldexp fraction, exponent
225
+ end
226
+
227
+ def left_brace
228
+ "{"
229
+ end
230
+
231
+ def lgamma n
232
+ ensure_numeric Math::lgamma(n).first
233
+ end
234
+
235
+ def link_id
236
+ id_command_handler id, Link
237
+ end
238
+
239
+ def ln number
240
+ ensure_numeric Math.log number
241
+ end
242
+
243
+ def log base, number
244
+ if number.nil?
245
+ number, base = base, number
246
+ ensure_numeric Math.log number # default to natural logarithm
247
+ else
248
+ ensure_numeric Math.log number, base
249
+ end
250
+ end
251
+
252
+ def log10 number
253
+ ensure_numeric Math.log10 number
254
+ end
255
+
256
+ def pi
257
+ Math::PI
258
+ end
259
+
260
+ def radians2degrees radians
261
+ ensure_numeric(radians * 180.0 / Math::PI)
262
+ end
263
+
264
+ def right_brace
265
+ "}"
266
+ end
267
+
268
+ def sin angle
269
+ ensure_numeric Math.sin angle
270
+ end
271
+
272
+ def sinh number
273
+ ensure_numeric Math.sinh number
274
+ end
275
+
276
+ def small expressions
277
+ html_tag :small, expressions
278
+ end
279
+
280
+ def sqrt number
281
+ ensure_numeric Math.sqrt number
282
+ end
283
+
284
+ def sub expressions
285
+ html_tag :sub, expressions
286
+ end
287
+
288
+ def sup expressions
289
+ html_tag :sup, expressions
290
+ end
291
+
292
+ def tag_id id
293
+ id_command_handler id, Tag
294
+ end
295
+
296
+ def tan angle
297
+ ensure_numeric Math.tan angle
298
+ end
299
+
300
+ def tanh number
301
+ ensure_numeric Math.tanh number
302
+ end
303
+
304
+ def tt expressions
305
+ html_tag :tt, expressions
306
+ end
307
+
308
+ def u expressions
309
+ html_tag :u, expressions
310
+ end
311
+
312
+ def user user
313
+ if not user
314
+ command_error "user: error: no user specified"
315
+ else
316
+ tb_href "users/#{user}", user.to_s
317
+ end
318
+ end
319
+ end
320
+ end