class Guard::Haskell::Repl

Attributes

inferior[R]
listener[R]
status[R]
stdin[R]

Public Class Methods

finished_with(str) click to toggle source
# File lib/guard/haskell/repl.rb, line 12
def self.finished_with(str)
  case str
  when /\d+ examples?, 0 failures/,
       /Ok, modules loaded:/
    :success
  when /\d+ examples?, \d+ failures?/
    :runtime_failure
  when /Failed, modules loaded:/,
       /\*{3} Exception:/,
       /cannot find object file for module/,
       /phase `C pre-processor' failed/,
       /phase `Haskell pre-processor' failed/,
       /phase `Linker' failed/,
       /GHCi runtime linker: fatal error:/,
       /During interactive linking, GHCi couldn't find the following symbol:/,
       /ghc: could not execute:/
    :compile_failure
  end
end
new(cabal_target, repl_options) click to toggle source
# File lib/guard/haskell/repl.rb, line 32
def initialize(cabal_target, repl_options)
  @listening = false
  @status = :success
  raise NoCabalFile if Dir.glob('*.cabal').empty?
  start("cabal", "repl", cabal_target, *repl_options)
end

Public Instance Methods

exit() click to toggle source
# File lib/guard/haskell/repl.rb, line 46
def exit
  stdin.write(":quit\n")
  ::Thread.kill(listener)
end
reload_and_rerun() click to toggle source
# File lib/guard/haskell/repl.rb, line 61
def reload_and_rerun
  if run_command_and_wait_for_result(":reload\n")
    run_command_and_wait_for_result(":main --color --rerun\n")
  end
end
reload_and_run_matching(pattern = nil) click to toggle source
# File lib/guard/haskell/repl.rb, line 51
def reload_and_run_matching(pattern = nil)
  if run_command_and_wait_for_result(":reload\n")
    if pattern.nil?
      run_command_and_wait_for_result(":main --color\n")
    else
      run_command_and_wait_for_result(":main --color --match #{pattern}\n")
    end
  end
end
start(*cmd) click to toggle source
# File lib/guard/haskell/repl.rb, line 39
def start(*cmd)
  @listening = true
  @stdin, stdout, @inferior = ::Open3.popen2e(*cmd)
  @listener = ::Thread.new { listen_or_die(stdout, STDOUT) }
  wait_for_result
end

Private Instance Methods

listen(in_stream, out_stream) click to toggle source
# File lib/guard/haskell/repl.rb, line 84
def listen(in_stream, out_stream)
  while (line = in_stream.gets)
    out_stream.print(line)
    if @listening
      res = self.class.finished_with(line)
      case res
      when :success, :runtime_failure, :compile_failure
        # A horrible hack to show the cursor again
        #
        # The problem is that '\e[?25h' code from hspec is waiting on
        # the next line, which we probably will never read :-(
        out_stream.print("\e[?25h")
        stop(res)
      end
    end
  end
end
listen_or_die(in_stream, out_stream) click to toggle source
# File lib/guard/haskell/repl.rb, line 79
def listen_or_die(in_stream, out_stream)
  listen(in_stream, out_stream) # should never return
  stop(:loading_failure)
end
run_command_and_wait_for_result(command) click to toggle source
# File lib/guard/haskell/repl.rb, line 68
def run_command_and_wait_for_result(command)
  @listening = true
  stdin.write(command)
  wait_for_result == :success
end
stop(status) click to toggle source
# File lib/guard/haskell/repl.rb, line 102
def stop(status)
  @status = status
  @listening = false
end
wait_for_result() click to toggle source
# File lib/guard/haskell/repl.rb, line 74
def wait_for_result
  while @listening do sleep(0.01) end
  @status
end