Skip to content

Loading…

Drop consecutive duplicates when refilling readline history #1003

Merged
merged 4 commits into from

3 participants

@takluyver
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.

@takluyver
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.

@takluyver
IPython member

Found the relevant bit for the Qt console too.

@minrk minrk commented on an outdated diff
IPython/core/interactiveshell.py
@@ -1804,6 +1806,7 @@ class InteractiveShell(SingletonConfigurable, Magic):
for line in cell.splitlines():
self.readline.add_history(py3compat.unicode_to_str(line,
stdin_encoding))
+ 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
@fperez
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/interactiveshell.py
  2. +7 −1 IPython/frontend/qt/console/ipython_widget.py
View
16 IPython/core/interactiveshell.py
@@ -1794,16 +1794,20 @@ def refill_readline_hist(self):
# Load the last 1000 lines from history
self.readline.clear_history()
stdin_encoding = sys.stdin.encoding or "utf-8"
+ last_cell = u""
for _, _, cell in self.history_manager.get_tail(1000,
include_latest=True):
- 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))
else:
for line in cell.splitlines():
self.readline.add_history(py3compat.unicode_to_str(line,
- 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):
View
8 IPython/frontend/qt/console/ipython_widget.py
@@ -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
self._set_history(items)
def _handle_pyout(self, msg):
Something went wrong with that request. Please try again.