Class: Termcontroller::Controller

Inherits:
Object
  • Object
show all
Defined in:
lib/termcontroller/controller.rb

Constant Summary collapse

@@controllers =
[]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target = nil, keybindings = {}) ⇒ Controller

Returns a new instance of Controller.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/termcontroller/controller.rb', line 43

def initialize(target=nil, keybindings={})
  @m = Mutex.new

  @target = target
  @target_stack = []

  @keybindings = keybindings
  @buf = ""
  @commands = Queue.new
  @mode = :cooked

  @kb = KeyboardMap.new
  @con = IO.console
  raise if !@con

  at_exit { quit }
  trap("CONT")  { resume }
  trap("WINCH") { @commands << :resize }

  setup

  @t = Thread.new { readloop }

  @@controllers << @t

end

Instance Attribute Details

#commandsObject (readonly)

Returns the value of attribute commands.



41
42
43
# File 'lib/termcontroller/controller.rb', line 41

def commands
  @commands
end

#lastcmdObject (readonly)

Returns the value of attribute lastcmd.



41
42
43
# File 'lib/termcontroller/controller.rb', line 41

def lastcmd
  @lastcmd
end

Instance Method Details

#handle_inputObject



119
120
121
122
123
124
# File 'lib/termcontroller/controller.rb', line 119

def handle_input
  if c = @commands.pop
    do_command(c)
  end
  return Array(c)
end

#hide_cursorObject



149
150
151
# File 'lib/termcontroller/controller.rb', line 149

def hide_cursor
  STDOUT.print "\e[?25l"   # Hide cursor
end

#pauseObject

Pause processing so you can read directly from stdin yourself. E.g. to use Readline, or to suspend



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/termcontroller/controller.rb', line 88

def pause
  @m.synchronize do
    old = @mode
    begin
      @mode = :pause
      IO.console.cooked!
      cleanup
      r = yield
      r
    rescue Interrupt
    ensure
      @mode = old
      setup
    end
  end
end

#paused?Boolean

Returns:

  • (Boolean)


70
# File 'lib/termcontroller/controller.rb', line 70

def paused?; @mode == :pause; end

#pop_targetObject



77
78
79
80
81
# File 'lib/termcontroller/controller.rb', line 77

def pop_target
  t = @target
  @target = @target_stack.pop
  t
end

#push_target(t) ⇒ Object



72
73
74
75
# File 'lib/termcontroller/controller.rb', line 72

def push_target(t)
  @target_stack << @target
  @target = t
end

#rawObject

FIXME: The first event after the yield appears to fail to pass the mapping. Maybe move the mapping to the client thread?



108
109
110
111
112
113
114
115
116
117
# File 'lib/termcontroller/controller.rb', line 108

def raw
  keybindings = @keybindings
  @keybindings = {}
  push_target(nil)
  yield
rescue Interrupt
ensure
  @keybindings = keybindings
  pop_target
end

#resumeObject



143
144
145
146
147
# File 'lib/termcontroller/controller.rb', line 143

def resume
  @mode = :cooked
  setup
  @commands << [:resume]
end

#show_cursorObject



153
154
155
# File 'lib/termcontroller/controller.rb', line 153

def show_cursor
  STDOUT.print "\e[?25h"   # Show cursor
end

#suspendObject

USE WITH CAUTION. This will pause processing, yield to the provided block if any, and then send SIGSTOP to the process.

This is meant to allow for handling ctrl-z to suspend in processes that need to be able to reset the terminal to a better state before stopping.

FIXME: It seems like it does not work as expected.



136
137
138
139
140
141
# File 'lib/termcontroller/controller.rb', line 136

def suspend
  pause do
    yield if block_given?
    Process.kill("STOP", 0)
  end
end