Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP


Drop consecutive duplicates when refilling readline history #1003

merged 4 commits into from

3 participants


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.


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.


Found the relevant bit for the Qt console too.

@@ -1804,6 +1806,7 @@ class InteractiveShell(SingletonConfigurable, Magic):
for line in cell.splitlines():
+ last_cell = cell.rstrip()
@minrk Owner
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 Owner

Good point. Done.

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

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 from
@fperez fperez referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
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.