Module: Livetext::Helpers

Included in:
Livetext, Livetext::Handler::Import, Livetext::Handler::Mixin, Standard
Defined in:
lib/livetext/helpers.rb

Constant Summary collapse

Space =
" "
Sigil =

Can’t change yet

"."
ESCAPING =
{ "'" => ''', '&' => '&', '"' => '"',
'<' => '&lt;', '>' => '&gt;' }
TTY =
::File.open("/dev/tty", "w")
Comment =
rx(Sigil, Space)
DotCmd =
rx(Sigil)
DollarDot =
/^ *\$\.[A-Za-z]/

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.rx(str, space = nil) ⇒ Object



67
68
69
# File 'lib/livetext/helpers.rb', line 67

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

Instance Method Details

#check_disallowed(name) ⇒ Object



172
173
174
# File 'lib/livetext/helpers.rb', line 172

def check_disallowed(name)
  friendly_error DisallowedName(name) if disallowed?(name)
end

#check_file_exists(file) ⇒ Object



176
177
178
# File 'lib/livetext/helpers.rb', line 176

def check_file_exists(file)
  return File.exist?(file)
end

#debug(*args) ⇒ Object



51
52
53
# File 'lib/livetext/helpers.rb', line 51

def debug(*args)
  puts(*args) if ENV['debug']
end

#escape_html(string) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/livetext/helpers.rb', line 24

def escape_html(string)
  enc = string.encoding
  unless enc.ascii_compatible?
    if enc.dummy?
      origenc = enc
      enc = Encoding::Converter.asciicompat_encoding(enc)
      string = enc ? string.encode(enc) : string.b
    end
    table = Hash[ESCAPING.map {|pair|pair.map {|s|s.encode(enc)}}]
    string = string.gsub(/#{"['&\"<>]".encode(enc)}/, table)
    string.encode!(origenc) if origenc
    return string
  end
  string.gsub(/['&\"<>]/, ESCAPING)
end

#find_file(name, ext = ".rb", which = "imports") ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
# File 'lib/livetext/helpers.rb', line 55

def find_file(name, ext=".rb", which="imports")
  failed = "#{__method__}: expected 'imports' or 'plugin'"
  raise failed unless %w[imports plugin].include?(which)
  paths = [Livetext::Path.sub(/lib.livetext/, "#{which}/"), "./"]
  base  = "#{name}#{ext}"
  paths.each do |path|
    file = path + base
    return file if File.exist?(file)
  end
  return nil
end

#friendly_error(err) ⇒ Object



16
17
18
19
20
21
22
# File 'lib/livetext/helpers.rb', line 16

def friendly_error(err)
  return graceful_error(err) if self.respond_to?(:graceful_error)
  return self.parent.graceful_error(err) if self.respond_to?(:parent)
  raise err
#  rescue => myerr
#    TTY.puts "--- Warning: friendly_error #{myerr.inspect}"
end

#get_name_data(line) ⇒ Object



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

def get_name_data(line)
  line = line.chomp
  blank = line.index(" ")
  if blank
    name = line[1..(blank-1)]
    data0 = line[(blank+1)..-1]
  else
    name = line[1..-1]
    data0 = ""
  end
  name = "dot_" + name if %w[include def].include?(name)
  @main.check_disallowed(name)
  @main.api.data = data0  # FIXME kill this?
  [name.to_sym, data0]
end

#grab_file(fname) ⇒ Object



189
190
191
192
193
194
195
# File 'lib/livetext/helpers.rb', line 189

def grab_file(fname)
  File.read(fname)
rescue
  graceful_error NoSuchFile(fname)
  # ::STDERR.puts "Can't find #{fname.inspect} \n "
 # return nil
end

#graceful_error(err, msg = nil) ⇒ Object

def dump(file = nil) # not a dot command!

  file ||= ::STDOUT
  TTY.puts "--- Writing body (#{@body.size} bytes)" if @body
  file.puts @body
rescue => err
  TTY.puts "#dump had an error: #{err.inspect}"
end


269
270
271
272
273
# File 'lib/livetext/helpers.rb', line 269

def graceful_error(err, msg = nil)
  api.dump
  STDERR.puts msg if msg
  raise err
end

#handle_dollar_dot(line) ⇒ Object



117
118
119
120
121
122
123
124
# File 'lib/livetext/helpers.rb', line 117

def handle_dollar_dot(line)
  indent = line.index("$") + 1
  @indentation.push(indent)
  line.sub!(/^ *\$/, "")
  success = handle_dotcmd(line)
  indentation.pop
  success
end

#handle_dotcmd(line, indent = 0) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/livetext/helpers.rb', line 136

def handle_dotcmd(line, indent = 0)
  indent = @indentation.last # top of stack
  line = line.sub(/# .*$/, "")   # FIXME Could be problematic?
  name, data = get_name_data(line)
  success = true  # Be optimistic...  :P
  case
    when name == :end   # special case
      graceful_error EndWithoutOpening()
    when @main.respond_to?(name)
      success = invoke_dotcmd(name, data)    # was 141
  else
    graceful_error UnknownMethod(name)
  end
  success
end

#handle_scomment(line) ⇒ Object



152
153
154
# File 'lib/livetext/helpers.rb', line 152

def handle_scomment(line)
  return true
end

#include_file(file) ⇒ Object



218
219
220
221
222
# File 'lib/livetext/helpers.rb', line 218

def include_file(file)
  api.data = file
  api.args = [file]
  dot_include
end

#invoke_dotcmd(name, data0 = "") ⇒ Object



126
127
128
129
130
131
132
133
134
# File 'lib/livetext/helpers.rb', line 126

def invoke_dotcmd(name, data0="")
  api.data = data0.dup   # should permit _ in function names at least
  args0 = data0.split
  api.args = args0.dup
  retval = @main.send(name)  # , *args)      # was 125
  retval
rescue => err
  graceful_error(err)   # , "#{__method__}: name = #{name}")
end

#onoff(arg) ⇒ Object

helper

Raises:

  • (ExpectedOnOff)


224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/livetext/helpers.rb', line 224

def onoff(arg)   # helper
  arg ||= "on"
  raise ExpectedOnOff unless String === arg
  case arg.downcase
    when "on"
      return true
    when "off"
      return false
  else
    raise ExpectedOnOff
  end
end

#process_file(fname, btrace = false) ⇒ Object

FIXME process_file should call process ?



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/livetext/helpers.rb', line 77

def process_file(fname, btrace=false)
  unless File.exist?(fname)
    api.dump
    raise FileNotFound(fname) 
  end
  setfile(fname)
  text = File.readlines(fname)
  enum = text.each
  @backtrace = btrace
  @main.source(enum, fname, 0)
  line = nil
  loop do
    line = @main.nextline
    break if line.nil?
    success = process_line(line)
    break unless success
  end
  val = @main.finalize rescue nil
  @body    # FIXME?   @body.join("\n")  # array
  return true
end

#process_line(line) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/livetext/helpers.rb', line 99

def process_line(line)
  success = true
  case line  # must apply these in order
  when Comment
    success = handle_scomment(line)
  when DotCmd
    success = handle_dotcmd(line)       # was 102
  when DollarDot
    success = handle_dollar_dot(line)
  else
    api.passthru(line)  # must succeed?
  end
  success
rescue => err
  STDERR.puts "ERROR: #{err.inspect}\n#{err.backtrace.join("\n")}"
  exit
end

#read_variables(file) ⇒ Object



180
181
182
183
# File 'lib/livetext/helpers.rb', line 180

def read_variables(file)
  pairs = File.readlines(file).map {|x| x.chomp.split }
  @api.setvars(pairs)
end

#search_upward(file) ⇒ Object



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/livetext/helpers.rb', line 197

def search_upward(file)
  value = nil
  return file if File.exist?(file)

  count = 1
  loop do
    front = "../" * count
    count += 1
    here = Pathname.new(front).expand_path.dirname.to_s
    break if here == "/"
    path = front + file
    value = path if File.exist?(path)
    break if value
  end
  ::STDERR.puts "Cannot find #{file.inspect} from #{Dir.pwd}" unless value
 return value
rescue
  ::STDERR.puts "Can't find #{file.inspect} from #{Dir.pwd}"
 return nil
end

#set_variables(pairs) ⇒ Object



185
186
187
# File 'lib/livetext/helpers.rb', line 185

def set_variables(pairs)
  @api.setvars(pairs)
end

#setfile(file) ⇒ Object



246
247
248
249
250
251
252
253
254
255
# File 'lib/livetext/helpers.rb', line 246

def setfile(file)
  if file
    api.setvar(:File, file)
    dir = File.dirname(File.expand_path(file))
    api.setvar(:FileDir, dir)
  else
    api.setvar(:File,    "[no file]")
    api.setvar(:FileDir, "[no dir]")
  end
end

#setfile!(file) ⇒ Object

FIXME why does this variant exist?



257
258
259
# File 'lib/livetext/helpers.rb', line 257

def setfile!(file)  # FIXME why does this variant exist?
  api.setvar(:File, file)
end

#setvar(var, val) ⇒ Object



237
238
239
240
241
242
243
244
# File 'lib/livetext/helpers.rb', line 237

def setvar(var, val)
  api.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

#showme(obj, tag = "") ⇒ Object



40
41
42
43
44
45
46
47
48
49
# File 'lib/livetext/helpers.rb', line 40

def showme(obj, tag = "")
  whence = caller[0]
  file, line, meth = whence.split(":")
  file = File.basename(file)
  meth = meth[4..-2]
  tag << " =" if tag
  hide_class = [true, false, nil].include?(obj)
  klass = hide_class ? "" : "(#{obj.class}) "
  puts " #{tag} #{klass}#{obj.inspect}  in ##{meth}  [#{file} line #{line}]"
end