livetext 0.9.11 → 0.9.17
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/README.lt3 +2 -2
- data/lib/cmdargs.rb +93 -0
- data/lib/errors.rb +15 -0
- data/lib/formatline.rb +59 -88
- data/lib/functions.rb +6 -2
- data/lib/handler/icanhaz.rb +35 -0
- data/lib/handler.rb +1 -0
- data/lib/helpers.rb +194 -0
- data/lib/html.rb +32 -0
- data/lib/livetext/importable.rb +2 -0
- data/lib/livetext.rb +35 -152
- data/lib/parser/file.rb +8 -0
- data/lib/parser/general.rb +38 -0
- data/lib/parser/import.rb +15 -0
- data/lib/parser/mixin.rb +38 -0
- data/lib/parser/set.rb +145 -0
- data/lib/parser/string.rb +70 -0
- data/lib/parser.rb +5 -0
- data/lib/processor.rb +23 -27
- data/lib/standard.rb +164 -346
- data/lib/userapi.rb +3 -5
- data/livetext.gemspec +1 -2
- data/plugin/bookish.rb +26 -22
- data/plugin/calibre.rb +1 -1
- data/plugin/livemagick.rb +10 -10
- data/plugin/markdown.rb +13 -11
- data/plugin/pyggish.rb +94 -84
- data/plugin/tutorial.rb +10 -5
- data/test/all.rb +3 -0
- data/test/snapshots/OMIT.txt +11 -0
- 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/snapshots/clusion.txt +70 -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 → snapshots}/error_inc_line_num/expected-output.txt +0 -0
- data/test/{data → snapshots}/error_inc_line_num/file2.lt3 +0 -0
- data/test/snapshots/error_inc_line_num/match-error.txt +1 -0
- data/test/{data → snapshots}/error_inc_line_num/source.lt3 +0 -0
- data/test/{data → snapshots}/error_invalid_name/expected-output.txt +0 -0
- data/test/snapshots/error_invalid_name/match-error.txt +1 -0
- data/test/{data → snapshots}/error_invalid_name/source.lt3 +0 -0
- data/test/{data → snapshots}/error_line_num/expected-output.txt +0 -0
- data/test/snapshots/error_line_num/match-error.txt +1 -0
- data/test/{data → snapshots}/error_line_num/source.lt3 +0 -0
- data/test/{data → snapshots}/error_mismatched_end/expected-output.txt +0 -2
- data/test/snapshots/error_mismatched_end/match-error.txt +1 -0
- data/test/{data → snapshots}/error_mismatched_end/source.lt3 +0 -0
- data/test/{data → snapshots}/error_missing_end/expected-output.txt +0 -0
- data/test/snapshots/error_missing_end/match-error.txt +1 -0
- data/test/{data → snapshots}/error_missing_end/source.lt3 +0 -0
- data/test/{data/error_no_such_mixin → 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/{data → snapshots}/error_no_such_copy/expected-output.txt +0 -5
- data/test/snapshots/error_no_such_copy/match-error.txt +1 -0
- data/test/{data → snapshots}/error_no_such_copy/source.lt3 +0 -1
- data/test/{data → snapshots}/error_no_such_inc/expected-output.txt +0 -4
- data/test/snapshots/error_no_such_inc/match-error.txt +1 -0
- data/test/{data → snapshots}/error_no_such_inc/source.lt3 +0 -0
- data/test/snapshots/error_no_such_mixin/expected-output.txt +5 -0
- data/test/snapshots/error_no_such_mixin/match-error.txt +1 -0
- data/test/{data → snapshots}/error_no_such_mixin/source.lt3 +0 -0
- data/test/{data → 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 → 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 → 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 → 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/snapshots/icanhaz/expected-output.txt +5 -0
- data/test/snapshots/icanhaz/match-error.txt +1 -0
- data/test/snapshots/icanhaz/simple_import.rb +5 -0
- data/test/snapshots/icanhaz/source.lt3 +10 -0
- data/test/{data/more_complex_vars → snapshots/icanhaz2}/expected-error.txt +0 -0
- data/test/snapshots/icanhaz2/expected-output.txt +6 -0
- data/test/snapshots/icanhaz2/simple_canhaz.rb +5 -0
- data/test/snapshots/icanhaz2/source.lt3 +6 -0
- data/test/{data/predef_vars → 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/raw_lines → snapshots/predef_vars}/expected-error.txt +0 -0
- data/test/snapshots/predef_vars/match-output.txt +6 -0
- data/test/{data → snapshots}/predef_vars/source.lt3 +0 -0
- data/test/{data/raw_text_block → 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_copy → 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/simple_include → 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/simple_mixin → snapshots/simple_import}/expected-error.txt +0 -0
- data/test/snapshots/simple_import/expected-output.txt +7 -0
- data/test/snapshots/simple_import/simple_import.rb +5 -0
- data/test/snapshots/simple_import/source.lt3 +7 -0
- data/test/{data/simple_vars → 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 -1
- data/test/{data/single_raw_line → snapshots/simple_mixin}/expected-error.txt +0 -0
- data/test/{data → snapshots}/simple_mixin/expected-output.txt +0 -0
- data/test/{data → snapshots}/simple_mixin/simple_mixin.rb +0 -0
- data/test/{data → snapshots}/simple_mixin/source.lt3 +0 -0
- data/test/{data/table_with_heredocs → 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/{data/subset.txt → 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 +177 -0
- data/test/testlines.rb +2 -2
- data/test/unit/all.rb +4 -0
- data/test/unit/formatline.rb +650 -0
- data/test/unit/html.rb +38 -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 +164 -0
- data/test/unit/parser/string.rb +130 -0
- data/test/unit/parser.rb +6 -0
- data/test/unit/standard.rb +23 -0
- data/test/unit/stringparser.rb +140 -0
- metadata +137 -100
- data/test/data/error_inc_line_num/FOO +0 -21
- data/test/data/error_inc_line_num/expected-err-line1match.txt +0 -1
- data/test/data/error_invalid_name/expected-err-line1match.txt +0 -1
- data/test/data/error_line_num/expected-err-line1match.txt +0 -1
- data/test/data/error_mismatched_end/expected-err-line1match.txt +0 -1
- data/test/data/error_missing_end/ERR +0 -32
- data/test/data/error_missing_end/expected-err-line1match.txt +0 -1
- data/test/data/error_name_not_permitted/expected-error.txt +0 -1
- data/test/data/error_name_not_permitted/expected-output.txt +0 -4
- 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/data/error_no_such_mixin/expected-err-line1match.txt +0 -1
- data/test/data/lines.txt +0 -124
- data/test/data/predef_vars/expected-output.txt +0 -6
- data/test/formatting.rb +0 -110
- 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: d027612469e45b953a3e8589ebbedf1f746f87f50c4a90b502f4daac56d28605
|
|
4
|
+
data.tar.gz: b811285f434d3b2760e201eb403f864ba31cb12e31f21105fc8c4fe5e3b743a2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1e1b08d7d900ae551d7777576a7284d776422d2039813a764c3d9d9b0495ac14eec4e53225e1e0f3b97a1a548377f14b861e72d4b24d2a52055cd0f75404d2bf
|
|
7
|
+
data.tar.gz: 025055edd14e392750b482f4b0a9a973f213b24a5991bb9c7e9939c225a21bfe77398cc118983599a0fd1ccf1c1aa4c8bbf62874745a2cf5257410b747db72ee
|
data/README.lt3
CHANGED
data/lib/cmdargs.rb
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
require_relative 'livetext'
|
|
2
|
+
|
|
3
|
+
=begin
|
|
4
|
+
Weird concepts to understand here...
|
|
5
|
+
|
|
6
|
+
1. A Livetext dot-command (flush left) usually looks like:
|
|
7
|
+
.foobar
|
|
8
|
+
2. A dot-command (left-indented) usually looks like:
|
|
9
|
+
$.foobar
|
|
10
|
+
3. More generally, it may have any number of parameters (0, 1, ...)
|
|
11
|
+
.redirect somefile.txt append
|
|
12
|
+
4. Variables and functions *can* appear (rare in practice??)
|
|
13
|
+
.redirect somefile$my_suffix $$my_mode
|
|
14
|
+
5. A trailing # comment may appear
|
|
15
|
+
a. Stripped... saved in #raw ? #data ? #comment ? elsewhere?
|
|
16
|
+
b. NOT the "dot" as a comment!
|
|
17
|
+
6. .foobar # This here is a comment
|
|
18
|
+
7. #data accessor returns all data on the .foo line...
|
|
19
|
+
a. ...After the initial space
|
|
20
|
+
b. ...Including spaces
|
|
21
|
+
c. Including comment??
|
|
22
|
+
d. .foo This is o n l y a test.
|
|
23
|
+
# #data returns: "This is o n l y a test."
|
|
24
|
+
e. What about formatting???
|
|
25
|
+
f. What about: comments? variables? functions?
|
|
26
|
+
|
|
27
|
+
7. Some commands have NO body while others have an OPTIONAL or REQUIRED body
|
|
28
|
+
a. Assume .cmd1 definition forbids a body (then a body is an error)
|
|
29
|
+
.cmd1 # may NOT have a body
|
|
30
|
+
b. Assume .cmd2 definition PERMITS a body
|
|
31
|
+
.cmd2 # may or MAY NOT have body/.end
|
|
32
|
+
c. Assume .cmd3 definition PERMITS a body
|
|
33
|
+
.cmd3 # REQUIRES a body/.end
|
|
34
|
+
. stuff...
|
|
35
|
+
.end
|
|
36
|
+
8. Inside a body:
|
|
37
|
+
8a. Leading dot has no special meaning (though the associated method may parse it!)
|
|
38
|
+
8b. BUG? Currently leading dot is a comment INSIDE a body?
|
|
39
|
+
8a. No leading char is special (though the associated method may parse it!)
|
|
40
|
+
8a. No trailing #-comments (though the associated method may parse it!)
|
|
41
|
+
8c. ?? We should or shouldn't look for variables/functions? or make it an option?
|
|
42
|
+
8d. .end may naturally not be used (but see .raw where it may)
|
|
43
|
+
9. the args accessor is a simple array of strings
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
=end
|
|
47
|
+
|
|
48
|
+
class Livetext::CmdData
|
|
49
|
+
|
|
50
|
+
attr_reader :data, :args, :nargs, :arity, :comment, :raw # , ...?
|
|
51
|
+
|
|
52
|
+
def initialize(data, body: false, arity: :N) # FIXME maybe just add **options ??
|
|
53
|
+
# arity: (num) fixed number 0 or more
|
|
54
|
+
# :N arbitrary number
|
|
55
|
+
# n1..n2 range
|
|
56
|
+
# body: true => this command has a body + .end
|
|
57
|
+
# how raw is raw?
|
|
58
|
+
# remove comment - always/sometimes/never?
|
|
59
|
+
# var_func_parse - always/sometimes/never?
|
|
60
|
+
# var_func_parse inside body??
|
|
61
|
+
@data = data.dup # comment? vars? funcs?
|
|
62
|
+
@raw = data.dup # comment? vars? funcs?
|
|
63
|
+
@args = data.split # simple array
|
|
64
|
+
@nargs = nargs # not really "needed"
|
|
65
|
+
check_num_args(nargs)
|
|
66
|
+
|
|
67
|
+
# @varfunc = _var_func_parse(data.dup)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def check_num_args(num)
|
|
71
|
+
num_range = /(\d{0,2})(\.\.)(\d{0,2})/
|
|
72
|
+
min, max = 0, 9999
|
|
73
|
+
md = num_range.match(@nargs).to_a
|
|
74
|
+
bad_args = nil
|
|
75
|
+
case
|
|
76
|
+
when @nargs == ":N" # arbitrary
|
|
77
|
+
# max already set
|
|
78
|
+
when md[2] == ".." # range: 4..6 1.. ..4
|
|
79
|
+
vmin, vmax = md.values_at(1, 2)
|
|
80
|
+
min = Integer(vmin) unless vmin.empty?
|
|
81
|
+
max = Integer(vmax) unless vmax.empty?
|
|
82
|
+
min, max = Integer(min), Integer(max)
|
|
83
|
+
when %r[^\d+$] =~ num
|
|
84
|
+
min = max = Integer(num) # can raise error
|
|
85
|
+
else
|
|
86
|
+
raise "Invalid value or range '#{num.inspect}'"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
bad_args = @args.size.between?(min, max)
|
|
90
|
+
raise "Expected #{num} args but found #{@args.size}!" if bad_args
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
end
|
data/lib/errors.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
# More later?
|
|
3
|
+
|
|
4
|
+
def make_exception(sym, str, target_class = Object)
|
|
5
|
+
return if target_class.constants.include?(sym)
|
|
6
|
+
klass = sym # :"#{sym}_Class"
|
|
7
|
+
target_class.const_set(klass, StandardError.dup)
|
|
8
|
+
define_method(sym) do |*args|
|
|
9
|
+
args = [] unless args.first
|
|
10
|
+
msg = str.dup
|
|
11
|
+
args.each.with_index {|arg, i| msg.sub!("%#{i+1}", arg) }
|
|
12
|
+
target_class.class_eval(klass.to_s).new(msg)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
data/lib/formatline.rb
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
# Class FormatLine handles the parsing of comments, dot commands, and
|
|
2
|
+
# simple formatting characters.
|
|
3
|
+
|
|
4
|
+
class FormatLine < StringParser
|
|
2
5
|
SimpleFormats = {}
|
|
3
6
|
SimpleFormats[:b] = %w[<b> </b>]
|
|
4
7
|
SimpleFormats[:i] = %w[<i> </i>]
|
|
@@ -21,20 +24,11 @@ class FormatLine
|
|
|
21
24
|
|
|
22
25
|
Syms = { "*" => :b, "_" => :i, "`" => :t, "~" => :s }
|
|
23
26
|
|
|
24
|
-
def terminate?(terminators, ch)
|
|
25
|
-
if terminators.is_a? Regexp
|
|
26
|
-
terminators === ch
|
|
27
|
-
else
|
|
28
|
-
terminators.include?(ch)
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
27
|
attr_reader :out
|
|
33
28
|
attr_reader :tokenlist
|
|
34
29
|
|
|
35
30
|
def initialize(line)
|
|
36
|
-
|
|
37
|
-
@i = -1
|
|
31
|
+
super
|
|
38
32
|
@token = Null.dup
|
|
39
33
|
@tokenlist = []
|
|
40
34
|
end
|
|
@@ -42,26 +36,27 @@ class FormatLine
|
|
|
42
36
|
def self.parse!(line)
|
|
43
37
|
return nil if line.nil?
|
|
44
38
|
x = self.new(line.chomp)
|
|
45
|
-
t = x.tokenize
|
|
39
|
+
t = x.tokenize
|
|
40
|
+
# TTY.puts "tokens = \n#{t.inspect}\n "
|
|
46
41
|
x.evaluate
|
|
47
42
|
end
|
|
48
43
|
|
|
49
|
-
def tokenize
|
|
50
|
-
|
|
44
|
+
def tokenize
|
|
45
|
+
# add grab
|
|
51
46
|
loop do
|
|
52
|
-
case
|
|
53
|
-
when Escape; grab; add
|
|
47
|
+
case peek
|
|
48
|
+
when Escape; grab; add peek; grab; add peek
|
|
54
49
|
when "$"
|
|
55
50
|
dollar
|
|
56
51
|
when "*", "_", "`", "~"
|
|
57
|
-
marker
|
|
58
|
-
add
|
|
52
|
+
marker peek
|
|
53
|
+
add peek
|
|
59
54
|
when LF
|
|
60
55
|
break if @i >= line.size - 1
|
|
61
56
|
when nil
|
|
62
57
|
break
|
|
63
58
|
else
|
|
64
|
-
add
|
|
59
|
+
add peek
|
|
65
60
|
end
|
|
66
61
|
grab
|
|
67
62
|
end
|
|
@@ -69,24 +64,33 @@ class FormatLine
|
|
|
69
64
|
@tokenlist
|
|
70
65
|
end
|
|
71
66
|
|
|
67
|
+
def terminate?(terminators, ch)
|
|
68
|
+
if terminators.is_a? Regexp
|
|
69
|
+
terminators === ch
|
|
70
|
+
else
|
|
71
|
+
terminators.include?(ch)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
72
75
|
def self.var_func_parse(str)
|
|
73
76
|
return nil if str.nil?
|
|
74
77
|
x = self.new(str.chomp)
|
|
75
|
-
x.
|
|
76
|
-
loop do
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
break
|
|
83
|
-
else
|
|
84
|
-
x.add x.curr
|
|
85
|
-
end
|
|
86
|
-
x.grab
|
|
78
|
+
char = x.peek
|
|
79
|
+
loop do
|
|
80
|
+
char = x.grab
|
|
81
|
+
break if char == LF || char == nil
|
|
82
|
+
x.handle_escaping if char == Escape
|
|
83
|
+
x.dollar if char == "$"
|
|
84
|
+
x.add char
|
|
87
85
|
end
|
|
88
86
|
x.add_token(:str)
|
|
89
|
-
x.evaluate
|
|
87
|
+
result = x.evaluate
|
|
88
|
+
result
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def handle_escaping
|
|
92
|
+
grab
|
|
93
|
+
add grab
|
|
90
94
|
end
|
|
91
95
|
|
|
92
96
|
def embed(sym, str)
|
|
@@ -127,27 +131,6 @@ class FormatLine
|
|
|
127
131
|
@out
|
|
128
132
|
end
|
|
129
133
|
|
|
130
|
-
def curr
|
|
131
|
-
@line[@i]
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def prev
|
|
135
|
-
return nil if @i <= 0
|
|
136
|
-
@line[@i-1]
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def next!
|
|
140
|
-
@line[@i+1]
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
def grab
|
|
144
|
-
@line[@i+=1]
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def ungrab
|
|
148
|
-
@line[@i-=1]
|
|
149
|
-
end
|
|
150
|
-
|
|
151
134
|
def grab_colon_param
|
|
152
135
|
grab # grab :
|
|
153
136
|
param = ""
|
|
@@ -184,7 +167,7 @@ class FormatLine
|
|
|
184
167
|
end
|
|
185
168
|
end
|
|
186
169
|
|
|
187
|
-
add
|
|
170
|
+
add peek
|
|
188
171
|
grab
|
|
189
172
|
param = nil if param.empty?
|
|
190
173
|
param
|
|
@@ -204,8 +187,8 @@ class FormatLine
|
|
|
204
187
|
str = Null.dup
|
|
205
188
|
grab
|
|
206
189
|
loop do
|
|
207
|
-
break if
|
|
208
|
-
str <<
|
|
190
|
+
break if eos?
|
|
191
|
+
str << peek
|
|
209
192
|
break if terminate?(NoAlpha, next!)
|
|
210
193
|
grab
|
|
211
194
|
end
|
|
@@ -216,8 +199,8 @@ class FormatLine
|
|
|
216
199
|
str = Null.dup
|
|
217
200
|
grab
|
|
218
201
|
loop do
|
|
219
|
-
break if
|
|
220
|
-
str <<
|
|
202
|
+
break if eos? # peek.nil?
|
|
203
|
+
str << peek
|
|
221
204
|
break if terminate?(NoAlphaDot, next!)
|
|
222
205
|
grab
|
|
223
206
|
end
|
|
@@ -226,7 +209,7 @@ class FormatLine
|
|
|
226
209
|
|
|
227
210
|
def dollar
|
|
228
211
|
grab
|
|
229
|
-
case
|
|
212
|
+
case peek
|
|
230
213
|
when LF; add "$"; add_token :str
|
|
231
214
|
when " "; add "$ "; add_token :str
|
|
232
215
|
when nil; add "$"; add_token :str
|
|
@@ -234,10 +217,10 @@ class FormatLine
|
|
|
234
217
|
# when "."; dollar_dot
|
|
235
218
|
when /[A-Za-z]/
|
|
236
219
|
add_token :str
|
|
237
|
-
var =
|
|
220
|
+
var = peek + grab_alpha_dot
|
|
238
221
|
add_token(:var, var)
|
|
239
222
|
else
|
|
240
|
-
add "$" +
|
|
223
|
+
add "$" + peek
|
|
241
224
|
add_token(:string)
|
|
242
225
|
end
|
|
243
226
|
end
|
|
@@ -255,7 +238,7 @@ class FormatLine
|
|
|
255
238
|
when "["; param = grab_func_param; add_token(:brackets, param)
|
|
256
239
|
end
|
|
257
240
|
else
|
|
258
|
-
grab; add_token :str, "$$" +
|
|
241
|
+
grab; add_token :str, "$$" + peek; return
|
|
259
242
|
end
|
|
260
243
|
end
|
|
261
244
|
|
|
@@ -272,7 +255,7 @@ class FormatLine
|
|
|
272
255
|
end
|
|
273
256
|
|
|
274
257
|
grab
|
|
275
|
-
case
|
|
258
|
+
case peek
|
|
276
259
|
when Space
|
|
277
260
|
add char + " "
|
|
278
261
|
add_token :str
|
|
@@ -283,7 +266,7 @@ class FormatLine
|
|
|
283
266
|
when char; double_marker(char)
|
|
284
267
|
when LBrack; long_marker(char)
|
|
285
268
|
else
|
|
286
|
-
str =
|
|
269
|
+
str = peek + collect!(sym, Blank)
|
|
287
270
|
add str
|
|
288
271
|
add_token sym, str
|
|
289
272
|
grab
|
|
@@ -316,21 +299,19 @@ class FormatLine
|
|
|
316
299
|
str = Null.dup # next is not " ","*","["
|
|
317
300
|
grab # ZZZ
|
|
318
301
|
loop do
|
|
319
|
-
if
|
|
320
|
-
str << grab # ch = escaped char
|
|
302
|
+
if peek == Escape
|
|
321
303
|
grab
|
|
304
|
+
str << grab
|
|
322
305
|
next
|
|
323
306
|
end
|
|
324
|
-
if terminate?(terminators,
|
|
307
|
+
if terminate?(terminators, peek)
|
|
325
308
|
break
|
|
326
309
|
end
|
|
327
|
-
|
|
328
|
-
str << curr # not a terminator
|
|
310
|
+
str << peek # not a terminator
|
|
329
311
|
grab
|
|
330
|
-
# STDERR.puts "After grab, curr is #{curr.inspect}"
|
|
331
312
|
end
|
|
332
313
|
|
|
333
|
-
if
|
|
314
|
+
if peek == "]" # skip right bracket
|
|
334
315
|
grab
|
|
335
316
|
end
|
|
336
317
|
add str
|
|
@@ -341,8 +322,8 @@ class FormatLine
|
|
|
341
322
|
end
|
|
342
323
|
|
|
343
324
|
def escaped
|
|
344
|
-
ch = grab
|
|
345
325
|
grab
|
|
326
|
+
ch = grab
|
|
346
327
|
ch
|
|
347
328
|
end
|
|
348
329
|
|
|
@@ -353,15 +334,15 @@ class FormatLine
|
|
|
353
334
|
grab # ZZZ
|
|
354
335
|
loop do
|
|
355
336
|
case
|
|
356
|
-
when
|
|
337
|
+
when peek.nil?
|
|
357
338
|
return str
|
|
358
|
-
when
|
|
339
|
+
when peek == Escape
|
|
359
340
|
str << escaped
|
|
360
341
|
next
|
|
361
|
-
when terminate?(terminators,
|
|
342
|
+
when terminate?(terminators, peek)
|
|
362
343
|
break
|
|
363
344
|
else
|
|
364
|
-
str <<
|
|
345
|
+
str << peek # not a terminator
|
|
365
346
|
end
|
|
366
347
|
grab
|
|
367
348
|
end
|
|
@@ -373,17 +354,14 @@ class FormatLine
|
|
|
373
354
|
STDERR.puts "=== str = #{str.inspect}"
|
|
374
355
|
end
|
|
375
356
|
|
|
376
|
-
############
|
|
377
|
-
|
|
378
|
-
### From FormatLine:
|
|
379
|
-
|
|
380
357
|
def funcall(name, param)
|
|
358
|
+
err = "[Error evaluating $$#{name}(#{param})]"
|
|
381
359
|
result =
|
|
382
360
|
if self.respond_to?("func_" + name.to_s)
|
|
383
361
|
self.send("func_" + name.to_s, param)
|
|
384
362
|
else
|
|
385
363
|
fobj = ::Livetext::Functions.new
|
|
386
|
-
fobj.send(name, param)
|
|
364
|
+
fobj.send(name, param) rescue err
|
|
387
365
|
end
|
|
388
366
|
result
|
|
389
367
|
end
|
|
@@ -393,13 +371,6 @@ class FormatLine
|
|
|
393
371
|
result
|
|
394
372
|
end
|
|
395
373
|
|
|
396
|
-
#####
|
|
397
|
-
|
|
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
374
|
def embedded?
|
|
404
375
|
! (['"', "'", " ", nil].include? prev)
|
|
405
376
|
end
|
data/lib/functions.rb
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
require 'standard' # FIXME
|
|
2
1
|
|
|
3
|
-
|
|
2
|
+
require_relative 'standard' # FIXME umm, why is this necessary??
|
|
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
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
class Livetext::Handler::ICanHaz
|
|
3
|
+
include Helpers
|
|
4
|
+
|
|
5
|
+
attr_reader :file
|
|
6
|
+
|
|
7
|
+
def initialize(name)
|
|
8
|
+
@name = name
|
|
9
|
+
@file = find_file(name)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.get_module(name)
|
|
13
|
+
handler = self.new(name)
|
|
14
|
+
const1 = Object.constants
|
|
15
|
+
@file = handler.file.sub(/.rb$/, "")
|
|
16
|
+
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
|
|
21
|
+
newmod = Object.const_get("::" + modname)
|
|
22
|
+
newmod # return actual module
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def cwd_root?
|
|
28
|
+
File.dirname(File.expand_path(".")) == "/"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def fname2module(name)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
data/lib/handler.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require_relative 'handler/icanhaz'
|
data/lib/helpers.rb
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
|
|
2
|
+
module Helpers
|
|
3
|
+
|
|
4
|
+
Space = " "
|
|
5
|
+
Sigil = "." # Can't change yet
|
|
6
|
+
|
|
7
|
+
def escape_html(string)
|
|
8
|
+
enc = string.encoding
|
|
9
|
+
unless enc.ascii_compatible?
|
|
10
|
+
if enc.dummy?
|
|
11
|
+
origenc = enc
|
|
12
|
+
enc = Encoding::Converter.asciicompat_encoding(enc)
|
|
13
|
+
string = enc ? string.encode(enc) : string.b
|
|
14
|
+
end
|
|
15
|
+
table = Hash[TABLE_FOR_ESCAPE_HTML__.map {|pair|pair.map {|s|s.encode(enc)}}]
|
|
16
|
+
string = string.gsub(/#{"['&\"<>]".encode(enc)}/, table)
|
|
17
|
+
string.encode!(origenc) if origenc
|
|
18
|
+
return string
|
|
19
|
+
end
|
|
20
|
+
string.gsub(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def find_file(name, ext=".rb")
|
|
24
|
+
paths = [Livetext::Path.sub(/lib/, "imports/"), "./"]
|
|
25
|
+
base = "#{name}#{ext}"
|
|
26
|
+
paths.each do |path|
|
|
27
|
+
file = path + base
|
|
28
|
+
return file if File.exist?(file)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
raise "No such mixin '#{name}'"
|
|
32
|
+
|
|
33
|
+
# # Really want to search upward??
|
|
34
|
+
# raise "No such mixin '#{name}'" if cwd_root?
|
|
35
|
+
# Dir.chdir("..") { find_file(name) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.rx(str, space=nil)
|
|
39
|
+
Regexp.compile("^" + Regexp.escape(str) + "#{space}")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
Comment = rx(Sigil, Space)
|
|
43
|
+
Dotcmd = rx(Sigil)
|
|
44
|
+
Ddotcmd = /^ *\$\.[A-Za-z]/
|
|
45
|
+
|
|
46
|
+
## FIXME process_file[!] should call process[_text]
|
|
47
|
+
|
|
48
|
+
def process_file(fname, btrace=false)
|
|
49
|
+
setfile(fname)
|
|
50
|
+
text = File.readlines(fname)
|
|
51
|
+
enum = text.each
|
|
52
|
+
@backtrace = btrace
|
|
53
|
+
@main.source(enum, fname, 0)
|
|
54
|
+
line = nil
|
|
55
|
+
loop do
|
|
56
|
+
line = @main.nextline
|
|
57
|
+
break if line.nil?
|
|
58
|
+
process_line(line)
|
|
59
|
+
end
|
|
60
|
+
val = @main.finalize if @main.respond_to? :finalize
|
|
61
|
+
@body
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def process_line(line) # FIXME inefficient?
|
|
65
|
+
nomarkup = true
|
|
66
|
+
case line # must apply these in order
|
|
67
|
+
when Comment
|
|
68
|
+
handle_scomment(line)
|
|
69
|
+
when Dotcmd
|
|
70
|
+
handle_dotcmd(line)
|
|
71
|
+
when Ddotcmd
|
|
72
|
+
indent = line.index("$") + 1
|
|
73
|
+
@indentation.push(indent)
|
|
74
|
+
line.sub!(/^ *\$/, "")
|
|
75
|
+
handle_dotcmd(line)
|
|
76
|
+
indentation.pop
|
|
77
|
+
else
|
|
78
|
+
@main._passthru(line)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def handle_dotcmd(line, indent = 0)
|
|
83
|
+
indent = @indentation.last # top of stack
|
|
84
|
+
line = line.sub(/# .*$/, "")
|
|
85
|
+
name = get_name(line).to_sym
|
|
86
|
+
result = nil
|
|
87
|
+
case
|
|
88
|
+
when name == :end # special case
|
|
89
|
+
puts @body
|
|
90
|
+
raise EndWithoutOpening()
|
|
91
|
+
when @main.respond_to?(name)
|
|
92
|
+
result = @main.send(name)
|
|
93
|
+
else
|
|
94
|
+
puts @body # earlier correct output, not flushed yet
|
|
95
|
+
raise "Name '#{name}' is unknown"
|
|
96
|
+
return
|
|
97
|
+
end
|
|
98
|
+
result
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def handle_scomment(line)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def get_name(line)
|
|
105
|
+
name, data = line.split(" ", 2)
|
|
106
|
+
name = name[1..-1] # chop off sigil
|
|
107
|
+
name = "dot_" + name if %w[include def].include?(name)
|
|
108
|
+
@main.data = data
|
|
109
|
+
@main.check_disallowed(name)
|
|
110
|
+
name
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def check_disallowed(name)
|
|
114
|
+
raise DisallowedName(name) if disallowed?(name)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def check_file_exists(file)
|
|
118
|
+
raise FileNotFound(file) unless File.exist?(file)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def set_variables(pairs)
|
|
122
|
+
pairs.each do |pair|
|
|
123
|
+
var, value = *pair
|
|
124
|
+
@parent.setvar(var, value)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def grab_file(fname)
|
|
129
|
+
File.read(fname)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def search_upward(file)
|
|
133
|
+
value = nil
|
|
134
|
+
return file if File.exist?(file)
|
|
135
|
+
|
|
136
|
+
count = 1
|
|
137
|
+
loop do
|
|
138
|
+
front = "../" * count
|
|
139
|
+
count += 1
|
|
140
|
+
here = Pathname.new(front).expand_path.dirname.to_s
|
|
141
|
+
break if here == "/"
|
|
142
|
+
path = front + file
|
|
143
|
+
value = path if File.exist?(path)
|
|
144
|
+
break if value
|
|
145
|
+
end
|
|
146
|
+
STDERR.puts "Cannot find #{file.inspect} from #{Dir.pwd}" unless value
|
|
147
|
+
return value
|
|
148
|
+
rescue
|
|
149
|
+
STDERR.puts "Can't find #{file.inspect} from #{Dir.pwd}"
|
|
150
|
+
return nil
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def include_file(file)
|
|
154
|
+
@_args = [file]
|
|
155
|
+
dot_include
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def onoff(arg) # helper
|
|
159
|
+
arg ||= "on"
|
|
160
|
+
raise ExpectedOnOff unless String === arg
|
|
161
|
+
case arg.downcase
|
|
162
|
+
when "on"
|
|
163
|
+
return true
|
|
164
|
+
when "off"
|
|
165
|
+
return false
|
|
166
|
+
else
|
|
167
|
+
raise ExpectedOnOff
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def setvar(var, val)
|
|
172
|
+
str, sym = var.to_s, var.to_sym
|
|
173
|
+
Livetext::Vars[str] = val
|
|
174
|
+
Livetext::Vars[sym] = val
|
|
175
|
+
@_vars[str] = val
|
|
176
|
+
@_vars[sym] = val
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def setfile(file)
|
|
180
|
+
if file
|
|
181
|
+
setvar(:File, file)
|
|
182
|
+
dir = File.dirname(File.expand_path(file))
|
|
183
|
+
setvar(:FileDir, dir)
|
|
184
|
+
else
|
|
185
|
+
setvar(:File, "[no file]")
|
|
186
|
+
setvar(:FileDir, "[no dir]")
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def setfile!(file) # FIXME why does this variant exist?
|
|
191
|
+
setvar(:File, file)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
end
|