Skip to content

Commit

Permalink
Merge from 3.x: PR #4000
Browse files Browse the repository at this point in the history
Fixes #916
  • Loading branch information
ccordoba12 committed Jun 14, 2017
2 parents c6955dc + f2277d2 commit 8422957
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 28 deletions.
2 changes: 2 additions & 0 deletions spyder/plugins/configdialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,8 @@ def setup_page(self):
def apply_settings(self, options):
self.set_option('selected', self.current_scheme)
self.main.editor.apply_plugin_settings(['color_scheme_name'])
if self.main.ipyconsole is not None:
self.main.ipyconsole.apply_plugin_settings(['color_scheme_name'])
if self.main.historylog is not None:
self.main.historylog.apply_plugin_settings(['color_scheme_name'])
if self.main.help is not None:
Expand Down
33 changes: 16 additions & 17 deletions spyder/plugins/ipythonconsole.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
from spyder.api.preferences import PluginConfigPage
from spyder.py3compat import (iteritems, PY2, to_binary_string,
to_text_string)
from spyder.utils.ipython.style import create_qss_style
from spyder.utils.qthelpers import create_action, MENU_SEPARATOR
from spyder.utils import icon_manager as ima
from spyder.utils import encoding, programs
Expand Down Expand Up @@ -316,17 +317,6 @@ def setup_page(self):
comp_layout.addWidget(comp_box)
comp_group.setLayout(comp_layout)

# Background Color Group
bg_group = QGroupBox(_("Background color"))
light_radio = self.create_radiobutton(_("Light background"),
'light_color')
dark_radio = self.create_radiobutton(_("Dark background"),
'dark_color')
bg_layout = QVBoxLayout()
bg_layout.addWidget(light_radio)
bg_layout.addWidget(dark_radio)
bg_group.setLayout(bg_layout)

