livetext 0.9.19 → 0.9.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +4 -2
  3. data/README.md +330 -339
  4. data/bin/livetext +0 -2
  5. data/imports/bookish.rb +8 -10
  6. data/imports/markdown.rb +6 -6
  7. data/imports/pyggish.rb +2 -34
  8. data/imports/tutorial.rb +4 -4
  9. data/lib/cmdargs.rb +30 -20
  10. data/lib/errors.rb +2 -0
  11. data/lib/formatline.rb +54 -124
  12. data/lib/funcall.rb +93 -0
  13. data/lib/functions.rb +17 -2
  14. data/lib/global_helpers.rb +39 -0
  15. data/lib/handler/import.rb +44 -0
  16. data/lib/handler.rb +3 -1
  17. data/lib/helpers.rb +46 -12
  18. data/lib/html.rb +2 -0
  19. data/lib/livetext.rb +34 -6
  20. data/lib/parser/file.rb +0 -2
  21. data/lib/parser/general.rb +1 -4
  22. data/lib/parser/mixin.rb +4 -8
  23. data/lib/parser/set.rb +3 -8
  24. data/lib/parser/string.rb +11 -10
  25. data/lib/parser.rb +2 -0
  26. data/lib/parsing.rb +31 -0
  27. data/lib/processor.rb +66 -60
  28. data/lib/standard.rb +28 -17
  29. data/lib/userapi.rb +8 -4
  30. data/plugin/bookish.rb +4 -5
  31. data/plugin/markdown.rb +6 -6
  32. data/plugin/pyggish.rb +46 -77
  33. data/plugin/tutorial.rb +3 -3
  34. data/test/snapshots/error_inc_line_num/OUT +17 -0
  35. data/test/snapshots/{icanhaz2/expected-error.txt → error_inc_line_num/actual-error.txt} +0 -0
  36. data/test/snapshots/error_inc_line_num/actual-output.txt +17 -0
  37. data/test/snapshots/error_invalid_name/actual-error.txt +10 -0
  38. data/test/snapshots/error_invalid_name/actual-output.txt +0 -0
  39. data/test/snapshots/error_invalid_name/out-sdiff.txt +6 -0
  40. data/test/snapshots/error_missing_end/actual-error.txt +10 -0
  41. data/test/snapshots/error_missing_end/actual-output.txt +0 -0
  42. data/test/snapshots/error_missing_end/out-sdiff.txt +6 -0
  43. data/test/snapshots/error_no_such_copy/actual-error.txt +10 -0
  44. data/test/snapshots/error_no_such_copy/actual-output.txt +0 -0
  45. data/test/snapshots/error_no_such_copy/match-error.txt +1 -1
  46. data/test/snapshots/error_no_such_copy/out-sdiff.txt +5 -0
  47. data/test/snapshots/error_no_such_inc/actual-error.txt +10 -0
  48. data/test/snapshots/error_no_such_inc/actual-output.txt +0 -0
  49. data/test/snapshots/error_no_such_inc/match-error.txt +1 -1
  50. data/test/snapshots/error_no_such_inc/out-sdiff.txt +6 -0
  51. data/test/snapshots/error_no_such_mixin/actual-error.txt +13 -0
  52. data/test/snapshots/error_no_such_mixin/actual-output.txt +0 -0
  53. data/test/snapshots/error_no_such_mixin/out-sdiff.txt +6 -0
  54. data/test/snapshots/{icanhaz → import}/expected-output.txt +0 -0
  55. data/test/snapshots/{icanhaz → import}/match-error.txt +0 -0
  56. data/test/snapshots/{icanhaz → import}/simple_import.rb +0 -0
  57. data/test/snapshots/{icanhaz → import}/source.lt3 +2 -2
  58. data/test/snapshots/import2/expected-error.txt +0 -0
  59. data/test/snapshots/{icanhaz2 → import2}/expected-output.txt +3 -1
  60. data/test/snapshots/{icanhaz2/simple_canhaz.rb → import2/simple_import.rb} +0 -0
  61. data/test/snapshots/import2/source.lt3 +8 -0
  62. data/test/snapshots/import_bookish/expected-error.txt +0 -0
  63. data/test/snapshots/import_bookish/expected-output.txt +10 -0
  64. data/test/snapshots/import_bookish/source.lt3 +7 -0
  65. data/test/snapshots/import_bookish/toc.tmp +0 -0
  66. data/test/snapshots/mixin_bookish/expected-error.txt +0 -0
  67. data/test/snapshots/mixin_bookish/expected-output.txt +10 -0
  68. data/test/snapshots/mixin_bookish/source.lt3 +7 -0
  69. data/test/snapshots/mixin_bookish/toc.tmp +0 -0
  70. data/test/snapshots/more_functions/expected-error.txt +0 -0
  71. data/test/snapshots/more_functions/expected-output.txt +37 -0
  72. data/test/snapshots/more_functions/source.lt3 +40 -0
  73. data/test/snapshots/simple_import/expected-output.txt +2 -0
  74. data/test/snapshots/simple_import/source.lt3 +3 -1
  75. data/test/snapshots/subset.txt +84 -0
  76. data/test/snapshots.rb +39 -43
  77. data/test/unit/formatline.rb +253 -134
  78. data/test/unit/html.rb +1 -1
  79. data/test/unit/parser/general.rb +1 -2
  80. data/test/unit/parser/mixin.rb +1 -3
  81. data/test/unit/parser/set.rb +22 -24
  82. data/test/unit/parser/string.rb +46 -7
  83. data/test/unit/parser.rb +0 -1
  84. data/test/unit/standard.rb +0 -1
  85. metadata +43 -24
  86. data/imports/markdown_importable.rb +0 -46
  87. data/lib/handler/icanhaz.rb +0 -35
  88. data/lib/livetext/importable.rb +0 -2
  89. data/lib/parser/import.rb +0 -15
  90. data/test/affirm/kbks.jpg +0 -0
  91. data/test/affirm/lm-kbks.lt +0 -19
  92. data/test/cleanup +0 -1
  93. data/test/newtest +0 -14
  94. data/test/sdtest +0 -6
  95. data/test/snapshots/OMIT.txt +0 -11
  96. data/test/snapshots/clusion.txt +0 -84
  97. data/test/snapshots/crap +0 -16
  98. data/test/snapshots/fixit +0 -6
  99. data/test/snapshots/icanhaz2/source.lt3 +0 -6
  100. data/test/unit/parser/importable.rb +0 -19
