livetext 0.9.30 → 0.9.33

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee3796664666616d6b5428f4b27f81c3f902171fc8afc8fd351631c6c774e730
4
- data.tar.gz: 5dd5250915ef13d930dca6b147e84b5e04e42d1a7b9c0f4b1e95d510ea49e476
3
+ metadata.gz: 4c6ed527394d333fd5c667d5737093c26595794269dcf444d72bc28cdcbf8c61
4
+ data.tar.gz: 7eb6d6907ebfd5bfd2ee7f8253a0c3a051d06cd83ffaac5baca388406168db6c
5
5
  SHA512:
6
- metadata.gz: d0e81ca1d3990468ae49f3c5e23ab608160f7db301f692757200fe57b5434f125bd83b3a7af80dd22ea8cc278972dcb39fe3b408f3a800871f3fb243e6c3639c
7
- data.tar.gz: 4bc7641f62f63215fbcf52192a74956991e540a2282922da21a5b0ea2a5d959420a9226c52745c635fc91521d860921b4d7d69defb8b540868d73df9b8fbfd99
6
+ metadata.gz: 57b37bb2795cacaa81f86f4d251d438b92dd8d0fd7f71839eb68edda95a4bf5d60a56af46d93d9ba93de118b7b878eea53f5daecab6459dd73a0167a5aba33d4
7
+ data.tar.gz: 7c7fb6ac4101629dd86b0901a961fc8d4c4901b661ff0eb8553081f7617601c7d807df03212ac57ab14b8c740a3a60efcfd3c2d951bea6b509f57a89170fa2b9
data/bin/livetext CHANGED
@@ -66,7 +66,7 @@ end
66
66
 
67
67
  def install_plugin
68
68
  lib = ARGV.shift
69
- system("cp #{lib} #{Livetext::Path}/../plugin/")
69
+ system("cp #{lib} #{Livetext::Path}/../../plugin/")
70
70
  end
71
71
 
72
72
  def parse_command_line
data/imports/bookish.rb CHANGED
@@ -173,7 +173,7 @@ module Bookish
173
173
  lines = api.body(true)
174
174
  maxw = nil
175
175
  lines.each do |line|
176
- api.format(line)
176
+ # line = api.format(line)
177
177
  cells = line.split(delim)
178
178
  wide = cells.map {|x| x.length }
179
179
  maxw = [0] * cells.size
@@ -12,21 +12,23 @@ class Livetext::Expansion
12
12
  @live = instance
13
13
  end
14
14
 
15
- def format(line) # new/experimental
15
+ def format(line)
16
16
  return "" if line == "\n" || line.nil?
17
- formatted = Formatter.format(line)
18
- with_vars = expand_variables(formatted)
17
+ with_vars = expand_variables(line)
19
18
  with_func = expand_function_calls(with_vars)
19
+ formatted = Formatter.format(with_func)
20
20
  end
21
21
 
22
22
  def expand_variables(str)
23
23
  rx = Regexp.compile("(?<result>" + Var + Dotted + ")")
24
- enum = str.each_char
25
24
  buffer = ""
26
25
  loop do |i|
27
26
  case # var or func or false alarm
28
27
  when str.empty? # end of string
29
28
  break
29
+ when str.slice(0..1) == "\\$" # escaped, ignore it
30
+ str.slice!(0..1)
31
+ buffer << "$"
30
32
  when str.slice(0..1) == "$$" # func?
31
33
  buffer << str.slice!(0..1)
32
34
  when str.slice(0) == "$" # var?
@@ -41,7 +43,8 @@ class Livetext::Expansion
41
43
  vars = @live.vars
42
44
  buffer << vars.get(vsym)
43
45
  else # other
44
- buffer << str.slice!(0)
46
+ char = str.slice!(0)
47
+ buffer << char
45
48
  end
46
49
  end
47
50
  buffer
@@ -82,14 +85,12 @@ class Livetext::Expansion
82
85
  param = fmatch["param"] # may be nil
83
86
  full = fmatch["full_param"]
84
87
  fsym = fname[2..-1] # no $$
