Skip to content

Commit 44a6644

Browse files
committed
REPL: Query libuv for virtual terminal support
The query-and-restore logic here was pretty flawed: - it had no way to guarantee when the "default" mode is available to query, so it could easily save a "bad" mode - it did not ensure / check whether the "default" mode is compatible with the output generated by REPL (esp. ASCII escape codes / color) - it persisted the "default" mode from pre-compilation to runtime, causing #56073 `ENABLE_VIRTUAL_TERMINAL_PROCESSING` is the only flag that we're agnostic about. It was added relatively recently (Windows 10 version 1511), and `libuv` has support to emulate its behavior when it's not available natively. Otherwise this PR resets ENABLE_PROCESSED_OUTPUT and ENABLE_WRAP_AT_EOL_OUTPUT always, since we output ASCII control sequences unconditionally. Resolves #56073.
1 parent 61e8f1d commit 44a6644

File tree

1 file changed

+26
-20
lines changed

1 file changed

+26
-20
lines changed

stdlib/REPL/src/LineEdit.jl

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,29 +1638,35 @@ end
16381638
# not leave the console mode in a corrupt state.
16391639
# FIXME: remove when pseudo-tty are implemented for child processes
16401640
if Sys.iswindows()
1641-
function _console_mode()
1642-
hOutput = ccall(:GetStdHandle, stdcall, Ptr{Cvoid}, (UInt32,), -11 % UInt32) # STD_OUTPUT_HANDLE
1643-
dwMode = Ref{UInt32}()
1644-
ccall(:GetConsoleMode, stdcall, Int32, (Ref{Cvoid}, Ref{UInt32}), hOutput, dwMode)
1645-
return dwMode[]
1646-
end
1647-
const default_console_mode_ref = Ref{UInt32}()
1648-
const default_console_mode_assigned = Ref(false)
1649-
function get_default_console_mode()
1650-
if default_console_mode_assigned[] == false
1651-
default_console_mode_assigned[] = true
1652-
default_console_mode_ref[] = _console_mode()
1653-
end
1654-
return default_console_mode_ref[]
1655-
end
1641+
1642+
#= Get/SetConsoleMode flags =#
1643+
const ENABLE_PROCESSED_OUTPUT = UInt32(0x0001)
1644+
const ENABLE_WRAP_AT_EOL_OUTPUT = UInt32(0x0002)
1645+
const ENABLE_VIRTUAL_TERMINAL_PROCESSING = UInt32(0x0004)
1646+
const DISABLE_NEWLINE_AUTO_RETURN = UInt32(0x0008)
1647+
const ENABLE_LVB_GRID_WORLDWIDE = UInt32(0x0010)
1648+
1649+
#= libuv flags =#
1650+
const UV_TTY_SUPPORTED = 0
1651+
const UV_TTY_UNSUPPORTED = 1
1652+
16561653
function _reset_console_mode()
1657-
mode = _console_mode()
1658-
if mode !== get_default_console_mode()
1659-
hOutput = ccall(:GetStdHandle, stdcall, Ptr{Cvoid}, (UInt32,), -11 % UInt32) # STD_OUTPUT_HANDLE
1660-
ccall(:SetConsoleMode, stdcall, Int32, (Ptr{Cvoid}, UInt32), hOutput, default_console_mode_ref[])
1654+
# Query libuv to see whether it expects the console to support virtual
1655+
# terminal sequences.
1656+
vterm_state = Ref{CInt}()
1657+
ccall(:uv_tty_get_vterm_state, Cint, (Ref{Cint},), vterm_state)
1658+
1659+
mode::UInt32 = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT
1660+
if vterm_state[] == UV_TTY_SUPPORTED
1661+
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING
16611662
end
1662-
nothing
1663+
1664+
hOutput = ccall(:GetStdHandle, stdcall, Ptr{Cvoid}, (UInt32,), -11 % UInt32) # STD_OUTPUT_HANDLE
1665+
hOutput == Ptr{Cvoid}(-1) && return nothing # error
1666+
ccall(:SetConsoleMode, stdcall, Int32, (Ptr{Cvoid}, UInt32), hOutput, mode)
1667+
return nothing
16631668
end
1669+
16641670
end
16651671

16661672
# returns the width of the written prompt

0 commit comments

Comments
 (0)