-
-
Notifications
You must be signed in to change notification settings - Fork 45
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
Colors doesn't look right! #56
Comments
hmmm we saw a similar thing when putty was being used -- it looks like some color is being used but the escape sequences are incorrect can you echo $TERM and $COLORTERM and also try |
can you try this script: import curses
def c_main(stdscr):
curses.use_default_colors()
stdscr.addstr(0, 0, f'can_change_color: {curses.can_change_color()}')
stdscr.addstr(1, 0, f'colors: {curses.COLORS}')
stdscr.addstr(3, 0, f'256 color test (should be a blue)')
curses.init_pair(1, -1, 27)
stdscr.addstr(4, 0, ' ' * 20, curses.color_pair(1))
stdscr.addstr(6, 0, 'true color test (should be a slightly different blue)')
curses.init_color(
255,
int(0x1e * 1000 / 255),
int(0x77 * 1000 / 255),
int(0xd3 * 1000 / 255),
)
curses.init_pair(2, -1, 255)
stdscr.addstr(7, 0, ' ' * 20, curses.color_pair(2))
stdscr.get_wch()
if __name__ == '__main__':
exit(curses.wrapper(c_main)) it should look something like this: |
interesting, the terminal reports it can change the color, but it can't! the colors before actually make a lot more sense now, those are the default 256-color colors, (babi chooses ones at the end in the greyscale zone to change) and since it can't change them you get a weird greyscale "theme" I wonder if there's a way to detect this and fall back to the 256color rendering 🤔 |
I have a terrible idea import curses
import os
import sys
import tempfile
def c_main(stdscr):
curses.use_default_colors()
curses.init_color(
255,
0x1e * 1000 // 0xff,
0x77 * 1000 // 0xff,
0xd3 * 1000 // 0xff,
)
curses.init_pair(1, 255, -1)
stdscr.insstr(0, 0, 'hello world', curses.color_pair(1))
stdscr.get_wch()
def main():
saved = os.dup(sys.stdout.fileno())
with tempfile.TemporaryFile(buffering=False) as tmp:
os.dup2(tmp.fileno(), sys.stdout.fileno())
try:
curses.wrapper(c_main)
finally:
os.dup2(saved, sys.stdout.fileno())
print(tmp.tell())
tmp.seek(0)
print(tmp.read())
if __name__ == '__main__':
exit(main()) this is the start of it (a proof of concept) and it doesn't work yet the idea is to:
|
this is actually very very close to working: import contextlib
import curses
import functools
import os
import re
import sys
import tempfile
import threading
from typing import Generator
from typing import Match
CHANGE_COLOR_RE = re.compile(
br'\033]4;(?P<color>\d+);rgb:'
br'(?P<r>[0-9A-Fa-f]+)/(?P<g>[0-9A-Fa-f]+)/(?P<b>[0-9A-Fa-f]+)'
br'\033\\'
)
ESC_256_RE = re.compile(br'\033\[(?P<fgbg>[34]8);5;(?P<color>\d+)m')
def gen(fd: int) -> Generator[bytes, None, None]:
bts = os.read(fd, 1024)
while bts:
yield bts
bts = os.read(fd, 1024)
def brrr(saved: int, fd: int) -> None:
colors: Dict[bytes, bytes] = {}
def sub_color(match: Match[bytes]) -> bytes:
color = colors.get(match['color'])
if color is None:
return match[0]
else:
return b'\033[' + match['fgbg'] + b';2;' + color + b'm'
for chunk in gen(fd):
for match in CHANGE_COLOR_RE.finditer(chunk):
r = int(match['r'], 16)
g = int(match['g'], 16)
b = int(match['b'], 16)
colors[match['color']] = f'{r};{g};{b}'.encode()
chunk = ESC_256_RE.sub(sub_color, chunk)
os.write(saved, chunk)
def c_main(stdscr):
if curses.has_colors():
curses.use_default_colors()
if curses.can_change_color():
curses.init_color(
255,
0x1e * 1000 // 0xff,
0x77 * 1000 // 0xff,
0xd3 * 1000 // 0xff,
)
curses.init_pair(1, 255, -1)
stdscr.insstr(0, 0, 'hello world', curses.color_pair(1))
stdscr.get_wch()
@contextlib.contextmanager
def fixup_true_color_escapes() -> Generator[None, None, None]:
saved = os.dup(sys.stdout.fileno())
r, w = os.pipe()
thread = threading.Thread(target=functools.partial(brrr, saved, r))
thread.start()
os.dup2(w, sys.stdout.fileno())
try:
yield
finally:
os.dup2(saved, sys.stdout.fileno())
os.close(w)
thread.join()
def main():
with fixup_true_color_escapes():
curses.wrapper(c_main)
if __name__ == '__main__':
exit(main()) still need to fix partial sequences aren't handled properly (an escape sequence split across multiple but here's babi in true color mode running in Konsole (notice the white background on some things, that's the partial sequences problem) there's also something weird about resizing not working as expected that I'll have to look into 🤔 |
I don't know if already known, but when I set
Question: Can this be a practical solution? |
screen-256color (even with the truecolor set) falls back to 256 only color (which is why it appears to work since it doesn't do color reassignment) -- this'll make the colors slightly off from the 24bit colors but they'll at least not be greys |
Colors doesnt look right, thats the theme i used https://raw.githubusercontent.com/Binaryify/OneDark-Pro/master/themes/OneDark-Pro.json.
The text was updated successfully, but these errors were encountered: