Skip to content
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

Use selected syntax style for tracebacks and improve ANSI color codes support #608

Merged
merged 16 commits into from
Aug 12, 2024
Merged
31 changes: 26 additions & 5 deletions qtconsole/ansi_code_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,31 @@ def _replace_special(self, match):
self.actions.append(ScrollAction('scroll', 'down', 'page', 1))
return ''

def _parse_ansi_color(self, color, intensity):
"""
Map an ANSI color code to color name or a RGB tuple.
Based on: https://gist.github.com/MightyPork/1d9bd3a3fd4eb1a661011560f6921b5b
"""
parsed_color = None
if color < 16:
# Adjust for intensity, if possible.
if intensity > 0 and color < 8:
color += 8
parsed_color = self.color_map.get(color, None)
elif (color > 231):
s = int((color - 232) * 10 + 8)
parsed_color = (s, s, s)
else:
n = color - 16
b = n % 6
g = (n - b) / 6 % 6
r = (n - b - g * 6) / 36 % 6
r = int(r * 40 + 55) if r else 0
g = int(g * 40 + 55) if g else 0
b = int(b * 40 + 55) if b else 0
parsed_color = (r, g, b)
return parsed_color


class QtAnsiCodeProcessor(AnsiCodeProcessor):
""" Translates ANSI escape codes into QTextCharFormats.
Expand Down Expand Up @@ -323,12 +348,8 @@ def get_color(self, color, intensity=0):
""" Returns a QColor for a given color code or rgb list, or None if one
cannot be constructed.
"""

if isinstance(color, int):
# Adjust for intensity, if possible.
if color < 8 and intensity > 0:
color += 8
constructor = self.color_map.get(color, None)
constructor = self._parse_ansi_color(color, intensity)
elif isinstance(color, (tuple, list)):
constructor = color
else:
Expand Down
14 changes: 13 additions & 1 deletion qtconsole/mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,7 @@ def set_syntax_style(self, syntax_style):
colors='nocolor'
elif styles.dark_style(syntax_style):
colors='linux'

else:
colors='lightbg'
self.active_frontend.syntax_style = syntax_style
Expand All @@ -809,7 +810,18 @@ def set_syntax_style(self, syntax_style):
self.active_frontend._syntax_style_changed()
self.active_frontend._style_sheet_changed()
self.active_frontend.reset(clear=True)
self.active_frontend._execute("%colors linux", True)
self.active_frontend._execute(
f"""
from IPython.core.ultratb import VerboseTB
if getattr(VerboseTB, 'tb_highlight_style', None) is not None:
VerboseTB.tb_highlight_style = '{syntax_style}'
elif getattr(VerboseTB, '_tb_highlight_style', None) is not None:
VerboseTB._tb_highlight_style = '{syntax_style}'
else:
get_ipython().run_line_magic('colors', '{colors}')
""",
True)


def close_active_frontend(self):
self.close_tab(self.active_frontend)
Expand Down
6 changes: 6 additions & 0 deletions qtconsole/tests/test_jupyter_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,15 @@ def test_stylesheet_changed(self):
# By default, the background is light. White text is rendered as black
self.assertEqual(w._ansi_processor.get_color(15).name(), '#000000')

# Color code 40
self.assertEqual(w._ansi_processor.get_color(40).name(), '#00d700')

# Change to a dark colorscheme. White text is rendered as white
w.syntax_style = 'monokai'
self.assertEqual(w._ansi_processor.get_color(15).name(), '#ffffff')

# Color code 40 with monokai
self.assertEqual(w._ansi_processor.get_color(40).name(), '#00d700')

@pytest.mark.skipif(not sys.platform.startswith('linux'),
reason="Works only on Linux")
Expand Down
Loading