livetext 0.9.21 → 0.9.25

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +8 -8
  3. data/bin/livetext +57 -40
  4. data/imports/bookish.rb +89 -90
  5. data/imports/calibre.rb +3 -3
  6. data/imports/livemagick.rb +17 -17
  7. data/imports/markdown.rb +10 -10
  8. data/imports/pyggish.rb +15 -47
  9. data/imports/tutorial.rb +18 -18
  10. data/lib/cmdargs.rb +10 -6
  11. data/lib/{errors.rb → livetext/errors.rb} +1 -1
  12. data/lib/{formatline.rb → livetext/formatline.rb} +69 -125
  13. data/lib/livetext/funcall.rb +84 -0
  14. data/lib/{functions.rb → livetext/functions.rb} +16 -3
  15. data/lib/livetext/global_helpers.rb +37 -0
  16. data/lib/livetext/handler/import.rb +44 -0
  17. data/lib/livetext/handler/mixin.rb +37 -0
  18. data/lib/livetext/handler.rb +3 -0
  19. data/lib/{helpers.rb → livetext/helpers.rb} +89 -67
  20. data/lib/{html.rb → livetext/html.rb} +3 -2
  21. data/lib/{parser → livetext/parser}/general.rb +0 -3
  22. data/lib/{parser → livetext/parser}/set.rb +1 -6
  23. data/lib/{parser → livetext/parser}/string.rb +2 -2
  24. data/lib/{parser.rb → livetext/parser.rb} +0 -1
  25. data/lib/livetext/parsing.rb +29 -0
  26. data/lib/livetext/paths.rb +13 -0
  27. data/lib/livetext/processor.rb +89 -0
  28. data/lib/livetext/reopen.rb +12 -0
  29. data/lib/livetext/skeleton.rb +17 -0
  30. data/lib/{standard.rb → livetext/standard.rb} +152 -122
  31. data/lib/livetext/userapi.rb +153 -0
  32. data/lib/livetext/version.rb +6 -0
  33. data/lib/livetext.rb +66 -27
  34. data/plugin/bookish.rb +85 -85
  35. data/plugin/calibre.rb +3 -3
  36. data/plugin/livemagick.rb +17 -17
  37. data/plugin/markdown.rb +10 -10
  38. data/plugin/pyggish.rb +131 -162
  39. data/plugin/tutorial.rb +15 -16
  40. data/test/all.rb +6 -0
  41. data/test/snapshots/def_method/expected-output.txt +2 -0
  42. data/test/snapshots/def_method/source.lt3 +4 -2
  43. data/test/snapshots/error_inc_line_num/OUT +17 -0
  44. data/test/snapshots/error_inc_line_num/README.txt +20 -0
  45. data/test/snapshots/error_inc_line_num/expected-output.txt +0 -6
  46. data/test/snapshots/error_inc_line_num/match-error.txt +1 -1
  47. data/test/snapshots/error_line_num/match-error.txt +1 -1
  48. data/test/snapshots/error_missing_end/expected-output.txt +0 -1
  49. data/test/snapshots/error_name_not_permitted/expected-output.txt +4 -0
  50. data/test/snapshots/error_name_not_permitted/match-error.txt +1 -1
  51. data/test/snapshots/error_no_such_copy/duh +26 -0
  52. data/test/snapshots/error_no_such_copy/expected-output.txt +1 -0
  53. data/test/snapshots/error_no_such_copy/match-error.txt +1 -1
  54. data/test/snapshots/error_no_such_copy/mystery.txt +36 -0
  55. data/test/snapshots/error_no_such_inc/match-error.txt +1 -1
  56. data/test/snapshots/error_no_such_mixin/expected-output.txt +1 -0
  57. data/test/snapshots/error_no_such_mixin/match-error.txt +1 -1
  58. data/test/snapshots/error_no_such_mixin/source.lt3 +1 -1
  59. data/test/snapshots/example_alpha/source.lt3 +2 -2
  60. data/test/snapshots/example_alpha2/expected-output.txt +0 -2
  61. data/test/snapshots/example_alpha2/source.lt3 +5 -4
  62. data/test/snapshots/{icanhaz → import}/expected-output.txt +2 -1
  63. data/test/snapshots/import/match-error.txt +1 -0
  64. data/test/snapshots/{icanhaz → import}/simple_import.rb +1 -1
  65. data/test/snapshots/{icanhaz → import}/source.lt3 +2 -2
  66. data/test/snapshots/{icanhaz2 → import2}/expected-error.txt +0 -0
  67. data/test/snapshots/{icanhaz2 → import2}/expected-output.txt +3 -1
  68. data/test/snapshots/{icanhaz2/simple_canhaz.rb → import2/simple_import.rb} +1 -1
  69. data/test/snapshots/import2/source.lt3 +8 -0
  70. data/test/snapshots/import_bookish/expected-error.txt +0 -0
  71. data/test/snapshots/import_bookish/expected-output.txt +10 -0
  72. data/test/snapshots/import_bookish/source.lt3 +7 -0
  73. data/test/snapshots/import_bookish/toc.tmp +0 -0
  74. data/test/snapshots/mixin_bookish/expected-error.txt +0 -0
  75. data/test/snapshots/mixin_bookish/expected-output.txt +10 -0
  76. data/test/snapshots/mixin_bookish/source.lt3 +7 -0
  77. data/test/snapshots/mixin_bookish/toc.tmp +0 -0
  78. data/test/snapshots/more_functions/expected-error.txt +0 -0
  79. data/test/snapshots/more_functions/expected-output.txt +37 -0
  80. data/test/snapshots/more_functions/source.lt3 +40 -0
  81. data/test/snapshots/raw_lines/expected-output.txt +0 -2
  82. data/test/snapshots/simple_import/expected-output.txt +2 -0
  83. data/test/snapshots/simple_import/simple_import.rb +1 -1
  84. data/test/snapshots/simple_import/source.lt3 +3 -1
  85. data/test/snapshots/simple_mixin/simple_mixin.rb +1 -1
  86. data/test/snapshots/single_raw_line/expected-output.txt +0 -2
  87. data/test/snapshots/subset.txt +14 -14
  88. data/test/snapshots.rb +30 -13
  89. data/test/unit/formatline.rb +253 -134
  90. data/test/unit/html.rb +2 -3
  91. data/test/unit/parser/general.rb +1 -2
  92. data/test/unit/parser/mixin.rb +1 -3
  93. data/test/unit/parser/set.rb +8 -12
  94. data/test/unit/parser/string.rb +6 -6
  95. data/test/unit/parser.rb +0 -1
  96. data/test/unit/standard.rb +0 -2
  97. metadata +47 -30
  98. data/imports/markdown_importable.rb +0 -45
  99. data/lib/handler/icanhaz.rb +0 -35
  100. data/lib/handler.rb +0 -1
  101. data/lib/livetext/importable.rb +0 -2
  102. data/lib/parser/file.rb +0 -8
  103. data/lib/parser/import.rb +0 -15
  104. data/lib/parser/mixin.rb +0 -38
  105. data/lib/processor.rb +0 -83
  106. data/lib/userapi.rb +0 -160
  107. data/test/snapshots/icanhaz/match-error.txt +0 -1
  108. data/test/snapshots/icanhaz2/source.lt3 +0 -6
  109. data/test/unit/parser/importable.rb +0 -19
