livetext 0.9.22 → 0.9.23

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +2 -2
  3. data/imports/tutorial.rb +1 -1
  4. data/lib/cmdargs.rb +2 -0
  5. data/lib/errors.rb +2 -0
  6. data/lib/formatline.rb +10 -108
  7. data/lib/funcall.rb +93 -0
  8. data/lib/functions.rb +1 -1
  9. data/lib/global_helpers.rb +39 -0
  10. data/lib/handler/import.rb +20 -11
  11. data/lib/handler.rb +2 -0
  12. data/lib/helpers.rb +12 -4
  13. data/lib/html.rb +2 -0
  14. data/lib/livetext.rb +23 -2
  15. data/lib/parser/file.rb +0 -2
  16. data/lib/parser/general.rb +0 -3
  17. data/lib/parser/mixin.rb +4 -8
  18. data/lib/parser/set.rb +0 -3
  19. data/lib/parser.rb +2 -0
  20. data/lib/parsing.rb +31 -0
  21. data/lib/processor.rb +65 -71
  22. data/lib/standard.rb +12 -1
  23. data/lib/userapi.rb +3 -1
  24. data/plugin/pyggish.rb +1 -0
  25. data/test/snapshots/error_inc_line_num/OUT +17 -0
  26. data/test/snapshots/error_inc_line_num/actual-error.txt +0 -14
  27. data/test/snapshots/error_inc_line_num/actual-output.txt +10 -0
  28. data/test/snapshots/error_invalid_name/actual-error.txt +6 -6
  29. data/test/snapshots/error_missing_end/actual-error.txt +5 -5
  30. data/test/snapshots/error_no_such_copy/actual-error.txt +7 -7
  31. data/test/snapshots/error_no_such_copy/match-error.txt +1 -1
  32. data/test/snapshots/error_no_such_copy/out-sdiff.txt +5 -0
  33. data/test/snapshots/error_no_such_inc/actual-error.txt +6 -6
  34. data/test/snapshots/error_no_such_inc/match-error.txt +1 -1
  35. data/test/snapshots/error_no_such_inc/out-sdiff.txt +6 -0
  36. data/test/snapshots/error_no_such_mixin/actual-error.txt +7 -7
  37. data/test/snapshots/{wtf_bookish → import_bookish}/expected-error.txt +0 -0
  38. data/test/snapshots/{wtf_bookish → import_bookish}/expected-output.txt +0 -0
  39. data/test/snapshots/{wtf_bookish → import_bookish}/source.lt3 +0 -0
  40. data/test/snapshots/{wtf_bookish → import_bookish}/toc.tmp +0 -0
  41. data/test/snapshots/{import/actual-output.txt → mixin_bookish/expected-error.txt} +0 -0
  42. data/test/snapshots/mixin_bookish/expected-output.txt +10 -0
  43. data/test/snapshots/mixin_bookish/source.lt3 +7 -0
  44. data/test/snapshots/mixin_bookish/toc.tmp +0 -0
  45. data/test/snapshots/subset.txt +4 -3
  46. data/test/snapshots.rb +15 -6
  47. data/test/unit/formatline.rb +2 -0
  48. data/test/unit/html.rb +1 -1
  49. data/test/unit/parser/general.rb +1 -2
  50. data/test/unit/parser/mixin.rb +1 -3
  51. data/test/unit/parser/set.rb +2 -2
  52. data/test/unit/parser/string.rb +1 -1
  53. data/test/unit/parser.rb +0 -1
  54. metadata +16 -12
  55. data/imports/markdown_importable.rb +0 -45
  56. data/test/snapshots/error_inc_line_num/out-sdiff.txt +0 -14
  57. data/test/snapshots/import/actual-error.txt +0 -13
  58. data/test/snapshots/import/out-sdiff.txt +0 -6
  59. data/test/unit/parser/importable.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3d2ff056cfc390401ec0517a7a74bb0eadf9128fff5eaff5c60a548775bdde9f