85
- =begin
86
- puts "rx = #{rx.inspect}"
87
- puts "fmatch = #{fmatch.inspect}"
88
- puts "fname = #{fname.inspect}"
89
- puts "param = #{param.inspect}"
90
- puts "full = #{full.inspect}"
91
- puts "fsym = #{fsym.inspect}"
92
- =end
88
+ #STDERR.puts "rx = #{rx.inspect}"
89
+ #STDERR.puts "fmatch = #{fmatch.inspect}"
90
+ #STDERR.puts "fname = #{fname.inspect}"
91
+ #STDERR.puts "param = #{param.inspect}"
92
+ #STDERR.puts "full = #{full.inspect}"
93
+ #STDERR.puts "fsym = #{fsym.inspect}"
93
94
  str.sub!(fname, "")
94
95
  str.sub!(full, "") if full
95
96
  retval = funcall(fsym, param)
@@ -100,6 +101,7 @@ puts "fsym = #{fsym.inspect}"
100
101
  buffer << char
101
102
  end
102
103
  end
104
+ # STDERR.puts "buffer = #{buffer.inspect}"
103
105
  buffer
104
106
  end
105
107
  end
@@ -1,104 +1,203 @@
1
1
  module Formatter
2
-
3
- Start = /(?<start>(^| ))/
4
- Stop = /(?<stop> |$)/
5
2
 
6
- def self.make_regex(sigil, cdata, stop = Stop)
7
- rx = /#{Start}#{sigil}#{cdata}#{stop}/
3
+ ## Hmmm...
4
+ #
5
+ # Double: b, i, t, s
6
+ # Single: bits
7
+ # Brackt: bits
8
+ #
9
+
10
+
11
+ def self.format(str)
12
+ str = str.chomp
13
+ s2 = Double.process(str.chomp)
14
+ s3 = Bracketed.process(s2)
15
+ s4 = Single.process(s3)
16
+ s4
8
17
  end
18
+
19
+ class Delimited
20
+ def initialize(str, marker, tag)
21
+ @str, @marker, @tag = str.dup, marker, tag
22
+ @buffer = ""
23
+ @cdata = ""
24
+ @state = :INITIAL
25
+ end
9
26
 
10
- def self.iterate(str, rx, tag)
11
- loop do
12
- str, more = make_string(str, rx, tag)
13
- break unless more
27
+ def status(where)
28
+ if $debug
29
+ STDERR.printf "%-11s %-7s #{@marker.inspect} \n #{' '*11} state = %-8s str = %-20s buffer = %-20s cdata = %-20s\n",
30
+ where, self.class, @state, @str.inspect, @buffer.inspect, @cdata.inspect
31
+ end
14
32
  end
15
- str
16
- end
17
33
 
18
- def self.double(str, char, tag)
19
- cdata = /(?<cdata>[^ \.,]*?)/
20
- stop = /(?<stop>[\.,]|$)/
21
- sigil = Regexp.escape(char+char)
22
- rx = make_regex(sigil, cdata, stop)
23
- str = iterate(str, rx, tag)
24
- str
25
- end
34
+ def front
35
+ @str[0]
36
+ end
26
37
 
