# Highly inspired by https://github.com/sickill/ascii.io-cli/blob/master/bin/asciiio

require 'pty'

CTRL_C_CODE = ?\C-c

def record(command)
  old_state = `stty -g`

  begin
    # stolen from ruby/ext/pty/script.rb
    # disable echoing and enable raw (not having to press enter)
    system "stty -echo raw lnext ^_"

    f = File.open("test.out", "w")
    f.sync = true

    writer = nil
    PTY.spawn(command) do |r_pty, w_pty, pid|
      reader = Thread.current
      writer = Thread.new do
        while true
          break if (ch = STDIN.getc).nil?
          ch = ch.chr
          if ch == CTRL_C_CODE
            reader.raise Interrupt, "Interrupted by user"
          else
            w_pty.print ch
            w_pty.flush
          end
        end
      end
      writer.abort_on_exception = true

      loop do
        c = begin
              r_pty.sysread(2048)
            rescue Errno::EIO, EOFError
              nil
            end
        break if c.nil?

        f.write c
        STDOUT.print c
        STDOUT.flush
      end

      begin
        # try to invoke waitpid() before the signal handler does it
        Process::waitpid2(pid)
      rescue Errno::ECHILD
        # the signal handler managed to call waitpid() first;
        # PTY::ChildExited will be delivered pretty soon, so just wait for it
        sleep 1
      end
    end
  rescue PTY::ChildExited => e
    # Quit 
  ensure
    writer && writer.kill
    system "stty #{ old_state }"
  end
  f.close
end

# record it
record("/bin/zsh")
# cleanup
puts "\e[H\e[2J"