-
-
Notifications
You must be signed in to change notification settings - Fork 257
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds support for reverse video and underline on Windows 10. #267
Conversation
Also prevents SGR codes 30-37 from appearing BRIGHT when the terminal is using a bright colour by default.
Hi, |
Hi @jpwroberts. Thanks for the pull request! |
Thanks for clarifying. I understand, these are chaotic times. |
Hey. FYI, yesterday I created a PR to test releases before we push them to PyPI. When that is merged, I'll be more confident about resuming merges and releases. I'll try to look at this PR soon. Thank you for creating it! |
Thanks for the update :-) |
@wiggin15 Any estimate as to when this PR will be merged? I maintain a project that would benefit from underlining support. Thanks in advance! |
CHANGELOG.rst
Outdated
* ANSI codes CSI [ 0-37 m no longer render as BRIGHT if the default terminal | ||
foreground color is BRIGHT. | ||
* The demo01.py file now demonstrates reverse video and underlining effects. | ||
* winterm_test.py updated to assert on term._default_style rather than _style. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this change is prominent enough to appear in the changelog. It's more "internal".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may have been a bit over-zealous there. Definitely agree about the last two not being in the changelog. The first two result in a change in behaviour, especially no longer getting a BRIGHT foreground colour with CSI [ 30-37 m. That should be documented somewhere, but I'm happy to remove it from the changelog.
README.rst
Outdated
Style: DIM, NORMAL, BRIGHT, RESET_ALL | ||
Style: DIM, NORMAL, BRIGHT, BRIGHT_OFF, REVERSE, UNDERLINE, RESET_ALL | ||
|
||
``Style.REVERSE_OFF`` and ``Style.UNDERLINE_OFF`` are provided to allow intent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, regular ANSI-compliant terminals do have a special code for REVERSE_OFF
and UNDERLINE_OFF
, but Windows doesn't have an attribute to "clear" these.
Does this mean that we'll have different behaviors on Windows/Linux? e.g. the following two calls
print(colorama.Style.REVERSE_OFF + colorama.Back.GREEN + "off?" + colorama.Style.RESET_ALL)
and
print(colorama.Style.REVERSE_OFF + colorama.Style.REVERSE_OFF + colorama.Back.GREEN + "off?" + colorama.Style.RESET_ALL)
will have "REVERSE" off in both on Linux, but will have "REVERSE" on in the first call on Windows?
Maybe we can call a different function, or use a special value in WinStyle
to make sure OFF
means OFF
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the behaviour I expected (and intended) but there seems to be a problem there. I'll work on that (after rebasing to the current version).
I think the Windows behaviour can be fixed by tracking the current state of REVERSE and UNDERLINE. I'll make sure OFF really means off (and ON doesn't mean OFF if the attribute is already set).
Thanks for nudging me, @jtesta . |
Thanks for updating the PR. If I understand correctly, this is a different implementation that before, and we don't use the Win32 calls any more? This commit contains changes from the already-current master branch (looks like it's a merge commit) - is it supposed to look like this? It's harder to review and I don't know what merging it like this will mean. 752c327 |
old_mode = wintypes.DWORD() | ||
|
||
stdout_handle = windll.kernel32.GetStdHandle(STDOUT) | ||
# If the next call failed, we may be running on Windows pre 10.0.10586. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, this call isn't supposed to fail (GetConsoleMode
existed in prior versions), but it will not return the ENABLE_VIRTUAL_TERMINAL_PROCESSING
flag which only exists on later versions. The "set" call with the flag may fail, though. Please update the comments to reflect this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I think there's more than just the comment to change. The only way to be sure that we've enabled the virtual terminal is to call GetConsoleMode again, and check. Only if that test passes should I set conversion_supported to False.
To be safe, I need to find an old version of Windows 10 to test on. I'll also test on Cygwin.
print("Stored old_mode_value = " + str(old_mode_value)) | ||
# Only enable if it's not already enabled | ||
print("enabling virtual terminal for " + str(self.stream)) | ||
if windll.kernel32.SetConsoleMode(stdout_handle, old_mode_value | ENABLE_VIRTUAL_TERMINAL_PROCESSING): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a bit reluctant to do this here. Normally "init" itself doesn't change any console properties, and everything is controllable with the init flags. This call is now made implicitly and in any case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't think of a cleaner way to do it, unfortunately. We're basically putting Windows into the same mode as Linux, and avoiding win32 calls. As far as I can see, that has to be done here.
on_windows = os.name == 'nt' | ||
# We test if the WinAPI works, because even if we are on Windows | ||
# we may be using a terminal that doesn't support the WinAPI | ||
# (e.g. Cygwin Terminal). In this case it's up to the terminal | ||
# to support the ANSI codes. | ||
conversion_supported = on_windows and winapi_test() | ||
if on_windows and platform.release().startswith('10'): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment above this line mismatches the code now. We do need to call winapi_test
before using the other WinAPI functions inside the "if".
# We turn virtual terminal support back on, then set | ||
# `conversion_supported` to False. Behaviour will then be the same | ||
# as for Linux - colorama doesn't use win32 calls. | ||
from ctypes import wintypes, byref # import wintypes now we know we're on Windows. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move relevant code to win32.py, that's where we check the imports and define the ctypes functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After reading #300 I checked through the outstanding PRs. #139 by @segevfiner has used win32.py. That PR also enables vt via a function in winterm.py (as you suggested I should do). Once I've set up appropriate test environments (old Windows 10, Cygwin, etc), I'll run the same tests using #139. That may be a better candidate for implementing this functionality. @segevfiner identified vt as a more appropriate solution while I was still trying to make win32 calls behave.
It looks like I messed up there, sorry. |
After thinking about this further, I think the new approach is less than ideal, because it leaves older operating systems unsupported for specific new codes. colorama's purpose is to add support for terminals that don't support ANSI codes using Win32 API calls. |
This might mean you need both. As the Win 10 VT support enables support for additional escape sequences that aren't supported by the WinAPI such as 24-bit colors. |
That's what I started off doing, then it became apparent that older Windows versions just don't have the necessary API calls to support the new codes I wanted to add (reverse video and underline). |
It looks like I have a lot to learn about using github. I've just managed to accidentally close this PR while trying to delete all my previous commits. |
Hi folks. I'm looking at Colorama stuff after many many months (years?) away. @jpwroberts, would you like some help getting this PR into shape? Do you think the basic approach is sound, and can solve (or already has solved) the issues @wiggin15 raised here? Or have you given up on it? Thoughts appreciated. |
Hi, |
@jpwroberts OK, thanks for the info. I'm sure I can help out with git/github and this PR. I'll take a look at it later. Many thanks for your efforts and your patience. |
Hi. This PR has a laudable goal but cannot be merged in its current state (it contains diffs for many disparate changes and a large number of conflicts.) I'm closing it. Apologies for the extent to which my inattention has contributed to the difficulty of sorting this out. Hugs! |
Also prevents SGR codes 30-37 from appearing BRIGHT when the terminal is using a bright colour by default.
closes #265