27
- def self.single(str, char, tag)
28
- cdata = /((?<cdata>[^$ \[\*][^ ]*))/
29
- sigil = Regexp.escape(char)
30
- rx = make_regex(sigil, cdata)
31
- str = iterate(str, rx, tag)
32
- str
33
- end
38
+ def grab(n=1)
39
+ char = @str.slice!(0..(n-1)) # grab n chars
40
+ char
41
+ end
42
+
43
+ def grab_terminator
44
+ @state = :LOOPING
45
+ # goes onto buffer by default
46
+ # Don't? what if searching for space_marker?
47
+ # @buffer << grab
48
+ end
49
+
50
+ def eol?
51
+ @str.empty?
52
+ end
53
+
54
+ def space?
55
+ front == " "
56
+ end
57
+
58
+ def escape?
59
+ front == "\\"
60
+ end
61
+
62
+ def terminated?
63
+ space? # Will be overridden except in Single
64
+ end
65
+
66
+ def marker?
67
+ @str.start_with?(@marker)
68
+ end
69
+
70
+ def space_marker?
71
+ @str.start_with?(" " + @marker)
72
+ end
34
73
 
35
- def self.bracket(str, char, tag)
36
- cdata = /(?<cdata>[^\]]*)\]/
37
- stop = /(?<stop> |$)/
38
- sigil = Regexp.escape(char + "[")
39
- rx = make_regex(sigil, cdata, stop)
40
- str = iterate(str, rx, tag)
41
- str
74
+ def wrap(text)
75
+ if text.empty?
76
+ result = @marker
77
+ result = "" if @marker[1] == "["
78
+ return result
79
+ end
80
+ "<#{@tag}>#{text}</#{@tag}>"
81
+ end
82
+
83
+ def initial
84
+ n = @marker.length
85
+ case
86
+ when escape?
87
+ grab # backslash
88
+ @buffer << grab # char
89
+ when space_marker?
90
+ @buffer << grab # append the space
91
+ grab(n) # eat the marker
92
+ @state = :CDATA
93
+ when marker?
94
+ grab(n) # Eat the marker
95
+ @state = :CDATA
96
+ when eol?
97
+ @state = :FINAL
98
+ else
99
+ @state = :BUFFER
100
+ end
101
+ end
102
+
103
+ def buffer
104
+ @buffer << grab
105
+ @state = :LOOPING
106
+ end
107
+
108
+ def cdata
109
+ case
110
+ when eol?
111
+ if @cdata.empty?
112
+ @buffer << @marker unless @marker[1] == "["
113
+ else
114
+ @buffer << wrap(@cdata)
115
+ end
116
+ @state = :FINAL
117
+ when terminated?
118
+ @buffer << wrap(@cdata)
119
+ grab_terminator # "*a *b" case???
120
+ @cdata = ""
121
+ @state = :LOOPING
122
+ else
123
+ @cdata << grab
124
+ @state = :CDATA
125
+ end
126
+ end
127
+
128
+ def looping
129
+ n = @marker.length
130
+ case
131
+ when escape?
132
+ grab # backslash
133
+ @buffer << grab # char
134
+ when space_marker?
135
+ @buffer << grab # append the space
136
+ grab(n) # eat the marker
137
+ @state = :CDATA
138
+ when eol?
139
+ @state = :FINAL
140
+ else # includes marker not preceded by space!
141
+ @buffer << grab
142
+ end
143
+ end
144
+
145
+ def handle
146
+ loop do
147
+ break if @state == :FINAL
148
+ meth = @state.downcase
149
+ send(meth)
150
+ end
151
+ return @buffer
152
+ end
153
+
154
+ def self.process(str)
155
+ bold = self.new(str, "*", "b")
156
+ sb = bold.handle
157
+ # return sb
158
+ ital = self.new(sb, "_", "i")
159
+ si = ital.handle
160
+ code = self.new(si, "`", "tt")
161
+ sc = code.handle
162
+ stri = self.new(sc, "~", "strike")
163
+ si = stri.handle
164
+ si
165
+ end
42
166
  end
43
167
 
44
- def self.make_string(str, rx, tag)
45
- md = rx.match(str)
46
- return [str, false] if md.nil?
47
- start, cdata, stop = md.values_at(:start, :cdata, :stop)
48
- str = str.sub(rx, start + "<#{tag}>" + cdata + "<\/#{tag}>" + stop)
49
- [str, true]
168
+ class Single < Delimited
169
+ # Yeah, this one is that simple
50
170
  end
51
-
52
- def self.handle(str, char, tag)
53
- s2 = double(str, char, tag) # in this order...
54
- s2 = single(s2, char, tag)
55
- s2 = bracket(s2, char, tag)
56
- s2
171
+
172
+ class Double < Delimited
173
+ def initialize(str, sigil, tag)
174
+ super
175
+ # Convention: marker is "**", sigil is "*"
176
+ @marker = sigil + sigil
177
+ end
178
+
179
+ def terminated?
180
+ terms = [" ", ".", ","]
181
+ terms.include?(front)
182
+ end
57
183
  end
