Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在windows终端中启用ANSI序列_Windows_Terminal_Lua_Ansi - Fatal编程技术网

在windows终端中启用ANSI序列

在windows终端中启用ANSI序列,windows,terminal,lua,ansi,Windows,Terminal,Lua,Ansi,我偶然发现了一个有趣的问题 在Windows中: C:\> lua > print("\x1b[95mMagenta\x1b[0m") -[95mMagenta-[0m 但是如果我运行os.execute(),即使使用空命令, 在此之前,它按预期工作: C:\> lua > os.system(""); print("\x1b[95mMagenta\x1b[0m") Magenta (最后一行用洋红色打印

我偶然发现了一个有趣的问题 在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
来设置特定的
启用虚拟终端处理模式

当您在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首先在此终端上启动时,不会发生这种情况?终端的模式不是终端窗口的属性。它是控制台句柄的属性。父进程(
cmd.exe
)和子进程(
lua.exe
)通过不同的控制台句柄访问同一终端窗口。当
os.execute
创建
cmd.exe
子进程时,控制台句柄由子进程继承,这是默认行为。但是当
cmd.exe
创建
lua.exe
子进程时,控制台句柄不会被继承,故意将子进程彼此隔离(您的程序不依赖于在同一控制台中运行的上一个程序的名称)。是的,似乎正是这样,但它如何知道在什么情况下必须创建新的控制台句柄,以及必须继承什么,目前还不清楚。或者cmd.exe总是为每个子进程创建新的控制台句柄?
cmd.exe
在创建子进程时故意禁止控制台句柄继承。这是通过WinAPI函数
CreateProcessW()