From ff78eaa35c3c92e06b77409d7f878eeff40595d2 Mon Sep 17 00:00:00 2001
From: ZyX <kp-pav@yandex.ru>
Date: Mon, 18 Aug 2014 22:45:32 +0400
Subject: [PATCH 1/8] Do not override Powerline.setup(), use .do_setup() for
 this

Same reason as for `.__init__()` which was replaced by `.init()`
---
 powerline/__init__.py | 14 ++++++++++++--
 powerline/ipython.py  |  3 +--
 powerline/shell.py    |  3 +--
 powerline/vim.py      |  3 +--
 4 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/powerline/__init__.py b/powerline/__init__.py
index dd3d37c3..1f57940e 100644
--- a/powerline/__init__.py
+++ b/powerline/__init__.py
@@ -744,11 +744,21 @@ class Powerline(object):
 	def setup(self, *args, **kwargs):
 		'''Setup the environment to use powerline.
 
-		To be overridden by subclasses, this one only saves args and kwargs and 
-		unsets shutdown_event.
+		Must not be overridden by subclasses. This one only saves setup 
+		arguments for :py:meth:`reload` method and calls :py:meth:`do_setup`.
 		'''
 		self.shutdown_event.clear()
 		self.setup_args = (args, kwargs)
+		self.do_setup(*args, **kwargs)
+
+	@staticmethod
+	def do_setup():
+		'''Function that does initialization
+
+		Should be overridden by subclasses. May accept any number of regular or 
+		keyword arguments.
+		'''
+		pass
 
 	def reload(self):
 		'''Reload powerline after update.
diff --git a/powerline/ipython.py b/powerline/ipython.py
index 7d675058..5626713e 100644
--- a/powerline/ipython.py
+++ b/powerline/ipython.py
@@ -56,6 +56,5 @@ class IpythonPowerline(Powerline):
 			mergedicts(r, self.theme_overrides[name])
 		return r
 
-	def setup(self, attr, obj):
+	def do_setup(self, attr, obj):
 		setattr(obj, attr, self)
-		super(IpythonPowerline, self).setup(attr, obj)
diff --git a/powerline/shell.py b/powerline/shell.py
index cbd55fae..5920f897 100644
--- a/powerline/shell.py
+++ b/powerline/shell.py
@@ -43,9 +43,8 @@ class ShellPowerline(Powerline):
 			for key, val in local_themes.items()
 		))
 
-	def setup(self, obj):
+	def do_setup(self, obj):
 		obj.powerline = self
-		super(ShellPowerline, self).setup(obj)
 
 
 def get_argparser(parser=None, *args, **kwargs):
diff --git a/powerline/vim.py b/powerline/vim.py
index 3594a6c0..23a59900 100644
--- a/powerline/vim.py
+++ b/powerline/vim.py
@@ -110,8 +110,7 @@ class VimPowerline(Powerline):
 		except KeyError:
 			return super(VimPowerline, self).get_config_paths()
 
-	def setup(self, pyeval=None, pycmd=None, can_replace_pyeval=True):
-		super(VimPowerline, self).setup()
+	def do_setup(self, pyeval=None, pycmd=None, can_replace_pyeval=True):
 		import __main__
 		if not pyeval:
 			pyeval = 'pyeval' if sys.version_info < (3,) else 'py3eval'

From 015a2160ce728ffb4ed25cfa950a9477b9008f8d Mon Sep 17 00:00:00 2001
From: ZyX <kp-pav@yandex.ru>
Date: Tue, 19 Aug 2014 19:05:14 +0400
Subject: [PATCH 2/8] Import sys in reload() function

It may be None sometimes
---
 powerline/__init__.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/powerline/__init__.py b/powerline/__init__.py
index 1f57940e..c19b0424 100644
--- a/powerline/__init__.py
+++ b/powerline/__init__.py
@@ -774,6 +774,7 @@ class Powerline(object):
 			may break your python code.
 		'''
 		from imp import reload
+		import sys
 		modules = self.imported_modules | set((module for module in sys.modules if module.startswith('powerline')))
 		modules_holder = []
 		for module in modules:

From 23a3dc8f3cfcd6aa0b7489a361b65191496f9100 Mon Sep 17 00:00:00 2001
From: ZyX <kp-pav@yandex.ru>
Date: Tue, 19 Aug 2014 19:05:49 +0400
Subject: [PATCH 3/8] Implement powerline reloading in libzpython bindings

---
 powerline/bindings/zsh/__init__.py   | 49 ++++++++++++++++++----------
 powerline/bindings/zsh/powerline.zsh |  2 +-
 2 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/powerline/bindings/zsh/__init__.py b/powerline/bindings/zsh/__init__.py
index 1f6ae40b..ad3fa90b 100644
--- a/powerline/bindings/zsh/__init__.py
+++ b/powerline/bindings/zsh/__init__.py
@@ -1,18 +1,22 @@
 # vim:fileencoding=utf-8:noet
 from __future__ import absolute_import, unicode_literals, division, print_function
 
-import zsh
 import atexit
+
+import zsh
+
+from weakref import WeakValueDictionary, ref
+
 from powerline.shell import ShellPowerline
 from powerline.lib import parsedotval
 from powerline.lib.unicode import unicode
 
 
-used_powerlines = []
+used_powerlines = WeakValueDictionary()
 
 
 def shutdown():
-	for powerline in used_powerlines:
+	for powerline in tuple(used_powerlines.values()):
 		powerline.shutdown()
 
 
@@ -94,17 +98,28 @@ environ = Environment()
 
 
 class ZshPowerline(ShellPowerline):
+	def init(self, **kwargs):
+		super(ZshPowerline, self).init(Args(), **kwargs)
+
 	def precmd(self):
 		self.args.last_pipe_status = zsh.pipestatus()
 		self.args.last_exit_code = zsh.last_exit_code()
 
