在 windows 终端中启用 ANSI 序列
Enable ANSI sequences in windows terminal
我偶然发现了一个有趣的问题
在 Windows:
C:\> lua
> print("\x1b[95mMagenta\x1b[0m")
-[95mMagenta-[0m
但是如果我 运行 os.execute()
即使是一个空命令,
在它之前,它按预期工作:
C:\> lua
> os.system(""); print("\x1b[95mMagenta\x1b[0m")
Magenta
(最后一行用洋红色打印)
为什么会这样,我怎样才能使 ANSI 代码工作
不调用 os.execute()
?
要使 ANSI 代码在控制台中工作,您应该通过调用 WinAPI 函数 SetConsoleMode
.
来设置特定的 ENABLE_VIRTUAL_TERMINAL_PROCESSING
模式
当您在 Lua 中调用 os.execute()
时,Lua 调用 C 运行时函数 system()
,它创建 cmd.exe
进程,初始化所有的铃声和口哨声。
但是 Lua 当然不知道 Windows 控制台功能;它只适用于具有默认设置的控制台。
更新:
这是一个关于如何从 LuaJIT 脚本打开 ANSI 转义序列的示例:
local ffi = require"ffi"
ffi.cdef[[
typedef int BOOL;
static const int INVALID_HANDLE_VALUE = -1;
static const int STD_OUTPUT_HANDLE = -11;
static const int ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4;
intptr_t GetStdHandle(int nStdHandle);
BOOL GetConsoleMode(intptr_t hConsoleHandle, int* lpMode);
BOOL SetConsoleMode(intptr_t hConsoleHandle, int dwMode);
]]
local console_handle = ffi.C.GetStdHandle(ffi.C.STD_OUTPUT_HANDLE)
assert(console_handle ~= ffi.C.INVALID_HANDLE_VALUE)
local prev_console_mode = ffi.new"int[1]"
assert(ffi.C.GetConsoleMode(console_handle, prev_console_mode) ~= 0, "This script must be run from a console application")
local function turn_VT(on_off)
assert(ffi.C.SetConsoleMode(console_handle, bit.bor(prev_console_mode[0], on_off and ffi.C.ENABLE_VIRTUAL_TERMINAL_PROCESSING or 0)) ~= 0)
end
print('\x1b[95mMagenta\x1b[m')
turn_VT(true)
print('\x1b[95mMagenta\x1b[m')
turn_VT(false)
print('\x1b[95mMagenta\x1b[m')
我偶然发现了一个有趣的问题 在 Windows:
C:\> lua
> print("\x1b[95mMagenta\x1b[0m")
-[95mMagenta-[0m
但是如果我 运行 os.execute()
即使是一个空命令,
在它之前,它按预期工作:
C:\> lua
> os.system(""); print("\x1b[95mMagenta\x1b[0m")
Magenta
(最后一行用洋红色打印)
为什么会这样,我怎样才能使 ANSI 代码工作
不调用 os.execute()
?
要使 ANSI 代码在控制台中工作,您应该通过调用 WinAPI 函数 SetConsoleMode
.
ENABLE_VIRTUAL_TERMINAL_PROCESSING
模式
当您在 Lua 中调用 os.execute()
时,Lua 调用 C 运行时函数 system()
,它创建 cmd.exe
进程,初始化所有的铃声和口哨声。
但是 Lua 当然不知道 Windows 控制台功能;它只适用于具有默认设置的控制台。
更新:
这是一个关于如何从 LuaJIT 脚本打开 ANSI 转义序列的示例:
local ffi = require"ffi"
ffi.cdef[[
typedef int BOOL;
static const int INVALID_HANDLE_VALUE = -1;
static const int STD_OUTPUT_HANDLE = -11;
static const int ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4;
intptr_t GetStdHandle(int nStdHandle);
BOOL GetConsoleMode(intptr_t hConsoleHandle, int* lpMode);
BOOL SetConsoleMode(intptr_t hConsoleHandle, int dwMode);
]]
local console_handle = ffi.C.GetStdHandle(ffi.C.STD_OUTPUT_HANDLE)
assert(console_handle ~= ffi.C.INVALID_HANDLE_VALUE)
local prev_console_mode = ffi.new"int[1]"
assert(ffi.C.GetConsoleMode(console_handle, prev_console_mode) ~= 0, "This script must be run from a console application")
local function turn_VT(on_off)
assert(ffi.C.SetConsoleMode(console_handle, bit.bor(prev_console_mode[0], on_off and ffi.C.ENABLE_VIRTUAL_TERMINAL_PROCESSING or 0)) ~= 0)
end
print('\x1b[95mMagenta\x1b[m')
turn_VT(true)
print('\x1b[95mMagenta\x1b[m')
turn_VT(false)
print('\x1b[95mMagenta\x1b[m')