4
- data.tar.gz: c76d7b425e3c19b0c44c752ff5705757415f60ee1d2647b538cfb9e6eb263ec3
3
+ metadata.gz: 8b1fc83442ee9361739a1d0024eebcaa342b3d75242824d0127644a03c2a6d12
4
+ data.tar.gz: c6bb5f661e43f438b65f40d4cb3b7f71a7ebb8a87951d6c157f932d418c0ea4a
5
5
  SHA512:
6
- metadata.gz: bc98e86fdc72cbe0441ad2b80cbff64d3afbf4cae68eaba12e6e84ba5dd51913e6cdc9c687678782db61f64796347a2cf5d149e2eb74c4ed436634efa0c8b9fb
7
- data.tar.gz: e6359fd712953b1579bb36d56b5dfd9546963064e4a5f08165ccf4a61dcc1de0a52374a15d7f038e63fe9ff00f25a5d3c0febdac501fea067399bf3c682075eb
6
+ metadata.gz: 17ac68b8a91831199d1e6effaca85add11311251cbf6388214219768ebba937198cebc6fe314bed95d8b5c8ddabf86672601be274fbfe26601a6622c899049e6
7
+ data.tar.gz: cce50c49518fc8440ba7295d9d7bd6d711307115106b8f707d3b2f7a2f38a470b6a21f0dfa4ca2345329621e9c400dab9ea7758b4ad68cf345201dea2fcc970c
data/README.lt3 CHANGED
@@ -1,5 +1,5 @@
1
- .icanhaz tutorial
2
- .icanhaz markdown
1
+ .import tutorial
2
+ .import markdown
3
3
 
4
4
  . copy basic.css
5
5
 
data/imports/tutorial.rb CHANGED
@@ -3,7 +3,7 @@ require 'helpers'
3
3
  # Created as an "ad hoc" lib for generating the README
4
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
data/lib/cmdargs.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # p __FILE__
2
+
1
3
  require_relative 'livetext'
2
4
 
3
5
  =begin
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,30 +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
- 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 }
9
+ class Livetext::FormatLine < StringParser
10
+ include Livetext::ParsingConstants
11
+ include Livetext::FormatLine::FunCall
28
12
 
29
13
  attr_reader :out
30
14
  attr_reader :tokenlist
@@ -39,7 +23,6 @@ class FormatLine < StringParser
39
23
  return nil if line.nil?
40
24
  x = self.new(line.chomp)
41
25
  t = x.tokenize
42
- # TTY.puts "tokens = \n#{t.inspect}\n "
43
26
  x.evaluate
44
27
  end
45
28
 
@@ -47,7 +30,7 @@ class FormatLine < StringParser
47
30
  # add grab
48
31
  loop do
49
32
  case peek
50
- when Escape; grab; add peek; grab; # add peek # <-- last is an error??
33
+ when Escape; grab; add peek; grab
51
34
  when "$"
52
35
  dollar
53
36
  when "*", "_", "`", "~"
@@ -82,7 +65,7 @@ class FormatLine < StringParser
82
65
  char = x.grab
83
66
  break if char == LF || char == nil
84
67
  x.handle_escaping if char == Escape
85
- x.dollar if char == "$"
68
+ x.dollar if char == "$" # Could be $$
86
69
  x.add char
87
70
  end
88
71
  x.add_token(:str)
@@ -121,18 +104,6 @@ class FormatLine < StringParser
121
104
  @out
122
105
  end
123
106
 
124
- def grab_func_param
125
- case lookahead
126
- when "["
127
- param = grab_bracket_param
128
- add_token(:brackets, param)
129
- when ":"
130
- param = grab_colon_param
131
- add_token(:colon, param)
132
- else # do nothing
133
- end
134
- end
135
-
136
107
  def add(str)
137
108
  @token << str unless str.nil?
138
109
  end
@@ -185,20 +156,6 @@ class FormatLine < StringParser
185
156
  end
186
157
  end
187
158
 