data/bin/livetext CHANGED
@@ -82,8 +82,6 @@ loop do
82
82
  when "-i", "--install"
83
83
  lib = ARGV.shift
84
84
  system("cp #{lib} #{Livetext::Path}/../plugin/")
85
- # when /-.*/
86
- # raise "Unknown argument '#{arg}'"
87
85
  when Object
88
86
  x.process_file(arg, true) # , @backtrace)
89
87
  end
data/imports/bookish.rb CHANGED
@@ -33,10 +33,6 @@ module Bookish
33
33
  _out "</table>"
34
34
  end
35
35
 
36
- # def comment
37
- # _body { } # ignore body
38
- # end
39
-
40
36
  def _errout(*args)
41
37
  ::STDERR.puts *args
42
38
  end
@@ -46,13 +42,15 @@ module Bookish
46
42
  end
47
43
 
48
44
  def _slug(str)
49
- s2 = str.chomp.strip.gsub(/[?:,()'"\/]/,"").gsub(/ /, "-").downcase
50
- # _errout "SLUG: #{str} => #{s2}"
51
- s2
45
+ str2 = str.chomp.strip
46
+ str2 = str2.gsub(/[?:,()'"\/]/,"")
47
+ str2 = str2.gsub(/ /, "-")
48
+ str2.downcase!
49
+ str2
52
50
  end
53
51
 
54
-
55
52
  # FIXME duplicated?
53
+
56
54
  def image(args = nil, body = nil)
57
55
  name = @_args[0]
58
56
  _out "<img src='#{name}'></img>"
@@ -109,7 +107,7 @@ module Bookish
109
107
  next_output
110
108
  _out "<h3>#@section #{title}</h3>\n"
111
109
  rescue => err
112
- STDERR.puts "#{err}\n#{err.backtrace}"
110
+ ::STDERR.puts "#{err}\n#{err.backtrace}"
113
111
  exit
114
112
  end
115
113
 
@@ -276,7 +274,7 @@ module Bookish
276
274
  _body {|line| _out line }
277
275
  _out "</blockquote>"
278
276
  rescue => err
279
- STDERR.puts "#{err}\n#{err.backtrace}"
277
+ ::STDERR.puts "#{err}\n#{err.backtrace}"
280
278
  exit
281
279
  end
282
280
 
data/imports/markdown.rb CHANGED
@@ -9,12 +9,12 @@ module Markdown
9
9
  SimpleFormats[:s] = %w[<strike> </strike>]
10
10
 
11
11
 
12
- def h1(args = nil, body = nil); _out "# #{FormatLine.var_func_parse(@_data)}"; _optional_blank_line end # atx style for now
13
- def h2(args = nil, body = nil); _out "## #{FormatLine.var_func_parse(@_data)}"; _optional_blank_line end
14
- def h3(args = nil, body = nil); _out "### #{FormatLine.var_func_parse(@_data)}"; _optional_blank_line end
15
- def h4(args = nil, body = nil); _out "#### #{FormatLine.var_func_parse(@_data)}"; _optional_blank_line end
16
- def h5(args = nil, body = nil); _out "##### #{FormatLine.var_func_parse(@_data)}"; _optional_blank_line end
17
- def h6(args = nil, body = nil); _out "###### #{FormatLine.var_func_parse(@_data)}"; _optional_blank_line end
12
+ def h1(args = nil, body = nil); _out "# #{Livetext.interpolate(@_data)}"; _optional_blank_line end # atx style for now
13
+ def h2(args = nil, body = nil); _out "## #{Livetext.interpolate(@_data)}"; _optional_blank_line end
14
+ def h3(args = nil, body = nil); _out "### #{Livetext.interpolate(@_data)}"; _optional_blank_line end
15
+ def h4(args = nil, body = nil); _out "#### #{Livetext.interpolate(@_data)}"; _optional_blank_line end
16
+ def h5(args = nil, body = nil); _out "##### #{Livetext.interpolate(@_data)}"; _optional_blank_line end
17
+ def h6(args = nil, body = nil); _out "###### #{Livetext.interpolate(@_data)}"; _optional_blank_line end
18
18
 
19
19
  def title(args = nil, body = nil)
20
20
  h1
data/imports/pyggish.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'rouge'
2
2
 
3
+ # FIXME This file has suboptimal juju. See plugin/pyggish.rb also
4
+
3
5
  module Pyggish
4
6
  def self.pyg_change(code, klass, style)
5
7
  color = style[0..6]
@@ -29,7 +31,6 @@ module Pyggish
29
31
 
30
32
  def self.pyg_finalize(code, lexer=:elixir)
31
33
  Styles.each_pair {|klass, style| pyg_change(code, klass, style) }
32
- File.open("debug-pf1", "w") {|f| f.puts code }
33
34
  code.sub!(/<pre>/, "<pre>\n")
34
35
  code.gsub!(/<span class="[np]">/, "")
35
36
  code.gsub!(/<\/span>/, "")
@@ -37,9 +38,7 @@ File.open("debug-pf1", "w") {|f| f.puts code }
37
38
  code.sub!(/<td class="linenos"/, "<td width=2%></td><td width=5% bgcolor=#{color}")
38
39
  code.gsub!(/<td/, "<td valign=top ")
39
40
  code.gsub!(/ class="[^"]*?"/, "") # Get rid of remaining Pygments CSS
40
- File.open("debug-pf2", "w") {|f| f.puts code }
41
41
  lines = code.split("\n")
42
- # lines.each {|line| line << "\n" }
43
42
  n1 = lines.index {|x| x =~ /<pre>/ }
44
43
  n2 = lines.index {|x| x =~ /<\/pre>/ }
45
44
  # FIXME ?
@@ -48,12 +47,10 @@ File.open("debug-pf2", "w") {|f| f.puts code }
48
47
  lines[n1].sub!(/ 1$/, " 1 ")
49
48
  (n1+1).upto(n2) {|n| lines[n].replace(" " + lines[n] + " ") }
50
49
  code = lines.join("\n")
51
- File.open("debug-pf3", "w") {|f| f.puts code }
52
50
  code
53
51
  end
54
52
 
55
53
  def _process_code(text)
56
- File.open("debug-pc1", "w") {|f| f.puts text }
57
54
  lines = text.split("\n")
58
55
  lines = lines.select {|x| x !~ /##~ omit/ }
59
56
  @refs = {}
@@ -66,7 +63,6 @@ File.open("debug-pf3", "w") {|f| f.puts code }
66
63
  end
67
64
  lines.map! {|line| " " + line }
68
65
  text2 = lines.join("\n")
69
- File.open("debug-pc2", "w") {|f| f.puts text2 }
70
66
  text.replace(text2)
71
67
  end
72
68
 
@@ -86,34 +82,6 @@ File.open("debug-pf3", "w") {|f| f.puts code }
86
82
  result
87
83
  end
88
84
 
89
- def OLD_ruby
90
- file = @_args.first
91
- if file.nil?
92
- code = "# Ruby code\n"
93
- _body {|line| code << line + "\n" }
94
- else
95
- code = "# Ruby code\n\n" + ::File.read(file)
96
- end
97
-
98
- _process_code(code)
99
- html = _colorize(code, :ruby)
100
- _out "\n#{html}\n "
101
- end
102
-
103
- def OLD_elixir
104
- file = @_args.first
105
- if file.nil?
106
- code = ""
107
- _body {|line| code << line + "\n" }
108
- else
109
- code = ::File.read(file)
110
- end
111
-
112
- _process_code(code)
113
- html = _colorize(code, :elixir)
114
- _out "\n#{html}\n "
115
- end
116
-
117
85
  def fragment
118
86
  lang = @_args.empty? ? :elixir : @_args.first.to_sym # ruby or elixir
119
87
  @_args = []
data/imports/tutorial.rb CHANGED
@@ -1,9 +1,9 @@
1
- # require 'cgi'
2
-
3
1
  require 'helpers'
4
2
 
3
+ # Created as an "ad hoc" lib for generating the README
4
+
5
5
  module Tutorial
6
- include Helpers
6
+ include Livetext::Helpers
7
7
 
8
8
  def title(args = nil, body = nil)
9
9
  h1
@@ -85,7 +85,7 @@ module Tutorial
85
85
  def testcase(args = nil, body = nil)
86
86
  name = _args.first
87
87
  _out "\n<font size=+1><b>Test: </font><font size=+2><tt>#{name}</tt></font></b></h3><br>"
88
- src, exp = "test/data/#{name}/source.lt3", "test/data/#{name}/expected-output.txt"
88
+ src, exp = "test/snapshots/#{name}/source.lt3", "test/snapshots/#{name}/expected-output.txt"
89
89
  @_args = [src, exp] # Better way to do this??
90
90
  put_table(src, exp)
91
91
  _out "<br>"
data/lib/cmdargs.rb CHANGED
@@ -1,47 +1,58 @@
1
+ # p __FILE__
2
+
1
3
  require_relative 'livetext'
2
4
 
3
5
  =begin
4
6
  Weird concepts to understand here...
5
7
 
6
8
  1. A Livetext dot-command (flush left) usually looks like:
7
- .foobar
9
+ .foobar
10
+
8
11
  2. A dot-command (left-indented) usually looks like:
9
- $.foobar
12
+ $.foobar
13
+
10
14
  3. More generally, it may have any number of parameters (0, 1, ...)
11
- .redirect somefile.txt append
15
+ .redirect somefile.txt append
16
+
12
17
  4. Variables and functions *can* appear (rare in practice??)
13
- .redirect somefile$my_suffix $$my_mode
18
+ .redirect somefile$my_suffix $$my_mode
19
+
14
20
  5. A trailing # comment may appear
15
21
  a. Stripped... saved in #raw ? #data ? #comment ? elsewhere?
16
22
  b. NOT the "dot" as a comment!
23
+
17
24
  6. .foobar # This here is a comment
25
+
18
26
  7. #data accessor returns all data on the .foo line...
19
27
  a. ...After the initial space
20
- b. ...Including spaces
28
+ b. ...Including later spaces
21
29
  c. Including comment??
22
30
  d. .foo This is o n l y a test.
23
31
  # #data returns: "This is o n l y a test."
24
32
  e. What about formatting???
25
33
  f. What about: comments? variables? functions?
26
34
 
27
- 7. Some commands have NO body while others have an OPTIONAL or REQUIRED body
35
+ 8. Some commands have NO body while others have an OPTIONAL or REQUIRED body
28
36
  a. Assume .cmd1 definition forbids a body (then a body is an error)
29
37
  .cmd1 # may NOT have a body
30
38
  b. Assume .cmd2 definition PERMITS a body
31
39
  .cmd2 # may or MAY NOT have body/.end
32
- c. Assume .cmd3 definition PERMITS a body
40
+ c. Assume .cmd3 definition REQUIRES a body
33
41
  .cmd3 # REQUIRES a body/.end
34
42
  . stuff...
35
43
  .end
36
- 8. Inside a body:
37
- 8a. Leading dot has no special meaning (though the associated method may parse it!)
38
- 8b. BUG? Currently leading dot is a comment INSIDE a body?
39
- 8a. No leading char is special (though the associated method may parse it!)
40
- 8a. No trailing #-comments (though the associated method may parse it!)
41
- 8c. ?? We should or shouldn't look for variables/functions? or make it an option?
42
- 8d. .end may naturally not be used (but see .raw where it may)
43
- 9. the args accessor is a simple array of strings
44
44
 
45
+ 9. Inside a body:
46
+ a. Leading dot has no special meaning (though the associated method may parse it!)
47
+ b. BUG? Currently leading dot is a comment INSIDE a body?
48
+ c. No leading char is special (though the associated method may parse it!)
49
+ d. No trailing #-comments (though the associated method may parse it!)
50
+ e. ?? We should or shouldn't look for variables/functions? or make it an option?
51
+ f. .end may naturally not be used (but see .raw where it may)
52
+
53
+ 10. The args accessor is a simple array of strings
54
+ a. there is also raw_args (without variables/functions, etc.)
55
+ b. Much of this HAS NOT been thought through yet!
45
56
 
46
57
  =end
47
58
 
@@ -56,19 +67,18 @@ class Livetext::CmdData
56
67
  # body: true => this command has a body + .end
57
68
  # how raw is raw?
58
69
  # remove comment - always/sometimes/never?
59
- # var_func_parse - always/sometimes/never?
60
- # var_func_parse inside body??
70
+ # interpolate - always/sometimes/never?
71
+ # interpolate inside body??
61
72
  @data = data.dup # comment? vars? funcs?
62
73
  @raw = data.dup # comment? vars? funcs?
63
74
  @args = data.split # simple array
64
75
  @nargs = nargs # not really "needed"
65
76
  check_num_args(nargs)
66
-
67
- # @varfunc = _var_func_parse(data.dup)
77
+ # @varfunc = Livetext.interpolate(data.dup)
68
78
  end
69
79
 
70
80
  def check_num_args(num)
71
- num_range = /(\d{0,2})(\.\.)(\d{0,2})/
81
+ num_range = /(\d{0,2})(\.\.)(\d{0,2})/ # Not "really" right...
72
82
  min, max = 0, 9999
73
83
  md = num_range.match(@nargs).to_a
74
84
  bad_args = nil
data/lib/errors.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # p __FILE__
2
+
1
3
 
2
4
  # More later?
3
5
 
data/lib/formatline.rb CHANGED
@@ -1,28 +1,14 @@
1
+ # p __FILE__
2
+
3
+ require_relative 'parsing'
4
+ require_relative 'funcall'
5
+
1
6
  # Class FormatLine handles the parsing of comments, dot commands, and
2
7
  # simple formatting characters.
3
8
 
4
- class FormatLine < StringParser
5
- SimpleFormats = {}
6
- SimpleFormats[:b] = %w[<b> </b>]
7
- SimpleFormats[:i] = %w[<i> </i>]
8
- SimpleFormats[:t] = ["<font size=+1><tt>", "</tt></font>"]
9
- SimpleFormats[:s] = %w[<strike> </strike>]
10
-
11
- Null = ""
12
- Space = " "
13
- Alpha = /[A-Za-z]/
14
- AlNum = /[A-Za-z0-9_]/
15
- LF = "\n"
16
- LBrack = "["
17
-
18
- Blank = [" ", nil, "\n"]
19
- Punc = [")", ",", ".", " ", "\n"]
20
- NoAlpha = /[^A-Za-z0-9_]/
21
- NoAlphaDot = /[^.A-Za-z0-9_]/
22
- Param = ["]", "\n", nil]
23
- Escape = "\\" # not an ESC char
24
-
25
- Syms = { "*" => :b, "_" => :i, "`" => :t, "~" => :s }
9
+ class Livetext::FormatLine < StringParser
10
+ include Livetext::ParsingConstants
11
+ include Livetext::FormatLine::FunCall
26
12
 
27
13
  attr_reader :out
28
14
  attr_reader :tokenlist
@@ -37,7 +23,6 @@ class FormatLine < StringParser
37
23
  return nil if line.nil?
38
24
  x = self.new(line.chomp)
39
25
  t = x.tokenize
40
- # TTY.puts "tokens = \n#{t.inspect}\n "
41
26
  x.evaluate
42
27
  end
43
28
 
@@ -45,14 +30,14 @@ class FormatLine < StringParser
45
30
  # add grab
46
31
  loop do
47
32
  case peek
48
- when Escape; grab; add peek; grab; add peek
33
+ when Escape; grab; add peek; grab
49
34
  when "$"
50
35
  dollar
51
36
  when "*", "_", "`", "~"
52
37
  marker peek
53
38
  add peek
54
39
  when LF
55
- break if @i >= line.size - 1
40
+ break if eos? # @i >= line.size - 1
56
41
  when nil
57
42
  break
58
43
  else
@@ -80,7 +65,7 @@ class FormatLine < StringParser
80
65
  char = x.grab
81
66
  break if char == LF || char == nil
82
67
  x.handle_escaping if char == Escape
83
- x.dollar if char == "$"
68
+ x.dollar if char == "$" # Could be $$
84
69
  x.add char
85
70
  end
86
71
  x.add_token(:str)
@@ -107,22 +92,10 @@ class FormatLine < StringParser
107
92
  break if token.nil?
108
93
  sym, val = *token
109
94
  case sym
110
- when :str
111
- @out << val unless val == "\n" # BUG
112
- when :var
113
- @out << varsub(val)
114
- when :func
115
- param = nil
116
- arg = gen.peek
117
- if [:colon, :brackets].include? arg[0]
118
- arg = gen.next # for real
119
- param = arg[1]
120
- param = FormatLine.var_func_parse(param)
121
- end
122
- @out << funcall(val, param)
123
- when :b, :i, :t, :s
124
- val = FormatLine.var_func_parse(val)
125
- @out << embed(sym, val)
95
+ when :str; eval_str(val)
96
+ when :var; eval_var(val)
97
+ when :func; eval_func(val, gen)
98
+ when *BITS; eval_bits(sym, val)
126
99
  else
127
100
  add_token :str
128
101
  end
@@ -131,48 +104,6 @@ class FormatLine < StringParser
131
104
  @out
132
105
  end
133
106
 
134
- def grab_colon_param
135
- grab # grab :
136
- param = ""
137
- loop do
138
- case next!
139
- when Escape
140
- grab
141
- param << next!
142
- grab
143
- when Space, LF, nil; break
144
- else
145
- param << next!
146
- grab
147
- end
148
- end
149
-
150
- param = nil if param.empty?
151
- param
152
- end
153
-
154
- def grab_func_param
155
- grab # [
156
- param = ""
157
- loop do
158
- case next!
159
- when Escape
160
- grab
161
- param << next!
162
- grab
163
- when "]", LF, nil; break
164
- else
165
- param << next!
166
- grab
167
- end
168
- end
169
-
170
- add peek
171
- grab
172
- param = nil if param.empty?
173
- param
174
- end
175
-
176
107
  def add(str)
177
108
  @token << str unless str.nil?
178
109
  end
@@ -189,7 +120,7 @@ class FormatLine < StringParser
189
120
  loop do
190
121
  break if eos?
191
122
  str << peek
192
- break if terminate?(NoAlpha, next!)
123
+ break if terminate?(NoAlpha, lookahead)
193
124
  grab
194
125
  end
195
126
  str
@@ -199,9 +130,9 @@ class FormatLine < StringParser
199
130
  str = Null.dup
200
131
  grab
201
132
  loop do
202
- break if eos? # peek.nil?
133
+ break if peek.nil? # eos?
203
134
  str << peek
204
- break if terminate?(NoAlphaDot, next!)
135
+ break if terminate?(NoAlphaDot, lookahead)
205
136
  grab
206
137
  end
207
138
  str
@@ -216,7 +147,7 @@ class FormatLine < StringParser
216
147
  when "$"; double_dollar
217
148
  # when "."; dollar_dot
218
149
  when /[A-Za-z]/
219
- add_token :str
150
+ add_token :str
220
151
  var = peek + grab_alpha_dot
221
152
  add_token(:var, var)
222
153
  else
@@ -225,23 +156,6 @@ class FormatLine < StringParser
225
156
  end
226
157
  end
227
158
 
228
- def double_dollar
229
- case next!
230
- when Space; add_token :string, "$$ "; grab; return
231
- when LF, nil; add "$$"; add_token :str
232
- when Alpha
233
- add_token(:str, @token)
234
- func = grab_alpha
235
- add_token(:func, func)
236
- case next!
237
- when ":"; param = grab_colon_param; add_token(:colon, param)
238
- when "["; param = grab_func_param; add_token(:brackets, param)
239
- end
240
- else
241
- grab; add_token :str, "$$" + peek; return
242
- end
243
- end
244
-
245
159
  # def dollar_dot
246
160
  # add_token :ddot, @line[@i..-1]
247
161
  # end
@@ -276,7 +190,7 @@ class FormatLine < StringParser
276
190
  def double_marker(char)
277
191
  sym = Syms[char]
278
192
  kind = sym
279
- case next! # first char after **
193
+ case lookahead # first char after **
280
194
  when Space, LF, nil
281
195
  pre, post = SimpleFormats[sym]
282
196
  add_token kind
@@ -317,13 +231,12 @@ class FormatLine < StringParser
317
231
  add str
318
232
  str
319
233
  rescue => err
320
- STDERR.puts "ERR = #{err}\n#{err.backtrace}"
321
- STDERR.puts "=== str = #{str.inspect}"
234
+ ::STDERR.puts "ERR = #{err}\n#{err.backtrace}"
322
235
  end
323
236
 
324
237
  def escaped
325
- grab
326
- ch = grab
238
+ grab # Eat the backslash
239
+ ch = grab # Take next char
327
240
  ch
328
241
  end
329
242
 
@@ -350,20 +263,7 @@ class FormatLine < StringParser
350
263
  add str
351
264
  str
352
265
  rescue => err
353
- STDERR.puts "ERR = #{err}\n#{err.backtrace}"
354
- STDERR.puts "=== str = #{str.inspect}"
355
- end
356
-
357
- def funcall(name, param)
358
- err = "[Error evaluating $$#{name}(#{param})]"
359
- result =
360
- if self.respond_to?("func_" + name.to_s)
361
- self.send("func_" + name.to_s, param)
362
- else
363
- fobj = ::Livetext::Functions.new
364
- fobj.send(name, param) rescue err
365
- end
366
- result
266
+ ::STDERR.puts "ERR = #{err}\n#{err.backtrace}"
367
267
  end
368
268
 
369
269
  def varsub(name)
@@ -374,4 +274,34 @@ class FormatLine < StringParser
374
274
  def embedded?
375
275
  ! (['"', "'", " ", nil].include? prev)
376
276
  end
277
+
278
+ private
279
+
280
+ def eval_bits(sym, val)
281
+ val = Livetext.interpolate(val)
282
+ @out << embed(sym, val)
283
+ end
284
+
285
+ def eval_func(val, gen)
286
+ param = nil
287
+ arg = gen.peek rescue :bogus
288
+ unless arg == :bogus
289
+ if [:colon, :brackets].include? arg[0]
290
+ arg = gen.next # for real
291
+ param = arg[1]
292
+ # FIXME - unsure - interpolate again??
293
+ # param = Livetext.interpolate(param)
294
+ end
295
+ end
296
+ @out << funcall(val, param)
297
+ end
298
+
299
+ def eval_var(val)
300
+ @out << varsub(val)
301
+ end
302
+
303
+ def eval_str(val)
304
+ @out << val unless val == "\n" # BUG
305
+ end
306
+
377
307
  end
data/lib/funcall.rb ADDED
@@ -0,0 +1,93 @@
1
+ # p __FILE__
2
+
3
+ require_relative 'livetext'
4
+ # require_relative 'formatline'
5
+
6
+ # Parse function calls
7
+
8
+ module Livetext::FormatLine::FunCall
9
+
10
+ include Livetext::ParsingConstants
11
+
12
+ def grab_colon_param
13
+ grab # grab :
14
+ param = ""
15
+ loop do
16
+ case lookahead
17
+ when Escape
18
+ grab
19
+ param << lookahead
20
+ grab
21
+ when Space, LF, nil; break
22
+ else
23
+ param << lookahead
24
+ grab
25
+ end
26
+ end
27
+
28
+ param = nil if param.empty?
29
+ param
30
+ end
31
+
32
+ def grab_bracket_param
33
+ grab # [
34
+ param = ""
35
+ loop do
36
+ case lookahead
37
+ when Escape
38
+ grab
39
+ param << lookahead
40
+ grab
41
+ when "]", LF, nil
42
+ break
43
+ else
44
+ param << lookahead
45
+ grab
46
+ end
47
+ end
48
+ add peek
49
+ grab
50
+ param = nil if param.empty?
51
+ param
52
+ end
53
+
54
+ def funcall(name, param)
55
+ err = "[Error evaluating $$#{name}(#{param})]"
56
+ func_name = name # "func_" + name.to_s
57
+ result =
58
+ if self.send?(func_name, param) # self.respond_to?(func_name)
59
+ # do nothing
60
+ else
61
+ fobj = ::Livetext::Functions.new
62
+ fobj.send(name, param) rescue err
63
+ end
64
+ result.to_s
65
+ end
66
+
67
+ def double_dollar
68
+ case lookahead
69
+ when Space; add_token :string, "$$ "; grab; return
70
+ when LF, nil; add "$$"; add_token :str
71
+ when Alpha
72
+ add_token(:str, @token)
73
+ func = grab_alpha
74
+ add_token(:func, func)
75
+ param = grab_func_param # may be null/missing
76
+ else
77
+ grab; add_token :str, "$$" + peek; return
78
+ end
79
+ end
80
+
81
+ def grab_func_param
82
+ case lookahead
83
+ when "["
84
+ param = grab_bracket_param
85
+ add_token(:brackets, param)
86
+ when ":"
87
+ param = grab_colon_param
88
+ add_token(:colon, param)
89
+ else # do nothing
90
+ end
91
+ end
92
+
93
+ end
data/lib/functions.rb CHANGED
@@ -1,5 +1,5 @@
1
+ # p __FILE__
1
2
 
2
- require_relative 'standard' # FIXME umm, why is this necessary??
3
3
 
4
4
  # Class Functions is where '$$func' functions are stored dynamically...
5
5
  # user-def AND pre-def??
@@ -13,6 +13,21 @@ class Livetext::Functions
13
13
  attr_accessor :param # kill this?
14
14
  end
15
15
 
16
+ # FIXME Function parameters need to be fixed...
17
+
18
+ def isqrt(param = nil) # "integer square root" - Just for testing
19
+ arg = num = param # Takes any number
20
+ if num.nil? || num.empty?
21
+ arg = "NO PARAM" # Just for error text
22
+ end
23
+ # Integer()/Float() can raise error
24
+ num = num.include?(".") ? Float(num) : Integer(num)
25
+ # Returns truncated integer
26
+ Math.sqrt(num).to_i # user need not do to_s
27
+ rescue => err # Malformed number? negative?
28
+ "[Error evaluating $$isqrt(#{arg})]"
29
+ end
30
+
16
31
  def date(param=nil)
17
32
  Time.now.strftime("%F")
18
33
  end
@@ -40,7 +55,7 @@ class Livetext::Functions
40
55
  "<br>"*n
41
56
  end
42
57
 
43
- def yt(param)
58
+ def yt(param) # FIXME uh, this is crap
44
59
  param = self.class.param
45
60
  "https://www.youtube.com/watch?v=#{param}"
46
61
  end