livetext 0.9.11 → 0.9.13
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.
- checksums.yaml +4 -4
- data/lib/errors.rb +13 -0
- data/lib/formatline.rb +3 -5
- data/lib/functions.rb +6 -2
- data/lib/helpers.rb +21 -0
- data/lib/html.rb +32 -0
- data/lib/livetext/importable.rb +2 -0
- data/lib/livetext.rb +44 -42
- data/lib/parser/general.rb +38 -0
- data/lib/parser/import.rb +17 -0
- data/lib/parser/mixin.rb +46 -0
- data/lib/parser/set.rb +136 -0
- data/lib/parser/string.rb +55 -0
- data/lib/parser.rb +5 -0
- data/lib/processor.rb +22 -16
- data/lib/standard.rb +144 -292
- data/lib/userapi.rb +2 -1
- data/livetext.gemspec +1 -2
- data/test/all.rb +3 -0
- data/test/formatting.rb +2 -9
- data/test/{data → snapshots}/basic_formatting/expected-error.txt +0 -0
- data/test/{data → snapshots}/basic_formatting/expected-output.txt +0 -0
- data/test/{data → snapshots}/basic_formatting/source.lt3 +0 -0
- data/test/{data → snapshots}/block_comment/expected-error.txt +0 -0
- data/test/{data → snapshots}/block_comment/expected-output.txt +0 -0
- data/test/{data → snapshots}/block_comment/source.lt3 +0 -0
- data/test/{data → snapshots}/comments_ignored_1/expected-error.txt +0 -0
- data/test/{data → snapshots}/comments_ignored_1/expected-output.txt +0 -0
- data/test/{data → snapshots}/comments_ignored_1/source.lt3 +0 -0
- data/test/{data → snapshots}/copy_is_raw/expected-error.txt +0 -0
- data/test/{data → snapshots}/copy_is_raw/expected-output.txt +0 -0
- data/test/{data → snapshots}/copy_is_raw/rawtext.inc +0 -0
- data/test/{data → snapshots}/copy_is_raw/source.lt3 +0 -0
- data/test/{data → snapshots}/crap +0 -0
- data/test/{data → snapshots}/def_method/expected-error.txt +0 -0
- data/test/{data → snapshots}/def_method/expected-output.txt +0 -0
- data/test/{data → snapshots}/def_method/source.lt3 +0 -0
- data/test/{data/error_inc_line_num/expected-err-line1match.txt → snapshots/error_inc_line_num/actual-error.txt} +0 -0
- data/test/{data/error_inc_line_num/expected-output.txt → snapshots/error_inc_line_num/actual-output.txt} +0 -0
- data/test/{data/error_line_num → snapshots/error_inc_line_num}/expected-err-line1match.txt +0 -0
- data/test/snapshots/error_inc_line_num/expected-output.txt +13 -0
- data/test/{data → snapshots}/error_inc_line_num/file2.lt3 +0 -0
- data/test/snapshots/error_inc_line_num/out-sdiff.txt +14 -0
- data/test/{data → snapshots}/error_inc_line_num/source.lt3 +0 -0
- data/test/snapshots/error_invalid_name/actual-error.txt +10 -0
- data/test/{data/error_no_such_mixin/expected-output.txt → snapshots/error_invalid_name/actual-output.txt} +0 -0
- data/test/{data → snapshots}/error_invalid_name/expected-err-line1match.txt +0 -0
- data/test/{data → snapshots}/error_invalid_name/expected-output.txt +0 -0
- data/test/snapshots/error_invalid_name/out-sdiff.txt +6 -0
- data/test/{data → snapshots}/error_invalid_name/source.lt3 +0 -0
- data/test/snapshots/error_line_num/actual-error.txt +1 -0
- data/test/snapshots/error_line_num/actual-output.txt +5 -0
- data/test/snapshots/error_line_num/expected-err-line1match.txt +1 -0
- data/test/{data → snapshots}/error_line_num/expected-output.txt +0 -0
- data/test/snapshots/error_line_num/out-sdiff.txt +6 -0
- data/test/{data → snapshots}/error_line_num/source.lt3 +0 -0
- data/test/snapshots/error_mismatched_end/actual-error.txt +1 -0
- data/test/{data/error_mismatched_end/expected-output.txt → snapshots/error_mismatched_end/actual-output.txt} +0 -0
- data/test/{data → snapshots}/error_mismatched_end/expected-err-line1match.txt +0 -0
- data/test/snapshots/error_mismatched_end/expected-output.txt +8 -0
- data/test/snapshots/error_mismatched_end/out-sdiff.txt +9 -0
- data/test/{data → snapshots}/error_mismatched_end/source.lt3 +0 -0
- data/test/{data/error_missing_end/expected-err-line1match.txt → snapshots/error_missing_end/actual-error.txt} +0 -0
- data/test/{data/error_missing_end/expected-output.txt → snapshots/error_missing_end/actual-output.txt} +0 -0
- data/test/snapshots/error_missing_end/expected-err-line1match.txt +1 -0
- data/test/snapshots/error_missing_end/expected-output.txt +5 -0
- data/test/snapshots/error_missing_end/out-sdiff.txt +6 -0
- data/test/{data → snapshots}/error_missing_end/source.lt3 +0 -0
- data/test/{data/error_name_not_permitted/expected-output.txt → snapshots/error_name_not_permitted/OLD-exp-out} +0 -0
- data/test/{data/example_alpha/expected-error.txt → snapshots/error_name_not_permitted/expected-output.txt} +0 -0
- data/test/snapshots/error_name_not_permitted/match-error.txt +1 -0
- data/test/{data → snapshots}/error_name_not_permitted/source.lt3 +0 -0
- data/test/snapshots/error_no_such_copy/actual-error.txt +10 -0
- data/test/{data/example_alpha2/expected-error.txt → snapshots/error_no_such_copy/actual-output.txt} +0 -0
- data/test/snapshots/error_no_such_copy/expected-err-line1match.txt +1 -0
- data/test/{data → snapshots}/error_no_such_copy/expected-output.txt +0 -5
- data/test/snapshots/error_no_such_copy/out-sdiff.txt +5 -0
- data/test/{data → snapshots}/error_no_such_copy/source.lt3 +0 -0
- data/test/snapshots/error_no_such_inc/actual-error.txt +10 -0
- data/test/{data/functions/expected-error.txt → snapshots/error_no_such_inc/actual-output.txt} +0 -0
- data/test/snapshots/error_no_such_inc/expected-err-line1match.txt +1 -0
- data/test/{data → snapshots}/error_no_such_inc/expected-output.txt +0 -4
- data/test/snapshots/error_no_such_inc/out-sdiff.txt +6 -0
- data/test/{data → snapshots}/error_no_such_inc/source.lt3 +0 -0
- data/test/snapshots/error_no_such_mixin/actual-error.txt +1 -0
- data/test/snapshots/error_no_such_mixin/actual-output.txt +11 -0
- data/test/{data → snapshots}/error_no_such_mixin/expected-err-line1match.txt +0 -0
- data/test/snapshots/error_no_such_mixin/expected-output.txt +5 -0
- data/test/snapshots/error_no_such_mixin/out-sdiff.txt +12 -0
- data/test/{data → snapshots}/error_no_such_mixin/source.lt3 +0 -0
- data/test/{data/hello_world → snapshots/example_alpha}/expected-error.txt +0 -0
- data/test/{data → snapshots}/example_alpha/expected-output.txt +0 -0
- data/test/{data → snapshots}/example_alpha/source.lt3 +0 -0
- data/test/{data/more_complex_vars → snapshots/example_alpha2}/expected-error.txt +0 -0
- data/test/{data → snapshots}/example_alpha2/expected-output.txt +0 -0
- data/test/{data → snapshots}/example_alpha2/source.lt3 +0 -0
- data/test/{data → snapshots}/fixit +0 -0
- data/test/{data/predef_vars → snapshots/functions}/expected-error.txt +0 -0
- data/test/{data → snapshots}/functions/expected-output.txt +0 -0
- data/test/{data → snapshots}/functions/source.lt3 +0 -0
- data/test/{data/raw_lines → snapshots/hello_world}/expected-error.txt +0 -0
- data/test/{data → snapshots}/hello_world/expected-output.txt +0 -0
- data/test/{data → snapshots}/hello_world/source.lt3 +0 -0
- data/test/{data → snapshots}/lines.txt +0 -0
- data/test/{data/raw_text_block → snapshots/more_complex_vars}/expected-error.txt +0 -0
- data/test/{data → snapshots}/more_complex_vars/expected-output.txt +0 -0
- data/test/{data → snapshots}/more_complex_vars/source.lt3 +0 -0
- data/test/{data/simple_copy/expected-error.txt → snapshots/predef_vars/actual-error.txt} +0 -0
- data/test/snapshots/predef_vars/actual-output.txt +6 -0
- data/test/{data/simple_include → snapshots/predef_vars}/expected-error.txt +0 -0
- data/test/{data → snapshots}/predef_vars/expected-output.txt +1 -1
- data/test/snapshots/predef_vars/out-sdiff.txt +7 -0
- data/test/{data → snapshots}/predef_vars/source.lt3 +0 -0
- data/test/{data/simple_mixin → snapshots/raw_lines}/expected-error.txt +0 -0
- data/test/{data → snapshots}/raw_lines/expected-output.txt +0 -0
- data/test/{data → snapshots}/raw_lines/source.lt3 +0 -0
- data/test/{data/simple_vars → snapshots/raw_text_block}/expected-error.txt +0 -0
- data/test/{data → snapshots}/raw_text_block/expected-output.txt +0 -0
- data/test/{data → snapshots}/raw_text_block/rawtext.inc +0 -0
- data/test/{data → snapshots}/raw_text_block/source.lt3 +0 -0
- data/test/{data/single_raw_line → snapshots/simple_copy}/expected-error.txt +0 -0
- data/test/{data → snapshots}/simple_copy/expected-output.txt +0 -0
- data/test/{data → snapshots}/simple_copy/simplefile.inc +0 -0
- data/test/{data → snapshots}/simple_copy/source.lt3 +0 -0
- data/test/{data/table_with_heredocs → snapshots/simple_include}/expected-error.txt +0 -0
- data/test/{data → snapshots}/simple_include/expected-output.txt +0 -0
- data/test/{data → snapshots}/simple_include/simplefile.inc +0 -0
- data/test/{data → snapshots}/simple_include/source.lt3 +0 -0
- data/test/snapshots/simple_mixin/actual-error.txt +2 -0
- data/test/snapshots/simple_mixin/actual-output.txt +4 -0
- data/test/{data/subset.txt → snapshots/simple_mixin/expected-error.txt} +0 -0
- data/test/{data → snapshots}/simple_mixin/expected-output.txt +0 -0
- data/test/snapshots/simple_mixin/out-sdiff.txt +6 -0
- data/test/{data → snapshots}/simple_mixin/simple_mixin.rb +0 -0
- data/test/{data → snapshots}/simple_mixin/source.lt3 +0 -0
- data/test/snapshots/simple_vars/expected-error.txt +0 -0
- data/test/{data → snapshots}/simple_vars/expected-output.txt +0 -0
- data/test/{data → snapshots}/simple_vars/source.lt3 +0 -0
- data/test/snapshots/single_raw_line/expected-error.txt +0 -0
- data/test/{data → snapshots}/single_raw_line/expected-output.txt +0 -0
- data/test/{data → snapshots}/single_raw_line/source.lt3 +0 -0
- data/test/snapshots/subset.txt +0 -0
- data/test/snapshots/table_with_heredocs/expected-error.txt +0 -0
- data/test/{data → snapshots}/table_with_heredocs/expected-output.txt +0 -0
- data/test/{data → snapshots}/table_with_heredocs/source.lt3 +0 -0
- data/test/snapshots.rb +219 -0
- data/test/testlines.rb +2 -2
- data/test/unit/all.rb +3 -0
- data/test/unit/html.rb +38 -0
- data/test/unit/parse_misc.rb +60 -0
- data/test/unit/parse_set.rb +157 -0
- data/test/unit/parser/all.rb +3 -0
- data/test/unit/parser/general.rb +59 -0
- data/test/unit/parser/importable.rb +19 -0
- data/test/unit/parser/mixin.rb +19 -0
- data/test/unit/parser/set.rb +157 -0
- data/test/unit/parser/string.rb +130 -0
- data/test/unit/parser.rb +4 -0
- data/test/unit/standard.rb +23 -0
- data/test/unit/stringparser.rb +140 -0
- metadata +152 -99
- data/test/data/error_inc_line_num/FOO +0 -21
- data/test/data/error_missing_end/ERR +0 -32
- data/test/data/error_name_not_permitted/expected-error.txt +0 -1
- data/test/data/error_no_such_copy/expected-err-line1match.txt +0 -1
- data/test/data/error_no_such_inc/expected-err-line1match.txt +0 -1
- data/test/test.rb +0 -140
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f9a5d4be00258f23687ca280b306794cb67f2e7c89ba1a453c60dfd59f4268d
|
|
4
|
+
data.tar.gz: 423d1901855f09e06f5448008e12095713110d1d4dc8ba4f31ddf871319d2bb3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dfd42d9206980d3819e45fc174baf74378c01d13e61c8a8ce58f00bc3d3b7889b1bace1b74076c5491657978e704b55e6f82543e57ffdaa128993f6ec584c5e9
|
|
7
|
+
data.tar.gz: 570a8c6f92f4baaadad6c946871910e7ae2107741bef4212e16e7a49e90e1f929a8149c9f99553319a811eb42a6ce37fff0e15b8985235b91858f800d3ca77be
|
data/lib/errors.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
# More later?
|
|
3
|
+
|
|
4
|
+
def make_exception(sym, str, target_class = Object)
|
|
5
|
+
return if target_class.constants.include?(sym)
|
|
6
|
+
target_class.const_set(sym, StandardError.dup)
|
|
7
|
+
define_method(sym) do |*args|
|
|
8
|
+
msg = str.dup
|
|
9
|
+
args.each.with_index {|arg, i| msg.sub!("%#{i+1}", arg) }
|
|
10
|
+
target_class.class_eval(sym.to_s).new(msg)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
data/lib/formatline.rb
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
# Class FormatLine handles the parsing of comments, dot commands, and
|
|
2
|
+
# simple formatting characters.
|
|
3
|
+
|
|
1
4
|
class FormatLine
|
|
2
5
|
SimpleFormats = {}
|
|
3
6
|
SimpleFormats[:b] = %w[<b> </b>]
|
|
@@ -395,11 +398,6 @@ class FormatLine
|
|
|
395
398
|
|
|
396
399
|
#####
|
|
397
400
|
|
|
398
|
-
def showme(tag)
|
|
399
|
-
char = @line[@cc]
|
|
400
|
-
puts "--- #{tag}: ch=#{@ch.inspect} next=#{@next.inspect} (cc=#@cc:#{char.inspect}) out=#{@out.inspect}"
|
|
401
|
-
end
|
|
402
|
-
|
|
403
401
|
def embedded?
|
|
404
402
|
! (['"', "'", " ", nil].include? prev)
|
|
405
403
|
end
|
data/lib/functions.rb
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
require 'standard' # FIXME
|
|
2
1
|
|
|
3
|
-
|
|
2
|
+
require_relative 'standard' # FIXME?
|
|
3
|
+
|
|
4
|
+
# Class Functions is where '$$func' functions are stored dynamically...
|
|
5
|
+
# user-def AND pre-def??
|
|
6
|
+
|
|
7
|
+
class Livetext::Functions
|
|
4
8
|
Formats = ::Livetext::Standard::SimpleFormats
|
|
5
9
|
|
|
6
10
|
@param = nil
|
data/lib/helpers.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
|
|
2
|
+
module Helpers
|
|
3
|
+
|
|
4
|
+
def check_disallowed(name)
|
|
5
|
+
# raise "Illegal name '#{name}'" if _disallowed?(name)
|
|
6
|
+
# FIXME use custom exception
|
|
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 set_variables(pairs)
|
|
15
|
+
pairs.each do |pair|
|
|
16
|
+
var, value = *pair
|
|
17
|
+
@parent._setvar(var, value)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
data/lib/html.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module HTMLHelper
|
|
2
|
+
|
|
3
|
+
def wrapped(str, *tags) # helper
|
|
4
|
+
open, close = open_close_tags(*tags)
|
|
5
|
+
open + str + close
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def wrapped!(str, tag, **extras) # helper
|
|
9
|
+
open, close = open_close_tags(tag)
|
|
10
|
+
extras.each_pair do |name, value|
|
|
11
|
+
open.sub!(">", " #{name}='#{value}'>")
|
|
12
|
+
end
|
|
13
|
+
open + str + close
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def wrap(*tags) # helper
|
|
17
|
+
open, close = open_close_tags(*tags)
|
|
18
|
+
_out open
|
|
19
|
+
yield
|
|
20
|
+
_out close
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def open_close_tags(*tags)
|
|
24
|
+
open, close = "", ""
|
|
25
|
+
tags.each do |tag|
|
|
26
|
+
open << "<#{tag}>"
|
|
27
|
+
close.prepend("</#{tag}>")
|
|
28
|
+
end
|
|
29
|
+
[open, close]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
data/lib/livetext.rb
CHANGED
|
@@ -1,34 +1,48 @@
|
|
|
1
|
+
# Class Livetext skeleton (top level).
|
|
2
|
+
|
|
1
3
|
class Livetext
|
|
2
|
-
VERSION = "0.9.
|
|
4
|
+
VERSION = "0.9.13"
|
|
3
5
|
Path = File.expand_path(File.join(File.dirname(__FILE__)))
|
|
4
6
|
end
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
# $LOAD_PATH << Livetext::Path
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
require 'fileutils'
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
require_relative 'errors'
|
|
13
|
+
require_relative 'functions'
|
|
14
|
+
require_relative 'userapi'
|
|
15
|
+
require_relative 'standard'
|
|
16
|
+
require_relative 'formatline'
|
|
17
|
+
require_relative 'processor'
|
|
15
18
|
|
|
16
19
|
Plugins = File.expand_path(File.join(File.dirname(__FILE__), "../plugin"))
|
|
17
20
|
|
|
18
21
|
TTY = ::File.open("/dev/tty", "w")
|
|
19
22
|
|
|
23
|
+
# Class Livetext reopened (top level).
|
|
24
|
+
|
|
20
25
|
class Livetext
|
|
26
|
+
|
|
21
27
|
Vars = {}
|
|
22
28
|
|
|
29
|
+
Space = " "
|
|
30
|
+
Sigil = "." # Can't change yet
|
|
31
|
+
|
|
32
|
+
def self.rx(str, space=nil)
|
|
33
|
+
Regexp.compile("^" + Regexp.escape(str) + "#{space}")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
Comment = rx(Sigil, Livetext::Space)
|
|
37
|
+
Dotcmd = rx(Sigil)
|
|
38
|
+
Ddotcmd = /^ *\$\.[A-Za-z]/
|
|
39
|
+
|
|
23
40
|
attr_reader :main
|
|
24
41
|
attr_accessor :no_puts
|
|
25
42
|
attr_accessor :body, :indentation
|
|
26
43
|
|
|
27
|
-
# FIXME - phase out stupid 'parameters' method
|
|
28
|
-
|
|
29
44
|
class << self
|
|
30
|
-
attr_accessor :
|
|
31
|
-
attr_accessor :output # both bad solutions?
|
|
45
|
+
attr_accessor :output # bad solution?
|
|
32
46
|
end
|
|
33
47
|
|
|
34
48
|
def vars
|
|
@@ -54,17 +68,6 @@ class Livetext
|
|
|
54
68
|
self
|
|
55
69
|
end
|
|
56
70
|
|
|
57
|
-
Space = " "
|
|
58
|
-
Sigil = "." # Can't change yet
|
|
59
|
-
|
|
60
|
-
def self.rx(str, space=nil)
|
|
61
|
-
Regexp.compile("^" + Regexp.escape(str) + "#{space}")
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
Comment = rx(Sigil, Livetext::Space)
|
|
65
|
-
Dotcmd = rx(Sigil)
|
|
66
|
-
Ddotcmd = /^ *\$\.[A-Za-z]/
|
|
67
|
-
|
|
68
71
|
def initialize(output = ::STDOUT)
|
|
69
72
|
@source = nil
|
|
70
73
|
@_mixins = []
|
|
@@ -115,9 +118,14 @@ class Livetext
|
|
|
115
118
|
end
|
|
116
119
|
|
|
117
120
|
def _setfile(file)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
+
if file
|
|
122
|
+
_setvar(:File, file)
|
|
123
|
+
dir = File.dirname(File.expand_path(file))
|
|
124
|
+
_setvar(:FileDir, dir)
|
|
125
|
+
else
|
|
126
|
+
_setvar(:File, "[no file]")
|
|
127
|
+
_setvar(:FileDir, "[no dir]")
|
|
128
|
+
end
|
|
121
129
|
end
|
|
122
130
|
|
|
123
131
|
def _setfile!(file)
|
|
@@ -130,7 +138,6 @@ class Livetext
|
|
|
130
138
|
when Comment
|
|
131
139
|
handle_scomment(line)
|
|
132
140
|
when Dotcmd
|
|
133
|
-
# STDERR.puts "line = #{line.inspect}"
|
|
134
141
|
handle_dotcmd(line)
|
|
135
142
|
when Ddotcmd
|
|
136
143
|
indent = line.index("$") + 1
|
|
@@ -185,7 +192,7 @@ class Livetext
|
|
|
185
192
|
|
|
186
193
|
def process_file(fname, btrace=false)
|
|
187
194
|
_setfile(fname)
|
|
188
|
-
text = File.readlines(fname)
|
|
195
|
+
text = File.readlines(fname) # FIXME currently causes failure
|
|
189
196
|
enum = text.each
|
|
190
197
|
@backtrace = btrace
|
|
191
198
|
@main.source(enum, fname, 0)
|
|
@@ -197,28 +204,23 @@ class Livetext
|
|
|
197
204
|
end
|
|
198
205
|
val = @main.finalize if @main.respond_to? :finalize
|
|
199
206
|
@body
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
207
|
+
rescue => err
|
|
208
|
+
STDERR.puts "[process_file] fname = #{fname.inspect}\n line = #{line.inspect}"
|
|
209
|
+
STDERR.puts "ERROR #{err} in process_file"
|
|
210
|
+
err.backtrace.each {|x| STDERR.puts " " + x }
|
|
211
|
+
# @body = ""
|
|
205
212
|
end
|
|
206
213
|
|
|
207
214
|
def handle_scomment(line)
|
|
208
215
|
end
|
|
209
216
|
|
|
210
|
-
def _check_name(name)
|
|
211
|
-
@main._error! "Name '#{name}' is not permitted" if @main._disallowed?(name)
|
|
212
|
-
@main._error! "Mismatched 'end'" if name == "end"
|
|
213
|
-
name = "_" + name if %w[def include].include?(name)
|
|
214
|
-
name
|
|
215
|
-
end
|
|
216
|
-
|
|
217
217
|
def _get_name(line)
|
|
218
218
|
name, data = line.split(" ", 2)
|
|
219
219
|
name = name[1..-1] # chop off sigil
|
|
220
|
+
name = "_" + name if %w[include def].include?(name)
|
|
220
221
|
@main.data = data
|
|
221
|
-
|
|
222
|
+
@main.check_disallowed(name)
|
|
223
|
+
name
|
|
222
224
|
end
|
|
223
225
|
|
|
224
226
|
def handle_dotcmd(line, indent = 0)
|
|
@@ -235,7 +237,7 @@ class Livetext
|
|
|
235
237
|
result
|
|
236
238
|
rescue => err
|
|
237
239
|
STDERR.puts "Error: #{err.inspect}"
|
|
238
|
-
STDERR.puts err.backtrace
|
|
240
|
+
# STDERR.puts err.backtrace
|
|
239
241
|
# @main._error!(err)
|
|
240
242
|
puts @body
|
|
241
243
|
@body = ""
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
|
|
2
|
+
require_relative '../livetext'
|
|
3
|
+
require_relative 'string'
|
|
4
|
+
|
|
5
|
+
make_exception(:MismatchedQuotes, "Error: mismatched quotes")
|
|
6
|
+
make_exception(:NilValue, "Error: nil value")
|
|
7
|
+
make_exception(:NullString, "Error: null string")
|
|
8
|
+
make_exception(:ExpectedString, "Error: expected a string")
|
|
9
|
+
|
|
10
|
+
class Livetext::ParseMisc < StringParser
|
|
11
|
+
|
|
12
|
+
def initialize(str)
|
|
13
|
+
super
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def strip_quotes
|
|
17
|
+
raise NullString if @line.empty?
|
|
18
|
+
start, stop = @line[0], @line[-1]
|
|
19
|
+
return @line unless %['"].include?(start)
|
|
20
|
+
raise MismatchedQuotes if start != stop
|
|
21
|
+
@line[1..-2]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.parse_vars(lines, prefix: nil)
|
|
25
|
+
lines.map! {|line| line.sub(/# .*/, "").strip } # strip comments
|
|
26
|
+
pairs = []
|
|
27
|
+
lines.each do |line|
|
|
28
|
+
next if line.strip.empty?
|
|
29
|
+
var, value = line.split(" ", 2)
|
|
30
|
+
val = FormatLine.var_func_parse(value)
|
|
31
|
+
var = prefix + "." + var if prefix
|
|
32
|
+
pairs << [var, value]
|
|
33
|
+
end
|
|
34
|
+
pairs
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
require '../livetext/importable'
|
|
3
|
+
|
|
4
|
+
make_exception(:BadVariableName, "Error: invalid variable name")
|
|
5
|
+
make_exception(:NoEqualSign, "Error: no equal sign found")
|
|
6
|
+
|
|
7
|
+
# FIXME probably belongs elsewhere?
|
|
8
|
+
|
|
9
|
+
class Livetext::ParseImport
|
|
10
|
+
def use_import(name)
|
|
11
|
+
require name
|
|
12
|
+
include name
|
|
13
|
+
init = "init_#{name}"
|
|
14
|
+
self.send(init) if self.respond_to? init
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
data/lib/parser/mixin.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require_relative '../livetext'
|
|
2
|
+
require_relative 'string'
|
|
3
|
+
|
|
4
|
+
make_exception(:BadVariableName, "Error: invalid variable name")
|
|
5
|
+
make_exception(:NoEqualSign, "Error: no equal sign found")
|
|
6
|
+
|
|
7
|
+
# FIXME probably belongs elsewhere?
|
|
8
|
+
|
|
9
|
+
class Livetext::ParseMixin # < StringParser
|
|
10
|
+
|
|
11
|
+
# def self.parse(str)
|
|
12
|
+
# self.new(str).parse
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
# def initialize(line)
|
|
16
|
+
# super
|
|
17
|
+
# end
|
|
18
|
+
|
|
19
|
+
def cwd_root?
|
|
20
|
+
File.dirname(File.expand_path(".")) == "/"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def find_mixin(name)
|
|
24
|
+
file = "#{Plugins}/" + name.downcase + ".rb"
|
|
25
|
+
return file if File.exist?(file)
|
|
26
|
+
|
|
27
|
+
file = "./#{name}.rb"
|
|
28
|
+
return file if File.exist?(file)
|
|
29
|
+
|
|
30
|
+
raise "No such mixin '#{name}'" if cwd_root?
|
|
31
|
+
Dir.chdir("..") { find_mixin(name) }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def use_mixin(name, file)
|
|
35
|
+
modname = name.gsub("/","_").capitalize
|
|
36
|
+
meths = grab_file(file)
|
|
37
|
+
string = "module ::#{modname}; #{meths}\nend"
|
|
38
|
+
eval(string)
|
|
39
|
+
newmod = Object.const_get("::" + modname)
|
|
40
|
+
self.extend(newmod)
|
|
41
|
+
init = "init_#{name}"
|
|
42
|
+
self.send(init) if self.respond_to? init
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
data/lib/parser/set.rb
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
|
|
2
|
+
require_relative '../livetext'
|
|
3
|
+
require_relative 'string'
|
|
4
|
+
|
|
5
|
+
make_exception(:BadVariableName, "Error: invalid variable name")
|
|
6
|
+
make_exception(:NoEqualSign, "Error: no equal sign found")
|
|
7
|
+
|
|
8
|
+
class Livetext::ParseSet < StringParser
|
|
9
|
+
|
|
10
|
+
attr_reader :line, :eos, :i, :len
|
|
11
|
+
|
|
12
|
+
def self.parse(str)
|
|
13
|
+
self.new(str).parse
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(line)
|
|
17
|
+
super
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def parse
|
|
21
|
+
pairs = []
|
|
22
|
+
|
|
23
|
+
loop do
|
|
24
|
+
skip_spaces
|
|
25
|
+
char = self.peek
|
|
26
|
+
break if eos? # end of string
|
|
27
|
+
raise "Expected alpha to start var name" unless char =~ /[a-z]/i
|
|
28
|
+
pairs << assignment
|
|
29
|
+
skip_spaces
|
|
30
|
+
char = self.peek
|
|
31
|
+
break if eos? # end of string
|
|
32
|
+
case char
|
|
33
|
+
when nil # end of string
|
|
34
|
+
when ","
|
|
35
|
+
self.next # skip comma
|
|
36
|
+
else
|
|
37
|
+
raise "Expected comma or end of string (found #{char.inspect})"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
pairs
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def assignment # one single var=value
|
|
44
|
+
pair = nil
|
|
45
|
+
var = value = nil
|
|
46
|
+
return if eos?
|
|
47
|
+
var = get_var
|
|
48
|
+
skip_equal
|
|
49
|
+
value = get_value
|
|
50
|
+
value = FormatLine.var_func_parse(value)
|
|
51
|
+
pair = [var, value]
|
|
52
|
+
pair
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def get_var
|
|
56
|
+
name = ""
|
|
57
|
+
loop do
|
|
58
|
+
char = self.peek
|
|
59
|
+
break if eos? # end of string
|
|
60
|
+
case char
|
|
61
|
+
when /[a-zA-Z_\.0-9]/
|
|
62
|
+
name << self.next
|
|
63
|
+
next
|
|
64
|
+
when /[ =]/
|
|
65
|
+
return name
|
|
66
|
+
else
|
|
67
|
+
raise BadVariableName, char, name
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
raise NoEqualSign
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def skip_equal
|
|
74
|
+
found = false
|
|
75
|
+
skip_spaces
|
|
76
|
+
raise NoEqualSign unless self.peek == "="
|
|
77
|
+
found = true
|
|
78
|
+
self.next # skip =... spaces too
|
|
79
|
+
self.skip_spaces
|
|
80
|
+
peek = self.peek
|
|
81
|
+
return peek # just for testing
|
|
82
|
+
rescue StopIteration
|
|
83
|
+
raise NoEqualSign unless found
|
|
84
|
+
return nil
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def escaped
|
|
88
|
+
self.next # skip backslash
|
|
89
|
+
self.next # return following char
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
make_exception(:BadQuotedString, "Bad quoted string: %1")
|
|
93
|
+
|
|
94
|
+
def quoted_value
|
|
95
|
+
quote = self.next # opening quote...
|
|
96
|
+
value = ""
|
|
97
|
+
char = nil
|
|
98
|
+
loop do
|
|
99
|
+
char = self.peek
|
|
100
|
+
break if self.eos?
|
|
101
|
+
break if char == quote
|
|
102
|
+
char = escaped if char == "\\"
|
|
103
|
+
value << char
|
|
104
|
+
char = self.next
|
|
105
|
+
end
|
|
106
|
+
if char == quote
|
|
107
|
+
char = self.next
|
|
108
|
+
return value
|
|
109
|
+
end
|
|
110
|
+
raise BadQuotedString, quote + value
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def unquoted_value
|
|
114
|
+
# puts "#{__method__}: #{@line.inspect} i = #@i peek = #{self.peek.inspect}"
|
|
115
|
+
value = ""
|
|
116
|
+
loop do
|
|
117
|
+
char = self.peek
|
|
118
|
+
break if self.eos?
|
|
119
|
+
break if char == " " || char == ","
|
|
120
|
+
value << char
|
|
121
|
+
char = self.next
|
|
122
|
+
end
|
|
123
|
+
value
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def quote?(char)
|
|
127
|
+
char == ?" || char == ?'
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def get_value
|
|
131
|
+
char = self.peek
|
|
132
|
+
value = quote?(char) ? quoted_value : unquoted_value
|
|
133
|
+
value
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
class StringParser
|
|
2
|
+
|
|
3
|
+
attr_reader :line, :eos, :i, :len
|
|
4
|
+
|
|
5
|
+
def initialize(line)
|
|
6
|
+
raise NilValue if line.nil?
|
|
7
|
+
raise ExpectedString unless String === line
|
|
8
|
+
# raise NullString if line.empty?
|
|
9
|
+
@line = line
|
|
10
|
+
@len = @line.length
|
|
11
|
+
@eos = @len == 0 ? true : false
|
|
12
|
+
@i = 0
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def next
|
|
16
|
+
return nil if @eos
|
|
17
|
+
char = @line[@i]
|
|
18
|
+
@i += 1
|
|
19
|
+
@eos = true if @i > @len
|
|
20
|
+
char
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def last?
|
|
24
|
+
@i > @len - 1
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def eos?
|
|
28
|
+
@eos = true if last? # duh?
|
|
29
|
+
@eos
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def peek
|
|
33
|
+
return nil if @eos
|
|
34
|
+
@line[@i]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def skip_spaces
|
|
38
|
+
loop do
|
|
39
|
+
break if peek != " "
|
|
40
|
+
break if eos?
|
|
41
|
+
self.next
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
=begin
|
|
48
|
+
skip
|
|
49
|
+
next! skip! peek!(?)
|
|
50
|
+
expect_alpha
|
|
51
|
+
expect_number
|
|
52
|
+
skip_spaces
|
|
53
|
+
expect_eos
|
|
54
|
+
=end
|
|
55
|
+
|
data/lib/parser.rb
ADDED
data/lib/processor.rb
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
|
+
# Class Livetext is the actual top-level class.
|
|
2
|
+
|
|
1
3
|
class Livetext
|
|
2
4
|
|
|
5
|
+
# Class Processor does the actual work of processing input.
|
|
6
|
+
|
|
3
7
|
class Processor
|
|
8
|
+
|
|
9
|
+
GenericError = Class.new(StandardError)
|
|
10
|
+
|
|
4
11
|
include Livetext::Standard
|
|
5
12
|
include Livetext::UserAPI
|
|
6
13
|
|
|
7
|
-
Disallowed = [
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
:instance_exec, :__send__, :__id__, :__binding__]
|
|
14
|
+
Disallowed = %i[ ! != !~ <=> == === =~ __binding__ __id__ __send__ class
|
|
15
|
+
clone define_singleton_method display dup enum_for eql?
|
|
16
|
+
equal? extend freeze frozen? hash inspect instance_eval
|
|
17
|
+
instance_exec instance_of? instance_variable_defined?
|
|
18
|
+
instance_variable_get instance_variable_set instance_variables is_a?
|
|
19
|
+
kind_of? method methods nil? object_id
|
|
20
|
+
pretty_inspect private_methods protected_methods public_method
|
|
21
|
+
public_methods public_send remove_instance_variable
|
|
22
|
+
respond_to? send singleton_class singleton_method
|
|
23
|
+
singleton_methods taint tainted? tap to_enum
|
|
24
|
+
to_s trust untaint untrust untrusted?]
|
|
19
25
|
|
|
20
26
|
def initialize(parent, output = nil)
|
|
21
27
|
@parent = parent
|
|
@@ -32,15 +38,15 @@ class Livetext
|
|
|
32
38
|
@output = io
|
|
33
39
|
end
|
|
34
40
|
|
|
35
|
-
def _error!(err,
|
|
41
|
+
def _error!(err, raise_error=false, trace=false) # FIXME much bullshit happens here
|
|
36
42
|
where = @sources.last || @save_location
|
|
37
43
|
# puts @parent.body
|
|
38
44
|
# puts "[lib/processor] Error: #{err}"
|
|
39
45
|
# puts err.backtrace.join("\n") if err.respond_to?(:backtrace)
|
|
40
|
-
STDERR.puts "
|
|
46
|
+
STDERR.puts "Error: #{err}" # (at #{where[1]} line #{where[2]})"
|
|
41
47
|
STDERR.puts err.backtrace if err.respond_to?(:backtrace) # && trace
|
|
42
48
|
# raise "lib/processor error!" # FIXME
|
|
43
|
-
|
|
49
|
+
raise GenericError.new("Error: #{err}") if raise_error
|
|
44
50
|
end
|
|
45
51
|
|
|
46
52
|
def _disallowed?(name)
|
|
@@ -56,7 +62,7 @@ class Livetext
|
|
|
56
62
|
rescue StopIteration
|
|
57
63
|
@sources.pop
|
|
58
64
|
nil
|
|
59
|
-
rescue
|
|
65
|
+
rescue => err
|
|
60
66
|
nil
|
|
61
67
|
end
|
|
62
68
|
|