Repository navigation
Read the terminal colour scheme on REPL startup - #59958
Conversation
5633335 to
7e22584
Compare
7e22584 to
c89eef3
Compare
80b448e to
0c05f5b
Compare
Any issue that we can file upstream? This is a fairly common configuration, esp. since iTerm2 has tmux integration |
Potentially, there seem to be a few closed OSC-related issues on tmux's repo. I'm also not 100% on the performance: it might be passing through fg/bg info, in which case as of some recent (unpushed) improvements we will still be able to set pick light/dark appropriately and set fg/bg colours. Testing tmux locally myself, I see that it does pass through OSC 10 and OSC 11 codes (these are the fg/bg codes): |
|
I'm not sure what's a good idea to do here in terms of unit testing, since this should be tested against a collection of different terminal emulators. |
Yes please! |
0c05f5b to
9869f0c
Compare
|
I now plan on getting this merged after #60527, and have adjusted the PR accordingly. |
|
Given #61151 and and (my) interest in supporting KKP eventually, it would probably be good to support non-OSC queries too, specifically primary device attributes (DA1: As it is, OSC support lets us query more than just colour: such as clipboard contents (when possible), and OSC 99 support. |
This is prepratory work for #61151 and #59958. The key problem is that when we issue informational queries to the terminal emulator, we don't really have any way of knowing when they'll come back. There could be arbitrary amount of actual user input before or after. Thus, any code that would attempt to read from the terminal inline to read OSC responses faces the problem of accidentally getting user input and likewise, the REPL may see delayed OSC responses that are not inteded for it. To avoid all that complication, just put the REPL in charge of OSC response processing. The idea here is that at some point something issues the OSC query (possibly at startup) and whenever the response comes in, the REPL will just process it as if it was user input. This PR intentionally does not define a query interface, which is delagated to the follow on PRs that actually make use of this information. Example: ``` julia> write(stdout, "\e[c") 3 julia> 52 in Base.active_repl.mistate.terminal_properties.da1 true ```
This is prepratory work for #61151 and #59958. The key problem is that when we issue informational queries to the terminal emulator, we don't really have any way of knowing when they'll come back. There could be arbitrary amount of actual user input before or after. Thus, any code that would attempt to read from the terminal inline to read OSC responses faces the problem of accidentally getting user input and likewise, the REPL may see delayed OSC responses that are not inteded for it. To avoid all that complication, just put the REPL in charge of OSC response processing. The idea here is that at some point something issues the OSC query (possibly at startup) and whenever the response comes in, the REPL will just process it as if it was user input. This PR intentionally does not define a query interface, which is delagated to the follow on PRs that actually make use of this information. Example: ``` julia> write(stdout, "\e[c") 3 julia> 52 in Base.active_repl.mistate.terminal_properties.da1 true ```
This is prepratory work for #61151 and #59958. The key problem is that when we issue informational queries to the terminal emulator, we don't really have any way of knowing when they'll come back. There could be arbitrary amount of actual user input before or after. Thus, any code that would attempt to read from the terminal inline to read OSC responses faces the problem of accidentally getting user input and likewise, the REPL may see delayed OSC responses that are not inteded for it. To avoid all that complication, just put the REPL in charge of OSC response processing. The idea here is that at some point something issues the OSC query (possibly at startup) and whenever the response comes in, the REPL will just process it as if it was user input. This PR intentionally does not define a query interface, which is delagated to the follow on PRs that actually make use of this information. Example: ``` julia> write(stdout, "\e[c") 3 julia> 52 in Base.active_repl.mistate.terminal_properties.da1 true ```
This is prepratory work for #61151 (and could be extended in #59958). The key problem is that when we issue informational queries to the terminal emulator, we don't really have any way of knowing when they'll come back. There could be arbitrary amount of actual user input before or after. Thus, any code that would attempt to read from the terminal inline to read OSC responses faces the problem of accidentally getting user input and likewise, the REPL may see delayed OSC responses that are not inteded for it. To avoid all that complication, just put the REPL in charge of OSC response processing. The idea here is that at some point something issues the OSC query (possibly at startup) and whenever the response comes in, the REPL will just process it as if it was user input. This PR intentionally does not define a query interface, which is delagated to the follow on PRs that actually make use of this information. Example: ``` julia> write(stdout, "\e[c") 3 julia> 52 in Base.active_repl.mistate.terminal_properties.da1 true ```
This is prepratory work for #61151 (and could be extended in #59958). The key problem is that when we issue informational queries to the terminal emulator, we don't really have any way of knowing when they'll come back. There could be arbitrary amount of actual user input before or after. Thus, any code that would attempt to read from the terminal inline to read OSC responses faces the problem of accidentally getting user input and likewise, the REPL may see delayed OSC responses that are not inteded for it. To avoid all that complication, just put the REPL in charge of OSC response processing. The idea here is that at some point something issues the OSC query (possibly at startup) and whenever the response comes in, the REPL will just process it as if it was user input. This PR intentionally does not define a query interface, which is delagated to the follow on PRs that actually make use of this information. Example: ``` julia> write(stdout, "\e[c") 3 julia> 52 in Base.active_repl.mistate.terminal_properties.da1 true ```
This is prepratory work for #61151 and #59958. The key problem is that when we issue informational queries to the terminal emulator, we don't really have any way of knowing when they'll come back. There could be arbitrary amount of actual user input before or after. Thus, any code that would attempt to read from the terminal inline to read OSC responses faces the problem of accidentally getting user input and likewise, the REPL may see delayed OSC responses that are not inteded for it. To avoid all that complication, just put the REPL in charge of OSC response processing. The idea here is that at some point something issues the OSC query (possibly at startup) and whenever the response comes in, the REPL will just process it as if it was user input. This PR intentionally does not define a query interface, which is delagated to the follow on PRs that actually make use of this information. Example: ``` julia> write(stdout, "\e[c") 3 julia> 52 in Base.active_repl.mistate.terminal_properties.da1 true ``` Written by Claude.
This is prepratory work for #61151 and #59958. The key problem is that when we issue informational queries to the terminal emulator, we don't really have any way of knowing when they'll come back. There could be arbitrary amount of actual user input before or after. Thus, any code that would attempt to read from the terminal inline to read OSC responses faces the problem of accidentally getting user input and likewise, the REPL may see delayed OSC responses that are not inteded for it. To avoid all that complication, just put the REPL in charge of OSC response processing. The idea here is that at some point something issues the OSC query (possibly at startup) and whenever the response comes in, the REPL will just process it as if it was user input. This PR intentionally does not define a query interface, which is delagated to the follow on PRs that actually make use of this information. Example: ``` julia> write(stdout, "\e[c") 3 julia> 52 in Base.active_repl.mistate.terminal_properties.da1 true ``` Written by Claude. (cherry picked from commit 331421e)
This is prepratory work for JuliaLang#61151 and JuliaLang#59958. The key problem is that when we issue informational queries to the terminal emulator, we don't really have any way of knowing when they'll come back. There could be arbitrary amount of actual user input before or after. Thus, any code that would attempt to read from the terminal inline to read OSC responses faces the problem of accidentally getting user input and likewise, the REPL may see delayed OSC responses that are not inteded for it. To avoid all that complication, just put the REPL in charge of OSC response processing. The idea here is that at some point something issues the OSC query (possibly at startup) and whenever the response comes in, the REPL will just process it as if it was user input. This PR intentionally does not define a query interface, which is delagated to the follow on PRs that actually make use of this information. Example: ``` julia> write(stdout, "\e[c") 3 julia> 52 in Base.active_repl.mistate.terminal_properties.da1 true ``` Written by Claude.
7175f77 to
ca6a67a
Compare
Query the terminal for its foreground, background, and ANSI palette colours on REPL startup, and apply them via StyledStrings.setcolors!, so that displayed content adapts to the user's actual terminal theme. The palette is queried before the foreground and background, letting the latter's response act as a completion sentinel: terminals answer queries in order, so once fg/bg arrive, every colour the terminal intends to report has been seen. Terminals that answer only fg/bg still yield a usable partial result, and those that answer nothing leave the colours untouched. This avoids waiting on a timeout, which would misbehave over high-latency connections and under multiplexers. Responses are collected through the keymap, alongside the existing DA1 handling, so we don't need to block and wait.
|
I think this should be good to go now |
|
BTW, there's also a more modern way to do this query now with |
|
Thanks for raising that, I'll look into it. |
|
Looks like it's actually decently supported, according to https://github.com/contour-terminal/contour/blob/master/docs/vt-extensions/color-palette-update-notifications.md |
Wouldn't it be nice if Julia/the REPL knew what your terminal colours were, and displayed content appropriately?
This introduces light/dark theme detection, as well as your ANSI 8-colour theme. With this capability, we can avoid accidental low-contrast highlights and related issues that will only become worse as we try to extend the graphical capabilities of the REPL.
Sneak peek:
Query durations
Important
This is asynchronous, and does not impact startup latency
Tested terminals
Test script
Everything works
Misbehaving (terminal's fault)
Misbehaving (our fault)