Class: Reline::Windows

Inherits:
Object
  • Object
show all
Defined in:
lib/reline/windows.rb

Defined Under Namespace

Classes: Win32API

Constant Summary collapse

RAW_KEYSTROKE_CONFIG =
{
  [224, 72] => :ed_prev_history, # ↑
  [224, 80] => :ed_next_history, # ↓
  [224, 77] => :ed_next_char,    # →
  [224, 75] => :ed_prev_char,    # ←
  [224, 83] => :key_delete,      # Del
  [224, 71] => :ed_move_to_beg,  # Home
  [224, 79] => :ed_move_to_end,  # End
}.each_key(&:freeze).freeze
VK_MENU =
0x12
VK_SHIFT =
0x10
STD_OUTPUT_HANDLE =
-11
@@getwch =
Win32API.new('msvcrt', '_getwch', [], 'I')
@@kbhit =
Win32API.new('msvcrt', '_kbhit', [], 'I')
@@GetKeyState =
Win32API.new('user32', 'GetKeyState', ['L'], 'L')
@@GetConsoleScreenBufferInfo =
Win32API.new('kernel32', 'GetConsoleScreenBufferInfo', ['L', 'P'], 'L')
@@SetConsoleCursorPosition =
Win32API.new('kernel32', 'SetConsoleCursorPosition', ['L', 'L'], 'L')
@@GetStdHandle =
Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L')
@@FillConsoleOutputCharacter =
Win32API.new('kernel32', 'FillConsoleOutputCharacter', ['L', 'L', 'L', 'L', 'P'], 'L')
@@ScrollConsoleScreenBuffer =
Win32API.new('kernel32', 'ScrollConsoleScreenBuffer', ['L', 'P', 'P', 'L', 'P'], 'L')
@@hConsoleHandle =
@@GetStdHandle.call(STD_OUTPUT_HANDLE)
@@buf =
[]

Class Method Summary collapse

Class Method Details

.clear_screenObject



174
175
176
177
178
# File 'lib/reline/windows.rb', line 174

def self.clear_screen
  # TODO: Use FillConsoleOutputCharacter and FillConsoleOutputAttribute
  print "\e[2J"
  print "\e[1;1H"
end

.cursor_posObject



130
131
132
133
134
135
136
# File 'lib/reline/windows.rb', line 130

def self.cursor_pos
  csbi = 0.chr * 24
  @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
  x = csbi[4, 2].unpack('s*').first
  y = csbi[6, 4].unpack('s*').first
  Reline::CursorPos.new(x, y)
end

.deprep(otio) ⇒ Object



189
190
191
# File 'lib/reline/windows.rb', line 189

def self.deprep(otio)
  # do nothing
end

.erase_after_cursorObject



158
159
160
161
162
163
164
# File 'lib/reline/windows.rb', line 158

def self.erase_after_cursor
  csbi = 0.chr * 24
  @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
  cursor = csbi[4, 4].unpack('L').first
  written = 0.chr * 4
  @@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, get_screen_size.last - cursor_pos.x, cursor, written)
end

.get_screen_sizeObject



124
125
126
127
128
# File 'lib/reline/windows.rb', line 124

def self.get_screen_size
  csbi = 0.chr * 24
  @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
  csbi[0, 4].unpack('SS').reverse
end

.getcObject



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/reline/windows.rb', line 83

def self.getc
  unless @@buf.empty?
    return @@buf.shift
  end
  input = getwch
  alt = (@@GetKeyState.call(VK_MENU) & 0x80) != 0
  shift_enter = (@@GetKeyState.call(VK_SHIFT) & 0x80) != 0 && input.first == 0x0D
  if shift_enter
    # It's treated as Meta+Enter on Windows
    @@buf.concat(["\e".ord])
    @@buf.concat(input)
  elsif input.size > 1
    @@buf.concat(input)
  else # single byte
    case input[0]
    when 0x00
      getwch
      alt = false
      input = getwch
      @@buf.concat(input)
    when 0xE0
      @@buf.concat(input)
      input = getwch
      @@buf.concat(input)
    when 0x03
      @@buf.concat(input)
    else
      @@buf.concat(input)
    end
  end
  if alt
    "\e".ord
  else
    @@buf.shift
  end
end

.getwchObject



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/reline/windows.rb', line 66

def self.getwch
  while @@kbhit.call == 0
    sleep(0.001)
  end
  result = []
  until @@kbhit.call == 0
    ret = @@getwch.call
    begin
      result.concat(ret.chr(Encoding::UTF_8).encode(Encoding.default_external).bytes)
    rescue Encoding::UndefinedConversionError
      result << ret
      result << @@getwch.call if ret == 224
    end
  end
  result
end

.move_cursor_column(val) ⇒ Object



138
139
140
# File 'lib/reline/windows.rb', line 138

def self.move_cursor_column(val)
  @@SetConsoleCursorPosition.call(@@hConsoleHandle, cursor_pos.y * 65536 + val)
end

.move_cursor_down(val) ⇒ Object



150
151
152
153
154
155
156
# File 'lib/reline/windows.rb', line 150

def self.move_cursor_down(val)
  if val > 0
    @@SetConsoleCursorPosition.call(@@hConsoleHandle, (cursor_pos.y + val) * 65536 + cursor_pos.x)
  elsif val < 0
    move_cursor_up(-val)
  end
end

.move_cursor_up(val) ⇒ Object



142
143
144
145
146
147
148
# File 'lib/reline/windows.rb', line 142

def self.move_cursor_up(val)
  if val > 0
    @@SetConsoleCursorPosition.call(@@hConsoleHandle, (cursor_pos.y - val) * 65536 + cursor_pos.x)
  elsif val < 0
    move_cursor_down(-val)
  end
end

.prepObject



184
185
186
187
# File 'lib/reline/windows.rb', line 184

def self.prep
  # do nothing
  nil
end

.scroll_down(val) ⇒ Object



166
167
168
169
170
171
172
# File 'lib/reline/windows.rb', line 166

def self.scroll_down(val)
  return if val.zero?
  scroll_rectangle = [0, val, get_screen_size.first, get_screen_size.last].pack('s4')
  destination_origin = 0 # y * 65536 + x
  fill = [' '.ord, 0].pack('SS')
  @@ScrollConsoleScreenBuffer.call(@@hConsoleHandle, scroll_rectangle, nil, destination_origin, fill)
end

.set_screen_size(rows, columns) ⇒ Object

Raises:

  • (NotImplementedError)


180
181
182
# File 'lib/reline/windows.rb', line 180

def self.set_screen_size(rows, columns)
  raise NotImplementedError
end

.ungetc(c) ⇒ Object



120
121
122
# File 'lib/reline/windows.rb', line 120

def self.ungetc(c)
  @@buf.unshift(c)
end