+	def do_setup(self, zsh_globals):
+		set_prompt(self, 'PS1', 'left', None, above=True)
+		set_prompt(self, 'RPS1', 'right', None)
+		set_prompt(self, 'PS2', 'left', 'continuation')
+		set_prompt(self, 'RPS2', 'right', 'continuation')
+		set_prompt(self, 'PS3', 'left', 'select')
+		used_powerlines[id(self)] = self
+		zsh_globals['_powerline'] = self
+
 
 class Prompt(object):
-	__slots__ = ('powerline', 'side', 'savedpsvar', 'savedps', 'args', 'theme', 'above')
+	__slots__ = ('powerline', 'side', 'savedpsvar', 'savedps', 'args', 'theme', 'above', '__weakref__')
 
 	def __init__(self, powerline, side, theme, savedpsvar=None, savedps=None, above=False):
 		self.powerline = powerline
-		powerline.setup(self)
 		self.side = side
 		self.above = above
 		self.savedpsvar = savedpsvar
@@ -143,9 +158,7 @@ class Prompt(object):
 	def __del__(self):
 		if self.savedps:
 			zsh.setvalue(self.savedpsvar, self.savedps)
-		used_powerlines.remove(self.powerline)
-		if self.powerline not in used_powerlines:
-			self.powerline.shutdown()
+		self.powerline.shutdown()
 
 
 def set_prompt(powerline, psvar, side, theme, above=False):
@@ -155,18 +168,18 @@ def set_prompt(powerline, psvar, side, theme, above=False):
 		savedps = None
 	zpyvar = 'ZPYTHON_POWERLINE_' + psvar
 	prompt = Prompt(powerline, side, theme, psvar, savedps, above)
+	zsh.eval('unset ' + zpyvar)
 	zsh.set_special_string(zpyvar, prompt)
 	zsh.setvalue(psvar, '${' + zpyvar + '}')
+	return ref(prompt)
 
 
-def setup():
-	powerline = ZshPowerline(Args())
-	used_powerlines.append(powerline)
-	used_powerlines.append(powerline)
-	set_prompt(powerline, 'PS1', 'left', None, above=True)
-	set_prompt(powerline, 'RPS1', 'right', None)
-	set_prompt(powerline, 'PS2', 'left', 'continuation')
-	set_prompt(powerline, 'RPS2', 'right', 'continuation')
-	set_prompt(powerline, 'PS3', 'left', 'select')
+def reload():
+	for powerline in tuple(used_powerlines.values()):
+		powerline.reload()
+
+
+def setup(zsh_globals):
+	powerline = ZshPowerline()
+	powerline.setup(zsh_globals)
 	atexit.register(shutdown)
