Class: Livetext

Inherits:
Object
  • Object
show all
Defined in:
lib/livetext.rb,
lib/livetext.rb,
lib/processor.rb

Defined Under Namespace

Modules: Standard, UserAPI Classes: Functions, Processor

Constant Summary collapse

VERSION =
"0.9.05"
Path =
File.expand_path(File.join(File.dirname(__FILE__)))
Vars =
{}
Space =
" "
Sigil =

Can’t change yet

"."
Comment =
rx(Sigil, Livetext::Space)
Dotcmd =
rx(Sigil)
Ddotcmd =
/^ *\$\.[A-Za-z]/

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(output = ::STDOUT) ⇒ Livetext

Returns a new instance of Livetext.



68
69
70
71
72
73
74
75
76
77
# File 'lib/livetext.rb', line 68

def initialize(output = ::STDOUT)
  @source = nil
  @_mixins = []
  @_outdir = "."
  @no_puts = output.nil?
  @body = ""
  @main = Processor.new(self, output)
  @indentation = [0]
  @_vars = Livetext::Vars
end

Class Attribute Details

.outputObject

both bad solutions?



31
32
33
# File 'lib/livetext.rb', line 31

def output
  @output
end

.parametersObject

from outside world (process_text)



30
31
32
# File 'lib/livetext.rb', line 30

def parameters
  @parameters
end

Instance Attribute Details

#bodyObject

Returns the value of attribute body.



25
26
27
# File 'lib/livetext.rb', line 25

def body
  @body
end

#indentationObject

Returns the value of attribute indentation.



25
26
27
# File 'lib/livetext.rb', line 25

def indentation
  @indentation
end

#mainObject (readonly)

Returns the value of attribute main.



23
24
25
# File 'lib/livetext.rb', line 23

def main
  @main
end

#no_putsObject

Returns the value of attribute no_puts.



24
25
26
# File 'lib/livetext.rb', line 24

def no_puts
  @no_puts
end

Class Method Details

.customize(mix: [], call: [], vars: {}) ⇒ Object



38
39
40
41
42
43
44
45
46
# File 'lib/livetext.rb', line 38

def self.customize(mix: [], call: [], vars: {})
  obj = self.new
  mix  = Array(mix)
  call = Array(call)
  mix.each {|lib| obj.mixin(lib) }
  call.each {|cmd| obj.main.send(cmd[1..-1]) }  # ignores leading dot, no param
  vars.each_pair {|var, val| obj._setvar(var, val.to_s) }
  obj
end

.rx(str, space = nil) ⇒ Object



60
61
62
# File 'lib/livetext.rb', line 60

def self.rx(str, space=nil)
  Regexp.compile("^" + Regexp.escape(str) + "#{space}")
end

Instance Method Details

#_check_name(name) ⇒ Object



203
204
205
206
207
208
# File 'lib/livetext.rb', line 203

def _check_name(name)
  @main._error! "Name '#{name}' is not permitted" if @main._disallowed?(name)
  @main._error! "Mismatched 'end'" if name == "end"
  name = "_" + name if %w[def include].include?(name)
  name
end

#_get_arg(name, args) ⇒ Object

really belongs in livetext



92
93
94
95
96
97
98
99
# File 'lib/livetext.rb', line 92

def _get_arg(name, args)  # really belongs in livetext
  raise "(#{name}) Expected an array" unless args.is_a? Array
  raise "(#{name}) Expected an arg" if args.empty?
  raise "(#{name}) Too many args: #{args.inspect}" if args.size > 1
  val = args[0]
  raise "Expected an argument '#{name}'" if val.nil?
  val
end

#_get_name(line) ⇒ Object



210
211
212
213
214
215
# File 'lib/livetext.rb', line 210

def _get_name(line)
  name, data = line.split(" ", 2)
  name = name[1..-1]  # chop off sigil
  @main.data = data
  name = _check_name(name)
end

#_parse_colon_args(args, hash) ⇒ Object

really belongs in livetext



79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/livetext.rb', line 79

def _parse_colon_args(args, hash)  # really belongs in livetext
  h2 = hash.dup
  e = args.each
  loop do
    arg = e.next.chop.to_sym
    raise "_parse_args: #{arg} is unknown" unless hash.keys.include?(arg)
    h2[arg] = e.next
  end
  h2 = h2.reject {|k,v| v.nil? }
  h2.each_pair {|k, v| raise "#{k} has no value" if v.empty? }
  h2
end

#_setfile(file) ⇒ Object