188
- def double_dollar
189
- case lookahead
190
- when Space; add_token :string, "$$ "; grab; return
191
- when LF, nil; add "$$"; add_token :str
192
- when Alpha
193
- add_token(:str, @token)
194
- func = grab_alpha
195
- add_token(:func, func)
196
- param = grab_func_param # may be null/missing
197
- else
198
- grab; add_token :str, "$$" + peek; return
199
- end
200
- end
201
-
202
159
  # def dollar_dot
203
160
  # add_token :ddot, @line[@i..-1]
204
161
  # end
@@ -309,19 +266,6 @@ class FormatLine < StringParser
309
266
  ::STDERR.puts "ERR = #{err}\n#{err.backtrace}"
310
267
  end
311
268
 
312
- def funcall(name, param)
313
- err = "[Error evaluating $$#{name}(#{param})]"
314
- func_name = name # "func_" + name.to_s
315
- result =
316
- if self.send?(func_name, param) # self.respond_to?(func_name)
317
- # do nothing
318
- else
319
- fobj = ::Livetext::Functions.new
320
- fobj.send(name, param) rescue err
321
- end
322
- result.to_s
323
- end
324
-
325
269
  def varsub(name)
326
270
  result = Livetext::Vars[name] || "[#{name} is undefined]"
327
271
  result
@@ -333,48 +277,6 @@ class FormatLine < StringParser
333
277
 
334
278
  private
335
279
 
336
- def grab_colon_param
337
- grab # grab :
338
- param = ""
339
- loop do
340
- case lookahead
341
- when Escape
342
- grab
343
- param << lookahead
344
- grab
345
- when Space, LF, nil; break
346
- else
347
- param << lookahead
348
- grab
349
- end
350
- end
351
-
352
- param = nil if param.empty?
353
- param
354
- end
355
-
356
- def grab_bracket_param
357
- grab # [
358
- param = ""
359
- loop do
360
- case lookahead
361
- when Escape
362
- grab
363
- param << lookahead
364
- grab
365
- when "]", LF, nil
366
- break
367
- else
368
- param << lookahead
369
- grab
370
- end
371
- end
372
- add peek
373
- grab
374
- param = nil if param.empty?
375
- param
376
- end
377
-
378
280
  def eval_bits(sym, val)
379
281
  val = Livetext.interpolate(val)
380
282
  @out << embed(sym, val)
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??
@@ -0,0 +1,39 @@
1
+ # p __FILE__
2
+
3
+
4
+ module GlobalHelpers
5
+
6
+ def check_disallowed(name)
7
+ raise DisallowedName(name) if disallowed?(name)
8
+ end
9
+
10
+ def check_file_exists(file)
11
+ raise FileNotFound(file) unless File.exist?(file)
12
+ end
13
+
14
+ def grab_file(fname)
15
+ File.read(fname)
16
+ end
17
+
18
+ def search_upward(file)
19
+ value = nil
20
+ return file if File.exist?(file)
21
+
22
+ count = 1
23
+ loop do
24
+ front = "../" * count
25
+ count += 1
26
+ here = Pathname.new(front).expand_path.dirname.to_s
27
+ break if here == "/"
28
+ path = front + file
29
+ value = path if File.exist?(path)
30
+ break if value
31
+ end
32
+ ::STDERR.puts "Cannot find #{file.inspect} from #{Dir.pwd}" unless value
33
+ return value
34
+ rescue
35
+ ::STDERR.puts "Can't find #{file.inspect} from #{Dir.pwd}"
36
+ return nil
37
+ end
38
+
39
+ end
@@ -1,6 +1,10 @@
1
1
 
2
+ require_relative '../helpers'
3
+ require_relative '../global_helpers'
4
+
2
5
  class Livetext::Handler::Import
3
- include Helpers
6
+ include Livetext::Helpers
7
+ include GlobalHelpers
4
8
 
5
9
  attr_reader :file
6
10
 
@@ -9,15 +13,23 @@ class Livetext::Handler::Import
9
13
  @file = find_file(name)
10
14
  end
11
15
 