-	return powerline
diff --git a/powerline/bindings/zsh/powerline.zsh b/powerline/bindings/zsh/powerline.zsh
index 8a7078f1..113a306d 100644
--- a/powerline/bindings/zsh/powerline.zsh
+++ b/powerline/bindings/zsh/powerline.zsh
@@ -122,7 +122,7 @@ _powerline_setup_prompt() {
 	if test -z "${POWERLINE_NO_ZSH_ZPYTHON}" && { zmodload libzpython || zmodload zsh/zpython } &>/dev/null ; then
 		precmd_functions+=( _powerline_update_counter )
 		zpython 'from powerline.bindings.zsh import setup as _powerline_setup'
-		zpython '_powerline = _powerline_setup()'
+		zpython '_powerline_setup(globals())'
 		zpython 'del _powerline_setup'
 	else
 		if test -z "${POWERLINE_COMMAND}" ; then

From 50160e98897fb7e75d5f774b06fc7ddfda442938 Mon Sep 17 00:00:00 2001
From: ZyX <kp-pav@yandex.ru>
Date: Tue, 19 Aug 2014 21:57:23 +0400
Subject: [PATCH 4/8] Add powerline-reload function for libzpython bindings

---
 powerline/bindings/zsh/powerline.zsh | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/powerline/bindings/zsh/powerline.zsh b/powerline/bindings/zsh/powerline.zsh
index 113a306d..b75f138d 100644
--- a/powerline/bindings/zsh/powerline.zsh
+++ b/powerline/bindings/zsh/powerline.zsh
@@ -124,6 +124,11 @@ _powerline_setup_prompt() {
 		zpython 'from powerline.bindings.zsh import setup as _powerline_setup'
 		zpython '_powerline_setup(globals())'
 		zpython 'del _powerline_setup'
+		powerline-reload() {
+			zpython 'from powerline.bindings.zsh import reload as _powerline_reload'
+			zpython '_powerline_reload()'
+			zpython 'del _powerline_reload'
+		}
 	else
 		if test -z "${POWERLINE_COMMAND}" ; then
 			POWERLINE_COMMAND=( "$($POWERLINE_CONFIG shell command)" )

From b93f8d9b7bfbdd4247ae0a490363c8ce80073902 Mon Sep 17 00:00:00 2001
From: ZyX <kp-pav@yandex.ru>
Date: Tue, 19 Aug 2014 19:44:07 +0400
Subject: [PATCH 5/8] Rename Ipython to IPython (two capital letters in place
 of one)

---
 powerline/bindings/ipython/post_0_11.py | 14 +++++++-------
 powerline/bindings/ipython/pre_0_11.py  | 14 +++++++-------
 powerline/ipython.py                    | 12 ++++++------
 powerline/renderers/ipython/__init__.py |  6 +++---
 powerline/renderers/ipython/prompt.py   |  6 +++---
 tests/test_provided_config_files.py     |  4 ++--
 6 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/powerline/bindings/ipython/post_0_11.py b/powerline/bindings/ipython/post_0_11.py
index e30d8797..f119ad63 100644
--- a/powerline/bindings/ipython/post_0_11.py
+++ b/powerline/bindings/ipython/post_0_11.py
@@ -1,11 +1,11 @@
 # vim:fileencoding=utf-8:noet
-from powerline.ipython import IpythonPowerline, RewriteResult
+from powerline.ipython import IPythonPowerline, RewriteResult
 
 from IPython.core.prompts import PromptManager
 from IPython.core.hooks import TryNext
 
 
-class IpythonInfo(object):
+class IPythonInfo(object):
 	def __init__(self, shell):
 		self._shell = shell
 
@@ -18,7 +18,7 @@ class PowerlinePromptManager(PromptManager):
 	def __init__(self, prompt_powerline, non_prompt_powerline, shell):
 		prompt_powerline.setup('prompt_powerline', self)
 		non_prompt_powerline.setup('non_prompt_powerline', self)
-		self.powerline_segment_info = IpythonInfo(shell)
+		self.powerline_segment_info = IPythonInfo(shell)
 		self.shell = shell
 
 	def render(self, name, color=True, *args, **kwargs):
@@ -42,13 +42,13 @@ class PowerlinePromptManager(PromptManager):
 			return ret
 
 
-class ConfigurableIpythonPowerline(IpythonPowerline):
+class ConfigurableIPythonPowerline(IPythonPowerline):
 	def init(self, ip, is_prompt, old_widths):
 		config = ip.config.Powerline
 		self.config_overrides = config.get('config_overrides')
 		self.theme_overrides = config.get('theme_overrides', {})
 		self.paths = config.get('paths')
-		super(ConfigurableIpythonPowerline, self).init(is_prompt, old_widths)
+		super(ConfigurableIPythonPowerline, self).init(is_prompt, old_widths)
 
 
 old_prompt_manager = None
@@ -59,8 +59,8 @@ def load_ipython_extension(ip):
 
 	old_prompt_manager = ip.prompt_manager
 	old_widths = {}
-	prompt_powerline = ConfigurableIpythonPowerline(ip, True, old_widths)
-	non_prompt_powerline = ConfigurableIpythonPowerline(ip, False, old_widths)
+	prompt_powerline = ConfigurableIPythonPowerline(ip, True, old_widths)
+	non_prompt_powerline = ConfigurableIPythonPowerline(ip, False, old_widths)
 
 	ip.prompt_manager = PowerlinePromptManager(
 		prompt_powerline=prompt_powerline,
diff --git a/powerline/bindings/ipython/pre_0_11.py b/powerline/bindings/ipython/pre_0_11.py
index e740c8f3..4f6f40bc 100644
--- a/powerline/bindings/ipython/pre_0_11.py
+++ b/powerline/bindings/ipython/pre_0_11.py
@@ -1,5 +1,5 @@
 # vim:fileencoding=utf-8:noet
-from powerline.ipython import IpythonPowerline, RewriteResult
+from powerline.ipython import IPythonPowerline, RewriteResult
 from powerline.lib.unicode import string
 from IPython.Prompts import BasePrompt
 from IPython.ipapi import get as get_ipython
@@ -8,7 +8,7 @@ from IPython.ipapi import TryNext
 import re
 
 
-class IpythonInfo(object):
+class IPythonInfo(object):
 	def __init__(self, cache):
 		self._cache = cache
 
@@ -22,7 +22,7 @@ class PowerlinePrompt(BasePrompt):
 		powerline.setup('powerline', self)
 		other_powerline.setup('other_powerline', self)
 		self.powerline_last_in = powerline_last_in
-		self.powerline_segment_info = IpythonInfo(old_prompt.cache)
+		self.powerline_segment_info = IPythonInfo(old_prompt.cache)
 		self.cache = old_prompt.cache
 		if hasattr(old_prompt, 'sep'):
 			self.sep = old_prompt.sep
@@ -85,20 +85,20 @@ class PowerlinePrompt2(PowerlinePromptOut):
 	powerline_prompt_type = 'in2'
 
 
-class ConfigurableIpythonPowerline(IpythonPowerline):
+class ConfigurableIPythonPowerline(IPythonPowerline):
 	def init(self, is_prompt, old_widths, config_overrides=None, theme_overrides={}, paths=None):
 		self.config_overrides = config_overrides
 		self.theme_overrides = theme_overrides
 		self.paths = paths
-		super(ConfigurableIpythonPowerline, self).init(is_prompt, old_widths)
+		super(ConfigurableIPythonPowerline, self).init(is_prompt, old_widths)
 
 
 def setup(**kwargs):
 	ip = get_ipython()
 
 	old_widths = {}
-	prompt_powerline = ConfigurableIpythonPowerline(True, old_widths, **kwargs)
-	non_prompt_powerline = ConfigurableIpythonPowerline(False, old_widths, **kwargs)
+	prompt_powerline = ConfigurableIPythonPowerline(True, old_widths, **kwargs)
+	non_prompt_powerline = ConfigurableIPythonPowerline(False, old_widths, **kwargs)
 
 	def late_startup_hook():
 		last_in = {'nrspaces': 0}
diff --git a/powerline/ipython.py b/powerline/ipython.py
index 5626713e..8ad7c604 100644
--- a/powerline/ipython.py
+++ b/powerline/ipython.py
@@ -22,9 +22,9 @@ class RewriteResult(object):
 		return RewriteResult(self.prompt + s)
 
 
-class IpythonPowerline(Powerline):
+class IPythonPowerline(Powerline):
 	def init(self, is_prompt, old_widths):
-		super(IpythonPowerline, self).init(
+		super(IPythonPowerline, self).init(
 			'ipython',
 			renderer_module=('.prompt' if is_prompt else None),
 			use_daemon_threads=True
@@ -32,26 +32,26 @@ class IpythonPowerline(Powerline):
 		self.old_widths = old_widths
 
 	def create_renderer(self, *args, **kwargs):
-		super(IpythonPowerline, self).create_renderer(*args, **kwargs)
+		super(IPythonPowerline, self).create_renderer(*args, **kwargs)
 		self.renderer.old_widths = self.old_widths
 
 	def get_config_paths(self):
 		if self.paths:
 			return self.paths
 		else:
-			return super(IpythonPowerline, self).get_config_paths()
+			return super(IPythonPowerline, self).get_config_paths()
 
 	def get_local_themes(self, local_themes):
 		return dict(((type, {'config': self.load_theme_config(name)}) for type, name in local_themes.items()))
 
 	def load_main_config(self):
-		r = super(IpythonPowerline, self).load_main_config()
+		r = super(IPythonPowerline, self).load_main_config()
 		if self.config_overrides:
 			mergedicts(r, self.config_overrides)
 		return r
 
 	def load_theme_config(self, name):
-		r = super(IpythonPowerline, self).load_theme_config(name)
+		r = super(IPythonPowerline, self).load_theme_config(name)
 		if name in self.theme_overrides:
 			mergedicts(r, self.theme_overrides[name])
 		return r
diff --git a/powerline/renderers/ipython/__init__.py b/powerline/renderers/ipython/__init__.py
index 7d7e4c55..5361f8b8 100644
--- a/powerline/renderers/ipython/__init__.py
+++ b/powerline/renderers/ipython/__init__.py
@@ -4,7 +4,7 @@ from powerline.renderers.shell import ShellRenderer
 from powerline.theme import Theme
 
 
-class IpythonRenderer(ShellRenderer):
+class IPythonRenderer(ShellRenderer):
 	'''Powerline ipython segment renderer.'''
 	def get_segment_info(self, segment_info, mode):
 		r = self.segment_info.copy()
@@ -33,8 +33,8 @@ class IpythonRenderer(ShellRenderer):
 				match['theme'].shutdown()
 
 	def render(self, *args, **kwargs):
-		# XXX super(ShellRenderer), *not* super(IpythonRenderer)
+		# XXX super(ShellRenderer), *not* super(IPythonRenderer)
 		return super(ShellRenderer, self).render(*args, **kwargs)
 
 
-renderer = IpythonRenderer
+renderer = IPythonRenderer
diff --git a/powerline/renderers/ipython/prompt.py b/powerline/renderers/ipython/prompt.py
index a1103ec8..8516c889 100644
--- a/powerline/renderers/ipython/prompt.py
+++ b/powerline/renderers/ipython/prompt.py
@@ -1,12 +1,12 @@
 # vim:fileencoding=utf-8:noet
 
-from powerline.renderers.ipython import IpythonRenderer
+from powerline.renderers.ipython import IPythonRenderer
 
 
-class IpythonPromptRenderer(IpythonRenderer):
+class IPythonPromptRenderer(IPythonRenderer):
 	'''Powerline ipython prompt renderer'''
 	escape_hl_start = '\x01'
 	escape_hl_end = '\x02'
 
 
-renderer = IpythonPromptRenderer
+renderer = IPythonPromptRenderer
diff --git a/tests/test_provided_config_files.py b/tests/test_provided_config_files.py
index da160ab1..646b762a 100644
--- a/tests/test_provided_config_files.py
+++ b/tests/test_provided_config_files.py
@@ -109,9 +109,9 @@ class TestConfig(TestCase):
 			powerline.render(segment_info={'args': args})
 
 	def test_ipython(self):
-		from powerline.ipython import IpythonPowerline
+		from powerline.ipython import IPythonPowerline
 
-		class IpyPowerline(IpythonPowerline):
+		class IpyPowerline(IPythonPowerline):
 			paths = None
 			config_overrides = None
 			theme_overrides = {}

From 06175dcd747d036bdb5188865672b6100e1c7bb5 Mon Sep 17 00:00:00 2001
From: ZyX <kp-pav@yandex.ru>
Date: Tue, 19 Aug 2014 19:54:54 +0400
Subject: [PATCH 6/8] Refactor IPython bindings

- Replaced two powerline objects with one powerline object utilizing
  RendererProxy proxy class that holds two Renderer instances.
- Made .setup() functions do something more meaningful.
---
 powerline/bindings/ipython/post_0_11.py | 31 +++++++---------
 powerline/bindings/ipython/pre_0_11.py  | 49 ++++++++++++++++---------
 powerline/ipython.py                    | 14 +++----
 powerline/renderers/ipython/__init__.py | 36 +++++++++++++++++-
 powerline/renderers/ipython/prompt.py   | 12 ------
 powerline/renderers/shell/__init__.py   |  6 +--
 tests/test_provided_config_files.py     |  4 +-
 7 files changed, 90 insertions(+), 62 deletions(-)
 delete mode 100644 powerline/renderers/ipython/prompt.py

diff --git a/powerline/bindings/ipython/post_0_11.py b/powerline/bindings/ipython/post_0_11.py
index f119ad63..7148f641 100644
--- a/powerline/bindings/ipython/post_0_11.py
+++ b/powerline/bindings/ipython/post_0_11.py
@@ -1,4 +1,7 @@
 # vim:fileencoding=utf-8:noet
+
+from weakref import ref
+
 from powerline.ipython import IPythonPowerline, RewriteResult
 
 from IPython.core.prompts import PromptManager
@@ -15,18 +18,13 @@ class IPythonInfo(object):
 
 
 class PowerlinePromptManager(PromptManager):
-	def __init__(self, prompt_powerline, non_prompt_powerline, shell):
-		prompt_powerline.setup('prompt_powerline', self)
-		non_prompt_powerline.setup('non_prompt_powerline', self)
+	def __init__(self, powerline, shell):
 		self.powerline_segment_info = IPythonInfo(shell)
 		self.shell = shell
 
 	def render(self, name, color=True, *args, **kwargs):
-		if name == 'out' or name == 'rewrite':
-			powerline = self.non_prompt_powerline
-		else:
-			powerline = self.prompt_powerline
-		res = powerline.render(
+		res = self.powerline.render(
+			is_prompt=name.startswith('in'),
 			side='left',
 			output_width=True,
 			output_raw=not color,
@@ -43,12 +41,12 @@ class PowerlinePromptManager(PromptManager):
 
 
 class ConfigurableIPythonPowerline(IPythonPowerline):
-	def init(self, ip, is_prompt, old_widths):
+	def init(self, ip):
 		config = ip.config.Powerline
 		self.config_overrides = config.get('config_overrides')
 		self.theme_overrides = config.get('theme_overrides', {})
 		self.paths = config.get('paths')
-		super(ConfigurableIPythonPowerline, self).init(is_prompt, old_widths)
+		super(ConfigurableIPythonPowerline, self).init()
 
 
 old_prompt_manager = None
@@ -58,19 +56,16 @@ def load_ipython_extension(ip):
 	global old_prompt_manager
 
 	old_prompt_manager = ip.prompt_manager
-	old_widths = {}
-	prompt_powerline = ConfigurableIPythonPowerline(ip, True, old_widths)
-	non_prompt_powerline = ConfigurableIPythonPowerline(ip, False, old_widths)
+	powerline = ConfigurableIPythonPowerline(ip)
 
 	ip.prompt_manager = PowerlinePromptManager(
-		prompt_powerline=prompt_powerline,
-		non_prompt_powerline=non_prompt_powerline,
-		shell=ip.prompt_manager.shell
+		powerline=powerline,
+		shell=ip.prompt_manager.shell,
 	)
+	powerline.setup(ref(ip.prompt_manager))
 
 	def shutdown_hook():
-		prompt_powerline.shutdown()
-		non_prompt_powerline.shutdown()
+		powerline.shutdown()
 		raise TryNext()
 
 	ip.hooks.shutdown_hook.add(shutdown_hook)
diff --git a/powerline/bindings/ipython/pre_0_11.py b/powerline/bindings/ipython/pre_0_11.py
index 4f6f40bc..da2c315d 100644
--- a/powerline/bindings/ipython/pre_0_11.py
+++ b/powerline/bindings/ipython/pre_0_11.py
@@ -1,12 +1,16 @@
 # vim:fileencoding=utf-8:noet
+
+import re
+
+from weakref import ref
+
 from powerline.ipython import IPythonPowerline, RewriteResult
 from powerline.lib.unicode import string
+
 from IPython.Prompts import BasePrompt
 from IPython.ipapi import get as get_ipython
 from IPython.ipapi import TryNext
 
-import re
-
 
 class IPythonInfo(object):
 	def __init__(self, cache):
@@ -18,9 +22,7 @@ class IPythonInfo(object):
 
 
 class PowerlinePrompt(BasePrompt):
-	def __init__(self, powerline, other_powerline, powerline_last_in, old_prompt):
-		powerline.setup('powerline', self)
-		other_powerline.setup('other_powerline', self)
+	def __init__(self, powerline, powerline_last_in, old_prompt):
 		self.powerline_last_in = powerline_last_in
 		self.powerline_segment_info = IPythonInfo(old_prompt.cache)
 		self.cache = old_prompt.cache
@@ -35,6 +37,7 @@ class PowerlinePrompt(BasePrompt):
 	def set_p_str(self):
 		self.p_str, self.p_str_nocolor, self.powerline_prompt_width = (
 			self.powerline.render(
+				is_prompt=self.powerline_is_prompt,
 				side='left',
 				output_raw=True,
 				output_width=True,
@@ -50,6 +53,7 @@ class PowerlinePrompt(BasePrompt):
 
 class PowerlinePrompt1(PowerlinePrompt):
 	powerline_prompt_type = 'in'
+	powerline_is_prompt = True
 	rspace = re.compile(r'(\s*)$')
 
 	def __str__(self):
@@ -64,7 +68,8 @@ class PowerlinePrompt1(PowerlinePrompt):
 		self.powerline_last_in['nrspaces'] = self.nrspaces
 
 	def auto_rewrite(self):
-		return RewriteResult(self.other_powerline.render(
+		return RewriteResult(self.powerline.render(
+			is_prompt=False,
 			side='left',
 			matcher_info='rewrite',
 			segment_info=self.powerline_segment_info) + (' ' * self.nrspaces)
@@ -73,6 +78,7 @@ class PowerlinePrompt1(PowerlinePrompt):
 
 class PowerlinePromptOut(PowerlinePrompt):
 	powerline_prompt_type = 'out'
+	powerline_is_prompt = False
 
 	def set_p_str(self):
 		super(PowerlinePromptOut, self).set_p_str()
@@ -83,37 +89,46 @@ class PowerlinePromptOut(PowerlinePrompt):
 
 class PowerlinePrompt2(PowerlinePromptOut):
 	powerline_prompt_type = 'in2'
+	powerline_is_prompt = True
 
 
 class ConfigurableIPythonPowerline(IPythonPowerline):
-	def init(self, is_prompt, old_widths, config_overrides=None, theme_overrides={}, paths=None):
+	def init(self, config_overrides=None, theme_overrides={}, paths=None):
 		self.config_overrides = config_overrides
 		self.theme_overrides = theme_overrides
 		self.paths = paths
-		super(ConfigurableIPythonPowerline, self).init(is_prompt, old_widths)
+		super(ConfigurableIPythonPowerline, self).init()
+
+	def do_setup(self, wrefs):
+		for wref in wrefs:
+			obj = wref()
+			if obj is not None:
+				setattr(obj, 'powerline', self)
 
 
 def setup(**kwargs):
 	ip = get_ipython()
 
 	old_widths = {}
-	prompt_powerline = ConfigurableIPythonPowerline(True, old_widths, **kwargs)
-	non_prompt_powerline = ConfigurableIPythonPowerline(False, old_widths, **kwargs)
+	powerline = ConfigurableIPythonPowerline(**kwargs)
 
 	def late_startup_hook():
 		last_in = {'nrspaces': 0}
-		for attr, prompt_class, powerline, other_powerline in (
-			('prompt1', PowerlinePrompt1, prompt_powerline, non_prompt_powerline),
-			('prompt2', PowerlinePrompt2, prompt_powerline, None),
-			('prompt_out', PowerlinePromptOut, non_prompt_powerline, None)
+		prompts = []
+		for attr, prompt_class in (
+			('prompt1', PowerlinePrompt1),
+			('prompt2', PowerlinePrompt2),
+			('prompt_out', PowerlinePromptOut)
 		):
 			old_prompt = getattr(ip.IP.outputcache, attr)
-			setattr(ip.IP.outputcache, attr, prompt_class(powerline, other_powerline, last_in, old_prompt))
+			prompt = prompt_class(powerline, last_in, old_prompt)
+			setattr(ip.IP.outputcache, attr, prompt)
+			prompts.append(ref(prompt))
+		powerline.setup(prompts)
 		raise TryNext()
 
 	def shutdown_hook():
-		prompt_powerline.shutdown()
-		non_prompt_powerline.shutdown()
+		powerline.shutdown()
 		raise TryNext()
 
 	ip.IP.hooks.late_startup_hook.add(late_startup_hook)
diff --git a/powerline/ipython.py b/powerline/ipython.py
index 8ad7c604..7bb9d1e5 100644
--- a/powerline/ipython.py
+++ b/powerline/ipython.py
@@ -23,17 +23,11 @@ class RewriteResult(object):
 
 
 class IPythonPowerline(Powerline):
-	def init(self, is_prompt, old_widths):
+	def init(self):
 		super(IPythonPowerline, self).init(
 			'ipython',
-			renderer_module=('.prompt' if is_prompt else None),
 			use_daemon_threads=True
 		)
-		self.old_widths = old_widths
-
-	def create_renderer(self, *args, **kwargs):
-		super(IPythonPowerline, self).create_renderer(*args, **kwargs)
-		self.renderer.old_widths = self.old_widths
 
 	def get_config_paths(self):
 		if self.paths:
@@ -56,5 +50,7 @@ class IPythonPowerline(Powerline):
 			mergedicts(r, self.theme_overrides[name])
 		return r
 
-	def do_setup(self, attr, obj):
-		setattr(obj, attr, self)
+	def do_setup(self, wref):
+		obj = wref()
+		if obj:
+			setattr(obj, 'powerline', self)
diff --git a/powerline/renderers/ipython/__init__.py b/powerline/renderers/ipython/__init__.py
index 5361f8b8..1fce961e 100644
--- a/powerline/renderers/ipython/__init__.py
+++ b/powerline/renderers/ipython/__init__.py
@@ -37,4 +37,38 @@ class IPythonRenderer(ShellRenderer):
 		return super(ShellRenderer, self).render(*args, **kwargs)
 
 
-renderer = IPythonRenderer
+class IPythonPromptRenderer(IPythonRenderer):
+	'''Powerline ipython prompt (in and in2) renderer'''
+	escape_hl_start = '\x01'
+	escape_hl_end = '\x02'
+
+
+class IPythonNonPromptRenderer(IPythonRenderer):
+	'''Powerline ipython non-prompt (out and rewrite) renderer'''
+	pass
+
+
+class RendererProxy(object):
+	'''Powerline IPython renderer proxy which chooses appropriate renderer
+
+	Instantiates two renderer objects: one will be used for prompts and the 
+	other for non-prompts.
+	'''
+	def __init__(self, **kwargs):
+		old_widths = {}
+		self.non_prompt_renderer = IPythonNonPromptRenderer(old_widths=old_widths, **kwargs)
+		self.prompt_renderer = IPythonPromptRenderer(old_widths=old_widths, **kwargs)
+
+	def render_above_lines(self, *args, **kwargs):
+		return self.non_prompt_renderer.render_above_lines(*args, **kwargs)
+
+	def render(self, is_prompt, *args, **kwargs):
+		return (self.prompt_renderer if is_prompt else self.non_prompt_renderer).render(
+			*args, **kwargs)
+
+	def shutdown(self, *args, **kwargs):
+		self.prompt_renderer.shutdown(*args, **kwargs)
+		self.non_prompt_renderer.shutdown(*args, **kwargs)
+
+
+renderer = RendererProxy
diff --git a/powerline/renderers/ipython/prompt.py b/powerline/renderers/ipython/prompt.py
deleted file mode 100644
index 8516c889..00000000
--- a/powerline/renderers/ipython/prompt.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# vim:fileencoding=utf-8:noet
-
-from powerline.renderers.ipython import IPythonRenderer
-
-
-class IPythonPromptRenderer(IPythonRenderer):
-	'''Powerline ipython prompt renderer'''
-	escape_hl_start = '\x01'
-	escape_hl_end = '\x02'
-
-
-renderer = IPythonPromptRenderer
diff --git a/powerline/renderers/shell/__init__.py b/powerline/renderers/shell/__init__.py
index fdffaa25..70d9ac6a 100644
--- a/powerline/renderers/shell/__init__.py
+++ b/powerline/renderers/shell/__init__.py
@@ -24,9 +24,9 @@ class ShellRenderer(Renderer):
 
 	character_translations = Renderer.character_translations.copy()
 
-	def __init__(self, *args, **kwargs):
-		super(ShellRenderer, self).__init__(*args, **kwargs)
-		self.old_widths = {}
+	def __init__(self, old_widths=None, **kwargs):
+		super(ShellRenderer, self).__init__(**kwargs)
+		self.old_widths = old_widths if old_widths is not None else {}
 
 	def render(self, segment_info, **kwargs):
 		local_theme = segment_info.get('local_theme')
diff --git a/tests/test_provided_config_files.py b/tests/test_provided_config_files.py
index 646b762a..aeba0617 100644
--- a/tests/test_provided_config_files.py
+++ b/tests/test_provided_config_files.py
@@ -118,11 +118,11 @@ class TestConfig(TestCase):
 
 		segment_info = Args(prompt_count=1)
 
-		with IpyPowerline(True, {}) as powerline:
+		with IpyPowerline() as powerline:
 			for prompt_type in ['in', 'in2']:
 				powerline.render(matcher_info=prompt_type, segment_info=segment_info)
 				powerline.render(matcher_info=prompt_type, segment_info=segment_info)
-		with IpyPowerline(False, {}) as powerline:
+		with IpyPowerline() as powerline:
 			for prompt_type in ['out', 'rewrite']:
 				powerline.render(matcher_info=prompt_type, segment_info=segment_info)
 				powerline.render(matcher_info=prompt_type, segment_info=segment_info)

From 137fffc9f78827ef60d58cad0da190a8429dc017 Mon Sep 17 00:00:00 2001
From: ZyX <kp-pav@yandex.ru>
Date: Tue, 19 Aug 2014 21:29:32 +0400
Subject: [PATCH 7/8] Add `%powerline reload` IPython magic function

---
 powerline/bindings/ipython/post_0_11.py | 52 +++++++++++++++++++------
 powerline/bindings/ipython/pre_0_11.py  | 48 ++++++++++++++---------
 powerline/ipython.py                    |  9 +++--
 3 files changed, 75 insertions(+), 34 deletions(-)

diff --git a/powerline/bindings/ipython/post_0_11.py b/powerline/bindings/ipython/post_0_11.py
index 7148f641..5586fee4 100644
--- a/powerline/bindings/ipython/post_0_11.py
+++ b/powerline/bindings/ipython/post_0_11.py
@@ -5,7 +5,21 @@ from weakref import ref
 from powerline.ipython import IPythonPowerline, RewriteResult
 
 from IPython.core.prompts import PromptManager
-from IPython.core.hooks import TryNext
+from IPython.core.magic import Magics, magics_class, line_magic
+
+
+@magics_class
+class PowerlineMagics(Magics):
+	def __init__(self, ip, powerline):
+		super(PowerlineMagics, self).__init__(ip)
+		self._powerline = powerline
+
+	@line_magic
+	def powerline(self, line):
+		if line == 'reload':
+			self._powerline.reload()
+		else:
+			raise ValueError('Expected `reload`, but got {0}'.format(line))
 
 
 class IPythonInfo(object):
@@ -19,6 +33,7 @@ class IPythonInfo(object):
 
 class PowerlinePromptManager(PromptManager):
 	def __init__(self, powerline, shell):
+		self.powerline = powerline
 		self.powerline_segment_info = IPythonInfo(shell)
 		self.shell = shell
 
@@ -40,6 +55,17 @@ class PowerlinePromptManager(PromptManager):
 			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()
+
+
 class ConfigurableIPythonPowerline(IPythonPowerline):
 	def init(self, ip):
 		config = ip.config.Powerline
@@ -48,25 +74,29 @@ class ConfigurableIPythonPowerline(IPythonPowerline):
 		self.paths = config.get('paths')
 		super(ConfigurableIPythonPowerline, self).init()
 
+	def do_setup(self, ip, shutdown_hook):
+		prompt_manager = PowerlinePromptManager(
+			powerline=self,
+			shell=ip.prompt_manager.shell,
+		)
+		magics = PowerlineMagics(ip, self)
+		shutdown_hook.powerline = ref(self)
+
+		ip.prompt_manager = prompt_manager
+		ip.register_magics(magics)
+
 
 old_prompt_manager = None
 
 
 def load_ipython_extension(ip):
 	global old_prompt_manager
-
 	old_prompt_manager = ip.prompt_manager
+
 	powerline = ConfigurableIPythonPowerline(ip)
+	shutdown_hook = ShutdownHook()
 
-	ip.prompt_manager = PowerlinePromptManager(
-		powerline=powerline,
-		shell=ip.prompt_manager.shell,
-	)
-	powerline.setup(ref(ip.prompt_manager))
-
-	def shutdown_hook():
-		powerline.shutdown()
-		raise TryNext()
+	powerline.setup(ip, shutdown_hook)
 
 	ip.hooks.shutdown_hook.add(shutdown_hook)
 
diff --git a/powerline/bindings/ipython/pre_0_11.py b/powerline/bindings/ipython/pre_0_11.py
index da2c315d..d5389efe 100644
--- a/powerline/bindings/ipython/pre_0_11.py
+++ b/powerline/bindings/ipython/pre_0_11.py
@@ -23,6 +23,7 @@ class IPythonInfo(object):
 
 class PowerlinePrompt(BasePrompt):
 	def __init__(self, powerline, powerline_last_in, old_prompt):
+		self.powerline = powerline
 		self.powerline_last_in = powerline_last_in
 		self.powerline_segment_info = IPythonInfo(old_prompt.cache)
 		self.cache = old_prompt.cache
@@ -99,36 +100,45 @@ class ConfigurableIPythonPowerline(IPythonPowerline):
 		self.paths = paths
 		super(ConfigurableIPythonPowerline, self).init()
 
-	def do_setup(self, wrefs):
-		for wref in wrefs:
-			obj = wref()
-			if obj is not None:
-				setattr(obj, 'powerline', self)
+	def ipython_magic(self, ip, parameter_s=''):
+		if parameter_s == 'reload':
+			self.reload()
+		else:
+			raise ValueError('Expected `reload`, but got {0}'.format(parameter_s))
 
-
-def setup(**kwargs):
-	ip = get_ipython()
-
-	old_widths = {}
-	powerline = ConfigurableIPythonPowerline(**kwargs)
-
-	def late_startup_hook():
+	def do_setup(self, ip, shutdown_hook):
 		last_in = {'nrspaces': 0}
-		prompts = []
 		for attr, prompt_class in (
 			('prompt1', PowerlinePrompt1),
 			('prompt2', PowerlinePrompt2),
 			('prompt_out', PowerlinePromptOut)
 		):
 			old_prompt = getattr(ip.IP.outputcache, attr)
-			prompt = prompt_class(powerline, last_in, old_prompt)
+			prompt = prompt_class(self, last_in, old_prompt)
 			setattr(ip.IP.outputcache, attr, prompt)
-			prompts.append(ref(prompt))
-		powerline.setup(prompts)
+		ip.expose_magic('powerline', self.ipython_magic)
+		shutdown_hook.powerline = ref(self)
+
+
+class ShutdownHook(object):
+	powerline = lambda: None
+
+	def __call__(self):
+		from IPython.ipapi import TryNext
+		powerline = self.powerline()
+		if powerline is not None:
+			powerline.shutdown()
 		raise TryNext()
 
-	def shutdown_hook():
-		powerline.shutdown()
+
+def setup(**kwargs):
+	ip = get_ipython()
+
+	powerline = ConfigurableIPythonPowerline(**kwargs)
+	shutdown_hook = ShutdownHook()
+
+	def late_startup_hook():
+		powerline.setup(ip, shutdown_hook)
 		raise TryNext()
 
 	ip.IP.hooks.late_startup_hook.add(late_startup_hook)
diff --git a/powerline/ipython.py b/powerline/ipython.py
index 7bb9d1e5..f658f111 100644
--- a/powerline/ipython.py
+++ b/powerline/ipython.py
@@ -50,7 +50,8 @@ class IPythonPowerline(Powerline):
 			mergedicts(r, self.theme_overrides[name])
 		return r
 
-	def do_setup(self, wref):
-		obj = wref()
-		if obj:
-			setattr(obj, 'powerline', self)
+	def do_setup(self, wrefs):
+		for wref in wrefs:
+			obj = wref()
+			if obj is not None:
+				setattr(obj, 'powerline', self)

From 28bcb0134516f6557e52ba26bee59342ed516641 Mon Sep 17 00:00:00 2001
From: ZyX <kp-pav@yandex.ru>
Date: Tue, 19 Aug 2014 22:12:33 +0400
Subject: [PATCH 8/8] Update documentation

---
 docs/source/develop/segments.rst |  2 ++
 docs/source/tips-and-tricks.rst  | 43 ++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/docs/source/develop/segments.rst b/docs/source/develop/segments.rst
index 63ea35db..1715d3a7 100644
--- a/docs/source/develop/segments.rst
+++ b/docs/source/develop/segments.rst
@@ -53,6 +53,8 @@ Detailed description of used dictionary keys:
     Text displayed by segment. Should be a ``unicode`` (Python2) or ``str`` 
     (Python3) instance.
 
+.. _dev-segments-draw_inner_divider:
+
 ``draw_hard_divider``, ``draw_soft_divider``, ``draw_inner_divider``
     Determines whether given divider should be drawn. All have the same meaning 
     as :ref:`the similar keys in configuration <config-themes-seg-draw_divider>` 
diff --git a/docs/source/tips-and-tricks.rst b/docs/source/tips-and-tricks.rst
index b2216b12..4be6c764 100644
--- a/docs/source/tips-and-tricks.rst
+++ b/docs/source/tips-and-tricks.rst
@@ -49,3 +49,46 @@ of the fonts play a role in whether or not the > or the < separators showing up
 or not. Using font size 12, glyphs on the right hand side of the powerline are 
 present, but the ones on the left don't. Pixel size 14, brings the reverse 
 problem. Font size 13 seems to work just fine.
+
+Reloading powerline after update
+================================
+
+Once you have updated powerline you generally have the following options:
+
+#. Restart the application you are using it in. This is the safest one. Will not 
+   work if the application uses ``powerline-daemon``.
+#. For shell and tmux bindings (except for zsh with libzpython): do not do 
+   anything if you do not use ``powerline-daemon``, run ``powerline-daemon 
+   --replace`` if you do.
+#. Use powerline reloading feature.
+
+    .. warning::
+      This feature is an unsafe one. It is not guaranteed to work always, it may 
+      render your Python constantly error out in place of displaying powerline 
+      and sometimes may render your application useless, forcing you to 
+      restart.
+
+      *Do not report any bugs occurred when using this feature unless you know 
+      both what caused it and how this can be fixed.*
+
+   * When using zsh with libzpython use
+
+     .. code-block:: bash
+
+        powerline-reload
+
+     .. note:: This shell function is only defined when using libzpython.
+
+   * When using IPython use
+
+     ::
+
+        %powerline reload
+
+   * When using Vim use
+
+     .. code-block:: Vim
+
+        py powerline.reload()
+        " or (depending on Python version you are using)
+        py3 powerline.reload()