소스 검색

Added split-cell multicursor

Ben Thayer 5 년 전
부모
커밋
86fa75fcf0
1개의 변경된 파일44개의 추가작업 그리고 21개의 파일을 삭제
  1. 44 21
      packages/notebook/src/actions.tsx

+ 44 - 21
packages/notebook/src/actions.tsx

@@ -88,13 +88,13 @@ export class NotebookActions {
  */
 export namespace NotebookActions {
   /**
-   * Split the active cell into two cells.
+   * Split the active cell into two or more cells.
    *
    * @param widget - The target notebook widget.
    *
    * #### Notes
    * It will preserve the existing mode.
-   * The second cell will be activated.
+   * The last cell will be activated.
    * The existing selection will be cleared.
    * The leading whitespace in the second cell will be removed.
    * If there is no content, two empty cells will be created.
@@ -114,35 +114,58 @@ export namespace NotebookActions {
     const index = notebook.activeCellIndex;
     const child = notebook.widgets[index];
     const editor = child.editor;
-    const position = editor.getCursorPosition();
-    const offset = editor.getOffsetAt(position);
+    const selections = editor.getSelections();
     const orig = child.model.value.text;
 
-    // Create new models to preserve history.
-    const clone0 = Private.cloneCell(nbModel, child.model);
-    const clone1 = Private.cloneCell(nbModel, child.model);
+    let offsets = [0];
+
+    for (let i = 0; i < selections.length; i++) {
+      // append start and end to handle selections
+      // cursors will have same start and end
+      let start = editor.getOffsetAt(selections[i].start);
+      let end = editor.getOffsetAt(selections[i].end);
+      if (start < end) {
+        offsets.push(start);
+        offsets.push(end);
+      } else if (end < start) {
+        offsets.push(end);
+        offsets.push(start);
+      } else {
+        offsets.push(start);
+      }
+    }
+
+    offsets.push(orig.length);
 
-    if (clone0.type === 'code') {
-      (clone0 as ICodeCellModel).outputs.clear();
+    let clones: ICellModel[] = [];
+    for (let i = 0; i + 1 < offsets.length; i++) {
+      let clone = Private.cloneCell(nbModel, child.model);
+      clones.push(clone);
+    }
+
+    for (let i = 0; i < clones.length; i++) {
+      if (i !== clones.length - 1 && clones[i].type === 'code') {
+        (clones[i] as ICodeCellModel).outputs.clear();
+      }
+      clones[i].value.text = orig
+        .slice(offsets[i], offsets[i + 1])
+        .replace(/^\n+/, '')
+        .replace(/\n+$/, '');
     }
-    clone0.value.text = orig
-      .slice(0, offset)
-      .replace(/^\n+/, '')
-      .replace(/\n+$/, '');
-    clone1.value.text = orig
-      .slice(offset)
-      .replace(/^\n+/, '')
-      .replace(/\n+$/, '');
 
-    // Make the changes while preserving history.
     const cells = nbModel.cells;
 
     cells.beginCompoundOperation();
-    cells.set(index, clone0);
-    cells.insert(index + 1, clone1);
+    for (let i = 0; i < clones.length; i++) {
+      if (i === 0) {
+        cells.set(index, clones[i]);
+      } else {
+        cells.insert(index + i, clones[i]);
+      }
+    }
     cells.endCompoundOperation();
 
-    notebook.activeCellIndex++;
+    notebook.activeCellIndex = index + clones.length - 1;
     Private.handleState(notebook, state);
   }