Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions bpython/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ def loadini(struct, configfile):
"last_output": "F9",
"left": "C-b",
"pastebin": "F8",
"redo": "C-g",
"reimport": "F6",
"reverse_incremental_search": "M-r",
"right": "C-f",
Expand Down Expand Up @@ -193,6 +194,7 @@ def get_key_no_doublebind(command):
struct.suspend_key = get_key_no_doublebind("suspend")
struct.toggle_file_watch_key = get_key_no_doublebind("toggle_file_watch")
struct.undo_key = get_key_no_doublebind("undo")
struct.redo_key = get_key_no_doublebind("redo")
struct.reimport_key = get_key_no_doublebind("reimport")
struct.reverse_incremental_search_key = get_key_no_doublebind(
"reverse_incremental_search"
Expand Down
25 changes: 19 additions & 6 deletions bpython/curtsiesfrontend/repl.py
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,8 @@ def process_key_event(self, e):
self.on_tab(back=True)
elif e in key_dispatch[self.config.undo_key]: # ctrl-r for undo
self.prompt_undo()
elif e in key_dispatch[self.config.redo_key]: # ctrl-g for redo
self.redo()
elif e in key_dispatch[self.config.save_key]: # ctrl-s for save
greenlet.greenlet(self.write2file).switch()
elif e in key_dispatch[self.config.pastebin_key]: # F8 for pastebin
Expand Down Expand Up @@ -858,14 +860,17 @@ def readline_kill(self, e):
else:
self.cut_buffer = cut

def on_enter(self, insert_into_history=True, reset_rl_history=True):
def on_enter(self, new_code=True, reset_rl_history=True):
# so the cursor isn't touching a paren TODO: necessary?
if new_code:
self.redo_stack = []

self._set_cursor_offset(-1, update_completion=False)
if reset_rl_history:
self.rl_history.reset()

self.history.append(self.current_line)
self.push(self.current_line, insert_into_history=insert_into_history)
self.push(self.current_line, insert_into_history=new_code)

def on_tab(self, back=False):
"""Do something on tab key
Expand Down Expand Up @@ -1019,7 +1024,7 @@ def send_session_to_external_editor(self, filename=None):
source = preprocess("\n".join(from_editor), self.interp.compile)
lines = source.split("\n")
self.history = lines
self.reevaluate(insert_into_history=True)
self.reevaluate(new_code=True)
self.current_line = current_line
self.cursor_offset = len(self.current_line)
self.status_bar.message(_("Session edited and reevaluated"))
Expand All @@ -1030,7 +1035,7 @@ def clear_modules_and_reevaluate(self):
cursor, line = self.cursor_offset, self.current_line
for modname in set(sys.modules.keys()) - self.original_modules:
del sys.modules[modname]
self.reevaluate(insert_into_history=True)
self.reevaluate(new_code=True)
self.cursor_offset, self.current_line = cursor, line
self.status_bar.message(
_("Reloaded at %s by user.") % (time.strftime("%X"),)
Expand Down Expand Up @@ -1811,7 +1816,15 @@ def prompt_for_undo():

greenlet.greenlet(prompt_for_undo).switch()

def reevaluate(self, insert_into_history=False):
def redo(self):
if (self.redo_stack):
temp = self.redo_stack.pop()
self.push(temp)
self.history.append(temp)
else:
self.status_bar.message("Nothing to redo.")

def reevaluate(self, new_code=False):
"""bpython.Repl.undo calls this"""
if self.watcher:
self.watcher.reset()
Expand All @@ -1835,7 +1848,7 @@ def reevaluate(self, insert_into_history=False):
sys.stdin = ReevaluateFakeStdin(self.stdin, self)
for line in old_logical_lines:
self._current_line = line
self.on_enter(insert_into_history=insert_into_history)
self.on_enter(new_code=new_code)
while self.fake_refresh_requested:
self.fake_refresh_requested = False
self.process_event(bpythonevents.RefreshRequestEvent())
Expand Down
7 changes: 6 additions & 1 deletion bpython/repl.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,8 @@ def __init__(self, interp, config):
duplicates=config.hist_duplicates, hist_size=config.hist_length
)
self.s_hist = []
self.history = []
self.history = [] # commands executed since beginning of session
self.redo_stack = []
self.evaluating = False
self.matches_iter = MatchesIterator()
self.funcprops = None
Expand Down Expand Up @@ -1009,6 +1010,10 @@ def undo(self, n=1):

entries = list(self.rl_history.entries)

#Most recently undone command
last_entries = self.history[-n:]
last_entries.reverse()
self.redo_stack += last_entries
self.history = self.history[:-n]
self.reevaluate()

Expand Down
1 change: 1 addition & 0 deletions bpython/sample-config
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
# toggle_file_watch = F5
# save = C-s
# undo = C-r
# redo = C-g
# up_one_line = C-p
# down_one_line = C-n
# cut_to_buffer = C-k
Expand Down
6 changes: 3 additions & 3 deletions bpython/test/test_curtsies_painting.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def test_run_line(self):
orig_stdout = sys.stdout
sys.stdout = self.repl.stdout
[self.repl.add_normal_character(c) for c in "1 + 1"]
self.repl.on_enter(insert_into_history=False)
self.repl.on_enter(new_code=False)
screen = fsarray([">>> 1 + 1", "2", "Welcome to"])
self.assert_paint_ignoring_formatting(screen, (1, 1))
finally:
Expand Down Expand Up @@ -248,7 +248,7 @@ def enter(self, line=None):
self.repl._set_cursor_offset(len(line), update_completion=False)
self.repl.current_line = line
with output_to_repl(self.repl):
self.repl.on_enter(insert_into_history=False)
self.repl.on_enter(new_code=False)
self.assertEqual(self.repl.rl_history.entries, [""])
self.send_refreshes()

Expand Down Expand Up @@ -592,7 +592,7 @@ def test_cursor_stays_at_bottom_of_screen(self):
self.repl.width = 50
self.repl.current_line = "__import__('random').__name__"
with output_to_repl(self.repl):
self.repl.on_enter(insert_into_history=False)
self.repl.on_enter(new_code=False)
screen = [">>> __import__('random').__name__", "'random'"]
self.assert_paint_ignoring_formatting(screen)

Expand Down