livetext 0.9.21 → 0.9.25

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.
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
+