# Source Code Group
source_code_group = QGroupBox(_("Source code"))
buffer_spin = self.create_spinbox(
Expand Down Expand Up @@ -569,7 +559,7 @@ def setup_page(self):
# --- Tabs organization ---
tabs = QTabWidget()
tabs.addTab(self.create_tab(interface_group, comp_group,
bg_group, source_code_group), _("Display"))
source_code_group), _("Display"))
tabs.addTab(self.create_tab(pylab_group, backend_group, inline_group),
_("Graphics"))
tabs.addTab(self.create_tab(run_lines_group, run_file_group),
Expand Down Expand Up @@ -674,12 +664,16 @@ def apply_plugin_settings(self, options):
font_o = self.get_plugin_font()
help_n = 'connect_to_oi'
help_o = CONF.get('help', 'connect/ipython_console')
color_scheme_n = 'color_scheme_name'
color_scheme_o = CONF.get('color_schemes', 'selected')
for client in self.clients:
control = client.get_control()
if font_n in options:
client.set_font(font_o)
if help_n in options and control is not None:
control.set_help_enabled(help_o)
if color_scheme_n in options:
client.set_color_scheme(color_scheme_o)

def toggle_view(self, checked):
"""Toggle view"""
Expand Down Expand Up @@ -1029,6 +1023,12 @@ def config_options(self):
if out_prompt_o:
spy_cfg.JupyterWidget.out_prompt = out_prompt_o

# Style
color_scheme = CONF.get('color_schemes', 'selected')
style_sheet = create_qss_style(color_scheme)[0]
spy_cfg.JupyterWidget.style_sheet = style_sheet
spy_cfg.JupyterWidget.syntax_style = color_scheme

# Editor for %edit
if CONF.get('main', 'single_instance'):
spy_cfg.JupyterWidget.editor = self.set_editor()
Expand Down Expand Up @@ -1074,11 +1074,10 @@ def additional_options(self):
in JupyterWidget config options
"""
options = dict(
pylab = self.get_option('pylab'),
autoload_pylab = self.get_option('pylab/autoload'),
sympy = self.get_option('symbolic_math'),
light_color = self.get_option('light_color'),
show_banner = self.get_option('show_banner')
pylab=self.get_option('pylab'),
autoload_pylab=self.get_option('pylab/autoload'),
sympy=self.get_option('symbolic_math'),
show_banner=self.get_option('show_banner')
)

return options
Expand Down
37 changes: 37 additions & 0 deletions spyder/plugins/tests/test_ipythonconsole.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@

from flaky import flaky
from ipykernel.serialize import serialize_object
from pygments.token import Name
import pytest
from qtpy import PYQT5, PYQT_VERSION
from qtpy.QtCore import Qt, QTimer
from qtpy.QtWidgets import QApplication

from spyder.config.gui import get_color_scheme
from spyder.config.main import CONF
from spyder.py3compat import PY2
from spyder.plugins.ipythonconsole import (IPythonConsole,
KernelConnectionDialog)
from spyder.utils.environ import listdict2envdict
from spyder.utils.ipython.style import create_style_class
from spyder.utils.test import close_message_box
from spyder.widgets.variableexplorer.collectionseditor import CollectionsEditor

Expand All @@ -43,6 +47,16 @@ def open_client_from_connection_info(connection_info, qtbot):
w.cf.setText(connection_info)
qtbot.keyClick(w, Qt.Key_Enter)

def get_console_font_color(syntax_style):
styles = create_style_class(syntax_style).styles
font_color = styles[Name]

return font_color

def get_console_background_color(style_sheet):
background_color = style_sheet.split('background-color:')[1]
background_color = background_color.split(';')[0]
return background_color

#==============================================================================
# Qt Test Fixtures
Expand All @@ -62,6 +76,29 @@ def close_console():
#==============================================================================
# Tests
#==============================================================================
@flaky(max_runs=3)
def test_console_coloring(ipyconsole, qtbot):

config_options = ipyconsole.config_options()

syntax_style = config_options.JupyterWidget.syntax_style
style_sheet = config_options.JupyterWidget.style_sheet
console_font_color = get_console_font_color(syntax_style)
console_background_color = get_console_background_color(style_sheet)

selected_color_scheme = CONF.get('color_schemes', 'selected')
color_scheme = get_color_scheme(selected_color_scheme)
editor_background_color = color_scheme['background']
editor_font_color = color_scheme['normal'][0]

console_background_color = console_background_color.replace("'", "")
editor_background_color = editor_background_color.replace("'", "")
console_font_color = console_font_color.replace("'", "")
editor_font_color = editor_font_color.replace("'", "")

assert console_background_color.strip() == editor_background_color.strip()
assert console_font_color.strip() == editor_font_color.strip()

@flaky(max_runs=3)
@pytest.mark.skipif(os.name == 'nt', reason="It doesn't work on Windows")
def test_get_env(ipyconsole, qtbot):
Expand Down
176 changes: 176 additions & 0 deletions spyder/utils/ipython/style.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
# Licensed under the terms of the MIT License
# (see spyder/__init__.py for details)

"""
Style for IPython Console
"""

# Local imports
from spyder.config.gui import get_color_scheme

# Third party imports
from pygments.style import Style
from pygments.token import Name, Keyword, Comment, String, Number, Punctuation

from qtconsole.styles import dark_color


def create_qss_style(color_scheme):
"""Returns a QSS stylesheet with Spyder color scheme settings.
The stylesheet can contain classes for:
Qt: QPlainTextEdit, QFrame, QWidget, etc
Pygments: .c, .k, .o, etc. (see PygmentsHighlighter)
IPython: .error, .in-prompt, .out-prompt, etc
"""

def give_font_weight(is_bold):
if is_bold:
return 'bold'
else:
return 'normal'

def give_font_style(is_italic):
if is_italic:
return 'italic'
else:
return 'normal'

color_scheme = get_color_scheme(color_scheme)
fon_c, fon_fw, fon_fs = color_scheme['normal']
font_color = fon_c
if dark_color(font_color):
in_prompt_color = 'navy'
out_prompt_color = 'darkred'
else:
in_prompt_color = 'lime'
out_prompt_color = 'red'
background_color = color_scheme['background']
selection_background_color = '#ccc'
error_color = 'red'
in_prompt_number_font_weight = 'bold'
out_prompt_number_font_weight = 'bold'
inverted_background_color = font_color
inverted_font_color = background_color

sheet = """QPlainTextEdit, QTextEdit, ControlWidget {{
color: {} ;
background-color: {};
selection-background-color: {}
}}
.error {{ color: {}; }}
.in-prompt {{ color: {}; }}
.in-prompt-number {{ color: {}; font-weight: {}; }}
.out-prompt {{ color: {}; }}
.out-prompt-number {{ color: {}; font-weight: {}; }}
.inverted {{ color: {}; background-color: {}; }}
"""

sheet_formatted = sheet.format(font_color, background_color,
selection_background_color,
error_color,
in_prompt_color, in_prompt_color,
in_prompt_number_font_weight,
out_prompt_color, out_prompt_color,
out_prompt_number_font_weight,
inverted_background_color,
inverted_font_color)

return (sheet_formatted, dark_color(font_color))


def create_pygments_dict(color_scheme_name):
"""
Create a dictionary that saves the given color scheme as a
Pygments style.
"""

def give_font_weight(is_bold):
if is_bold:
return 'bold'
else:
return ''

def give_font_style(is_italic):
if is_italic:
return 'italic'
else:
return ''

color_scheme = get_color_scheme(color_scheme_name)

fon_c, fon_fw, fon_fs = color_scheme['normal']
font_color = fon_c
font_font_weight = give_font_weight(fon_fw)
font_font_style = give_font_style(fon_fs)
key_c, key_fw, key_fs = color_scheme['keyword']
keyword_color = key_c
keyword_font_weight = give_font_weight(key_fw)
keyword_font_style = give_font_style(key_fs)
bui_c, bui_fw, bui_fs = color_scheme['builtin']
builtin_color = bui_c
builtin_font_weight = give_font_weight(bui_fw)
builtin_font_style = give_font_style(bui_fs)
str_c, str_fw, str_fs = color_scheme['string']
string_color = str_c
string_font_weight = give_font_weight(str_fw)
string_font_style = give_font_style(str_fs)
num_c, num_fw, num_fs = color_scheme['number']
number_color = num_c
number_font_weight = give_font_weight(num_fw)
number_font_style = give_font_style(num_fs)
com_c, com_fw, com_fs = color_scheme['comment']
comment_color = com_c
comment_font_weight = give_font_weight(com_fw)
comment_font_style = give_font_style(com_fs)
def_c, def_fw, def_fs = color_scheme['definition']
definition_color = def_c
definition_font_weight = give_font_weight(def_fw)
definition_font_style = give_font_style(def_fs)
ins_c, ins_fw, ins_fs = color_scheme['instance']
instance_color = ins_c
instance_font_weight = give_font_weight(ins_fw)
instance_font_style = give_font_style(ins_fs)

font_token = font_font_style + ' ' + font_font_weight + ' ' + font_color
definition_token = (definition_font_style + ' ' + definition_font_weight +
' ' + definition_color)
builtin_token = (builtin_font_style + ' ' + builtin_font_weight + ' ' +
builtin_color)
instance_token = (instance_font_style + ' ' + instance_font_weight + ' ' +
instance_color)
keyword_token = (keyword_font_style + ' ' + keyword_font_weight + ' ' +
keyword_color)
comment_token = (comment_font_style + ' ' + comment_font_weight + ' ' +
comment_color)
string_token = (string_font_style + ' ' + string_font_weight + ' ' +
string_color)
number_token = (number_font_style + ' ' + number_font_weight + ' ' +
number_color)

syntax_style_dic = {Name: font_token.strip(),
Name.Class: definition_token.strip(),
Name.Function: definition_token.strip(),
Name.Builtin: builtin_token.strip(),
Name.Builtin.Pseudo: instance_token.strip(),
Keyword: keyword_token.strip(),
Keyword.Type: builtin_token.strip(),
Comment: comment_token.strip(),
String: string_token.strip(),
Number: number_token.strip(),
Punctuation: font_token.strip()}

return syntax_style_dic


def create_style_class(color_scheme_name):
"""Create a Pygments Style class with the given color scheme."""

class StyleClass(Style):
default_style = ""
styles = create_pygments_dict(color_scheme_name)

return StyleClass
10 changes: 10 additions & 0 deletions spyder/widgets/ipythonconsole/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from spyder.utils import sourcecode
from spyder.utils.encoding import get_coding
from spyder.utils.environ import RemoteEnvDialog
from spyder.utils.ipython.style import create_qss_style
from spyder.utils.programs import TEMPDIR
from spyder.utils.qthelpers import (add_actions, create_action,
create_toolbutton, DialogManager,
Expand Down Expand Up @@ -202,6 +203,11 @@ def configure_shellwidget(self, give_focus=True):
self.shellwidget.sig_show_syspath.connect(self.show_syspath)
self.shellwidget.sig_show_env.connect(self.show_env)

if not create_qss_style(self.shellwidget.syntax_style)[1]:
self.shellwidget.silent_execute("%colors linux")
else:
self.shellwidget.silent_execute("%colors lightbg")

def enable_stop_button(self):
self.stop_button.setEnabled(True)

Expand Down Expand Up @@ -347,6 +353,10 @@ def set_infowidget_font(self):
font = get_font(option='rich_font')
self.infowidget.set_font(font)

def set_color_scheme(self, color_scheme):
"""Set IPython color scheme."""
self.shellwidget.set_color_scheme(color_scheme)

def shutdown(self):
"""Shutdown kernel"""
if self.get_kernel() is not None and not self.slave:
Expand Down
Loading

0 comments on commit 8422957

Please sign in to comment.