123456789_123456789_123456789_123456789_123456789_

Class: RubyInstaller::Runtime::ConsoleUi

Relationships & Source Files
Namespace Children
Classes:
Inherits: Object
Defined in: lib/ruby_installer/runtime/console_ui.rb

Constant Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.newConsoleUi

[ GitHub ]

  
# File 'lib/ruby_installer/runtime/console_ui.rb', line 175

def initialize
  @GetStdHandle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L')
  @GetConsoleMode = Win32API.new('kernel32', 'GetConsoleMode', ['L', 'P'], 'L')
  @SetConsoleMode = Win32API.new('kernel32', 'SetConsoleMode', ['L', 'L'], 'L')

  @ev_r, @ev_w = IO.pipe.map(&:binmode)

  set_consolemode

  register_term_size_change
  register_stdin

  at_exit do
    unset_consolemode
  end
end

Instance Attribute Details

#widget (rw)

[ GitHub ]

  
# File 'lib/ruby_installer/runtime/console_ui.rb', line 173

attr_accessor :widget

Instance Method Details

#call_with_console_handle(win32func, *args) (private)

Calling Win32API with console handle is reported to fail after executing some external command. We need to refresh console handle and retry the call again.

[ GitHub ]

  
# File 'lib/ruby_installer/runtime/console_ui.rb', line 214

private def call_with_console_handle(win32func, *args)
  val = win32func.call(@hConsoleHandle, *args)
  return val if val != 0

  @hConsoleHandle = @GetStdHandle.call(STD_INPUT_HANDLE)
  win32func.call(@hConsoleHandle, *args)
end

#getconsolemode (private)

[ GitHub ]

  
# File 'lib/ruby_installer/runtime/console_ui.rb', line 222

private def getconsolemode
  mode = +"\0\0\0\0"
  call_with_console_handle(@GetConsoleMode, mode)
  mode.unpack1('L')
end

#handle_key_input(str) (private)

[ GitHub ]

  
# File 'lib/ruby_installer/runtime/console_ui.rb', line 271

private def handle_key_input(str)
  case str
  when "\e[D", "\xE0K".b # cursor left
    widget.cursor(:left)
  when "\e[A", "\xE0H".b # cursor up
    widget.cursor(:up)
  when "\e[C", "\xE0M".b # cursor right
    widget.cursor(:right)
  when "\e[B", "\xE0P".b # cursor down
    widget.cursor(:down)
  when "\r" # enter
    unset_consolemode do
      widget.select
    end
  when /\e\x5b<0;(\d+);(\d+)m/ # Mouse left button up
    if widget.click($1.to_i - 1, $2.to_i - 2)
      widget.repaint
      unset_consolemode do
        widget.select
      end
    end
  end
  widget.repaint
end

#main_loop (private)

[ GitHub ]

  
# File 'lib/ruby_installer/runtime/console_ui.rb', line 296

private def main_loop
  str = +""
  while char=@ev_r.read(1)
    case char
    when "\x01"
      widget.repaint
    when "\x02"
      strlen = @ev_r.read(1).unpack1("C")
      str = @ev_r.read(strlen)

      handle_key_input(str)
      widget.repaint
    else
      raise "unexpected event: #{char.inspect}"
    end
  end
end

#register_stdin (private)

[ GitHub ]

  
# File 'lib/ruby_installer/runtime/console_ui.rb', line 253

private def register_stdin
  Thread.new do
    str = +""
    c = IO.console
    while char=c.read(1)
      str << char
      next if !str.valid_encoding? ||
          str == "\e" ||
          str == "\e[" ||
          str == "\xE0" ||
          str.match(/\A\e\x5b<[^Mm]*\z/)

      @ev_w.write [2, str.size, str].pack("CCa*")
      str = +""
    end
  end
end

#register_term_size_change (private)

[ GitHub ]

  
# File 'lib/ruby_installer/runtime/console_ui.rb', line 232

private def register_term_size_change
  if RUBY_PLATFORM =~ /mingw|mswin/
    con = IO.console
    old_size = con.winsize
    Thread.new do
      loop do
        new_size = con.winsize
        if old_size != new_size
          old_size = new_size
          @ev_w.write "\x01"
        end
        sleep 1
      end
    end
  else
    Signal.trap('SIGWINCH') do
      @ev_w.write "\x01"
    end
  end
end

#run!

[ GitHub ]

  
# File 'lib/ruby_installer/runtime/console_ui.rb', line 314

def run!
  widget.repaint
  main_loop
end

#set_consolemode

[ GitHub ]

  
# File 'lib/ruby_installer/runtime/console_ui.rb', line 192

def set_consolemode
  @hConsoleHandle = @GetStdHandle.call(STD_INPUT_HANDLE)
  @base_console_input_mode = getconsolemode
  setconsolemode(ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS | ENABLE_VIRTUAL_TERMINAL_INPUT)
end

#setconsolemode(mode) (private)

[ GitHub ]

  
# File 'lib/ruby_installer/runtime/console_ui.rb', line 228

private def setconsolemode(mode)
  call_with_console_handle(@SetConsoleMode, mode)
end

#unset_consolemode

[ GitHub ]

  
# File 'lib/ruby_installer/runtime/console_ui.rb', line 198

def unset_consolemode
  if @base_console_input_mode
    setconsolemode(@base_console_input_mode | ENABLE_EXTENDED_FLAGS)
    @base_console_input_mode = nil
    if block_given?
      begin
        yield
      ensure
        set_consolemode
      end
    end
  end
end