Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR: Added shortcut and menu option to re-run last cell #3974

Merged
merged 11 commits into from
Mar 4, 2017
3 changes: 3 additions & 0 deletions spyder/config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@
RUN_CELL_SHORTCUT = 'Meta+Return'
else:
RUN_CELL_SHORTCUT = 'Ctrl+Return'
RE_RUN_LAST_CELL_SHORTCUT = 'Alt+Return'
RUN_CELL_AND_ADVANCE_SHORTCUT = 'Shift+Return'


# =============================================================================
# Defaults
# =============================================================================
Expand Down Expand Up @@ -423,6 +425,7 @@
'editor/close file 2': "Ctrl+F4",
'editor/run cell': RUN_CELL_SHORTCUT,
'editor/run cell and advance': RUN_CELL_AND_ADVANCE_SHORTCUT,
'editor/re-run last cell': RE_RUN_LAST_CELL_SHORTCUT,
# -- In plugins/editor.py
'editor/show/hide outline': "Ctrl+Alt+O",
# -- In Breakpoints
Expand Down
31 changes: 28 additions & 3 deletions spyder/plugins/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,12 @@ def setup_page(self):

interface_group = QGroupBox(_("Interface"))
newcb = self.create_checkbox
fpsorting_box = newcb(_("Sort files according to full path"),
'fullpath_sorting')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this option. It's not need anymore in the 3.x branch.

showtabbar_box = newcb(_("Show tab bar"), 'show_tab_bar')

interface_layout = QVBoxLayout()
interface_layout.addWidget(fpsorting_box)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also remove this.

interface_layout.addWidget(showtabbar_box)
interface_group.setLayout(interface_layout)

Expand Down Expand Up @@ -539,6 +542,9 @@ def restore_scrollbar_position(self):
def get_plugin_title(self):
"""Return widget title"""
title = _('Editor')
filename = self.get_current_filename()
if filename:
title += ' - '+to_text_string(filename)
Copy link
Member

@ccordoba12 ccordoba12 Feb 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these new lines are not needed either.

return title

def get_plugin_icon(self):
Expand Down Expand Up @@ -834,6 +840,17 @@ def get_plugin_actions(self):
triggered=self.run_cell_and_advance,
context=Qt.WidgetShortcut)

re_run_last_cell_action = create_action(self,
_("Re-run last cell"),
icon=ima.icon('run_cell'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please leave this action without an icon.

tip=_("Re run last cell "),
triggered=self.re_run_last_cell,
context=Qt.WidgetShortcut)
self.register_shortcut(re_run_last_cell_action,
context="Editor",
name='re-run last cell',
add_sc_to_tip=True)

# --- Source code Toolbar ---
self.todo_list_action = create_action(self,
_("Show todo list"), icon=ima.icon('todo_list'),
Expand Down Expand Up @@ -1041,13 +1058,14 @@ def get_plugin_actions(self):

# ---- Run menu/toolbar construction ----
run_menu_actions = [run_action, run_cell_action,
run_cell_advance_action, MENU_SEPARATOR,
run_cell_advance_action,
re_run_last_cell_action, MENU_SEPARATOR,
run_selected_action, re_run_action,
configure_action, MENU_SEPARATOR]
self.main.run_menu_actions += run_menu_actions
run_toolbar_actions = [run_action, run_cell_action,
run_cell_advance_action, run_selected_action,
re_run_action]
run_cell_advance_action,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the confusion, please restore run_selected_action here. It was fine before :-)

re_run_action, configure_action]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove configure_action from here.

self.main.run_toolbar_actions += run_toolbar_actions

# ---- Debug menu/toolbar construction ----
Expand Down Expand Up @@ -1115,6 +1133,7 @@ def get_plugin_actions(self):
debug_action, run_selected_action,
run_cell_action,
run_cell_advance_action,
re_run_last_cell_action,
blockcomment_action,
unblockcomment_action,
self.winpdb_action]
Expand Down Expand Up @@ -2413,6 +2432,12 @@ def run_cell_and_advance(self):
editorstack = self.get_current_editorstack()
editorstack.run_cell_and_advance()

@Slot()
def re_run_last_cell(self):
"""Run last executed cell."""
editorstack = self.get_current_editorstack()
editorstack.re_run_last_cell()

#------ Zoom in/out/reset
def zoom(self, factor):
"""Zoom in/out/reset"""
Expand Down
14 changes: 13 additions & 1 deletion spyder/widgets/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,13 +510,18 @@ def create_shortcuts(self):
context="Editor",
name="run cell and advance",
parent=self)
re_run_last_cell = config_shortcut(self.re_run_last_cell,
context="Editor",
name="re-run last cell",
parent=self)

# Return configurable ones
return [inspect, set_breakpoint, set_cond_breakpoint, gotoline, tab,
tabshift, run_selection, new_file, open_file, save_file,
save_all, save_as, close_all, prev_edit_pos, prev_cursor,
next_cursor, zoom_in_1, zoom_in_2, zoom_out, zoom_reset,
close_file_1, close_file_2, run_cell, run_cell_and_advance]
close_file_1, close_file_2, run_cell, run_cell_and_advance,
re_run_last_cell]