58
184
 
59
- def self.format(str)
60
- s2 = str.chomp
61
- s2 = handle(s2, "*", "b")
62
- s2 = handle(s2, "_", "i")
63
- s2 = handle(s2, "`", "tt")
64
- s2 = handle(s2, "~", "strike")
65
- s2
185
+ class Bracketed < Delimited
186
+ def initialize(str, sigil, tag)
187
+ super
188
+ # Convention: marker is "*[", sigil is "*"
189
+ @marker = sigil + "["
190
+ end
191
+
192
+ def terminated?
193
+ front == "]" || eol?
194
+ end
195
+
196
+ def grab_terminator
197
+ @state = :LOOPING
198
+ grab
199
+ end
66
200
  end
67
- end
68
201
 
69
- if $0 == __FILE__
70
- # str = "**bold up front... This is **bold, __italic, and ``code."
71
- str = "*bold and *bold and **more, and even *[more boldface] and *[still more] "
72
- max = str.length
73
- # str = "*bold "
74
- s2 = Formatter.format(str)
75
- printf "%-#{max}s => %-#{max}s\n", str.inspect, s2.inspect
76
- exit
77
-
78
- strings = ["*bold",
79
- " *bold",
80
- " *bold ",
81
- "**bold.",
82
- "**bold,",
83
- "**bold",
84
- " **bold.",
85
- " **bold,",
86
- " **bold",
87
- " **bold. ",
88
- " **bold, ",
89
- " **bold ",
90
- "*[fiat lux]",
91
- " *[fiat lux]",
92
- " *[fiat lux] ",
93
- " *[fiat lux"
94
- ]
95
-
96
- max = strings.max_by {|s| s.length }
97
- max = max.length + 2
98
-
99
- strings.each do |str|
100
- s2 = Formatter.format(str)
101
- printf "%-#{max}s => %-#{max}s\n", str.inspect, s2.inspect
102
202
  end
103
203
 
104
- end
@@ -10,6 +10,8 @@ module Livetext::Helpers
10
10
  ESCAPING = { "'" => '&#39;', '&' => '&amp;', '"' => '&quot;',
11
11
  '<' => '&lt;', '>' => '&gt;' }
12
12
 
13
+ TTY = ::File.open("/dev/tty", "w")
14
+
13
15
  def friendly_error(err)
14
16
  return graceful_error(err) if self.respond_to?(:graceful_error)
15
17
  return self.parent.graceful_error(err) if self.respond_to?(:parent)
@@ -56,10 +58,8 @@ module Livetext::Helpers
56
58
  base = "#{name}#{ext}"
57
59
  paths.each do |path|
58
60
  file = path + base
59
- # ::Livetext::TTY.puts " Checking: #{file}"
60
61
  return file if File.exist?(file)
61
62
  end
62
- # ::Livetext::TTY.puts " ...oops"
63
63
  return nil
64
64
  end
65
65
 
@@ -100,14 +100,14 @@ module Livetext::Helpers
100
100
  when DotCmd
101
101
  success = handle_dotcmd(line)
102
102
  when DollarDot
103
- success = handle_dollar_dot
103
+ success = handle_dollar_dot(line)
104
104
  else
105
105
  api.passthru(line) # must succeed?
106
106
  end
107
107
  success
108
108
  end
109
109
 
110
- def handle_dollar_dot
110
+ def handle_dollar_dot(line)
111
111
  indent = line.index("$") + 1
112
112
  @indentation.push(indent)
113
113
  line.sub!(/^ *\$/, "")
@@ -116,25 +116,26 @@ module Livetext::Helpers
116
116
  success
117
117
  end
118
118
 
119
- def invoke_dotcmd(name, *args)
120
- # FIXME Add cmdargs stuff... depends on name, etc.
121
- retval = @main.send(name, *args)
119
+ def invoke_dotcmd(name, data0="")
120
+ api.data = data0.dup # should permit _ in function names at least
121
+ args0 = data0.split
122
+ api.args = args0.dup
123
+ retval = @main.send(name) # , *args)
122
124
  retval