@@ -1,6 +1,4 @@
1
1
 
2
- require_relative 'standard' # FIXME umm, why is this necessary??
3
-
4
2
  # Class Functions is where '$$func' functions are stored dynamically...
5
3
  # user-def AND pre-def??
6
4
 
@@ -13,6 +11,21 @@ class Livetext::Functions
13
11
  attr_accessor :param # kill this?
14
12
  end
15
13
 
14
+ # FIXME Function parameters need to be fixed...
15
+
16
+ def isqrt(param = nil) # "integer square root" - Just for testing
17
+ arg = num = param # Takes any number
18
+ if num.nil? || num.empty?
19
+ arg = "NO PARAM" # Just for error text
20
+ end
21
+ # Integer()/Float() can raise error
22
+ num = num.include?(".") ? Float(num) : Integer(num)
23
+ # Returns truncated integer
24
+ Math.sqrt(num).to_i # user need not do to_s
25
+ rescue => err # Malformed number? negative?
26
+ "[Error evaluating $$isqrt(#{arg})]"
27
+ end
28
+
16
29
  def date(param=nil)
17
30
  Time.now.strftime("%F")
18
31
  end
@@ -40,7 +53,7 @@ class Livetext::Functions
40
53
  "<br>"*n
41
54
  end
42
55
 
