Module: Everywhere::RawTty

Defined in:
lib/everywhere/raw_tty.rb

Overview

A terminal that reports keys as they're pressed, put back the way it was found on the way out.

io/console's getch holds full raw mode while blocked, which clears OPOST and stair-steps every log line we relay; stty -icanon -echo disables only line buffering and echo, leaving output processing (and Ctrl-C as SIGINT) intact.

Class Method Summary collapse

Class Method Details

.saved_tty_stateObject

The tty settings to put back on the way out, or nil when there's no usable stty to read them with — the one signal both the raw-mode setup and its restore key off.



31
32
33
34
35
36
37
38
# File 'lib/everywhere/raw_tty.rb', line 31

def saved_tty_state
  return nil unless Shellout.tool?("stty")

  state = `stty -g`.chomp
  state.empty? ? nil : state
rescue StandardError
  nil
end

.trap_exit_signalsObject

The dock hides the cursor and the key loop puts the tty in -icanon -echo; a SIGTERM that skipped our ensure blocks would leave the user's shell in that state. exit(1) from a trap unwinds normally, which is all this needs to do — a handler must stay this small, because anything that takes a lock (Console, the dock) raises ThreadError in trap context.



45
46
47
48
49
# File 'lib/everywhere/raw_tty.rb', line 45

def trap_exit_signals
  %w[TERM HUP].each { |sig| Signal.trap(sig) { exit(1) } }
rescue ArgumentError
  nil
end

.withObject



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/everywhere/raw_tty.rb', line 16

def with
  # stty is POSIX-only, and the non-pty spawn path otherwise works on
  # Windows: without it the menu simply stays line-buffered (press d,
  # then Enter) rather than the session dying on Errno::ENOENT.
  saved_tty = saved_tty_state
  system("stty", "-icanon", "-echo") if saved_tty
  trap_exit_signals
  yield
ensure
  system("stty", saved_tty) if saved_tty
end