livetext 0.9.19 → 0.9.23
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.lt3 +4 -2
- data/README.md +330 -339
- data/bin/livetext +0 -2
- data/imports/bookish.rb +8 -10
- data/imports/markdown.rb +6 -6
- data/imports/pyggish.rb +2 -34
- data/imports/tutorial.rb +4 -4
- data/lib/cmdargs.rb +30 -20
- data/lib/errors.rb +2 -0
- data/lib/formatline.rb +54 -124
- data/lib/funcall.rb +93 -0
- data/lib/functions.rb +17 -2
- data/lib/global_helpers.rb +39 -0
- data/lib/handler/import.rb +44 -0
- data/lib/handler.rb +3 -1
- data/lib/helpers.rb +46 -12
- data/lib/html.rb +2 -0
- data/lib/livetext.rb +34 -6
- data/lib/parser/file.rb +0 -2
- data/lib/parser/general.rb +1 -4
- data/lib/parser/mixin.rb +4 -8
- data/lib/parser/set.rb +3 -8
- data/lib/parser/string.rb +11 -10
- data/lib/parser.rb +2 -0
- data/lib/parsing.rb +31 -0
- data/lib/processor.rb +66 -60
- data/lib/standard.rb +28 -17
- data/lib/userapi.rb +8 -4
- data/plugin/bookish.rb +4 -5
- data/plugin/markdown.rb +6 -6
- data/plugin/pyggish.rb +46 -77
- data/plugin/tutorial.rb +3 -3
- data/test/snapshots/error_inc_line_num/OUT +17 -0
- data/test/snapshots/{icanhaz2/expected-error.txt → error_inc_line_num/actual-error.txt} +0 -0
- data/test/snapshots/error_inc_line_num/actual-output.txt +17 -0
- data/test/snapshots/error_invalid_name/actual-error.txt +10 -0
- data/test/snapshots/error_invalid_name/actual-output.txt +0 -0
- data/test/snapshots/error_invalid_name/out-sdiff.txt +6 -0
- data/test/snapshots/error_missing_end/actual-error.txt +10 -0
- data/test/snapshots/error_missing_end/actual-output.txt +0 -0
- data/test/snapshots/error_missing_end/out-sdiff.txt +6 -0
- data/test/snapshots/error_no_such_copy/actual-error.txt +10 -0
- data/test/snapshots/error_no_such_copy/actual-output.txt +0 -0
- data/test/snapshots/error_no_such_copy/match-error.txt +1 -1
- data/test/snapshots/error_no_such_copy/out-sdiff.txt +5 -0
- data/test/snapshots/error_no_such_inc/actual-error.txt +10 -0
- data/test/snapshots/error_no_such_inc/actual-output.txt +0 -0
- data/test/snapshots/error_no_such_inc/match-error.txt +1 -1
- data/test/snapshots/error_no_such_inc/out-sdiff.txt +6 -0
- data/test/snapshots/error_no_such_mixin/actual-error.txt +13 -0
- data/test/snapshots/error_no_such_mixin/actual-output.txt +0 -0
- data/test/snapshots/error_no_such_mixin/out-sdiff.txt +6 -0
- data/test/snapshots/{icanhaz → import}/expected-output.txt +0 -0
- data/test/snapshots/{icanhaz → import}/match-error.txt +0 -0
- data/test/snapshots/{icanhaz → import}/simple_import.rb +0 -0
- data/test/snapshots/{icanhaz → import}/source.lt3 +2 -2
- data/test/snapshots/import2/expected-error.txt +0 -0
- data/test/snapshots/{icanhaz2 → import2}/expected-output.txt +3 -1
- data/test/snapshots/{icanhaz2/simple_canhaz.rb → import2/simple_import.rb} +0 -0
- data/test/snapshots/import2/source.lt3 +8 -0
- data/test/snapshots/import_bookish/expected-error.txt +0 -0
- data/test/snapshots/import_bookish/expected-output.txt +10 -0
- data/test/snapshots/import_bookish/source.lt3 +7 -0
- data/test/snapshots/import_bookish/toc.tmp +0 -0
- data/test/snapshots/mixin_bookish/expected-error.txt +0 -0
- data/test/snapshots/mixin_bookish/expected-output.txt +10 -0
- data/test/snapshots/mixin_bookish/source.lt3 +7 -0
- data/test/snapshots/mixin_bookish/toc.tmp +0 -0
- data/test/snapshots/more_functions/expected-error.txt +0 -0
- data/test/snapshots/more_functions/expected-output.txt +37 -0
- data/test/snapshots/more_functions/source.lt3 +40 -0
- data/test/snapshots/simple_import/expected-output.txt +2 -0
- data/test/snapshots/simple_import/source.lt3 +3 -1
- data/test/snapshots/subset.txt +84 -0
- data/test/snapshots.rb +39 -43
- data/test/unit/formatline.rb +253 -134
- data/test/unit/html.rb +1 -1
- data/test/unit/parser/general.rb +1 -2
- data/test/unit/parser/mixin.rb +1 -3
- data/test/unit/parser/set.rb +22 -24
- data/test/unit/parser/string.rb +46 -7
- data/test/unit/parser.rb +0 -1
- data/test/unit/standard.rb +0 -1
- metadata +43 -24
- data/imports/markdown_importable.rb +0 -46
- data/lib/handler/icanhaz.rb +0 -35
- data/lib/livetext/importable.rb +0 -2
- data/lib/parser/import.rb +0 -15
- data/test/affirm/kbks.jpg +0 -0
- data/test/affirm/lm-kbks.lt +0 -19
- data/test/cleanup +0 -1
- data/test/newtest +0 -14
- data/test/sdtest +0 -6
- data/test/snapshots/OMIT.txt +0 -11
- data/test/snapshots/clusion.txt +0 -84
- data/test/snapshots/crap +0 -16
- data/test/snapshots/fixit +0 -6
- data/test/snapshots/icanhaz2/source.lt3 +0 -6
- data/test/unit/parser/importable.rb +0 -19
@@ -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
|
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
require_relative '../helpers'
|
3
|
+
require_relative '../global_helpers'
|
4
|
+
|
5
|
+
class Livetext::Handler::Import
|
6
|
+
include Livetext::Helpers
|
7
|
+
include GlobalHelpers
|
8
|
+
|
9
|
+
attr_reader :file
|
10
|
+
|
11
|
+
def initialize(name)
|
12
|
+
@name = name
|
13
|
+
@file = find_file(name)
|
14
|
+
end
|
15
|
+
|
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)
|
29
|
+
@file = handler.file.sub(/.rb$/, "")
|
30
|
+
require @file # + ".rb"
|
31
|
+
modname = get_mod_name
|
32
|
+
# TTY.puts "modname = #{modname.inspect}"
|
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
|
+
|
data/lib/handler.rb
CHANGED
data/lib/helpers.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
|
+
# p __FILE__
|
1
2
|
|
2
|
-
|
3
|
+
|
4
|
+
module Livetext::Helpers
|
3
5
|
|
4
6
|
Space = " "
|
5
7
|
Sigil = "." # Can't change yet
|
6
8
|
|
9
|
+
ESCAPING = { "'" => ''', '&' => '&', '"' => '"',
|
10
|
+
'<' => '<', '>' => '>' }
|
11
|
+
|
7
12
|
def escape_html(string)
|
8
13
|
enc = string.encoding
|
9
14
|
unless enc.ascii_compatible?
|
@@ -12,16 +17,18 @@ module Helpers
|
|
12
17
|
enc = Encoding::Converter.asciicompat_encoding(enc)
|
13
18
|
string = enc ? string.encode(enc) : string.b
|
14
19
|
end
|
15
|
-
table = Hash[
|
20
|
+
table = Hash[ESCAPING.map {|pair|pair.map {|s|s.encode(enc)}}]
|
16
21
|
string = string.gsub(/#{"['&\"<>]".encode(enc)}/, table)
|
17
22
|
string.encode!(origenc) if origenc
|
18
23
|
return string
|
19
24
|
end
|
20
|
-
string.gsub(/['&\"<>]/,
|
25
|
+
string.gsub(/['&\"<>]/, ESCAPING)
|
21
26
|
end
|
22
27
|
|
23
|
-
def find_file(name, ext=".rb")
|
24
|
-
|
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}/"), "./"]
|
25
32
|
base = "#{name}#{ext}"
|
26
33
|
paths.each do |path|
|
27
34
|
file = path + base
|
@@ -52,16 +59,20 @@ module Helpers
|
|
52
59
|
@backtrace = btrace
|
53
60
|
@main.source(enum, fname, 0)
|
54
61
|
line = nil
|
55
|
-
loop do
|
62
|
+
loop do
|
56
63
|
line = @main.nextline
|
57
64
|
break if line.nil?
|
58
65
|
process_line(line)
|
59
66
|
end
|
60
|
-
val = @main.finalize
|
61
|
-
@body
|
67
|
+
val = @main.finalize rescue nil
|
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
|
62
73
|
end
|
63
74
|
|
64
|
-
def process_line(line)
|
75
|
+
def process_line(line)
|
65
76
|
nomarkup = true
|
66
77
|
case line # must apply these in order
|
67
78
|
when Comment
|
@@ -90,6 +101,29 @@ module Helpers
|
|
90
101
|
raise EndWithoutOpening()
|
91
102
|
when @main.respond_to?(name)
|
92
103
|
result = @main.send(name)
|
104
|
+
|
105
|
+
# NOTE: The above line is where the magic happens!
|
106
|
+
# A name like 'foobar' results in an invocation of
|
107
|
+
# @main.foobar (where @main is a Processor, and any
|
108
|
+
# new methods (e.g. from a mixin) are added to @main
|
109
|
+
#
|
110
|
+
# So all the functionality from _args and _raw_args
|
111
|
+
# and _data (among others?) will be encapsulated in
|
112
|
+
# 'some' kind of PORO which handles access to all
|
113
|
+
# these things as well as the 'body' between the
|
114
|
+
# command and its corresponding .end
|
115
|
+
#
|
116
|
+
# The 'body' functionality is so commonly used, I plan
|
117
|
+
# to pass it in separately as needed (even though the
|
118
|
+
# args object should make it available also).
|
119
|
+
#
|
120
|
+
# Every method corresponding to a dot commmand will
|
121
|
+
# get args and body passed in as needed. Every one of
|
122
|
+
# the signatures already has (args = nil, body = nil)
|
123
|
+
# but nothing is being passed in that way yet.
|
124
|
+
#
|
125
|
+
# Refer to lib/cmdargs.rb for more! This is *strictly*
|
126
|
+
# experimental and a "work in progress."
|
93
127
|
else
|
94
128
|
puts @body # earlier correct output, not flushed yet
|
95
129
|
raise "Name '#{name}' is unknown"
|
@@ -105,8 +139,8 @@ module Helpers
|
|
105
139
|
name, data = line.split(" ", 2)
|
106
140
|
name = name[1..-1] # chop off sigil
|
107
141
|
name = "dot_" + name if %w[include def].include?(name)
|
108
|
-
@main.data = data
|
109
142
|
@main.check_disallowed(name)
|
143
|
+
@main.data = data
|
110
144
|
name
|
111
145
|
end
|
112
146
|
|
@@ -143,10 +177,10 @@ module Helpers
|
|
143
177
|
value = path if File.exist?(path)
|
144
178
|
break if value
|
145
179
|
end
|
146
|
-
STDERR.puts "Cannot find #{file.inspect} from #{Dir.pwd}" unless value
|
180
|
+
::STDERR.puts "Cannot find #{file.inspect} from #{Dir.pwd}" unless value
|
147
181
|
return value
|
148
182
|
rescue
|
149
|
-
STDERR.puts "Can't find #{file.inspect} from #{Dir.pwd}"
|
183
|
+
::STDERR.puts "Can't find #{file.inspect} from #{Dir.pwd}"
|
150
184
|
return nil
|
151
185
|
end
|
152
186
|
|
data/lib/html.rb
CHANGED
data/lib/livetext.rb
CHANGED
@@ -1,26 +1,47 @@
|
|
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.
|
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
|
9
|
-
end
|
10
13
|
|
11
|
-
|
14
|
+
module ParsingConstants
|
15
|
+
end
|
16
|
+
|
17
|
+
class FormatLine < StringParser
|
18
|
+
module FunCall
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
12
22
|
|
13
23
|
require 'fileutils'
|
14
24
|
|
25
|
+
class Object
|
26
|
+
def send?(meth, *args)
|
27
|
+
if self.respond_to?(meth)
|
28
|
+
self.send(meth, *args)
|
29
|
+
else
|
30
|
+
return nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
15
35
|
require_relative 'errors'
|
36
|
+
require_relative 'standard'
|
16
37
|
require_relative 'functions'
|
17
38
|
require_relative 'userapi'
|
18
|
-
require_relative 'standard'
|
19
39
|
require_relative 'formatline'
|
20
40
|
require_relative 'processor'
|
21
41
|
require_relative 'helpers'
|
22
42
|
require_relative 'handler'
|
23
43
|
|
44
|
+
|
24
45
|
Plugins = File.expand_path(File.join(File.dirname(__FILE__), "../plugin"))
|
25
46
|
Imports = File.expand_path(File.join(File.dirname(__FILE__), "../imports"))
|
26
47
|
|
@@ -49,6 +70,11 @@ class Livetext
|
|
49
70
|
Livetext::Vars.dup
|
50
71
|
end
|
51
72
|
|
73
|
+
def self.interpolate(str)
|
74
|
+
# FIXME There are issues here...
|
75
|
+
Livetext::FormatLine.var_func_parse(str)
|
76
|
+
end
|
77
|
+
|
52
78
|
def self.customize(mix: [], call: [], vars: {})
|
53
79
|
obj = self.new
|
54
80
|
mix = Array(mix)
|
@@ -62,8 +88,7 @@ class Livetext
|
|
62
88
|
def customize(mix: [], call: [], vars: {})
|
63
89
|
mix = Array(mix)
|
64
90
|
call = Array(call)
|
65
|
-
# FIXME HF won't this break??
|
66
|
-
mix.each {|lib| mixin(lib) }
|
91
|
+
mix.each {|lib| mixin(lib) } # FIXME HF won't this break??
|
67
92
|
call.each {|cmd| @main.send(cmd[1..-1]) } # ignores leading dot, no param
|
68
93
|
vars.each_pair {|var, val| setvar(var, val.to_s) }
|
69
94
|
self
|
@@ -81,6 +106,9 @@ class Livetext
|
|
81
106
|
initial_vars
|
82
107
|
end
|
83
108
|
|
109
|
+
def interpolate(str)
|
110
|
+
end
|
111
|
+
|
84
112
|
def initial_vars
|
85
113
|
# Other predefined variables (see also setfile)
|
86
114
|
setvar(:User, `whoami`.chomp)
|
data/lib/parser/file.rb
CHANGED
data/lib/parser/general.rb
CHANGED
@@ -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")
|
@@ -27,7 +24,7 @@ class Livetext::ParseGeneral < StringParser
|
|
27
24
|
lines.each do |line|
|
28
25
|
next if line.strip.empty?
|
29
26
|
var, value = line.split(" ", 2)
|
30
|
-
val =
|
27
|
+
val = Livetext.interpolate(value)
|
31
28
|
var = prefix + "." + var if prefix
|
32
29
|
pairs << [var, value]
|
33
30
|
end
|
data/lib/parser/mixin.rb
CHANGED
@@ -1,15 +1,13 @@
|
|
1
|
-
require_relative '../
|
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
|
|
@@ -31,8 +28,8 @@ class Livetext::ParseSet < StringParser
|
|
31
28
|
pairs = []
|
32
29
|
char = nil
|
33
30
|
loop do
|
34
|
-
break if eos? # end of string
|
35
31
|
char = skip_spaces
|
32
|
+
break if eos? # end of string
|
36
33
|
raise "Expected alpha to start var name" unless char =~ /[a-z]/i
|
37
34
|
pairs << assignment
|
38
35
|
char = skip_spaces
|
@@ -56,7 +53,7 @@ class Livetext::ParseSet < StringParser
|
|
56
53
|
var = get_var
|
57
54
|
skip_equal
|
58
55
|
value = get_value
|
59
|
-
value =
|
56
|
+
value = Livetext.interpolate(value)
|
60
57
|
pair = [var, value]
|
61
58
|
pair
|
62
59
|
end
|
@@ -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?
|
127
|
-
# break if char.nil?
|
122
|
+
break if eos?
|
128
123
|
break if char == " " || char == ","
|
129
124
|
value << char
|
130
125
|
char = grab
|
data/lib/parser/string.rb
CHANGED
@@ -15,15 +15,16 @@ class StringParser
|
|
15
15
|
return nil if @eos
|
16
16
|
char = @line[@i]
|
17
17
|
@i += 1
|
18
|
-
|
18
|
+
check_eos
|
19
19
|
char
|
20
20
|
end
|
21
21
|
|
22
22
|
def ungrab
|
23
|
-
@i -= 1
|
23
|
+
@i -= 1
|
24
|
+
check_eos
|
24
25
|
end
|
25
26
|
|
26
|
-
def
|
27
|
+
def lookahead
|
27
28
|
@line[@i + 1]
|
28
29
|
end
|
29
30
|
|
@@ -32,12 +33,7 @@ class StringParser
|
|
32
33
|
@line[@i-1]
|
33
34
|
end
|
34
35
|
|
35
|
-
def last?
|
36
|
-
@i > @len - 1
|
37
|
-
end
|
38
|
-
|
39
36
|
def eos?
|
40
|
-
@eos = true if last? # duh?
|
41
37
|
@eos
|
42
38
|
end
|
43
39
|
|
@@ -52,16 +48,21 @@ class StringParser
|
|
52
48
|
char = peek
|
53
49
|
break if eos?
|
54
50
|
break if char != " "
|
55
|
-
grab
|
51
|
+
char = grab
|
56
52
|
end
|
57
53
|
char
|
58
54
|
end
|
59
55
|
|
56
|
+
private
|
57
|
+
|
58
|
+
def check_eos
|
59
|
+
@eos = @i >= @len
|
60
|
+
end
|
60
61
|
end
|
61
62
|
|
62
63
|
=begin
|
63
64
|
skip
|
64
|
-
|
65
|
+
lookahead skip! peek!(?)
|
65
66
|
expect_alpha
|
66
67
|
expect_number
|
67
68
|
skip_spaces
|
data/lib/parser.rb
CHANGED
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
|
data/lib/processor.rb
CHANGED
@@ -1,75 +1,81 @@
|
|
1
|
-
#
|
1
|
+
# p __FILE__
|
2
2
|
|
3
|
-
class Livetext
|
4
3
|
|
5
|
-
|
4
|
+
# Class Processor does the actual work of processing input.
|
6
5
|
|
7
|
-
|
6
|
+
class Processor
|
8
7
|
|
9
|
-
|
8
|
+
GenericError = Class.new(StandardError)
|
10
9
|
|
11
|
-
|
12
|
-
|
10
|
+
include Livetext::Standard
|
11
|
+
include Livetext::UserAPI
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
13
|
+
Disallowed =
|
14
|
+
%i[ __binding__ __id__ __send__ class
|
15
|
+
clone display dup enum_for
|
16
|
+
eql? equal? extend freeze
|
17
|
+
frozen? hash inspect instance_eval
|
18
|
+
instance_exec instance_of? is_a? kind_of?
|
19
|
+
method methods nil? object_id
|
20
|
+
pretty_inspect private_methods protected_methods public_method
|
21
|
+
public_methods public_send respond_to? send
|
22
|
+
singleton_class singleton_method singleton_methods taint
|
23
|
+
tainted? tap to_enum to_s
|
24
|
+
trust untaint untrust untrusted?
|
25
|
+
define_singleton_method instance_variable_defined?
|
26
|
+
instance_variable_get instance_variable_set
|
27
|
+
remove_instance_variable instance_variables ]
|
25
28
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
def initialize(parent, output = nil)
|
30
|
+
@parent = parent
|
31
|
+
@_nopass = false
|
32
|
+
@_nopara = false
|
33
|
+
# Meh?
|
34
|
+
@output = ::Livetext.output = (output || File.open("/dev/null", "w"))
|
35
|
+
@sources = []
|
36
|
+
@indentation = @parent.indentation
|
37
|
+
@_mixins = []
|
38
|
+
end
|
39
|
+
|
40
|
+
def output=(io)
|
41
|
+
@output = io
|
42
|
+
end
|
36
43
|
|
37
|
-
|
38
|
-
|
39
|
-
|
44
|
+
def error(*args)
|
45
|
+
::STDERR.puts *args
|
46
|
+
end
|
40
47
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
48
|
+
def _error!(err, raise_error=false, trace=false) # FIXME much bullshit happens here
|
49
|
+
where = @sources.last || @save_location
|
50
|
+
error "Error: #{err} (at #{where[1]} line #{where[2]})"
|
51
|
+
error(err.backtrace) rescue nil
|
52
|
+
raise GenericError.new("Error: #{err}") if raise_error
|
53
|
+
end
|
47
54
|
|
48
|
-
|
49
|
-
|
50
|
-
|
55
|
+
def disallowed?(name)
|
56
|
+
Disallowed.include?(name.to_sym)
|
57
|
+
end
|
51
58
|
|
52
|
-
|
53
|
-
|
54
|
-
|
59
|
+
def source(enum, file, line)
|
60
|
+
@sources.push([enum, file, line])
|
61
|
+
end
|
55
62
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
63
|
+
def peek_nextline
|
64
|
+
line = @sources.last[0].peek
|
65
|
+
rescue StopIteration
|
66
|
+
@sources.pop
|
67
|
+
nil
|
68
|
+
rescue => err
|
69
|
+
nil
|
70
|
+
end
|
64
71
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
72
|
+
def nextline
|
73
|
+
return nil if @sources.empty?
|
74
|
+
line = @sources.last[0].next
|
75
|
+
@sources.last[2] += 1
|
76
|
+
line
|
77
|
+
rescue StopIteration
|
78
|
+
@sources.pop
|
79
|
+
nil
|
74
80
|
end
|
75
81
|
end
|