mirror of
https://github.com/jupyter/notebook.git
synced 2025-03-13 13:17:50 +08:00
multiple-undo for cell deletion
use a stack for undelete_backup instead of a singleton avoids data loss on multiple undelete
This commit is contained in:
parent
a3e074c3a7
commit
89b75c21e2
@ -123,9 +123,7 @@ define(function (require) {
|
||||
this.kernel = null;
|
||||
this.kernel_busy = false;
|
||||
this.clipboard = null;
|
||||
this.undelete_backup = null;
|
||||
this.undelete_index = null;
|
||||
this.undelete_below = false;
|
||||
this.undelete_backup_stack = [];
|
||||
this.paste_enabled = false;
|
||||
this.writable = false;
|
||||
// It is important to start out in command mode to match the intial mode
|
||||
@ -993,7 +991,11 @@ define(function (require) {
|
||||
indices = this.get_selected_cells_indices();
|
||||
}
|
||||
|
||||
this.undelete_backup = [];
|
||||
var undelete_backup = {
|
||||
cells: [],
|
||||
below: false,
|
||||
index: 0,
|
||||
};
|
||||
|
||||
var cursor_ix_before = this.get_selected_index();
|
||||
var deleting_before_cursor = 0;
|
||||
@ -1013,13 +1015,13 @@ define(function (require) {
|
||||
indices.sort(function(a, b) {return b-a;});
|
||||
for (i=0; i < indices.length; i++) {
|
||||
var cell = this.get_cell(indices[i]);
|
||||
this.undelete_backup.push(cell.toJSON());
|
||||
undelete_backup.cells.push(cell.toJSON());
|
||||
this.get_cell_element(indices[i]).remove();
|
||||
this.events.trigger('delete.Cell', {'cell': cell, 'index': indices[i]});
|
||||
}
|
||||
|
||||
// Flip the backup copy of cells back to first-to-last order
|
||||
this.undelete_backup.reverse();
|
||||
undelete_backup.cells.reverse();
|
||||
|
||||
var new_ncells = this.ncells();
|
||||
// Always make sure we have at least one cell.
|
||||
@ -1028,14 +1030,13 @@ define(function (require) {
|
||||
new_ncells = 1;
|
||||
}
|
||||
|
||||
this.undelete_below = false;
|
||||
var cursor_ix_after = this.get_selected_index();
|
||||
if (cursor_ix_after === null) {
|
||||
// Selected cell was deleted
|
||||
cursor_ix_after = cursor_ix_before - deleting_before_cursor;
|
||||
if (cursor_ix_after >= new_ncells) {
|
||||
cursor_ix_after = new_ncells - 1;
|
||||
this.undelete_below = true;
|
||||
undelete_backup.below = true;
|
||||
}
|
||||
this.select(cursor_ix_after);
|
||||
}
|
||||
@ -1043,15 +1044,16 @@ define(function (require) {
|
||||
// Check if the cells were after the cursor
|
||||
for (i=0; i < indices.length; i++) {
|
||||
if (indices[i] > cursor_ix_before) {
|
||||
this.undelete_below = true;
|
||||
undelete_backup.below = true;
|
||||
}
|
||||
}
|
||||
|
||||
// This will put all the deleted cells back in one location, rather than
|
||||
// where they came from. It will do until we have proper undo support.
|
||||
this.undelete_index = cursor_ix_after;
|
||||
undelete_backup.index = cursor_ix_after;
|
||||
$('#undelete_cell').removeClass('disabled');
|
||||
|
||||
this.undelete_backup_stack.push(undelete_backup);
|
||||
this.set_dirty(true);
|
||||
|
||||
return this;
|
||||
@ -1075,29 +1077,30 @@ define(function (require) {
|
||||
* Restore the most recently deleted cells.
|
||||
*/
|
||||
Notebook.prototype.undelete_cell = function() {
|
||||
if (this.undelete_backup !== null && this.undelete_index !== null) {
|
||||
if (this.undelete_backup_stack.length > 0) {
|
||||
var undelete_backup = this.undelete_backup_stack.pop();
|
||||
var i, cell_data, new_cell;
|
||||
if (this.undelete_below) {
|
||||
for (i = this.undelete_backup.length-1; i >= 0; i--) {
|
||||
cell_data = this.undelete_backup[i];
|
||||
if (undelete_backup.below) {
|
||||
for (i = undelete_backup.cells.length-1; i >= 0; i--) {
|
||||
cell_data = undelete_backup.cells[i];
|
||||
new_cell = this.insert_cell_below(cell_data.cell_type,
|
||||
this.undelete_index);
|
||||
undelete_backup.index);
|
||||
new_cell.fromJSON(cell_data);
|
||||
}
|
||||
} else {
|
||||
for (i=0; i < this.undelete_backup.length; i++) {
|
||||
cell_data = this.undelete_backup[i];
|
||||
for (i=0; i < undelete_backup.cells.length; i++) {
|
||||
cell_data = undelete_backup.cells[i];
|
||||
new_cell = this.insert_cell_above(cell_data.cell_type,
|
||||
this.undelete_index);
|
||||
undelete_backup.index);
|
||||
new_cell.fromJSON(cell_data);
|
||||
}
|
||||
}
|
||||
|
||||
this.set_dirty(true);
|
||||
this.undelete_backup = null;
|
||||
this.undelete_index = null;
|
||||
}
|
||||
$('#undelete_cell').addClass('disabled');
|
||||
if (this.undelete_backup_stack.length === 0) {
|
||||
$('#undelete_cell').addClass('disabled');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1202,11 +1205,13 @@ define(function (require) {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.undelete_index !== null && index <= this.undelete_index) {
|
||||
this.undelete_index = this.undelete_index + 1;
|
||||
this.set_dirty(true);
|
||||
}
|
||||
|
||||
this.undelete_backup_stack.map(function (undelete_backup) {
|
||||
if (index < undelete_backup.index) {
|
||||
undelete_backup.index += 1;
|
||||
}
|
||||
});
|
||||
this.set_dirty(true);
|
||||
return true;
|
||||
};
|
||||
|
||||
@ -1219,7 +1224,7 @@ define(function (require) {
|
||||
* @return {Cell|null} handle to created cell or null
|
||||
*/
|
||||
Notebook.prototype.insert_cell_above = function (type, index) {
|
||||
if (index === null || index === undefined) {
|
||||
if (index === null || index === undefined) {
|
||||
index = Math.min(this.get_selected_index(index), this.get_anchor_index());
|
||||
}
|
||||
return this.insert_cell_at_index(type, index);
|
||||
|
@ -47,12 +47,30 @@ casper.notebook_test(function () {
|
||||
this.trigger_keydown('esc');
|
||||
this.trigger_keydown('d', 'd');
|
||||
assert_cells("delete cell 1", [a, c, d], 1);
|
||||
|
||||
// Delete cell 1 (2)
|
||||
this.select_cell(1);
|
||||
this.trigger_keydown('esc');
|
||||
this.trigger_keydown('d', 'd');
|
||||
assert_cells("delete cell 1 (2)", [a, d], 1);
|
||||
|
||||
// Undelete cell 2
|
||||
this.evaluate(function () {
|
||||
IPython.notebook.undelete_cell();
|
||||
});
|
||||
assert_cells("undelete cell 1 (2)", [a, c, d], 2);
|
||||
|
||||
// Undelete cell 1
|
||||
this.evaluate(function () {
|
||||
IPython.notebook.undelete_cell();
|
||||
});
|
||||
assert_cells("undelete cell 1", [a, b, c, d], 2);
|
||||
assert_cells("undelete cell 1", [a, b, c, d], 3);
|
||||
|
||||
// Undelete cell (none)
|
||||
this.evaluate(function () {
|
||||
IPython.notebook.undelete_cell();
|
||||
});
|
||||
assert_cells("undelete cell (none)", [a, b, c, d], 3);
|
||||
|
||||
// Merge cells 1-2
|
||||
var bc = b + "\n\n" + c;
|
||||
|
Loading…
x
Reference in New Issue
Block a user