Class: RubyInstaller::Runtime::ConsoleUi
| Relationships & Source Files | |
| Namespace Children | |
|
Classes:
| |
| Inherits: | Object |
| Defined in: | lib/ruby_installer/runtime/console_ui.rb |
Constant Summary
-
ENABLE_EXTENDED_FLAGS =
# File 'lib/ruby_installer/runtime/console_ui.rb', line 1770x0080 -
ENABLE_MOUSE_INPUT =
# File 'lib/ruby_installer/runtime/console_ui.rb', line 1750x0010 -
ENABLE_PROCESSED_INPUT =
# File 'lib/ruby_installer/runtime/console_ui.rb', line 1740x0001 -
ENABLE_QUICK_EDIT_MODE =
# File 'lib/ruby_installer/runtime/console_ui.rb', line 1760x0040 -
ENABLE_VIRTUAL_TERMINAL_INPUT =
# File 'lib/ruby_installer/runtime/console_ui.rb', line 1780x200 -
KEY_EVENT =
# File 'lib/ruby_installer/runtime/console_ui.rb', line 1790x01 -
MOUSE_EVENT =
# File 'lib/ruby_installer/runtime/console_ui.rb', line 1800x02 -
STD_INPUT_HANDLE =
# File 'lib/ruby_installer/runtime/console_ui.rb', line 172-10
-
STD_OUTPUT_HANDLE =
# File 'lib/ruby_installer/runtime/console_ui.rb', line 173-11
-
WINDOW_BUFFER_SIZE_EVENT =
# File 'lib/ruby_installer/runtime/console_ui.rb', line 1810x04
Class Method Summary
- .new ⇒ ConsoleUi constructor
Instance Attribute Summary
- #widget rw
- #windows_terminal? ⇒ Boolean readonly private
- #winsize_changed? ⇒ Boolean readonly private
Instance Method Summary
- #clear_screen
- #get_console_screen_buffer_info
- #read_input_event
- #run!
- #set_consolemode
- #unset_consolemode
-
#call_with_console_handle(win32func, *args)
private
Calling Win32API with console handle is reported to fail after executing some external command.
- #getconsolemode private
- #handle_key_input(str) private
- #main_loop private
- #setconsolemode(mode) private
Constructor Details
.new ⇒ ConsoleUi
# File 'lib/ruby_installer/runtime/console_ui.rb', line 185
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') @ReadConsoleInputW = Win32API.new('kernel32', 'ReadConsoleInputW', ['L', 'P', 'L', 'P'], 'L') @GetConsoleScreenBufferInfo = Win32API.new('kernel32', 'GetConsoleScreenBufferInfo', ['L', 'P'], 'L') @hConsoleHandle = @GetStdHandle.call(STD_INPUT_HANDLE) @hConsoleOutHandle = @GetStdHandle.call(STD_OUTPUT_HANDLE) @mouse_state = 0 @old_winsize = IO.console.winsize set_consolemode at_exit do unset_consolemode end end
Instance Attribute Details
#widget (rw)
[ GitHub ]# File 'lib/ruby_installer/runtime/console_ui.rb', line 183
attr_accessor :
#windows_terminal? ⇒ Boolean (readonly, private)
[ GitHub ]
# File 'lib/ruby_installer/runtime/console_ui.rb', line 329
private def windows_terminal? !!ENV["WT_SESSION"] end
#winsize_changed? ⇒ Boolean (readonly, private)
[ GitHub ]
# File 'lib/ruby_installer/runtime/console_ui.rb', line 269
private def winsize_changed? con = IO.console new_size = con.winsize if @old_winsize != new_size @old_winsize = new_size true else false end end
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.
# File 'lib/ruby_installer/runtime/console_ui.rb', line 229
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
#clear_screen
[ GitHub ]# File 'lib/ruby_installer/runtime/console_ui.rb', line 204
def clear_screen IO.console.write "\e[H" "\e[2J" end
#get_console_screen_buffer_info
[ GitHub ]# File 'lib/ruby_installer/runtime/console_ui.rb', line 247
def get_console_screen_buffer_info # CONSOLE_SCREEN_BUFFER_INFO # [ 0,2] dwSize.X # [ 2,2] dwSize.Y # [ 4,2] dwCursorPositions.X # [ 6,2] dwCursorPositions.Y # [ 8,2] wAttributes # [10,2] srWindow.Left # [12,2] srWindow.Top # [14,2] srWindow.Right # [16,2] srWindow.Bottom # [18,2] dwMaximumWindowSize.X # [20,2] dwMaximumWindowSize.Y csbi = 0.chr * 22 if @GetConsoleScreenBufferInfo.call(@hConsoleOutHandle, csbi) != 0 # returns [width, height, x, y, attributes, left, top, right, bottom] csbi.unpack("s9") else return nil end end
#getconsolemode (private)
[ GitHub ]# File 'lib/ruby_installer/runtime/console_ui.rb', line 237
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 333
private def handle_key_input(str) case str when "\e[D", "\xE0K".b # cursor left .cursor(:left) when "\e[A", "\xE0H".b # cursor up .cursor(:up) when "\e[C", "\xE0M".b # cursor right .cursor(:right) when "\e[B", "\xE0P".b # cursor down .cursor(:down) when "\r" # enter unset_consolemode do .select end when /\A\e\x5b<0;(\d+);(\d+)m\z/ # Mouse left button up if .click($1.to_i - 1, $2.to_i - 2) .repaint unset_consolemode do .select end end when /\A\e\x5b<\d+;(\d+);(\d+)[Mm]\z/ # other mouse events return # no repaint end .repaint end
#main_loop (private)
[ GitHub ]# File 'lib/ruby_installer/runtime/console_ui.rb', line 360
private def main_loop str = +"" console_buffer = StringIO.new loop do if windows_terminal? c = IO.console rs, = IO.select([c], [], [], 0.5) if rs char = c.read(1) break unless char else # timeout -> check windows size change .repaint if winsize_changed? end else if console_buffer.eof? input = read_input_event if input == :winsize_changed .repaint if winsize_changed? elsif input console_buffer = StringIO.new(input) end end char = console_buffer.read(1) end next unless char str << char next if !str.valid_encoding? || str == "\e" || str == "\e[" || str == "\xE0" || str.match(/\A\e\x5b<[0-9;]*\z/) handle_key_input(str) str = +"" end end
#read_input_event
[ GitHub ]# File 'lib/ruby_installer/runtime/console_ui.rb', line 280
def read_input_event # Wait for reception of at least one event input_records = 0.chr * 20 * 1 read_event = 0.chr * 4 if @ReadConsoleInputW.(@hConsoleHandle, input_records, 1, read_event) != 0 read_events = read_event.unpack1('L') 0.upto(read_events-1) do |idx| input_record = input_records[idx * 20, 20] event = input_record[0, 2].unpack1('s*') case event when KEY_EVENT key_down = input_record[4, 4].unpack1('l*') repeat_count = input_record[8, 2].unpack1('s*') virtual_key_code = input_record[10, 2].unpack1('s*') virtual_scan_code = input_record[12, 2].unpack1('s*') char_code = input_record[14, 2].unpack1('S*') control_key_state = input_record[16, 2].unpack1('S*') is_key_down = key_down.zero? ? false : true if is_key_down # p [repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state] return char_code.chr end when MOUSE_EVENT click_x, click_y, state = input_record[4, 8].unpack("ssL") if @mouse_state != state # click state changed @mouse_state = state csbi = get_console_screen_buffer_info || raise("error at GetConsoleScreenBufferInfo") click_y -= csbi[6] # p mouse: [click_x, click_y, state] if state == 1 # mouse button down return "\e\x5b<0;#{click_x};#{click_y}M" else # mouse button up return "\e\x5b<0;#{click_x};#{click_y}m" end end when WINDOW_BUFFER_SIZE_EVENT return :winsize_changed end end end false end
#run!
[ GitHub ]# File 'lib/ruby_installer/runtime/console_ui.rb', line 400
def run! .repaint main_loop end
#set_consolemode
[ GitHub ]# File 'lib/ruby_installer/runtime/console_ui.rb', line 208
def set_consolemode @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 243
private def setconsolemode(mode) call_with_console_handle(@SetConsoleMode, mode) end
#unset_consolemode
[ GitHub ]# File 'lib/ruby_installer/runtime/console_ui.rb', line 213
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