From 5b16efa6ecde4cbcc506805830bb4b71c3e576f2 Mon Sep 17 00:00:00 2001 From: Foo Date: Fri, 8 Jul 2016 21:57:25 +0300 Subject: [PATCH] Switch how IPython is configured Now user is expected to use from powerline.bindings.ipython.since_5 import PowerlinePrompts c.TerminalInteractiveShell.prompts_class = PowerlinePrompts Note: still using hacks, now different ones. Main problem is that I cannot just register a powerline pygments style, user needs to specify his own style in order to change highlighting of non-powerline tokens (i.e. of everything, but prompt). --- powerline/bindings/ipython/post_0_11.py | 114 ++++++++++-------------- powerline/bindings/ipython/since_5.py | 79 ++++++++++++++++ powerline/renderers/ipython/since_5.py | 34 ++----- 3 files changed, 133 insertions(+), 94 deletions(-) create mode 100644 powerline/bindings/ipython/since_5.py diff --git a/powerline/bindings/ipython/post_0_11.py b/powerline/bindings/ipython/post_0_11.py index 7d2174ae..6c1efb15 100644 --- a/powerline/bindings/ipython/post_0_11.py +++ b/powerline/bindings/ipython/post_0_11.py @@ -2,12 +2,12 @@ from __future__ import (unicode_literals, division, absolute_import, print_function) from weakref import ref +from warnings import warn try: from IPython.core.prompts import PromptManager has_prompt_manager = True except ImportError: - from IPython.terminal.interactiveshell import TerminalInteractiveShell has_prompt_manager = False from IPython.core.magic import Magics, magics_class, line_magic @@ -15,8 +15,6 @@ from powerline.ipython import IPythonPowerline, IPythonInfo if has_prompt_manager: from powerline.ipython import RewriteResult -else: - from powerline.renderers.ipython.since_5 import PowerlinePromptStyle, PowerlinePrompts @magics_class @@ -33,6 +31,22 @@ class PowerlineMagics(Magics): raise ValueError('Expected `reload`, but got {0}'.format(line)) +old_prompt_manager = None + + +class ShutdownHook(object): + def __init__(self, ip): + self.powerline = lambda: None + ip.hooks.shutdown_hook.add(self) + + def __call__(self): + from IPython.core.hooks import TryNext + powerline = self.powerline() + if powerline is not None: + powerline.shutdown() + raise TryNext() + + if has_prompt_manager: class PowerlinePromptManager(PromptManager): def __init__(self, powerline, shell): @@ -57,43 +71,22 @@ if has_prompt_manager: else: return ret + class ConfigurableIPythonPowerline(IPythonPowerline): + def init(self, ip): + config = ip.config.Powerline + self.config_overrides = config.get('config_overrides') + self.theme_overrides = config.get('theme_overrides', {}) + self.config_paths = config.get('config_paths') + if has_prompt_manager: + renderer_module = '.pre_5' + else: + renderer_module = '.since_5' + super(ConfigurableIPythonPowerline, self).init( + renderer_module=renderer_module) -class ShutdownHook(object): - powerline = lambda: None + def do_setup(self, ip, shutdown_hook): + global old_prompt_manager - def __call__(self): - from IPython.core.hooks import TryNext - powerline = self.powerline() - if powerline is not None: - powerline.shutdown() - raise TryNext() - - -old_prompt_manager = None -old_style = None -old_prompts = None - - -class ConfigurableIPythonPowerline(IPythonPowerline): - def init(self, ip): - config = ip.config.Powerline - self.config_overrides = config.get('config_overrides') - self.theme_overrides = config.get('theme_overrides', {}) - self.config_paths = config.get('config_paths') - if has_prompt_manager: - renderer_module = '.pre_5' - else: - renderer_module = '.since_5' - super(ConfigurableIPythonPowerline, self).init( - renderer_module=renderer_module) - - - def do_setup(self, ip, shutdown_hook): - global old_prompt_manager - global old_style - global old_prompts - - if has_prompt_manager: if old_prompt_manager is None: old_prompt_manager = ip.prompt_manager prompt_manager = PowerlinePromptManager( @@ -101,41 +94,30 @@ class ConfigurableIPythonPowerline(IPythonPowerline): shell=ip.prompt_manager.shell, ) ip.prompt_manager = prompt_manager - else: - if ip.pt_cli is not None: - if old_style is None: - old_style = ip.pt_cli.application.style - prev_style = ip.pt_cli.application.style - while isinstance(prev_style, PowerlinePromptStyle): - prev_style = prev_style.get_style() - new_style = PowerlinePromptStyle(lambda: prev_style) - ip.pt_cli.application.style = new_style - ip.pt_cli.renderer.style = new_style - if old_prompts is None: - old_prompts = ip.prompts - ip.prompts = PowerlinePrompts(ip.prompts, self) - - magics = PowerlineMagics(ip, self) - shutdown_hook.powerline = ref(self) - ip.register_magics(magics) + magics = PowerlineMagics(ip, self) + shutdown_hook.powerline = ref(self) + ip.register_magics(magics) def load_ipython_extension(ip): - powerline = ConfigurableIPythonPowerline(ip) - shutdown_hook = ShutdownHook() - - powerline.setup(ip, shutdown_hook) - - ip.hooks.shutdown_hook.add(shutdown_hook) + if has_prompt_manager: + shutdown_hook = ShutdownHook(ip) + powerline = ConfigurableIPythonPowerline(ip) + powerline.setup(ip, shutdown_hook) + else: + from powerline.bindings.ipython.since_5 import PowerlinePrompts + ip.prompts_class = PowerlinePrompts + ip.prompts = PowerlinePrompts(ip) + warn(DeprecationWarning( + 'post_0_11 extension is deprecated since IPython 5, use\n' + ' from powerline.bindings.ipython.since_5 import PowerlinePrompts\n' + ' c.TerminalInteractiveShell.prompts_class = PowerlinePrompts\n' + )) def unload_ipython_extension(ip): + global old_prompt_manager if old_prompt_manager is not None: ip.prompt_manager = old_prompt_manager - if old_style is not None: - ip.pt_cli.application.style = old_style - ip.pt_cli.renderer.style = old_style - ip.prompts = old_prompts old_prompt_manager = None - old_style = None diff --git a/powerline/bindings/ipython/since_5.py b/powerline/bindings/ipython/since_5.py new file mode 100644 index 00000000..ab92d6d6 --- /dev/null +++ b/powerline/bindings/ipython/since_5.py @@ -0,0 +1,79 @@ +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +from weakref import ref + +from IPython.terminal.prompts import Prompts +from pygments.token import Token # NOQA + +from powerline.ipython import IPythonPowerline +from powerline.renderers.ipython.since_5 import PowerlinePromptStyle +from powerline.bindings.ipython.post_0_11 import PowerlineMagics, ShutdownHook + + +class ConfigurableIPythonPowerline(IPythonPowerline): + def init(self, ip): + config = ip.config.Powerline + self.config_overrides = config.get('config_overrides') + self.theme_overrides = config.get('theme_overrides', {}) + self.config_paths = config.get('config_paths') + super(ConfigurableIPythonPowerline, self).init( + renderer_module='.since_5') + + def do_setup(self, ip, prompts, shutdown_hook): + prompts.powerline = self + + saved_msfn = ip._make_style_from_name + + if hasattr(saved_msfn, 'powerline_original'): + saved_msfn = saved_msfn.powerline_original + + def _make_style_from_name(ip, name): + prev_style = saved_msfn(name) + new_style = PowerlinePromptStyle(lambda: prev_style) + return new_style + + _make_style_from_name.powerline_original = saved_msfn + + if not isinstance(ip._style, PowerlinePromptStyle): + prev_style = ip._style + ip._style = PowerlinePromptStyle(lambda: prev_style) + + if not isinstance(saved_msfn, type(self.init)): + _saved_msfn = saved_msfn + saved_msfn = lambda: _saved_msfn(ip) + + ip._make_style_from_name = _make_style_from_name + + magics = PowerlineMagics(ip, self) + ip.register_magics(magics) + + if shutdown_hook: + shutdown_hook.powerline = ref(self) + + +class PowerlinePrompts(Prompts): + '''Class that returns powerline prompts + ''' + def __init__(self, shell): + shutdown_hook = ShutdownHook(shell) + powerline = ConfigurableIPythonPowerline(shell) + self.shell = shell + powerline.do_setup(shell, self, shutdown_hook) + self.last_output_count = None + self.last_output = {} + + for prompt in ('in', 'continuation', 'rewrite', 'out'): + exec(( + 'def {0}_prompt_tokens(self, *args, **kwargs):\n' + ' if self.last_output_count != self.shell.execution_count:\n' + ' self.last_output.clear()\n' + ' self.last_output_count = self.shell.execution_count\n' + ' if "{0}" not in self.last_output:\n' + ' self.last_output["{0}"] = self.powerline.render(' + ' side="left",' + ' matcher_info="{1}",' + ' segment_info=self.shell,' + ' ) + [(Token.Generic.Prompt, " ")]\n' + ' return self.last_output["{0}"]' + ).format(prompt, 'in2' if prompt == 'continuation' else prompt)) diff --git a/powerline/renderers/ipython/since_5.py b/powerline/renderers/ipython/since_5.py index 17e05453..8a26da72 100644 --- a/powerline/renderers/ipython/since_5.py +++ b/powerline/renderers/ipython/since_5.py @@ -12,10 +12,10 @@ except ImportError: from pygments.token import Token from prompt_toolkit.styles import DynamicStyle, Attrs -from IPython.terminal.prompts import Prompts from powerline.renderers.ipython import IPythonRenderer from powerline.ipython import IPythonInfo +from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE PowerlinePromptToken = Token.Generic.Prompt.Powerline @@ -30,39 +30,13 @@ class PowerlineStyleDict(defaultdict): return defaultdict.__new__(cls) def __init__(self, missing_func): - super(IPythonPygmentsStyle, self).__init__() + super(PowerlineStyleDict, self).__init__() self.missing_func = missing_func def __missing__(self, key): return self.missing_func(key) -class PowerlinePrompts(Prompts): - '''Class that returns powerline prompts - ''' - def __init__(self, old_prompts, powerline): - self.old_prompts = old_prompts - self.shell = old_prompts.shell - self.powerline = powerline - self.last_output_count = None - self.last_output = {} - - for prompt in ('in', 'continuation', 'rewrite', 'out'): - exec(( - 'def {0}_prompt_tokens(self, *args, **kwargs):\n' - ' if self.last_output_count != self.shell.execution_count:\n' - ' self.last_output.clear()\n' - ' self.last_output_count = self.shell.execution_count\n' - ' if "{0}" not in self.last_output:\n' - ' self.last_output["{0}"] = self.powerline.render(' - ' side="left",' - ' matcher_info="{1}",' - ' segment_info=IPythonInfo(self.shell),' - ' ) + [(Token.Generic.Prompt, " ")]\n' - ' return self.last_output["{0}"]' - ).format(prompt, 'in2' if prompt == 'continuation' else prompt)) - - class PowerlinePromptStyle(DynamicStyle): def get_attrs_for_token(self, token): if ( @@ -108,6 +82,10 @@ class PowerlinePromptStyle(DynamicStyle): class IPythonPygmentsRenderer(IPythonRenderer): reduce_initial = [] + def get_segment_info(self, segment_info, mode): + return super(IPythonPygmentsRenderer, self).get_segment_info( + IPythonInfo(segment_info), mode) + @staticmethod def hl_join(segments): return reduce(operator.iadd, segments, [])