class Riml::Repl

Constants

COMPILE_ON
END_EVAL_RIML_ON
EVAL_RIML_ON
EXIT_ON
HELP_MSG

Attributes

compiler[R]
compiler_options[R]
line[R]
parser[R]

Public Class Methods

new(vi_readline = false, compile_options = {}) click to toggle source
# File lib/riml/repl.rb, line 30
def initialize(vi_readline = false, compile_options = {})
  @indent_amount = 0
  @line = nil
  @compiler_options = DEFAULT_COMPILE_OPTIONS.merge(compile_options)
  @in_eval_heredoc = false
  Riml.config = OpenStruct.new if Riml.config.nil?
  Riml.config.repl = true
  prepare_new_context
  Readline.vi_editing_mode if vi_readline
end

Public Instance Methods

run() click to toggle source
# File lib/riml/repl.rb, line 41
def run
  trap(:INT) { reset!; puts }
  puts HELP_MSG, "\n"
  while @line = Readline.readline(current_indent, true)
    line.strip!
    next if line.empty?
    line_dc = line.downcase
    if @in_eval_heredoc && END_EVAL_RIML_ON.include?(line_dc)
      begin
        riml = compile_unit! # raises errors
        output = eval_riml(riml)
        puts riml
        output = "Blank vim output! Try echoing something." if output.strip.empty?
        puts "\n", "#=>", output
      rescue => e
        handle_compile_error(e)
      end
      reset!
    elsif !@in_eval_heredoc && EVAL_RIML_ON.include?(line_dc)
      reset!
      @in_eval_heredoc = true
    elsif !@in_eval_heredoc && COMPILE_ON.include?(line_dc)
      next if current_compilation_unit.empty?
      compile_and_print_unit
    elsif !@in_eval_heredoc && EXIT_ON.include?(line_dc)
      exit_repl
    else
      current_compilation_unit << line
      check_indents
    end
  end
end

Private Instance Methods

check_indents() click to toggle source
# File lib/riml/repl.rb, line 83
def check_indents
  lexer = Lexer.new(line)
  lexer.ignore_indentation_check = true
  lexer.tokenize
  @indent_amount += lexer.current_indent
rescue => e
  print_error(e)
  reset!
  reload!
end
compile_and_print_unit() click to toggle source

handles and swallows errors

# File lib/riml/repl.rb, line 100
def compile_and_print_unit
  viml = compile_unit!
  puts viml, "\n"
rescue => e
  handle_compile_error(e)
ensure
  reset!
end
compile_unit!() click to toggle source

raises errors

# File lib/riml/repl.rb, line 110
def compile_unit!
  Riml.do_compile(current_compilation_unit.join("\n"), parser, compiler).chomp
end
current_compilation_unit() click to toggle source
# File lib/riml/repl.rb, line 138
def current_compilation_unit
  @current_compilation_unit ||= []
end
current_indent() click to toggle source
# File lib/riml/repl.rb, line 94
def current_indent
  return '' if @indent_amount <= 0
  ' ' * @indent_amount
end
eval_riml(riml) click to toggle source

TODO: Start only 1 vim process and use pipes to save time when using ‘eval <<riml` multiple times in the same repl session.

# File lib/riml/repl.rb, line 116
def eval_riml(riml)
  require 'tempfile' unless defined?(Tempfile)
  infile, outfile = Tempfile.new('riml_in'), Tempfile.new('vim_output')
  riml = Riml::GET_SID_FUNCTION_SRC + "\n#{riml}"
  infile.write("redir! > #{outfile.path}\n#{riml}\nredir END\nq!")
  infile.close
  system(%Q(vim -c "source #{infile.path}"))
  raw = outfile.read.sub(/\A\n/, '')
  # Since we don't show the generated SID function, we have to modify the
  # error line numbers to account for it.
  raw.gsub(/line\s+(\d+):/) do
    "line #{$1.to_i - (Riml::GET_SID_FUNCTION_SRC.each_line.to_a.size + 2)}:"
  end
rescue => e
  print_error(e)
  reload!
  nil
ensure
  infile.close
  outfile.close
end
exit_repl() click to toggle source
# File lib/riml/repl.rb, line 161
def exit_repl
  exit
end
handle_compile_error(e) click to toggle source
# File lib/riml/repl.rb, line 148
def handle_compile_error(e)
  print_error(e)
  reload!
end
prepare_new_context() click to toggle source
# File lib/riml/repl.rb, line 76
def prepare_new_context
  @compiler = Compiler.new
  @compiler.options = compiler_options
  @parser = Parser.new
end
Also aliased as: reload!
print_error(e) click to toggle source
reload!()
Alias for: prepare_new_context
reset!() click to toggle source
# File lib/riml/repl.rb, line 142
def reset!
  @indent_amount = 0
  @in_eval_heredoc = false
  current_compilation_unit.clear
end