Skip to content

Instantly share code, notes, and snippets.

@bitboxer
Last active December 17, 2015 17:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bitboxer/5648150 to your computer and use it in GitHub Desktop.
Save bitboxer/5648150 to your computer and use it in GitHub Desktop.
First version of a terminal recorder. Just for the fun of it
# 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"
@bitboxer
Copy link
Author

Current Problems:

  • Vertical separator in tmux does not have "|" and a few other problems
  • First frames of the sl train are corrupted
  • virtual terminal has not the full size

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment