Class: TBMX::CommandParser

Inherits:
ParserNode show all
Defined in:
lib/tbmx.rb

Constant Summary collapse

@@action_view =
nil
@@controller =
nil

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(command, expressions) ⇒ CommandParser

Returns a new instance of CommandParser.

Raises:

  • (ArgumentError)


254
255
256
257
258
259
260
# File 'lib/tbmx.rb', line 254

def initialize(command, expressions)
  raise ArgumentError if not command.is_a? WordToken
  @command = command
  raise ArgumentError if not expressions.is_a? Array
  expressions.each {|expression| raise ArgumentError if not expression.kind_of? ParserNode}
  @expressions = expressions
end

Instance Attribute Details

#commandObject (readonly)

Returns the value of attribute command.



252
253
254
# File 'lib/tbmx.rb', line 252

def command
  @command
end

#expressionsObject (readonly)

Returns the value of attribute expressions.



252
253
254
# File 'lib/tbmx.rb', line 252

def expressions
  @expressions
end

Class Method Details

.action_view=(new) ⇒ Object



504
505
506
# File 'lib/tbmx.rb', line 504

def action_view=(new)
  @@action_view = new
end

.controller=(new) ⇒ Object



508
509
510
# File 'lib/tbmx.rb', line 508

def controller=(new)
  @@controller = new
end

.parse(tokens) ⇒ Object

Raises:



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
# File 'lib/tbmx.rb', line 473

def parse(tokens)
  expressions = []
  rest = tokens
  backslash, command, left_brace = rest.shift(3)
  right_brace = nil
  raise ParseError if not backslash.is_a? BackslashToken
  raise ParseError if not command.is_a? WordToken
  if not left_brace.is_a? LeftBraceToken # A command with no interior.
    rest.unshift left_brace if not left_brace.is_a? WhitespaceToken
    return [CommandParser.new(command, []), rest]
  end
  while rest.length > 0
    if rest.first.is_a? WordToken
      expressions << rest.shift
    elsif rest.first.is_a? WhitespaceToken
      expressions << rest.shift
    elsif rest.first.is_a? BackslashToken
      result, rest = CommandParser.parse(rest)
      expressions << result
    elsif rest.first.is_a? RightBraceToken
      right_brace = rest.shift
      return [CommandParser.new(command, expressions), rest]
    else
      raise ParseError
    end
  end
  if right_brace.nil? # Allow a forgotten final right brace.
    return [CommandParser.new(command, expressions), rest]
  end
end

Instance Method Details

#bookmarks_folder_id_command_handlerObject



465
466
467
# File 'lib/tbmx.rb', line 465

def bookmarks_folder_id_command_handler
  id_command_handler Folder, "folder", "folders", "folders/bookmarks_inline", "bookmarks"
end

#command_error(message) ⇒ Object



262
263
264
# File 'lib/tbmx.rb', line 262

