2017-07-13 5 views
0

Windowsのバージョン10.0.14393ruby 2.3.1p112 (2016-04-26 revision 54768) [x64-mingw32]を使用してください。最初Windows 10でのRuby VT100エスケープシーケンスの予期しない動作

いくつかのこと:

  1. のWindows echoコマンドの挙動は、VT100のためのコンソールモードフラグをバイパスします。 MSDNによれば、フラグはWriteConsole()WriteFile()にしか影響しません。
  2. SetConsoleMode()でフラグを変更すると、Win32関数WriteConsole()が正しく動作しています。フラグが設定されている場合、VT100のエスケープシーケンスが解釈されます。

Rubyでは何が起こっていますか?それは赤色に緑色を表示していて、何とか私のコンソールフラグを無視しています。また、なぜそれはより暗い緑を示していますか?私の理論は、これがRubyの問題であり、コンソールへの出力の書き込みをどのように処理するかということです。

全スクリプト:Windows PowerShellの中

#!/usr/bin/ruby 
# encoding: UTF-8 

require 'rbconfig' 

unless RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ 
    raise 'This script only works on Windows. Quitting.' 
end 

require 'fiddle' 
require 'fiddle/types' 
require 'fiddle/import' 

class VirtMode 
    #TODO: Check Windows 10 build number (>= 1511) for mode support 
    module Kernel32 
    extend Fiddle::Importer 
    dlload 'kernel32' 
    include Fiddle::Win32Types 

    DWORD_SIZE = sizeof('DWORD') 
    STD_OUTPUT_HANDLE = -11 
    STD_INPUT_HANDLE = -10 
    VIRTUAL_TERMINAL_PROCESSING = 0x0004 

    extern 'HANDLE GetStdHandle(DWORD)' 
    extern 'DWORD SetConsoleMode(HANDLE, DWORD)' 
    extern 'DWORD GetConsoleMode(HANDLE, PDWORD)' 
    extern 'BOOL WriteConsole(HANDLE, const *char, DWORD, PDWORD, PVOID)' 
    end 

    class << self; attr_accessor :stdout, :stdin end 
    self.stdout = Kernel32::GetStdHandle(Kernel32::STD_OUTPUT_HANDLE) 
    self.stdin = Kernel32::GetStdHandle(Kernel32::STD_INPUT_HANDLE) 

    def self.get_mode 
    mode = [0].pack('L') 
    success = Kernel32::GetConsoleMode(stdout, mode) 
    return mode.unpack('L').first if success.nonzero? 
    raise 'Could not get console mode' 
    end 

    def self.enable_virtual_mode 
    new_mode = get_mode | Kernel32::VIRTUAL_TERMINAL_PROCESSING 
    #puts new_mode.to_s(2).rjust(32, '0') 
    return Kernel32::SetConsoleMode(stdout, new_mode).nonzero? 
    end 

    def self.disable_virtual_mode 
    new_mode = get_mode & ~Kernel32::VIRTUAL_TERMINAL_PROCESSING 
    #puts new_mode.to_s(2).rjust(32, '0') 
    return Kernel32::SetConsoleMode(stdout, new_mode).nonzero? 
    end 

    def self.write_console(text) 
    written = 0 
    Kernel32::WriteConsole(stdout, text, text.size, written, 0) 
    end 
end 

# It's already disabled but just in case 
VirtMode.disable_virtual_mode 
puts '--VT100 mode disabled--' 
puts "\e[38;2;255;0;32mRuby: Red!\e[0m" 
VirtMode.write_console "\e[38;2;255;0;32mWin32: Red!\e[0m\n" 
system "echo \e[38;2;255;0;32mEcho: Red!\e[0m\n" 

# Now we enable Windows 10 support for VT100 
# https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx 
VirtMode.enable_virtual_mode 
puts '--VT100 mode enabled--' 
puts "\e[38;2;0;255;32mRuby: Green!\e[0m" 
VirtMode.write_console "\e[38;2;0;255;32mWin32: Green!\e[0m\n" 
system "echo \e[38;2;0;255;32mEcho: Green!\e[0m\n" 

出力例:あなたはそれがWindowsコンソール、例えばPowerShellのか、コマンドプロンプトにoutputing持っていない限り enter image description here

はルビーマインで、このスクリプトをデバッグしないでくださいGetConsoleMode()が失敗するためです。

答えて

0

Windows 10以降のネイティブVT100のRubyサポートは、2016年3月8日のcommitに追加されました。これ以前は、独自のVT100エスケープシーケンスパーサーを使用しています。

私がインストールしたRubyのバージョンにはこの変更がなかったため、最新のリリースruby 2.4.1p111 (2017-03-22 revision 58053) [x64-mingw32]を手に入れました。

それはコミットので、Rubyは今、次のことを行います。コンソールモードがENABLE_VIRTUAL_TERMINAL_PROCESSINGフラグがない場合

  1. は独自のVT100パーサーを使用します。
  2. フラグが存在する場合、Windows VT100サポートを使用します。

Rubyが赤色に緑色を表示していた理由は、RGBカラーコードのRuby VT100パーサーのバグである可能性が高いです。たとえば、"\e[38;2;255;0;32mRuby: Red!\e[0m"に赤(255)がある場合、実際にはエスケープシーケンスを緑色の"\e[32mRuby: Red!\e[0m"と解釈しています。このバグは、VT100モードが有効になっているときの色の不一致も説明します。

Windows VTモードを使用するRuby 2.4では、緑色が正しく表示されます。 RGBはいくつかの仮想端末でサポートされている拡張機能なので、RubyはRGBカラーコードを解釈しません。(Thomas-Dickeyに感謝します)

enter image description here

+1

実際、Rubyは正しいです(VT100の場合、RGBを行ったことはありません)。それを混乱させたセミコロンセパレータの問題は、他の場所でよく議論されていました(FAQ)。 –

+0

ああ、私は完全にそれを逃した。今や意味をなさないその議論を見つけるのに苦労して、あなたはFAQへのリンクを持っていますか? – gavxn

+0

[ここ](http://aerie.jexium-island.net/xterm/xterm.faq.html#color_by_number)を開始し、[ここでも](http://aerie.jexium-island.net/ncurses /ncurses.faq。html#xterm_16MegaColors)。約10年間の既知の問題ですが、これはアプリケーション*が破損した最初のレポートです。 –

関連する問題