为了在控制台中使用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')
cmd.exe
)和子进程(lua.exe
)通过不同的控制台句柄访问同一个终端窗口。当os.execute
创建cmd.exe
子进程时,控制台句柄被子进程继承,这是默认行为。但是当cmd.exe
创建lua.exe
子进程时,控制台句柄故意不被继承,以使子进程相互隔离(您的程序不依赖于在同一控制台中运行的先前程序)。 - Egor Skriptunoffcmd.exe
deliberately prohibits console handle inheritance while creating subprocess. This is done by parameterbInheritHandles
of WinAPI functionCreateProcessW()
- Egor Skriptunoff