113
114
115
116
117
# File 'lib/livetext.rb', line 113

def _setfile(file)
  _setvar(:File, file)
  dir = File.dirname(File.expand_path(file))
  _setvar(:FileDir, dir)
end

#_setfile!(file) ⇒ Object



119
120
121
# File 'lib/livetext.rb', line 119

def _setfile!(file)
  _setvar(:File, file)
end

#_setvar(var, val) ⇒ Object



105
106
107
108
109
110
111
# File 'lib/livetext.rb', line 105

def _setvar(var, val)
  str, sym = var.to_s, var.to_sym
  Livetext::Vars[str] = val
  Livetext::Vars[sym] = val
  @_vars[str] = val
  @_vars[sym] = val
end

#customize(mix: [], call: [], vars: {}) ⇒ Object



48
49
50
51
52
53
54
55
# File 'lib/livetext.rb', line 48

def customize(mix: [], call: [], vars: {})
  mix  = Array(mix)
  call = Array(call)
  mix.each {|lib| mixin(lib) }
  call.each {|cmd| @main.send(cmd[1..-1]) }  # ignores leading dot, no param
  vars.each_pair {|var, val| _setvar(var, val.to_s) }
  self
end

#handle_dotcmd(line, indent = 0) ⇒ Object



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/livetext.rb', line 217

def handle_dotcmd(line, indent = 0)
  indent = @indentation.last # top of stack
  line = line.sub(/# .*$/, "")
  name = _get_name(line).to_sym
  result = nil
  if @main.respond_to?(name)
    result = @main.send(name)
  else
    @main._error! "Name '#{name}' is unknown"
    return
  end
  result
rescue => err
  @main._error!(err)
  puts @body
  @body = ""
  return @body
end

#handle_scomment(line) ⇒ Object



200
201
# File 'lib/livetext.rb', line 200

def handle_scomment(line)
end

#mixin(mod) ⇒ Object



101
102
103
# File 'lib/livetext.rb', line 101

def mixin(mod)
  @main._mixin(mod)
end

#process_file(fname, btrace = false) ⇒ Object

FIXME process_file should call process



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/livetext.rb', line 181

def process_file(fname, btrace=false)
  _setfile(fname)
  text = File.readlines(fname)
  enum = text.each
  @backtrace = btrace
  @main.source(enum, fname, 0)
  loop do 
    line = @main.nextline
    break if line.nil?
    process_line(line)
  end
  val = @main.finalize if @main.respond_to? :finalize
  @body
rescue => err
  STDERR.puts "ERROR #{err} in process_file"
  err.backtrace.each {|x| STDERR.puts "   " + x }
  @body = ""
end

#process_line(line) ⇒ Object

FIXME inefficient?



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/livetext.rb', line 123

def process_line(line)  # FIXME inefficient?
  nomarkup = true
  case line  # must apply these in order
    when Comment
      handle_scomment(line)
    when Dotcmd
      handle_dotcmd(line)
    when Ddotcmd
      indent = line.index("$") + 1
      @indentation.push(indent)
      line.sub!(/^ *\$/, "")
      handle_dotcmd(line)
      indentation.pop
  else
    @main._passthru(line)
  end
end

#transform(text) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/livetext.rb', line 141

def transform(text)
  _setfile!("(string)")
  enum = text.each_line
  front = text.match(/.*?\n/).to_a.first.chomp rescue ""
  @main.source(enum, "STDIN: '#{front}...'", 0)
  loop do 
    line = @main.nextline
    break if line.nil?
    process_line(line)
  end
  result = @body
  @body = ""
  result
end

#varsObject



34
35
36
# File 'lib/livetext.rb', line 34

def vars
  Livetext::Vars.dup
end

#xform(*args, file: nil, text: nil, vars: {}) ⇒ Object

EXPERIMENTAL and incomplete



157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/livetext.rb', line 157

def xform(*args, file: nil, text: nil, vars: {})
  case
    when file && text.nil?
      xform_file(file)
    when file.nil? && text
      transform(text)
    when file.nil? && text.nil?
      raise "Must specify file or text"
    when file && text
      raise "Cannot specify file and text"
  end
  self.process_file(file)
  self.body
end

#xform_file(file) ⇒ Object

, vars: {})



172
173
174
175
176
177
# File 'lib/livetext.rb', line 172

def xform_file(file)  # , vars: {})
  Livetext::Vars.replace(vars) unless vars.nil?
  @_vars.replace(vars) unless vars.nil?
  self.process_file(file)
  self.body
end