def get_shortcut_data(self):
"""
Expand Down Expand Up @@ -1735,6 +1740,7 @@ def create_new_editor(self, fname, enc, txt, set_current, new=False,
editor.run_selection.connect(self.run_selection)
editor.run_cell.connect(self.run_cell)
editor.run_cell_and_advance.connect(self.run_cell_and_advance)
editor.re_run_last_cell.connect(self.re_run_last_cell)
editor.sig_new_file.connect(self.sig_new_file.emit)
language = get_file_language(fname, txt)
editor.setup_editor(
Expand Down Expand Up @@ -1926,6 +1932,12 @@ def run_cell_and_advance(self):
self.get_current_editor().go_to_next_cell()
term.setFocus()

def re_run_last_cell(self):
text = self.get_current_editor().get_last_cell_as_executable_code()
finfo = self.get_current_finfo()
if finfo.editor.is_python() and text:
self.exec_in_extconsole.emit(text, self.focus_to_editor)

#------ Drag and drop
def dragEnterEvent(self, event):
"""Reimplement Qt method
Expand Down
21 changes: 18 additions & 3 deletions spyder/widgets/sourcecode/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ def __init__(self, parent=None):
self.matched_p_color = QColor(Qt.green)
self.unmatched_p_color = QColor(Qt.red)

self.last_cursor_cell = None

def setup_completion(self):
size = CONF.get('main', 'completion/size')
font = get_font()
Expand Down Expand Up @@ -621,18 +623,31 @@ def get_selection_as_executable_code(self):

return ls.join(lines)

def get_cell_as_executable_code(self):
"""Return cell contents as executable code"""
def __exec_cell(self):
init_cur = QTextCursor(self.textCursor())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename this variable to init_cursor

start_pos, end_pos = self.__save_selection()
cursor, whole_file_selected = self.select_current_cell()
if not whole_file_selected:
self.setTextCursor(cursor)
text = self.get_selection_as_executable_code()
self.last_cursor_cell = init_cur
self.__restore_selection(start_pos, end_pos)
if text is not None:
text = text.rstrip()
return text

def get_cell_as_executable_code(self):
"""Return cell contents as executable code"""
return self.__exec_cell()

def get_last_cell_as_executable_code(self):
text = None
if self.last_cursor_cell:
self.setTextCursor(self.last_cursor_cell)
self.highlight_current_cell()
text = self.__exec_cell()
return text

def is_cell_separator(self, cursor=None, block=None):
"""Return True if cursor (or text block) is on a block separator"""
assert cursor is not None or block is not None
Expand Down Expand Up @@ -691,7 +706,7 @@ def select_current_cell(self):
prev_pos = cur_pos
cell_at_file_end = cursor.atEnd()
return cursor, cell_at_file_start and cell_at_file_end

def select_current_cell_in_visible_portion(self):
"""Select cell under cursor in the visible portion of the file
cell = group of lines separated by CELL_SEPARATORS
Expand Down
11 changes: 9 additions & 2 deletions spyder/widgets/sourcecode/codeeditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ class CodeEditor(TextEditBaseWidget):
run_selection = Signal()
run_cell_and_advance = Signal()
run_cell = Signal()
re_run_last_cell = Signal()
go_to_definition_regex = Signal(int)
sig_cursor_position_changed = Signal(int, int)
focus_changed = Signal()
Expand Down Expand Up @@ -2643,6 +2644,10 @@ def setup_context_menu(self):
self, _("Run cell and advance"), icon=ima.icon('run_cell'),
shortcut=QKeySequence(RUN_CELL_AND_ADVANCE_SHORTCUT),
triggered=self.run_cell_and_advance.emit)
self.re_run_last_cell_action = create_action(
self, _("Re-run last cell"), icon=ima.icon('run_cell'),
shortcut=get_shortcut('editor', 're-run last cell'),
triggered=self.re_run_last_cell.emit)
self.run_selection_action = create_action(
self, _("Run &selection or current line"),
icon=ima.icon('run_selection'),
Expand All @@ -2665,8 +2670,9 @@ def setup_context_menu(self):
# Build menu
self.menu = QMenu(self)
actions_1 = [self.run_cell_action, self.run_cell_and_advance_action,
self.run_selection_action, self.gotodef_action, None,
self.undo_action, self.redo_action, None, self.cut_action,
self.re_run_last_cell_action, self.run_selection_action,
self.gotodef_action, None, self.undo_action,
self.redo_action, None, self.cut_action,
self.copy_action, self.paste_action, selectall_action]
actions_2 = [None, zoom_in_action, zoom_out_action, zoom_reset_action,
None, toggle_comment_action]
Expand Down Expand Up @@ -2960,6 +2966,7 @@ def contextMenuEvent(self, event):
self.run_cell_action.setVisible(self.is_python())
self.run_cell_and_advance_action.setVisible(self.is_python())
self.run_selection_action.setVisible(self.is_python())
self.re_run_last_cell_action.setVisible(self.is_python())
self.gotodef_action.setVisible(self.go_to_definition_enabled \
and self.is_python_like())

Expand Down