Open judah opened 4 years ago
This change seems reasonable to me. I would like to still be a little cautious about older versions, since GHC (which Haskeline depends on) still claims to support Windows Vista: https://www.haskell.org/ghc/download_ghc_8_8_1.html#windows64
But maybe we can just use something like CPP to check whether we're on a new enough version of Windows.
I found this documentation which suggests that we can enable it explicitly with ENABLE_VIRTUAL_TERMINAL_PROCESSING
:
https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences?redirectedfrom=MSDN#output-sequences
It looks like GHC (the compiler binary, and ghci) enables that mode itself, but probably not for compiled code: https://github.com/ghc/ghc/blob/70e56b272492b65e41a149ec39a939e794fea66b/compiler/main/SysTools/Terminal.hs#L72 Were you testing a standalone binary or within ghci?
I don't have a version of Windows easily available at the moment, but please feel free to send a PR.
I was testing within GHCi/stack exec --
.
Understood on backwards capability - disabling the existing 'blanket' fixEsc
does shift responsibility for handling legacy Windows sensibly to the code calling the haskeline
library. Where it is the ultimate users who decide whether or not the prompt
will contain any 'ANSI' control characters (as in the case of GHCi users and the :set prompt <prompt>
command etc) I would not expect that to be problematic; a user on legacy Windows is unlikely to set the prompt to include 'ANSI' control characters.
I think there may be no simple CPP approach to distinguish legacy Windows from Windows 10; when I was looking at 'CPP-type solutions' for the ansi-terminal
package, I did not find one.
it would be nice if this were at least an option I could enable - I have a haskeline app that uses ansi escapes for coloring, and it works fine on windows except for the prompt, which ends up mangled. I'm more than willing to opt-out of backward compatibility here.
@mokus0 you should follow these instructions for control sequences in the prompt: https://github.com/judah/haskeline/wiki/ControlSequencesInPrompt That approach will make your application use control sequences on Unix-like OSes but omit them on Windows. (It also improves some logic around how line widths are calculated.)
It has been about two and a half years since I proposed pull request #126. It is also about two and half years since Microsoft ceased mainstream support for the last mainstream-supported version of Windows that was not ANSI-capable (Windows 7, service pack 1 on 14 January 2020). Cygwin and, consequently, MSYS2 have announced that they will cease to support Windows Vista by the end of 2022 (Microsoft dropped its mainstream support for Vista on 11 April 2017). Perhaps now is a good time to place more weight on the needs of modern Windows users over those who are still on unsupported legacy versions?
I think there may be no simple CPP approach to distinguish legacy Windows from Windows 10; when I was looking at 'CPP-type solutions' for the
ansi-terminal
package, I did not find one.
How about this? https://stackoverflow.com/a/55080889
import System.Win32.Info.Version -- from Win32 package
main :: IO ()
main = do
osVersionInfo <- getVersionEx
print (dwBuildNumber osVersionInfo)
Thanks @aryairani, that looks like it may be a non-CPP solution. However, I think the underlying question remains: is it sensible for modern versions of haskeline
to seek to continue to support operating systems when the vendor of the OS will no longer do so (not even for a fee).
Maybe, maybe not; but if supporting the old OS is to get the consensus needed to support the new OS (the \STX
approach is problematic for us, so I feel the new OS is not supported), then I'd say let's support both; and have a separate conversation about removing legacy windows support.
Understood. When I have a moment, I'll revisit https://github.com/judah/haskeline/pull/126 accordingly.
It turns out my optimisim at https://github.com/judah/haskeline/issues/130#issuecomment-1216788939 was unfounded. The underlying Win32 API GetVersionEx
functions do not, in fact, return the version of Windows on modern Windows. See: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversionexw. On my Windows 11 system, the System.Win32.Info.Version.getVersionEx
returns:
OSVERSIONINFOEX {dwMajorVersion = 6, dwMinorVersion = 2, dwBuildNumber = 9200, dwPlatformId = 2, szCSDVersion = "", wServicePackMajor = 0, wServicePackMinor = 0, wSuiteMask = 256, wProductType = VerNTWorkStation}
which, as the documentation explains, is the Windows 8 OS version value (6.2).
Doh, sorry. It looks like the functions we'd want now would be like IsWindows10OrGreater
, but I don't see wrappers for them in the Win32 package yet.
When I have another moment, I'll see if I can add IsWindowsVersionOrGreater
to Win32
. For 'ANSI' codes, you would need something more fine grained than IsWindows10OrGreater
.
Actually, IsWindowsVersionOrGreater
is not fine-grained as all versions of Windows 10 are major 10, minor 0. I don't know if haskeline
has the appetite to either depend upon, or copy, the complex approach that ansi-terminal
takes to deciding whether a terminal still needs emulation on Windows.
I have modified #126 to use the same logic as the ansi-terminal
package to detect whether the Windows terminal is ANSI-capable or not. However, I cannot test on legacy Windows because I no longer have access to machines using it.
Splitting out a comment from @mpilgrem, originally on #88:
The native consoles on Windows 10 are ANSI-capable, and there is no longer any version of Windows that has mainstream support by Microsoft that is not ANSI-capable, although ANSI-capability needs to be 'turned on' because of backwards compatibility with consoles on legacy Windows. I think GHCi and
stack exec -- [command]
turns it on.A little knowledge is a dangerous thing, but when I disabled
fixEsc
indrawLineDiff
(in moduleSystem.Console.Haskeline.Backend.Win32
) as follows:then
haskeline
worked as expected. I tested it with: