diff --git a/docs/source/configuration/reference.rst b/docs/source/configuration/reference.rst
index 8f043e43..63181e44 100644
--- a/docs/source/configuration/reference.rst
+++ b/docs/source/configuration/reference.rst
@@ -283,6 +283,16 @@ ascii                       Theme without any unicode characters at all
     background colors, while the ``soft`` dividers are used to divide 
     segments with the same background color.
 
+.. _config-themes-cursor_space:
+
+``cursor_space``
+    Space reserved for user input in shell bindings. It is measured in per 
+    cents.
+
+``cursor_columns``
+    Space reserved for user input in shell bindings. Unlike :ref:`cursor_space 
+    <config-themes-cursor_space>` it is measured in absolute amout of columns.
+
 .. _config-themes-segment_data:
 
 ``segment_data``
diff --git a/powerline/bindings/bash/powerline.sh b/powerline/bindings/bash/powerline.sh
index b267c076..93670555 100644
--- a/powerline/bindings/bash/powerline.sh
+++ b/powerline/bindings/bash/powerline.sh
@@ -42,7 +42,7 @@ _powerline_init_tmux_support() {
 _powerline_prompt() {
 	# Arguments: side, last_exit_code, jobnum
 	$POWERLINE_COMMAND shell $1 \
-		-w "${COLUMNS:-$(_powerline_columns_fallback)}" \
+		--width="${COLUMNS:-$(_powerline_columns_fallback)}" \
 		-r bash_prompt \
 		--last_exit_code=$2 \
 		--jobnum=$3 \
diff --git a/powerline/bindings/ipython/post_0_11.py b/powerline/bindings/ipython/post_0_11.py
index f10006b9..ec3a4769 100644
--- a/powerline/bindings/ipython/post_0_11.py
+++ b/powerline/bindings/ipython/post_0_11.py
@@ -22,15 +22,14 @@ class PowerlinePromptManager(PromptManager):
 		self.shell = shell
 
 	def render(self, name, color=True, *args, **kwargs):
-		width = None if name == 'in' else self.width
 		if name == 'out' or name == 'rewrite':
 			powerline = self.non_prompt_powerline
 		else:
 			powerline = self.prompt_powerline
 		res = powerline.render(
+			side='left',
 			output_width=True,
 			output_raw=not color,
-			width=width,
 			matcher_info=name,
 			segment_info=self.powerline_segment_info,
 		)
@@ -44,12 +43,12 @@ class PowerlinePromptManager(PromptManager):
 
 
 class ConfigurableIpythonPowerline(IpythonPowerline):
-	def __init__(self, ip, is_prompt):
+	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)
+		super(ConfigurableIpythonPowerline, self).__init__(is_prompt, old_widths)
 
 
 old_prompt_manager = None
@@ -59,8 +58,9 @@ def load_ipython_extension(ip):
 	global old_prompt_manager
 
 	old_prompt_manager = ip.prompt_manager
-	prompt_powerline = ConfigurableIpythonPowerline(ip, True)
-	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 e10e4d5c..ed6ad75e 100644
--- a/powerline/bindings/ipython/pre_0_11.py
+++ b/powerline/bindings/ipython/pre_0_11.py
@@ -32,14 +32,14 @@ class PowerlinePrompt(BasePrompt):
 		self.set_p_str()
 		return string(self.p_str)
 
-	def set_p_str(self, width=None):
+	def set_p_str(self):
 		self.p_str, self.p_str_nocolor, self.powerline_prompt_width = (
 			self.powerline.render(
+				side='left',
 				output_raw=True,
 				output_width=True,
 				segment_info=self.powerline_segment_info,
 				matcher_info=self.powerline_prompt_type,
-				width=width
 			)
 		)
 
@@ -61,20 +61,21 @@ class PowerlinePrompt1(PowerlinePrompt):
 	def set_p_str(self):
 		super(PowerlinePrompt1, self).set_p_str()
 		self.nrspaces = len(self.rspace.search(self.p_str_nocolor).group())
-		self.prompt_text_len = self.powerline_prompt_width - self.nrspaces
 		self.powerline_last_in['nrspaces'] = self.nrspaces
-		self.powerline_last_in['prompt_text_len'] = self.prompt_text_len
 
 	def auto_rewrite(self):
-		return RewriteResult(self.other_powerline.render(matcher_info='rewrite', width=self.prompt_text_len, segment_info=self.powerline_segment_info)
-						+ (' ' * self.nrspaces))
+		return RewriteResult(self.other_powerline.render(
+			side='left',
+			matcher_info='rewrite',
+			segment_info=self.powerline_segment_info) + (' ' * self.nrspaces)
+		)
 
 
 class PowerlinePromptOut(PowerlinePrompt):
 	powerline_prompt_type = 'out'
 
 	def set_p_str(self):
-		super(PowerlinePromptOut, self).set_p_str(width=self.powerline_last_in['prompt_text_len'])
+		super(PowerlinePromptOut, self).set_p_str()
 		spaces = ' ' * self.powerline_last_in['nrspaces']
 		self.p_str += spaces
 		self.p_str_nocolor += spaces
@@ -85,21 +86,22 @@ class PowerlinePrompt2(PowerlinePromptOut):
 
 
 class ConfigurableIpythonPowerline(IpythonPowerline):
-	def __init__(self, is_prompt, config_overrides=None, theme_overrides={}, paths=None):
+	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)
+		super(ConfigurableIpythonPowerline, self).__init__(is_prompt, old_widths)
 
 
 def setup(**kwargs):
 	ip = get_ipython()
 