43
- def yt(param)
56
+ def yt(param) # FIXME uh, this is crap
44
57
  param = self.class.param
45
58
  "https://www.youtube.com/watch?v=#{param}"
46
59
  end
@@ -0,0 +1,37 @@
1
+
2
+ module GlobalHelpers
3
+
4
+ def check_disallowed(name)
5
+ raise DisallowedName(name) if disallowed?(name)
6
+ end
7
+
8
+ def check_file_exists(file)
9
+ graceful_error FileNotFound(file) unless File.exist?(file)
10
+ end
11
+
12
+ def grab_file(fname)
13
+ File.read(fname)
14
+ end
15
+
16
+ def search_upward(file)
17
+ value = nil
18
+ return file if File.exist?(file)
19
+
20
+ count = 1
21
+ loop do
22
+ front = "../" * count
23
+ count += 1
24
+ here = Pathname.new(front).expand_path.dirname.to_s
25
+ break if here == "/"
26
+ path = front + file
27
+ value = path if File.exist?(path)
28
+ break if value
29
+ end
30
+ ::STDERR.puts "Cannot find #{file.inspect} from #{Dir.pwd}" unless value
31
+ return value
32
+ rescue
33
+ ::STDERR.puts "Can't find #{file.inspect} from #{Dir.pwd}"
34
+ return nil
35
+ end
36
+
37
+ end
@@ -0,0 +1,44 @@
1
+
2
+ require_relative '../helpers'
3
+
4
+ class Livetext::Handler::Import
5
+ include Livetext::Helpers
6
+ include GlobalHelpers
7
+
8
+ attr_reader :file
9
+
10
+ def initialize(name)
11
+ @name = name
12
+ @file = find_file(name)
13
+ end
14
+
15
+ def self.get_mod_name
16
+ file = File.new(@file + ".rb")
17
+ str = nil
18
+ file.each_line do |line|
19
+ str = line
20
+ break if str =~ /^module /
21
+ end
22
+ junk, name, junk2 = str.split
23
+ name
24
+ end
25
+
26
+ def self.get_module(filename, parent)
27
+ # TTY.puts "#{__method__}: filename = #{filename.inspect}"
28
+ handler = self.new(filename)
29
+ parent.graceful_error FileNotFound(filename) if handler.file.nil?
30
+ @file = handler.file.sub(/.rb$/, "")
31
+ require @file # + ".rb"
32
+ modname = get_mod_name
33
+ newmod = Object.const_get("::" + modname)
34
+ newmod # return actual module
35
+ end
36
+
37
+ private
38
+
39
+ def cwd_root?
40
+ File.dirname(File.expand_path(".")) == "/"
41
+ end
42
+
43
+ end
44
+
@@ -0,0 +1,37 @@
1
+
2
+ require_relative '../helpers'
3
+
4
+ class Livetext::Handler::Mixin
5
+ include Livetext::Helpers
6
+ include GlobalHelpers
7
+
8
+ attr_reader :file
9
+
10
+ def initialize(name, parent)
11
+ @name = name
12
+ @file = find_file(name, ".rb", "plugin")
13
+ parent.graceful_error FileNotFound(name) if @file.nil?
14
+ end
15
+
16
+ def self.get_module(filename, parent)
17
+ handler = self.new(filename, parent)
18
+ modname, code = handler.read_mixin
19
+ eval(code) # Avoid in the future
20
+ newmod = Object.const_get("::" + modname)
21
+ newmod # return actual module
22
+ end
23
+
24
+ def read_mixin
25
+ modname = @name.gsub("/","_").capitalize
26
+ meths = grab_file(@file) # already has .rb?
27
+ [modname, "module ::#{modname}; #{meths}\nend"]
28
+ end
29
+
30
+ private
31
+
32
+ def cwd_root?
33
+ File.dirname(File.expand_path(".")) == "/"
34
+ end
35
+
36
+ end
37
+
@@ -0,0 +1,3 @@
1
+
2
+ require_relative 'handler/import'
3
+ require_relative 'handler/mixin'
@@ -1,5 +1,7 @@
1
1
 
