1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Reline: Use a more robust detection of MinTTY

The previous detection per get_screen_size fails when stdout is passed
to a pipe. That is the case when running ruby tests in parallel ("-j" switch).
In this case Reline believes that it's running on MinTTY and the tests
are running with ANSI IOGate instead of the Windows adapter on MINGW.
So parallel test results were different to that of a single process.
This commit fixes these differencies.

The code is taken from git sources and translated to ruby.
NtQueryObject() is replaced by GetFileInformationByHandleEx(), because
NtQueryObject() is undocumented and is more difficult to use:
  c5a03b1e29/compat/winansi.c (L558)
This commit is contained in:
Lars Kanis 2020-01-18 18:46:37 +01:00 committed by aycabta
parent 1de7941ff8
commit d1166c6d39
Notes: git 2020-01-21 21:27:30 +09:00
2 changed files with 30 additions and 2 deletions

View file

@ -415,8 +415,7 @@ end
if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/ if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
require 'reline/windows' require 'reline/windows'
if Reline::Windows.get_screen_size == [0, 0] if Reline::Windows.msys_tty?
# Maybe Mintty on Cygwin
require 'reline/ansi' require 'reline/ansi'
Reline::IOGate = Reline::ANSI Reline::IOGate = Reline::ANSI
else else

View file

@ -72,6 +72,8 @@ class Reline::Windows
STD_INPUT_HANDLE = -10 STD_INPUT_HANDLE = -10
STD_OUTPUT_HANDLE = -11 STD_OUTPUT_HANDLE = -11
WINDOW_BUFFER_SIZE_EVENT = 0x04 WINDOW_BUFFER_SIZE_EVENT = 0x04
FILE_TYPE_PIPE = 0x0003
FILE_NAME_INFO = 2
@@getwch = Win32API.new('msvcrt', '_getwch', [], 'I') @@getwch = Win32API.new('msvcrt', '_getwch', [], 'I')
@@kbhit = Win32API.new('msvcrt', '_kbhit', [], 'I') @@kbhit = Win32API.new('msvcrt', '_kbhit', [], 'I')
@@GetKeyState = Win32API.new('user32', 'GetKeyState', ['L'], 'L') @@GetKeyState = Win32API.new('user32', 'GetKeyState', ['L'], 'L')
@ -84,9 +86,36 @@ class Reline::Windows
@@hConsoleInputHandle = @@GetStdHandle.call(STD_INPUT_HANDLE) @@hConsoleInputHandle = @@GetStdHandle.call(STD_INPUT_HANDLE)
@@GetNumberOfConsoleInputEvents = Win32API.new('kernel32', 'GetNumberOfConsoleInputEvents', ['L', 'P'], 'L') @@GetNumberOfConsoleInputEvents = Win32API.new('kernel32', 'GetNumberOfConsoleInputEvents', ['L', 'P'], 'L')
@@ReadConsoleInput = Win32API.new('kernel32', 'ReadConsoleInput', ['L', 'P', 'L', 'P'], 'L') @@ReadConsoleInput = Win32API.new('kernel32', 'ReadConsoleInput', ['L', 'P', 'L', 'P'], 'L')
@@GetFileType = Win32API.new('kernel32', 'GetFileType', ['L'], 'L')
@@GetFileInformationByHandleEx = Win32API.new('kernel32', 'GetFileInformationByHandleEx', ['L', 'I', 'P', 'L'], 'I')
@@input_buf = [] @@input_buf = []
@@output_buf = [] @@output_buf = []
def self.msys_tty?(io=@@hConsoleInputHandle)
# check if fd is a pipe
if @@GetFileType.call(io) != FILE_TYPE_PIPE
return false
end
bufsize = 1024
p_buffer = "\0" * bufsize
res = @@GetFileInformationByHandleEx.call(io, FILE_NAME_INFO, p_buffer, bufsize - 2)
return false if res == 0
# get pipe name: p_buffer layout is:
# struct _FILE_NAME_INFO {
# DWORD FileNameLength;
# WCHAR FileName[1];
# } FILE_NAME_INFO
len = p_buffer[0, 4].unpack("L")[0]
name = p_buffer[4, len].encode(Encoding::UTF_8, Encoding::UTF_16LE, invalid: :replace)
# Check if this could be a MSYS2 pty pipe ('\msys-XXXX-ptyN-XX')
# or a cygwin pty pipe ('\cygwin-XXXX-ptyN-XX')
name =~ /(msys-|cygwin-).*-pty/ ? true : false
end
def self.getwch def self.getwch
unless @@input_buf.empty? unless @@input_buf.empty?
return @@input_buf.shift return @@input_buf.shift