12
- def self.get_module(name)
13
- handler = self.new(name)
14
- const1 = Object.constants
16
+ def self.get_mod_name
17
+ file = File.new(@file + ".rb")
18
+ str = nil
19
+ file.each_line do |line|
20
+ str = line
21
+ break if str =~ /^module /
22
+ end
23
+ junk, name, junk2 = str.split
24
+ name
25
+ end
26
+
27
+ def self.get_module(filename)
28
+ handler = self.new(filename)
15
29
  @file = handler.file.sub(/.rb$/, "")
16
30
  require @file # + ".rb"
17
- const2 = Object.constants
18
- names = (const2 - const1)
19
- abort "Expected ONE new constant: #{names.inspect}" if names.size != 1
20
- modname = names.first.to_s
31
+ modname = get_mod_name
32
+ # TTY.puts "modname = #{modname.inspect}"
21
33
  newmod = Object.const_get("::" + modname)
22
34
  newmod # return actual module
23
35
  end
@@ -28,8 +40,5 @@ class Livetext::Handler::Import
28
40
  File.dirname(File.expand_path(".")) == "/"
29
41
  end
30
42
 
31
- def fname2module(name)
32
- end
33
-
34
43
  end
35
44
 
data/lib/handler.rb CHANGED
@@ -1 +1,3 @@
1
+ # p __FILE__
2
+
1
3
  require_relative 'handler/import'
data/lib/helpers.rb CHANGED
@@ -1,5 +1,7 @@
1
+ # p __FILE__
1
2
 
2
- module Helpers
3
+
4
+ module Livetext::Helpers
3
5
 
4
6
  Space = " "
5
7
  Sigil = "." # Can't change yet
