Skip to content


Drop consecutive duplicates when refilling readline history #1003

merged 4 commits into from

3 participants

IPython member

I'd better fix that bug if I'm getting a tshirt for it.

This operates at the cell level, even if the user disables multiline_history in the terminal, so you can define a multiline function twice, and only have to flip through it once after you start a new session.

There's an added bonus fix for setting the next input at the terminal on Python 3.

IPython member

Aside: the equivalent thing also needs fixing in the Qt console. I'll see if I can track down the relevant code and add it to this PR.

IPython member

Found the relevant bit for the Qt console too.

@minrk minrk commented on an outdated diff
@@ -1804,6 +1806,7 @@ class InteractiveShell(SingletonConfigurable, Magic):
for line in cell.splitlines():
+ last_cell = cell.rstrip()
@minrk IPython member
minrk added a note

You can eliminate these three strip()/rstrip() calls by using a single stripped = cell.rstrip(), and if stripped and stripped != last_cell:, yes?

@takluyver IPython member

Good point. Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
IPython member

Looks great, works great, and fixes a really annoying little regression.

Great job, as always. Totally deserving of the issue #1000 award!! :) Will merge now, thanks a lot.

@fperez fperez merged commit 5e71407 into ipython:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Showing with 16 additions and 8 deletions.
  1. +9 −7 IPython/core/
  2. +7 −1 IPython/frontend/qt/console/
16 IPython/core/
@@ -1794,16 +1794,20 @@ def refill_readline_hist(self):
# Load the last 1000 lines from history
stdin_encoding = sys.stdin.encoding or "utf-8"
+ last_cell = u""
for _, _, cell in self.history_manager.get_tail(1000,
- if cell.strip(): # Ignore blank lines
+ # Ignore blank lines and consecutive duplicates
+ cell = cell.rstrip()
+ if cell and (cell != last_cell):
if self.multiline_history:
- self.readline.add_history(py3compat.unicode_to_str(cell.rstrip(),
- stdin_encoding))
+ self.readline.add_history(py3compat.unicode_to_str(cell,
+ stdin_encoding))
for line in cell.splitlines():
- stdin_encoding))
+ stdin_encoding))
+ last_cell = cell
def set_next_input(self, s):
""" Sets the 'default' input string for the next command line.
@@ -1815,9 +1819,7 @@ def set_next_input(self, s):
[D:\ipython]|1> _ip.set_next_input("Hello Word")
[D:\ipython]|2> Hello Word_ # cursor is here
- if isinstance(s, unicode):
- s = s.encode(self.stdin_encoding, 'replace')
- self.rl_next_input = s
+ self.rl_next_input = py3compat.cast_bytes_py2(s)
# Maybe move this to the terminal subclass?
def pre_readline(self):
8 IPython/frontend/qt/console/
@@ -197,7 +197,13 @@ def _handle_history_reply(self, msg):
# reset retry flag
self._retrying_history_request = False
history_items = content['history']
- items = [ line.rstrip() for _, _, line in history_items ]
+ items = []
+ last_cell = u""
+ for _, _, cell in history_items:
+ cell = cell.rstrip()
+ if cell != last_cell:
+ items.append(cell)
+ last_cell = cell
def _handle_pyout(self, msg):
Something went wrong with that request. Please try again.