-	prompt_powerline = ConfigurableIpythonPowerline(True, **kwargs)
-	non_prompt_powerline = ConfigurableIpythonPowerline(False, **kwargs)
+	old_widths = {}
+	prompt_powerline = ConfigurableIpythonPowerline(True, old_widths, **kwargs)
+	non_prompt_powerline = ConfigurableIpythonPowerline(False, old_widths, **kwargs)
 
 	def late_startup_hook():
-		last_in = {'nrspaces': 0, 'prompt_text_len': None}
+		last_in = {'nrspaces': 0}
 		for attr, prompt_class, powerline, other_powerline in (
 			('prompt1', PowerlinePrompt1, prompt_powerline, non_prompt_powerline),
 			('prompt2', PowerlinePrompt2, prompt_powerline, None),
diff --git a/powerline/bindings/shell/powerline.sh b/powerline/bindings/shell/powerline.sh
index 89da8d8f..d197c5be 100644
--- a/powerline/bindings/shell/powerline.sh
+++ b/powerline/bindings/shell/powerline.sh
@@ -135,7 +135,7 @@ _powerline_prompt() {
 	# Arguments: side, exit_code
 	_powerline_set_jobs
 	$POWERLINE_COMMAND shell $1 \
-		-w "${COLUMNS:-$(_powerline_columns_fallback)}" \
+		--width="${COLUMNS:-$(_powerline_columns_fallback)}" \
 		$_POWERLINE_RENDERER_ARG \
 		--renderer_arg="client_id=$$" \
 		--last_exit_code=$2 \
diff --git a/powerline/bindings/zsh/powerline.zsh b/powerline/bindings/zsh/powerline.zsh
index 626ee58c..631a6752 100644
--- a/powerline/bindings/zsh/powerline.zsh
+++ b/powerline/bindings/zsh/powerline.zsh
@@ -133,9 +133,9 @@ _powerline_setup_prompt() {
 		add_args+=' --last_pipe_status="$pipestatus"'
 		add_args+=' --renderer_arg="client_id=$$"'
 		add_args+=' --jobnum=$_POWERLINE_JOBNUM'
-		local new_args_2=' -R parser_state=${(%%):-%_}'
-		new_args_2+=' -R local_theme=continuation'
-		local add_args_3=$add_args' -R local_theme=select'
+		local new_args_2=' --renderer_arg="parser_state=${(%%):-%_}"'
+		new_args_2+=' --renderer_arg="local_theme=continuation"'
+		local add_args_3=$add_args' --renderer_arg="local_theme=select"'
 		local add_args_2=$add_args$new_args_2
 		add_args+=' --width=$(( ${COLUMNS:-$(_powerline_columns_fallback)} - 1 ))'
 		local add_args_r2=$add_args$new_args_2
diff --git a/powerline/ipython.py b/powerline/ipython.py
index 80327e72..5fc66b34 100644
--- a/powerline/ipython.py
+++ b/powerline/ipython.py
@@ -23,12 +23,17 @@ class RewriteResult(object):
 
 
 class IpythonPowerline(Powerline):
-	def __init__(self, is_prompt):
+	def __init__(self, is_prompt, old_widths):
 		super(IpythonPowerline, self).__init__(
 			'ipython',
 			renderer_module=('ipython_prompt' if is_prompt else 'ipython'),
 			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:
diff --git a/powerline/lint/__init__.py b/powerline/lint/__init__.py
index 7d894049..a1749790 100644
--- a/powerline/lint/__init__.py
+++ b/powerline/lint/__init__.py
@@ -1279,6 +1279,8 @@ spaces_spec = Spec().unsigned().cmp(
 ).copy
 common_theme_spec = Spec(
 	default_module=segment_module_spec().optional(),
+	cursor_space=Spec().type(int, float).cmp('le', 100).cmp('gt', 0).optional(),
+	cursor_columns=Spec().type(int).cmp('gt', 0).optional(),
 ).context_message('Error while loading theme').copy
 top_theme_spec = common_theme_spec().update(
 	dividers=dividers_spec(),
diff --git a/powerline/renderers/shell.py b/powerline/renderers/shell.py
index 931c1178..360acafc 100644
--- a/powerline/renderers/shell.py
+++ b/powerline/renderers/shell.py
@@ -1,6 +1,6 @@
 # vim:fileencoding=utf-8:noet
 
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, unicode_literals, division, print_function
 
 from powerline.renderer import Renderer
 from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
@@ -27,31 +27,55 @@ class ShellRenderer(Renderer):
 		super(ShellRenderer, self).__init__(*args, **kwargs)
 		self.old_widths = {}
 
-	def render(self, segment_info, *args, **kwargs):
-		client_id = segment_info.get('client_id')
-		key = (client_id, kwargs.get('side'))
-		kwargs = kwargs.copy()
-		width = kwargs.pop('width', None)
+	def render(self, segment_info, **kwargs):
 		local_theme = segment_info.get('local_theme')
-		if client_id and local_theme:
-			output_width = False
+		return super(ShellRenderer, self).render(
+			matcher_info=local_theme,
+			segment_info=segment_info,
+			**kwargs
+		)
+
+	def do_render(self, output_width, segment_info, side, theme, width=None, **kwargs):
+		if isinstance(segment_info, dict):
+			client_id = segment_info.get('client_id')
+		else:
+			client_id = None
+		local_key = (client_id, side, None if theme is self.theme else id(theme))
+		key = (client_id, side, None)
+		did_width = False
+		if local_key[-1] != key[-1] and side == 'left':
 			try:
 				width = self.old_widths[key]
 			except KeyError:
 				pass
-		else:
-			output_width = True
-		ret = super(ShellRenderer, self).render(
-			output_width=output_width,
+			else:
+				did_width = True
+		if not did_width:
+			if width is not None:
+				if theme.cursor_space_multiplier is not None:
+					width = int(width * theme.cursor_space_multiplier)
+				elif theme.cursor_columns:
+					width -= theme.cursor_columns
+
+				if side == 'right':
+					try:
+						width -= self.old_widths[(client_id, 'left', local_key[-1])]
+					except KeyError:
+						pass
+		res = super(ShellRenderer, self).do_render(
+			output_width=True,
 			width=width,
-			matcher_info=local_theme,
+			theme=theme,
 			segment_info=segment_info,
-			*args, **kwargs
+			side=side,
+			**kwargs
 		)
-		if output_width:
-			self.old_widths[key] = ret[1]
-			ret = ret[0]
-		return ret
+		self.old_widths[local_key] = res[-1]
+		ret = res if output_width else res[:-1]
+		if len(ret) == 1:
+			return ret[0]
+		else:
+			return ret
 
 	def hlstyle(self, fg=None, bg=None, attr=None):
 		'''Highlight a segment.
diff --git a/powerline/theme.py b/powerline/theme.py
index dbb4f3f5..d03b0a06 100644
--- a/powerline/theme.py
+++ b/powerline/theme.py
@@ -1,4 +1,5 @@
 # vim:fileencoding=utf-8:noet
+from __future__ import division
 
 from powerline.segment import gen_segment_getter, process_segment
 from powerline.lib.unicode import u
@@ -37,6 +38,11 @@ class Theme(object):
 			for k, v in val.items()))
 			for key, val in self.dividers.items()
 		))
+		try:
+			self.cursor_space_multiplier = 1 - (theme_config['cursor_space'] / 100)
+		except KeyError:
+			self.cursor_space_multiplier = None
+		self.cursor_columns = theme_config.get('cursor_columns')
 		self.spaces = theme_config['spaces']
 		self.segments = []
 		self.EMPTY_SEGMENT = {
diff --git a/tests/test_provided_config_files.py b/tests/test_provided_config_files.py
index e738301f..45cffcf6 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(True, {}) 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(False, {}) 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)