123
125
  rescue => err
124
126
  graceful_error(err)
125
127
  end
126
128
 
127
129
  def handle_dotcmd(line, indent = 0)
128
- # FIXME api.data is broken
129
130
  indent = @indentation.last # top of stack
130
131
  line = line.sub(/# .*$/, "") # FIXME Could be problematic?
131
- name = get_name(line)
132
+ name, data = get_name_data(line)
132
133
  success = true # Be optimistic... :P
133
134
  case
134
135
  when name == :end # special case
135
136
  graceful_error EndWithoutOpening()
136
137
  when @main.respond_to?(name)
137
- success = invoke_dotcmd(name)
138
+ success = invoke_dotcmd(name, data)
138
139
  else
139
140
  graceful_error UnknownMethod(name)
140
141
  end
@@ -145,14 +146,20 @@ module Livetext::Helpers
145
146
  return true
146
147
  end
147
148
 
148
- def get_name(line)
149
- name, data = line.split(" ", 2)
150
- name = name[1..-1] # chop off sigil
149
+ def get_name_data(line)
150
+ line = line.chomp
151
+ blank = line.index(" ")
152
+ if blank
153
+ name = line[1..(blank-1)]
154
+ data0 = line[(blank+1)..-1]
155
+ else
156
+ name = line[1..-1]
157
+ data0 = ""
158
+ end
151
159
  name = "dot_" + name if %w[include def].include?(name)
152
160
  @main.check_disallowed(name)
153
- @main.data = data
154
- @main.api.data = data
155
- name.to_sym
161
+ @main.api.data = data0 # FIXME kill this?
162
+ [name.to_sym, data0]
156
163
  end
157
164
 
158
165
  def check_disallowed(name)
data/lib/livetext/more.rb CHANGED
@@ -7,6 +7,7 @@ class Livetext
7
7
 
8
8
  class Variables
9
9
  attr_reader :vars
10
+
10
11
  def initialize(hash = {})
11
12
  @vars = {}
12
13
  hash.each_pair {|k, v| @vars[k.to_sym] = v }
@@ -34,6 +35,10 @@ class Livetext
34
35
  api.setvar(var, value)
35
36
  end
36
37
  end
38
+
39
+ def to_a
40
+ @vars.to_a
41
+ end
37
42
  end
38
43
 
39
44
  Vars = Variables.new
@@ -59,17 +64,6 @@ class Livetext
59
64
  str3
60
65
  end
61
66
 
62
- def self.customize(mix: [], call: [], vars: {})
63
- obj = self.new
64
- mix = Array(mix)
65
- call = Array(call)
66
- mix.each {|lib| obj.mixin(lib) }
67
- call.each {|cmd| obj.main.send(cmd[1..-1]) } # ignores leading dot, no param
68
- # vars.each_pair {|var, val| obj.setvar(var, val.to_s) }
69
- api.setvars(vars)
70
- obj
71
- end
72
-
73
67
  def peek_nextline
74
68
  @main.peek_nextline # delegate
75
69
  end
@@ -102,6 +96,20 @@ class Livetext
102
96
  raise err
103
97
  end
104
98
 
99
+ def self.customize(mix: [], call: [], vars: {})
100
+ obj = self.new
101
+ mix = Array(mix)
102
+ call = Array(call)
103
+ # STDERR.puts "#{__method__}: obj meth = #{obj.methods.sort.inspect}"
104
+ mix.each do |lib|
105
+ obj.invoke_dotcmd(:mixin, lib.dup)
106
+ end
107
+ call.each {|cmd| obj.main.send(cmd[1..-1]) } # ignores leading dot, no param
108
+ # vars.each_pair {|var, val| obj.setvar(var, val.to_s) }
109
+ obj.api.setvars(vars)
110
+ obj
111
+ end
112
+
105
113
  def customize(mix: [], call: [], vars: {})
106
114
  mix = Array(mix)
107
115
  call = Array(call)