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).
This commit is contained in:
Foo 2016-07-08 21:57:25 +03:00
parent 2954c83330
commit 5b16efa6ec
3 changed files with 133 additions and 94 deletions

View File

@ -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,23 +71,6 @@ if has_prompt_manager:
else:
return ret
class ShutdownHook(object):
powerline = lambda: None
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
@ -87,13 +84,9 @@ class ConfigurableIPythonPowerline(IPythonPowerline):
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,20 +94,6 @@ 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)
@ -122,20 +101,23 @@ class ConfigurableIPythonPowerline(IPythonPowerline):
def load_ipython_extension(ip):
if has_prompt_manager:
shutdown_hook = ShutdownHook(ip)
powerline = ConfigurableIPythonPowerline(ip)
shutdown_hook = ShutdownHook()
powerline.setup(ip, shutdown_hook)
ip.hooks.shutdown_hook.add(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

View File

@ -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))

View File

@ -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, [])