2
- module Helpers
2
+ require_relative 'global_helpers'
3
+
4
+ module Livetext::Helpers
3
5
 
4
6
  Space = " "
5
7
  Sigil = "." # Can't change yet
@@ -7,6 +9,14 @@ module Helpers
7
9
  ESCAPING = { "'" => '&#39;', '&' => '&amp;', '"' => '&quot;',
8
10
  '<' => '&lt;', '>' => '&gt;' }
9
11
 
12
+ def friendly_error(err)
13
+ return graceful_error(err) if self.respond_to?(:graceful_error)
14
+ return self.parent.graceful_error(err) if self.respond_to?(:parent)
15
+ raise err
16
+ rescue => myerr
17
+ TTY.puts "--- Warning: friendly_error #{myerr.inspect}"
18
+ end
19
+
10
20
  def escape_html(string)
11
21
  enc = string.encoding
12
22
  unless enc.ascii_compatible?
@@ -23,108 +33,115 @@ module Helpers
23
33
  string.gsub(/['&\"<>]/, ESCAPING)
24
34
  end
25
35
 
26
- def find_file(name, ext=".rb")
27
- paths = [Livetext::Path.sub(/lib/, "imports/"), "./"]
36
+ def showme(obj, tag = "")
37
+ whence = caller[0]
38
+ file, line, meth = whence.split(":")
39
+ file = File.basename(file)
40
+ meth = meth[4..-2]
41
+ tag << " =" if tag
42
+ hide_class = [true, false, nil].include?(obj)
43
+ klass = hide_class ? "" : "(#{obj.class}) "
44
+ puts " #{tag} #{klass}#{obj.inspect} in ##{meth} [#{file} line #{line}]"
45
+ end
46
+
47
+ def debug(*args)
48
+ puts(*args) if ENV['debug']
49
+ end
50
+
51
+ def find_file(name, ext=".rb", which="imports")
52
+ failed = "#{__method__}: expected 'imports' or 'plugin'"
53
+ raise failed unless %w[imports plugin].include?(which)
54
+ paths = [Livetext::Path.sub(/lib.livetext/, "#{which}/"), "./"]
28
55
  base = "#{name}#{ext}"
29
56
  paths.each do |path|
30
57
  file = path + base
31
58
  return file if File.exist?(file)
32
59
  end
33
-
34
- raise "No such mixin '#{name}'"
35
-
36
- # # Really want to search upward??
37
- # raise "No such mixin '#{name}'" if cwd_root?
38
- # Dir.chdir("..") { find_file(name) }
60
+ return nil
39
61
  end
40
62
 
41
63
  def self.rx(str, space=nil)
42
64
  Regexp.compile("^" + Regexp.escape(str) + "#{space}")
43
65
  end
44
66
 
45
- Comment = rx(Sigil, Space)
46
- Dotcmd = rx(Sigil)
47
- Ddotcmd = /^ *\$\.[A-Za-z]/
67
+ Comment = rx(Sigil, Space)
68
+ DotCmd = rx(Sigil)
69
+ DollarDot = /^ *\$\.[A-Za-z]/
48
70
 
49
- ## FIXME process_file[!] should call process[_text]
71
+ ## FIXME process_file[!] should call process[_text] ?
50
72
 
51
73
  def process_file(fname, btrace=false)
74
+ graceful_error FileNotFound(fname) unless File.exist?(fname)
52
75
  setfile(fname)
53
76
  text = File.readlines(fname)
54
77
  enum = text.each
55
78
  @backtrace = btrace
56
79
  @main.source(enum, fname, 0)
57
80
  line = nil
58
- loop do
81
+ loop do
59
82
  line = @main.nextline
60
83
  break if line.nil?
61
- process_line(line)
84
+ success = process_line(line)
85
+ break unless success
62
86
  end
63
- val = @main.finalize if @main.respond_to? :finalize
64
- @body
87
+ val = @main.finalize rescue nil
88
+ @body # FIXME? @body.join("\n") # array
89
+ return true
65
90
  end
66
91
 
67
92
  def process_line(line)
68
- nomarkup = true
93
+ success = true
69
94
  case line # must apply these in order
70
95
  when Comment
71
- handle_scomment(line)
72
- when Dotcmd
73
- handle_dotcmd(line)
74
- when Ddotcmd
75
- indent = line.index("$") + 1
76
- @indentation.push(indent)
77
- line.sub!(/^ *\$/, "")
78
- handle_dotcmd(line)
79
- indentation.pop
96
+ success = handle_scomment(line)
97
+ when DotCmd
98
+ success = handle_dotcmd(line)
99
+ when DollarDot
100
+ success = handle_dollar_dot
80
101
  else
81
- @main._passthru(line)
102
+ api.passthru(line) # must succeed?
82
103
  end
104
+ success
105
+ end
106
+
107
+ def handle_dollar_dot
108
+ indent = line.index("$") + 1
109
+ @indentation.push(indent)
110
+ line.sub!(/^ *\$/, "")
111
+ success = handle_dotcmd(line)
112
+ indentation.pop
113
+ success
114
+ end
115
+
116
+ def invoke_dotcmd(name)
117
+ # FIXME Add cmdargs stuff... depends on name, etc.
118
+ retval = @main.send(name)
119
+ retval
120
+ # rescue NoMethodError => err
121
+ # graceful_error(err)
122
+ rescue => err
123
+ graceful_error(err)
83
124
  end
84
125
 
85
126
  def handle_dotcmd(line, indent = 0)
127
+ # TTY.puts ">>> #{__method__} in #{__FILE__}" # if ENV['debug']
86
128
  indent = @indentation.last # top of stack
87
- line = line.sub(/# .*$/, "")
88
- name = get_name(line).to_sym
89
- result = nil
129
+ line = line.sub(/# .*$/, "") # FIXME Could be problematic?
130
+ name = get_name(line)
131
+ success = true # Be optimistic... :P
90
132
  case
91
133
  when name == :end # special case
92
- puts @body
93
- raise EndWithoutOpening()
134
+ graceful_error EndWithoutOpening()
94
135
  when @main.respond_to?(name)
95
- result = @main.send(name)
96
-
97
- # NOTE: The above line is where the magic happens!
98
- # A name like 'foobar' results in an invocation of
99
- # @main.foobar (where @main is a Processor, and any
100
- # new methods (e.g. from a mixin) are added to @main
101
- #
102
- # So all the functionality from _args and _raw_args
103
- # and _data (among others?) will be encapsulated in
104
- # 'some' kind of PORO which handles access to all
105
- # these things as well as the 'body' between the
106
- # command and its corresponding .end
107
- #
108
- # The 'body' functionality is so commonly used, I plan
109
- # to pass it in separately as needed (even though the
110
- # args object should make it available also).
111
- #
112
- # Every method corresponding to a dot commmand will
113
- # get args and body passed in as needed. Every one of
114
- # the signatures already has (args = nil, body = nil)
115
- # but nothing is being passed in that way yet.
116
- #
117
- # Refer to lib/cmdargs.rb for more! This is *strictly*
118
- # experimental and a "work in progress."
136
+ success = invoke_dotcmd(name)
119
137
  else
120
- puts @body # earlier correct output, not flushed yet
121
- raise "Name '#{name}' is unknown"
122
- return
138
+ graceful_error UnknownMethod(name)
123
139
  end
124
- result
140
+ success
125
141
  end
126
142
 
127
143
  def handle_scomment(line)
144
+ return true
128
145
  end
129
146
 
130
147
  def get_name(line)
@@ -133,15 +150,17 @@ module Helpers
133
150
  name = "dot_" + name if %w[include def].include?(name)
134
151
  @main.check_disallowed(name)
135
152
  @main.data = data
136
- name
153
+ @main.api.data = data
154
+ name.to_sym
137
155
  end
138
156
 
139
157
  def check_disallowed(name)
140
- raise DisallowedName(name) if disallowed?(name)
158
+ friendly_error DisallowedName(name) if disallowed?(name)
141
159
  end
142
160
 
143
161
  def check_file_exists(file)
144
- raise FileNotFound(file) unless File.exist?(file)
162
+ # raise FileNotFound(file) unless File.exist?(file)
163
+ return File.exist?(file)
145
164
  end
146
165
 
147
166
  def set_variables(pairs)
@@ -153,6 +172,9 @@ module Helpers
153
172
 
154
173
  def grab_file(fname)
155
174
  File.read(fname)
175
+ rescue
176
+ ::STDERR.puts "Can't find #{fname.inspect} \n "
177
+ return nil
156
178
  end
157
179
 
158
180
  def search_upward(file)
@@ -169,15 +191,15 @@ module Helpers
169
191
  value = path if File.exist?(path)
170
192
  break if value
171
193
  end
172
- STDERR.puts "Cannot find #{file.inspect} from #{Dir.pwd}" unless value
194
+ ::STDERR.puts "Cannot find #{file.inspect} from #{Dir.pwd}" unless value
173
195
  return value
174
196
  rescue
175
- STDERR.puts "Can't find #{file.inspect} from #{Dir.pwd}"
197
+ ::STDERR.puts "Can't find #{file.inspect} from #{Dir.pwd}"
176
198
  return nil
177
199
  end
178
200
 
179
201
  def include_file(file)
180
- @_args = [file]
202
+ api.args = [file]
181
203
  dot_include
182
204
  end
183
205
 
@@ -1,3 +1,4 @@
1
+
1
2
  module HTMLHelper
2
3
 
3
4
  def wrapped(str, *tags) # helper
@@ -15,9 +16,9 @@ module HTMLHelper
15
16
 
16
17
  def wrap(*tags) # helper
17
18
  open, close = open_close_tags(*tags)
18
- _out open
19
+ api.out open
19
20
  yield
20
- _out close
21
+ api.out close
21
22
  end
22
23
 
23
24
  def open_close_tags(*tags)
@@ -1,7 +1,4 @@
1
1
 
2
- require_relative '../livetext'
3
- require_relative 'string'
4
-
5
2
  make_exception(:MismatchedQuotes, "Error: mismatched quotes")
6
3
  make_exception(:NilValue, "Error: nil value")
7
4
  make_exception(:NullString, "Error: null string")
@@ -1,7 +1,4 @@
1
1
 
2
- require_relative '../livetext'
3
- require_relative 'string'
4
-
5
2
  make_exception(:BadVariableName, "Error: invalid variable name")
6
3
  make_exception(:NoEqualSign, "Error: no equal sign found")
7
4
 
@@ -107,7 +104,6 @@ class Livetext::ParseSet < StringParser
107
104
  char = grab
108
105
  break if eos?
109
106
  break if char == quote
110
- # break if char.nil?
111
107
  char = escaped if char == "\\"
112
108
  value << char
113
109
  end
@@ -123,8 +119,7 @@ class Livetext::ParseSet < StringParser
123
119
  value = ""
124
120
  loop do
125
121
  char = peek
126
- break if eos? # FIXME oops???
127
- # break if char.nil?
122
+ break if eos?
128
123
  break if char == " " || char == ","
129
124
  value << char
130
125
  char = grab
@@ -24,7 +24,7 @@ class StringParser
24
24
  check_eos
25
25
  end
26
26
 
27
- def next!
27
+ def lookahead
28
28
  @line[@i + 1]
29
29
  end
30
30
 
@@ -62,7 +62,7 @@ end
62
62
 
63
63
  =begin
64
64
  skip
65
- next! skip! peek!(?)
65
+ lookahead skip! peek!(?)
66
66
  expect_alpha
67
67
  expect_number
68
68
  skip_spaces
@@ -2,4 +2,3 @@
2
2
  require_relative 'parser/string'
3
3
  require_relative 'parser/general'
4
4
  require_relative 'parser/set'
5
- require_relative 'parser/mixin'
@@ -0,0 +1,29 @@
1
+
2
+ # Constants for parsing
3
+
4
+ module Livetext::ParsingConstants
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
+ BITS = SimpleFormats.keys
12
+
13
+ Null = ""
14
+ Space = " "
15
+ Alpha = /[A-Za-z]/
16
+ AlNum = /[A-Za-z0-9_]/
17
+ LF = "\n"
18
+ LBrack = "["
19
+
20
+ Blank = [" ", nil, "\n"]
21
+ Punc = [")", ",", ".", " ", "\n"]
22
+ NoAlpha = /[^A-Za-z0-9_]/
23
+ NoAlphaDot = /[^.A-Za-z0-9_]/
24
+ Param = ["]", "\n", nil]
25
+ Escape = "\\" # not an ESC char
26
+
27
+ Syms = { "*" => :b, "_" => :i, "`" => :t, "~" => :s }
28
+
29
+ end
@@ -0,0 +1,13 @@
1
+ # Reopening for paths... do differently?
2
+
3
+ class Livetext
4
+ def self.get_path(dir = "")
5
+ path = File.join(File.dirname(__FILE__), dir)
6
+ File.expand_path(path)
7
+ end
8
+
9
+ Path = self.get_path
10
+ Plugins = self.get_path("../plugin")
11
+ Imports = self.get_path("../imports")
12
+ end
13
+
@@ -0,0 +1,89 @@
1
+
2
+ # Class Processor does the actual work of processing input.
3
+
4
+ class Processor
5
+
6
+ GenericError = Class.new(StandardError)
7
+
8
+ include Livetext::Standard
9
+
10
+ Disallowed =
11
+ %i[ __binding__ __id__ __send__ class
12
+ clone display dup enum_for
13
+ eql? equal? extend freeze
14
+ frozen? hash inspect instance_eval
15
+ instance_exec instance_of? is_a? kind_of?
16
+ method methods nil? object_id
17
+ pretty_inspect private_methods protected_methods public_method
18
+ public_methods public_send respond_to? send
19
+ singleton_class singleton_method singleton_methods taint
20
+ tainted? tap to_enum to_s
21
+ trust untaint untrust untrusted?
22
+ define_singleton_method instance_variable_defined?
23
+ instance_variable_get instance_variable_set
24
+ remove_instance_variable instance_variables ]
25
+
26
+ attr_reader :parent, :sources
27
+
28
+ def initialize(parent, output = nil)
29
+ @parent = parent
30
+ @nopass = false
31
+ @nopara = false
32
+ # Meh?
33
+ @output = ::Livetext.output = (output || File.open("/dev/null", "w"))
34
+ @sources = []
35
+ @indentation = @parent.indentation
36
+ @_mixins = []
37
+ @_imports = []
38
+ end
39
+
40
+ def api
41
+ @parent.api # FIXME Is this weird??
42
+ end
43
+
44
+ def output=(io)
45
+ @output = io
46
+ end
47
+
48
+ def error(*args)
49
+ ::STDERR.puts *args
50
+ end
51
+
52
+ def _error!(err, raise_error=false, trace=false) # FIXME much bullshit happens here
53
+ where = @sources.last || @live.save_location
54
+ error "Error: #{err} (at #{where[1]} line #{where[2]})"
55
+ error(err.backtrace) rescue nil
56
+ raise GenericError.new("Error: #{err}") if raise_error
57
+ end
58
+
59
+ def disallowed?(name)
60
+ Disallowed.include?(name.to_sym)
61
+ end
62
+
63
+ def source(enum, file, line)
64
+ @sources.push([enum, file, line])
65
+ end
66
+
67
+ def peek_nextline
68
+ return nil if @sources.empty?
69
+ source = @sources.last
70
+ line = source[0].peek
71
+ line
72
+ rescue StopIteration
73
+ @sources.pop
74
+ nil
75
+ rescue => err
76
+ TTY.puts "#{__method__}: RESCUE err = #{err.inspect}"
77
+ nil
78
+ end
79
+
80
+ def nextline
81
+ return nil if @sources.empty?
82
+ line = @sources.last[0].next
83
+ @sources.last[2] += 1
84
+ line
85
+ rescue StopIteration
86
+ @sources.pop
87
+ nil
88
+ end
89
+ end
@@ -0,0 +1,12 @@
1
+ # Reopen for convenience... do differently
2
+
3
+ class Object
4
+ def send?(meth, *args)
5
+ if self.respond_to?(meth)
6
+ self.send(meth, *args)
7
+ else
8
+ return nil
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,17 @@
1
+ require_relative 'parser/string' # FIXME eh, should fix this
2
+
3
+ # Class Livetext skeleton (top level).
4
+
5
+ class Livetext
6
+ module Handler
7
+ end
8
+
9
+ module ParsingConstants
10
+ end
11
+
12
+ class FormatLine < StringParser
13
+ module FunCall
14
+ end
15
+ end
16
+ end
17
+