@@ -23,8 +25,10 @@ module Helpers
23
25
  string.gsub(/['&\"<>]/, ESCAPING)
24
26
  end
25
27
 
26
- def find_file(name, ext=".rb")
27
- paths = [Livetext::Path.sub(/lib/, "imports/"), "./"]
28
+ def find_file(name, ext=".rb", which="imports")
29
+ failed = "#{__method__}: expected 'imports' or 'plugin'"
30
+ raise failed unless %w[imports plugin].include?(which)
31
+ paths = [Livetext::Path.sub(/lib/, "#{which}/"), "./"]
28
32
  base = "#{name}#{ext}"
29
33
  paths.each do |path|
30
34
  file = path + base
@@ -61,7 +65,11 @@ module Helpers
61
65
  process_line(line)
62
66
  end
63
67
  val = @main.finalize rescue nil
64
- @body
68
+ @body # FIXME? @body.join("\n") # array
69
+ rescue StandardError => err
70
+ # TTY.puts ">>> rescue in process_file!! (helpers)"
71
+ # TTY.puts @body
72
+ raise err
65
73
  end
66
74
 
67
75
  def process_line(line)
data/lib/html.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # p __FILE__
2
+
1
3
  module HTMLHelper
2
4
 
3
5
  def wrapped(str, *tags) # helper
data/lib/livetext.rb CHANGED
@@ -1,11 +1,23 @@
1
+ # p __FILE__
2
+
3
+ require_relative 'parser/string'
4
+
1
5
  # Class Livetext skeleton (top level).
2
6
 
3
7
  class Livetext
4
- VERSION = "0.9.22"
8
+ VERSION = "0.9.23"
5
9
  Path = File.expand_path(File.join(File.dirname(__FILE__)))
6
10
 
7
11
  module Handler
8
12
  end
13
+
14
+ module ParsingConstants
15
+ end
16
+
17
+ class FormatLine < StringParser
18
+ module FunCall
19
+ end
20
+ end
9
21
  end
10
22
 
11
23
  require 'fileutils'
@@ -21,14 +33,15 @@ class Object
21
33
  end
22
34
 
23
35
  require_relative 'errors'
36
+ require_relative 'standard'
24
37
  require_relative 'functions'
25
38
  require_relative 'userapi'
26
- require_relative 'standard'
27
39
  require_relative 'formatline'
28
40
  require_relative 'processor'
29
41
  require_relative 'helpers'
30
42
  require_relative 'handler'
31
43
 
44
+
32
45
  Plugins = File.expand_path(File.join(File.dirname(__FILE__), "../plugin"))
33
46
  Imports = File.expand_path(File.join(File.dirname(__FILE__), "../imports"))
34
47
 
@@ -57,6 +70,11 @@ class Livetext
57
70
  Livetext::Vars.dup
58
71
  end
59
72
 
73
+ def self.interpolate(str)
74
+ # FIXME There are issues here...
75
+ Livetext::FormatLine.var_func_parse(str)
76
+ end
77
+
60
78
  def self.customize(mix: [], call: [], vars: {})
61
79
  obj = self.new
62
80
  mix = Array(mix)
@@ -88,6 +106,9 @@ class Livetext
88
106
  initial_vars
89
107
  end
90
108
 
109
+ def interpolate(str)
110
+ end
111
+
91
112
  def initial_vars
92
113
  # Other predefined variables (see also setfile)
93
114
  setvar(:User, `whoami`.chomp)
data/lib/parser/file.rb CHANGED
@@ -1,6 +1,4 @@
1
1
 
2
- require_relative '../livetext'
3
-
4
2
  # Hmm. not today?
5
3
 
6
4
  class Livetext::ParseFile
@@ -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")
data/lib/parser/mixin.rb CHANGED
@@ -1,15 +1,13 @@
1
- require_relative '../livetext'
2
- require_relative '../helpers'
3
- require_relative 'string'
1
+ require_relative '../helpers' # FIXME This seems wrong
4
2
 
5
3
  make_exception(:NoEqualSign, "Error: no equal sign found")
6
4
 
7
5
  class Livetext::ParseMixin
8
- include Helpers
6
+ include Livetext::Helpers
9
7
 
10
8
  def initialize(name)
11
9
  @name = name
12
- @file = find_file(name)
10
+ @file = find_file(name, ".rb", "plugin")
13
11
  end
14
12
 
15
13
  def self.get_module(name)
@@ -17,8 +15,7 @@ class Livetext::ParseMixin
17
15
  modname, code = parse.read_mixin
18
16
  eval(code) # Avoid in the future
19
17
  newmod = Object.const_get("::" + modname)
20
- # return actual module
21
- newmod
18
+ newmod # return actual module
22
19
  end
23
20
 
24
21
  def read_mixin
@@ -33,6 +30,5 @@ class Livetext::ParseMixin
33
30
  File.dirname(File.expand_path(".")) == "/"
34
31
  end
35
32
 
36
-
37
33
  end
38
34
 
data/lib/parser/set.rb CHANGED
@@ -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
 
data/lib/parser.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # p __FILE__
2
+
1
3
 
2
4
  require_relative 'parser/string'
3
5
  require_relative 'parser/general'
data/lib/parsing.rb ADDED
@@ -0,0 +1,31 @@
1
+ # p __FILE__
2
+
3
+
4
+ # Constants for parsing
5
+
6
+ module Livetext::ParsingConstants
7
+ SimpleFormats = {}
8
+ SimpleFormats[:b] = %w[<b> </b>]
9
+ SimpleFormats[:i] = %w[<i> </i>]
10
+ SimpleFormats[:t] = ["<font size=+1><tt>", "</tt></font>"]
11
+ SimpleFormats[:s] = %w[<strike> </strike>]
12
+
13
+ BITS = SimpleFormats.keys
14
+
15
+ Null = ""
16
+ Space = " "
17
+ Alpha = /[A-Za-z]/
18
+ AlNum = /[A-Za-z0-9_]/
19
+ LF = "\n"
20
+ LBrack = "["
21
+
22
+ Blank = [" ", nil, "\n"]
23
+ Punc = [")", ",", ".", " ", "\n"]
24
+ NoAlpha = /[^A-Za-z0-9_]/
25
+ NoAlphaDot = /[^.A-Za-z0-9_]/
26
+ Param = ["]", "\n", nil]
27
+ Escape = "\\" # not an ESC char
28
+
29
+ Syms = { "*" => :b, "_" => :i, "`" => :t, "~" => :s }
30
+
31
+ end