livetext 0.9.25 → 0.9.26
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/imports/bookish.rb +1 -2
- data/lib/livetext/errors.rb +3 -0
- data/lib/livetext/formatline.rb +102 -15
- data/lib/livetext/funcall.rb +86 -2
- data/lib/livetext/global_helpers.rb +5 -0
- data/lib/livetext/handler/import.rb +2 -6
- data/lib/livetext/handler/mixin.rb +2 -6
- data/lib/livetext/helpers.rb +9 -11
- data/lib/livetext/lineparser.rb +441 -0
- data/lib/livetext/more.rb +158 -0
- data/lib/livetext/processor.rb +3 -1
- data/lib/livetext/skeleton.rb +5 -0
- data/lib/livetext/standard.rb +12 -8
- data/lib/livetext/userapi.rb +27 -10
- data/lib/livetext/version.rb +1 -1
- data/lib/livetext.rb +3 -152
- data/test/snapshots/basic_formatting/actual-error.txt +0 -0
- data/test/snapshots/basic_formatting/actual-output.txt +13 -0
- data/test/snapshots/basic_formatting/err-sdiff.txt +1 -0
- data/test/snapshots/basic_formatting/out-sdiff.txt +14 -0
- data/test/snapshots/error_invalid_name/foo +5 -0
- data/test/snapshots/import_bookish/expected-output.txt +4 -4
- data/test/snapshots/more_functions/actual-error.txt +0 -0
- data/test/snapshots/more_functions/actual-output.txt +37 -0
- data/test/snapshots/more_functions/err-sdiff.txt +1 -0
- data/test/snapshots/more_functions/expected-output.txt +1 -1
- data/test/snapshots/more_functions/out-sdiff.txt +38 -0
- data/test/snapshots/more_functions/source.lt3 +1 -1
- data/test/snapshots/simple_vars/actual-error.txt +0 -0
- data/test/snapshots/simple_vars/actual-output.txt +6 -0
- data/test/snapshots/simple_vars/err-sdiff.txt +1 -0
- data/test/snapshots/simple_vars/out-sdiff.txt +7 -0
- data/test/snapshots/subset.txt +2 -0
- data/test/snapshots/var_into_func/actual-error.txt +0 -0
- data/test/snapshots/var_into_func/actual-output.txt +16 -0
- data/test/snapshots/var_into_func/err-sdiff.txt +1 -0
- data/test/snapshots/var_into_func/expected-error.txt +0 -0
- data/test/snapshots/var_into_func/expected-output.txt +16 -0
- data/test/snapshots/var_into_func/out-sdiff.txt +17 -0
- data/test/snapshots/var_into_func/source.lt3 +16 -0
- data/test/unit/all.rb +3 -1
- data/test/unit/formatline.rb +143 -274
- data/test/unit/lineparser.rb +650 -0
- data/test/unit/parser/set.rb +13 -12
- data/test/unit/tokenizer.rb +534 -0
- metadata +26 -5
- data/test/snapshots/error_inc_line_num/OUT +0 -17
- data/test/snapshots/error_no_such_copy/duh +0 -26
- data/test/snapshots/error_no_such_copy/mystery.txt +0 -36
data/lib/livetext/userapi.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
|
2
|
-
require_relative 'formatline'
|
2
|
+
# require_relative 'formatline' # FIXME meh, because of #format
|
3
|
+
require_relative 'lineparser' # FIXME meh, because of #format
|
3
4
|
|
4
5
|
# Encapsulate the UserAPI as a class
|
5
6
|
|
6
7
|
class Livetext::UserAPI
|
7
8
|
|
9
|
+
KBD = File.new("/dev/tty", "r")
|
10
|
+
TTY = File.new("/dev/tty", "w")
|
11
|
+
|
12
|
+
DotSpace = ". " # Livetext::Sigil + Livetext::Space
|
13
|
+
|
8
14
|
attr_accessor :data, :args
|
9
15
|
|
10
16
|
def initialize(live)
|
@@ -12,11 +18,16 @@ class Livetext::UserAPI
|
|
12
18
|
@vars = live.vars
|
13
19
|
end
|
14
20
|
|
21
|
+
def api
|
22
|
+
@live.api
|
23
|
+
end
|
24
|
+
|
25
|
+
def dot
|
26
|
+
@live
|
27
|
+
end
|
28
|
+
|
15
29
|
def setvar(var, val)
|
16
|
-
#
|
17
|
-
str, sym = var.to_s, var.to_sym
|
18
|
-
Livetext::Vars[str] = val
|
19
|
-
Livetext::Vars[sym] = val
|
30
|
+
Livetext::Vars[var] = val # Now indifferent and "safe"
|
20
31
|
end
|
21
32
|
|
22
33
|
def check_existence(file, msg)
|
@@ -24,6 +35,7 @@ class Livetext::UserAPI
|
|
24
35
|
end
|
25
36
|
|
26
37
|
def data=(value)
|
38
|
+
# TTY.puts "in #{__FILE__}: api = #{@live.api.inspect}"
|
27
39
|
@data = value
|
28
40
|
@args = format(@data).chomp.split
|
29
41
|
end
|
@@ -45,9 +57,7 @@ class Livetext::UserAPI
|
|
45
57
|
end
|
46
58
|
|
47
59
|
def comment?(str)
|
48
|
-
|
49
|
-
c1 = sigil + Livetext::Space
|
50
|
-
str.index(c1) == 0
|
60
|
+
str.index(DotSpace) == 0
|
51
61
|
end
|
52
62
|
|
53
63
|
def trailing?(char)
|
@@ -110,8 +120,7 @@ class Livetext::UserAPI
|
|
110
120
|
|
111
121
|
def format(line)
|
112
122
|
return "" if line == "\n" || line.nil?
|
113
|
-
line2 = Livetext::
|
114
|
-
# line.replace(line2)
|
123
|
+
line2 = Livetext::LineParser.parse!(line)
|
115
124
|
line2
|
116
125
|
end
|
117
126
|
|
@@ -133,6 +142,14 @@ class Livetext::UserAPI
|
|
133
142
|
@live.body << str # no newline
|
134
143
|
end
|
135
144
|
|
145
|
+
def tty(*args)
|
146
|
+
TTY.puts *args
|
147
|
+
end
|
148
|
+
|
149
|
+
def err(*args)
|
150
|
+
STDERR.puts *args
|
151
|
+
end
|
152
|
+
|
136
153
|
def puts(*args)
|
137
154
|
@live.output.puts *args
|
138
155
|
end
|
data/lib/livetext/version.rb
CHANGED
data/lib/livetext.rb
CHANGED
@@ -9,160 +9,11 @@ require_relative 'livetext/errors'
|
|
9
9
|
require_relative 'livetext/standard'
|
10
10
|
require_relative 'livetext/functions'
|
11
11
|
require_relative 'livetext/userapi'
|
12
|
-
require_relative 'livetext/formatline'
|
12
|
+
# require_relative 'livetext/formatline'
|
13
|
+
require_relative 'livetext/lineparser'
|
13
14
|
require_relative 'livetext/processor'
|
14
15
|
require_relative 'livetext/helpers'
|
15
16
|
require_relative 'livetext/handler'
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
make_exception(:EndWithoutOpening, "Error: found .end with no opening command")
|
20
|
-
make_exception(:UnknownMethod, "Error: name '%1' is unknown")
|
21
|
-
|
22
|
-
# Class Livetext reopened (top level).
|
23
|
-
|
24
|
-
class Livetext
|
25
|
-
|
26
|
-
include Helpers
|
27
|
-
|
28
|
-
Vars = {}
|
29
|
-
|
30
|
-
TTY = ::File.open("/dev/tty", "w")
|
31
|
-
|
32
|
-
attr_reader :main, :sources
|
33
|
-
attr_accessor :nopass, :nopara
|
34
|
-
attr_accessor :body, :indentation
|
35
|
-
|
36
|
-
class << self
|
37
|
-
attr_accessor :output # bad solution?
|
38
|
-
end
|
39
|
-
|
40
|
-
def vars
|
41
|
-
@_vars
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.interpolate(str)
|
45
|
-
# FIXME There are issues here...
|
46
|
-
# Livetext::FormatLine.var_func_parse(str)
|
47
|
-
parse = Livetext::FormatLine.new(str)
|
48
|
-
parse.var_func_parse
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.customize(mix: [], call: [], vars: {})
|
52
|
-
obj = self.new
|
53
|
-
mix = Array(mix)
|
54
|
-
call = Array(call)
|
55
|
-
mix.each {|lib| obj.mixin(lib) }
|
56
|
-
call.each {|cmd| obj.main.send(cmd[1..-1]) } # ignores leading dot, no param
|
57
|
-
vars.each_pair {|var, val| obj.setvar(var, val.to_s) }
|
58
|
-
obj
|
59
|
-
end
|
60
|
-
|
61
|
-
def peek_nextline
|
62
|
-
@main.peek_nextline # delegate
|
63
|
-
end
|
64
|
-
|
65
|
-
def nextline
|
66
|
-
@main.nextline # delegate
|
67
|
-
end
|
68
|
-
|
69
|
-
def sources
|
70
|
-
@main.sources # delegate
|
71
|
-
end
|
72
|
-
|
73
|
-
def save_location
|
74
|
-
@save_location # delegate
|
75
|
-
end
|
76
|
-
|
77
|
-
def save_location=(where)
|
78
|
-
@save_location = where # delegate
|
79
|
-
end
|
80
|
-
|
81
|
-
def dump(file = nil) # not a dot command!
|
82
|
-
file ||= ::STDOUT
|
83
|
-
file.puts @body
|
84
|
-
rescue => err
|
85
|
-
TTY.puts "#dump had an error: #{err.inspect}"
|
86
|
-
end
|
87
|
-
|
88
|
-
def graceful_error(err)
|
89
|
-
dump
|
90
|
-
raise err
|
91
|
-
end
|
92
|
-
|
93
|
-
def customize(mix: [], call: [], vars: {})
|
94
|
-
mix = Array(mix)
|
95
|
-
call = Array(call)
|
96
|
-
mix.each {|lib| mixin(lib) }
|
97
|
-
call.each {|cmd| @main.send(cmd[1..-1]) } # ignores leading dot, no param
|
98
|
-
vars.each_pair {|var, val| setvar(var, val.to_s) }
|
99
|
-
self
|
100
|
-
end
|
101
|
-
|
102
|
-
def initialize(output = ::STDOUT)
|
103
|
-
@source = nil
|
104
|
-
@_mixins = []
|
105
|
-
@_imports = []
|
106
|
-
@_outdir = "."
|
107
|
-
@no_puts = output.nil?
|
108
|
-
@body = ""
|
109
|
-
@main = Processor.new(self, output)
|
110
|
-
@indentation = [0]
|
111
|
-
@_vars = Livetext::Vars
|
112
|
-
initial_vars
|
113
|
-
@api = UserAPI.new(self)
|
114
|
-
end
|
115
|
-
|
116
|
-
def api
|
117
|
-
@api
|
118
|
-
end
|
119
|
-
|
120
|
-
def interpolate(str)
|
121
|
-
end
|
122
|
-
|
123
|
-
def initial_vars
|
124
|
-
# Other predefined variables (see also setfile)
|
125
|
-
setvar(:User, `whoami`.chomp)
|
126
|
-
setvar(:Version, Livetext::VERSION)
|
127
|
-
end
|
128
|
-
|
129
|
-
def transform(text)
|
130
|
-
setfile!("(string)")
|
131
|
-
enum = text.each_line
|
132
|
-
front = text.match(/.*?\n/).to_a.first.chomp rescue ""
|
133
|
-
@main.source(enum, "STDIN: '#{front}...'", 0)
|
134
|
-
loop do
|
135
|
-
line = @main.nextline
|
136
|
-
break if line.nil?
|
137
|
-
process_line(line)
|
138
|
-
end
|
139
|
-
result = @body
|
140
|
-
# @body = ""
|
141
|
-
result
|
142
|
-
end
|
143
|
-
|
144
|
-
# EXPERIMENTAL and incomplete
|
145
|
-
def xform(*args, file: nil, text: nil, vars: {})
|
146
|
-
case
|
147
|
-
when file && text.nil?
|
148
|
-
xform_file(file)
|
149
|
-
when file.nil? && text
|
150
|
-
transform(text)
|
151
|
-
when file.nil? && text.nil?
|
152
|
-
raise "Must specify file or text"
|
153
|
-
when file && text
|
154
|
-
raise "Cannot specify file and text"
|
155
|
-
end
|
156
|
-
self.process_file(file)
|
157
|
-
self.body
|
158
|
-
end
|
159
|
-
|
160
|
-
def xform_file(file, vars: nil)
|
161
|
-
Livetext::Vars.replace(vars) unless vars.nil?
|
162
|
-
@_vars.replace(vars) unless vars.nil?
|
163
|
-
self.process_file(file)
|
164
|
-
self.body
|
165
|
-
end
|
166
|
-
|
167
|
-
end
|
18
|
+
require_relative 'livetext/more'
|
168
19
|
|
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Here are examples of <b>boldface</b>
|
2
|
+
and <i>italics</i>
|
3
|
+
and <font size=+1><tt>code</tt></font>
|
4
|
+
as well as <b>ore complex</b>*examples
|
5
|
+
of <i>talicized text</i>
|
6
|
+
and <font size=+1><tt>ode font</tt></font>
|
7
|
+
<p>
|
8
|
+
|
9
|
+
Here are some random punctuation marks:
|
10
|
+
; # . * * ` ` @ % ^ & $
|
11
|
+
<p>
|
12
|
+
|
13
|
+
No need to escape these: * * `
|
@@ -0,0 +1 @@
|
|
1
|
+
ACTUAL | EXPECTED
|
@@ -0,0 +1,14 @@
|
|
1
|
+
ACTUAL | EXPECTED
|
2
|
+
Here are examples of <b>boldface</b> | Here are examples of <b>boldface</b>
|
3
|
+
and <i>italics</i> and <i>italics</i>
|
4
|
+
and <font size=+1><tt>code</tt></font> and <font size=+1><tt>code</tt></font>
|
5
|
+
as well as <b>ore complex</b>*examples | as well as <b>more complex</b> examples
|
6
|
+
of <i>talicized text</i> | of <i>italicized text</i>
|
7
|
+
and <font size=+1><tt>ode font</tt></font> | and <font size=+1><tt>code font</tt></font>.
|
8
|
+
<p> <p>
|
9
|
+
|
10
|
+
Here are some random punctuation marks: Here are some random punctuation marks:
|
11
|
+
; # . * * ` ` @ % ^ & $ | ; # . * _ ` : @ % ^ & $
|
12
|
+
<p> <p>
|
13
|
+
|
14
|
+
No need to escape these: * * ` | No need to escape these: * _ `
|
@@ -1,10 +1,10 @@
|
|
1
1
|
<table cellpadding=2>
|
2
2
|
<tr>
|
3
|
-
<td width=
|
4
|
-
<td width=
|
3
|
+
<td width=0% valign=top>this</td>
|
4
|
+
<td width=0% valign=top>that</td>
|
5
5
|
</tr>
|
6
6
|
<tr>
|
7
|
-
<td width=
|
8
|
-
<td width=
|
7
|
+
<td width=0% valign=top>foo</td>
|
8
|
+
<td width=0% valign=top>bar</td>
|
9
9
|
</tr>
|
10
10
|
</table>
|
File without changes
|
@@ -0,0 +1,37 @@
|
|
1
|
+
Testing some more functions here...
|
2
|
+
<p>
|
3
|
+
|
4
|
+
Here I am calling a function with
|
5
|
+
a colon parameter...
|
6
|
+
<p>
|
7
|
+
|
8
|
+
<p>
|
9
|
+
|
10
|
+
Next let's <b>do</b>*something with our parameter:
|
11
|
+
<p>
|
12
|
+
|
13
|
+
I'll call these variants...
|
14
|
+
<p>
|
15
|
+
|
16
|
+
"Motel" spelled backwards is letom :)
|
17
|
+
<p>
|
18
|
+
|
19
|
+
"lamina" reversed is animal
|
20
|
+
<p>
|
21
|
+
|
22
|
+
I can also use the erutaef tekcarb here.
|
23
|
+
<p>
|
24
|
+
|
25
|
+
If I don't use a parameter for [Error evaluating $$reverse()] - it gives
|
26
|
+
me an error. (Bug or feature??)
|
27
|
+
<p>
|
28
|
+
|
29
|
+
What if a function doesn't use parameters at all, but
|
30
|
+
we pass them? Hmm...
|
31
|
+
<p>
|
32
|
+
|
33
|
+
Now we succeed and succeed some more
|
34
|
+
and finally we succeed in life.
|
35
|
+
<p>
|
36
|
+
|
37
|
+
But can we succeed, when our beds are burning?
|
@@ -0,0 +1 @@
|
|
1
|
+
ACTUAL | EXPECTED
|
@@ -0,0 +1,38 @@
|
|
1
|
+
ACTUAL | EXPECTED
|
2
|
+
Testing some more functions here... Testing some more functions here...
|
3
|
+
<p> <p>
|
4
|
+
|
5
|
+
Here I am calling a function with Here I am calling a function with
|
6
|
+
a colon parameter... a colon parameter...
|
7
|
+
<p> <p>
|
8
|
+
|
9
|
+
<p> <p>
|
10
|
+
|
11
|
+
Next let's <b>do</b>*something with our parameter: | Next let's <b>do</b> something with our parameter:
|
12
|
+
<p> <p>
|
13
|
+
|
14
|
+
I'll call these variants... I'll call these variants...
|
15
|
+
<p> <p>
|
16
|
+
|
17
|
+
"Motel" spelled backwards is letom :) "Motel" spelled backwards is letom :)
|
18
|
+
<p> <p>
|
19
|
+
|
20
|
+
"lamina" reversed is animal "lamina" reversed is animal
|
21
|
+
<p> <p>
|
22
|
+
|
23
|
+
I can also use the erutaef tekcarb here. I can also use the erutaef tekcarb here.
|
24
|
+
<p> <p>
|
25
|
+
|
26
|
+
If I don't use a parameter for [Error evaluating $$reverse( If I don't use a parameter for [Error evaluating $$reverse(
|
27
|
+
me an error. (Bug or feature??) me an error. (Bug or feature??)
|
28
|
+
<p> <p>
|
29
|
+
|
30
|
+
What if a function doesn't use parameters at all, but What if a function doesn't use parameters at all, but
|
31
|
+
we pass them? Hmm... we pass them? Hmm...
|
32
|
+
<p> <p>
|
33
|
+
|
34
|
+
Now we succeed and succeed some more Now we succeed and succeed some more
|
35
|
+
and finally we succeed in life. and finally we succeed in life.
|
36
|
+
<p> <p>
|
37
|
+
|
38
|
+
But can we succeed, when our beds are burning? But can we succeed, when our beds are burning?
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
ACTUAL | EXPECTED
|
@@ -0,0 +1,7 @@
|
|
1
|
+
ACTUAL | EXPECTED
|
2
|
+
Just Just
|
3
|
+
some text. some text.
|
4
|
+
Hi, there. Hi, there.
|
5
|
+
GulliverFoyle is my name, and Terra is my nation. GulliverFoyle is my name, and Terra is my nation.
|
6
|
+
I'm GulliverFoyle, from Terra | I'm GulliverFoyle, from Terra.
|
7
|
+
That's all. That's all.
|
data/test/snapshots/subset.txt
CHANGED
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
ACTUAL | EXPECTED
|
File without changes
|
@@ -0,0 +1,17 @@
|
|
1
|
+
ACTUAL | EXPECTED
|
2
|
+
<p> <p>
|
3
|
+
|
4
|
+
Testing STILL more functions here... Testing STILL more functions here...
|
5
|
+
<p> <p>
|
6
|
+
|
7
|
+
<p> <p>
|
8
|
+
|
9
|
+
Now... let's try passing a variable to a function. Will thi Now... let's try passing a variable to a function. Will thi
|
10
|
+
<p> <p>
|
11
|
+
|
12
|
+
Variable \regal is regal, which reversed is ahpla$ | Variable $alpha is regal, which reversed is lager
|
13
|
+
<p> <p>
|
14
|
+
|
15
|
+
That's all. That's all.
|
16
|
+
<p> <p>
|
17
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
Testing STILL more functions here...
|
3
|
+
|
4
|
+
|
5
|
+
.func reverse
|
6
|
+
param.reverse # just reverse it
|
7
|
+
.end
|
8
|
+
|
9
|
+
Now... let's try passing a variable to a function. Will this work??
|
10
|
+
|
11
|
+
.set alpha = regal
|
12
|
+
|
13
|
+
Variable \$alpha is $alpha, which reversed is $$reverse:$alpha
|
14
|
+
|
15
|
+
That's all.
|
16
|
+
|