def command_error(message)
  %{<span style="color: red">[#{message}]</span>}
end

#folder_id_command_handlerObject



457
458
459
# File 'lib/tbmx.rb', line 457

def folder_id_command_handler
  id_command_handler Folder
end

#forum_id_command_handlerObject



461
462
463
# File 'lib/tbmx.rb', line 461

def forum_id_command_handler
  id_command_handler Forum
end

#html_tag(tag) ⇒ Object



370
371
372
# File 'lib/tbmx.rb', line 370

def html_tag(tag)
  "<#{tag}>" + expressions.map(&:to_html).join + "</#{tag}>"
end

#id_command_handler(klass, singular = klass.to_s.camelcase_to_snakecase, plural = singular.pluralize, partial = "#{plural}/inline", view = "") ⇒ Object



424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
# File 'lib/tbmx.rb', line 424

def id_command_handler(klass,
                       singular = klass.to_s.camelcase_to_snakecase,
                       plural = singular.pluralize,
                       partial = "#{plural}/inline",
                       view="")
  id = expressions.select {|expr| expr.is_a? WordToken}.first
  if not id
    command_error "#{singular}_id: error: no #{singular} ID specified"
  elsif not id.to_s =~ /\A[0-9]+\z/
    command_error "#{singular}_id: error: invalid #{singular} ID specified"
  else
    if @@action_view.kind_of? ActionView::Base
      thing = klass.find Integer(id.to_s)
      if thing
        @@action_view.render partial: partial,
                             locals: {singular.to_sym => thing}
      else
        command_error "unknown #{singular} ID #{id.to_s}"
      end
    else
      tb_href "/#{plural}/#{id.to_s}/#{view}", "#{klass} ##{id.to_s}"
    end
  end
end

#injectable_math_function_handler(initial, function) ⇒ Object



393
394
395
# File 'lib/tbmx.rb', line 393

def injectable_math_function_handler(initial, function)
  numbers_from_expressions.inject initial, function
end


449
450
451
# File 'lib/tbmx.rb', line 449

def link_id_command_handler
  id_command_handler Link
end

#math_function_handler(function) ⇒ Object



401
402
403
# File 'lib/tbmx.rb', line 401

def math_function_handler(function)
  Math.send function, numbers_from_expressions.first
end

#number_from_expressionObject



389
390
391
# File 'lib/tbmx.rb', line 389

def number_from_expression
  numbers_from_expressions.first
end

#numbers_from_expressionsObject



378
379
380
381
382
383
384
385
386
387
# File 'lib/tbmx.rb', line 378

def numbers_from_expressions
  expressions
    .map do |number|
      begin
        Float(number.to_html)
      rescue ArgumentError
        nil
      end
    end.reject &:nil?
end

#reducable_math_function_handler(function) ⇒ Object



397
398
399
# File 'lib/tbmx.rb', line 397

def reducable_math_function_handler(function)
  numbers_from_expressions.reduce function
end

#tag_id_command_handlerObject



453
454
455
# File 'lib/tbmx.rb', line 453

def tag_id_command_handler
  id_command_handler Tag
end

#tb_href(target, string) ⇒ Object



374
375
376
# File 'lib/tbmx.rb', line 374

def tb_href(target, string)
  %{<a href="#{TB_COM}/#{target}">#{string}</a>}
end

#to_htmlObject



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
# File 'lib/tbmx.rb', line 266

def to_html
  case command.word
  when "backslash", "bslash"
    "\\"
  when "left-brace", "left_brace", "leftbrace", "lbrace", "opening-brace", "opening_brace",
       "openingbrace", "obrace"
    "{"
  when "right-brace", "right_brace", "rightbrace", "rbrace", "closing-brace", "closing_brace",
       "closingbrace", "cbrace"
    "}"
  when "br", "newline"
    "\n</br>\n"
  when "bold", "b", "textbf"
    html_tag :b
  when "del", "s", "strike", "strikethrough", "strikeout"
    html_tag :del
  when "italic", "i", "textit"
    html_tag :i
  when "underline", "u"
    html_tag :u
  when "tt", "texttt", "teletype", "typewriter"
    html_tag :tt
  when "small"
    html_tag :small
  when "big"
    html_tag :big
  when "subscript", "sub"
    html_tag :sub
  when "superscript", "sup"
    html_tag :sup
  when "user", "user-id", "user_id"
    user_command_handler
  when "link-id", "link_id"
    link_id_command_handler
  when "keyword-id", "keyword_id"
    keyword_id_command_handler
  when "tag-id", "tag_id"
    tag_id_command_handler
  when "forum-id", "forum_id"
    forum_id_command_handler
  when "folder-id", "folder_id"
    folder_id_command_handler
  when "bookmarks-folder-id", "bookmarks_folder_id", "bookmarks_folder-id", "bookmarks-folder_id",
       "bookmark-folder-id",  "bookmark_folder_id",  "bookmark_folder-id",  "bookmark-folder_id"
    bookmarks_folder_id_command_handler
  when "pi"
    "#{Math::PI}"
  when "e"
    "#{Math::E}"
  when "+"
    injectable_math_function_handler 0, :+
  when "-"
    if (numbers = numbers_from_expressions).length == 1
      injectable_math_function_handler 0, :-
    else
      reducable_math_function_handler :-
    end
  when "*"
    injectable_math_function_handler 1, :*
  when "/"
    if (numbers = numbers_from_expressions).length == 1
      1 / numbers.first
    else
      reducable_math_function_handler :/
    end
  when "%"
    injectable_math_function_handler numbers_from_expressions.first, :%
  when "^", "**"
    number, exponent = numbers_from_expressions
    number.send :**, exponent
  when "sin", "cos", "tan",
    "asin", "acos", "atan",
    "sinh", "cosh", "tanh",
    "asinh", "acosh", "atanh",
    "erf", "erfc",
    "gamma", "log10", "sqrt"
    math_function_handler command.word.to_sym
  when "d2r", "deg->rad", "degrees->radians"
    MathFunctions::degrees2radians number_from_expression
  when "r2d", "rad->deg", "radians->degrees"
    MathFunctions::radians2degrees number_from_expression
  when "lgamma"
    MathFunctions::lgamma number_from_expression
  when "ld", "log2"
    Math.log2 number_from_expression
  when "ln"
    Math.log number_from_expression
  when "log"
    base, number = numbers_from_expressions
    if number.nil?
      Math.log base
    else
      Math.log number, base
    end
  when "ldexp"
    fraction, exponent = numbers_from_expressions
    Math.ldexp fraction, exponent
  when "hypot"
    Math.sqrt numbers_from_expressions.map {|n| n**2}
  else
    command_error "unknown command #{command.to_html}"
  end
end

#user_command_handlerObject



405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
# File 'lib/tbmx.rb', line 405

def user_command_handler
  user = expressions.select {|expr| expr.is_a? WordToken}.first
  if not user
    command_error "user: error: no user specified"
  else
    if @@action_view.kind_of? ActionView::Base
      the_user = User.smart_find user.to_s
      if the_user
        @@action_view.render partial: 'users/name_link',
                             locals: {the_user: the_user}
      else
        command_error "unknown user #{user.to_s}"
      end
    else
      tb_href "users/#{user}", user.to_s
    end
  end
end