From 7362b259278dbc966b6ad175e5793c6a084517cf Mon Sep 17 00:00:00 2001 From: David Kutugata Date: Tue, 10 Sep 2019 14:51:12 -0700 Subject: [PATCH] added commands for 'dd' (#7313) * added commands for 'dd', 'ctrl + enter', 'alt + enter', 'a', 'b', 'j', 'k' to behave just like jupyterLabs. * added news file * removed the addEmptyCell function, it was redundant. * Added parameter to insertCell to check if the cell being inserted should be monaco or not --- news/2 Fixes/7229.md | 1 + .../interactive-common/mainStateController.ts | 6 +- .../native-editor/nativeEditor.tsx | 92 ++++++++++++++++--- .../nativeEditorStateController.ts | 8 +- 4 files changed, 89 insertions(+), 18 deletions(-) create mode 100644 news/2 Fixes/7229.md diff --git a/news/2 Fixes/7229.md b/news/2 Fixes/7229.md new file mode 100644 index 000000000000..4bceafea6193 --- /dev/null +++ b/news/2 Fixes/7229.md @@ -0,0 +1 @@ +Added commands for 'dd', 'ctrl + enter', 'alt + enter', 'a', 'b', 'j', 'k' in the native Editor to behave just like JupyterLabs. \ No newline at end of file diff --git a/src/datascience-ui/interactive-common/mainStateController.ts b/src/datascience-ui/interactive-common/mainStateController.ts index b36cd0680b64..124489a00c08 100644 --- a/src/datascience-ui/interactive-common/mainStateController.ts +++ b/src/datascience-ui/interactive-common/mainStateController.ts @@ -701,7 +701,7 @@ export class MainStateController implements IMessageHandler { this.insertCell(cell); } - protected insertCell(cell: ICell, position?: number): ICellViewModel | undefined { + protected insertCell(cell: ICell, position?: number, isMonaco?: boolean): ICellViewModel | undefined { if (cell) { const showInputs = getSettings().showCellInputCode; const collapseInputs = getSettings().collapseCellInputCodeByDefault; @@ -711,6 +711,10 @@ export class MainStateController implements IMessageHandler { cellVM = this.alterCellVM(cellVM, showInputs, !collapseInputs); if (cellVM) { + if (isMonaco) { + cellVM.useQuickEdit = false; + } + const newList = [...this.state.cellVMs]; // Make sure to use the same array so our entire state doesn't update if (position && position >= 0) { diff --git a/src/datascience-ui/native-editor/nativeEditor.tsx b/src/datascience-ui/native-editor/nativeEditor.tsx index 880eedede945..d04063ade4d4 100644 --- a/src/datascience-ui/native-editor/nativeEditor.tsx +++ b/src/datascience-ui/native-editor/nativeEditor.tsx @@ -40,6 +40,7 @@ export class NativeEditor extends React.Component { + // tslint:disable-next-line: cyclomatic-complexity max-func-body-length + private keyDownCell = async (cellId: string, e: IKeyboardEvent) => { switch (e.code) { case 'ArrowUp': + this.pressedDOnce = false; if (this.state.focusedCell === cellId && e.editorInfo && e.editorInfo.isFirstLine && !e.editorInfo.isSuggesting) { this.arrowUpFromCell(cellId, e); } else if (!this.state.focusedCell) { this.arrowUpFromCell(cellId, e); } break; - case 'ArrowDown': + this.pressedDOnce = false; if (this.state.focusedCell === cellId && e.editorInfo && e.editorInfo.isLastLine && !e.editorInfo.isSuggesting) { this.arrowDownFromCell(cellId, e); } else if (!this.state.focusedCell) { this.arrowDownFromCell(cellId, e); } break; - case 'Escape': + this.pressedDOnce = false; if (this.state.focusedCell && e.editorInfo && !e.editorInfo.isSuggesting) { this.escapeCell(this.state.focusedCell, e); } break; - case 'y': + this.pressedDOnce = false; if (!this.state.focusedCell && this.state.selectedCell) { e.stopPropagation(); this.stateController.changeCellType(this.state.selectedCell, 'code'); } break; - case 'm': + this.pressedDOnce = false; if (!this.state.focusedCell && this.state.selectedCell) { e.stopPropagation(); this.stateController.changeCellType(this.state.selectedCell, 'markdown'); } break; - case 'l': + this.pressedDOnce = false; if (!this.state.focusedCell && this.state.selectedCell) { e.stopPropagation(); this.stateController.toggleLineNumbers(this.state.selectedCell); } break; - case 'o': + this.pressedDOnce = false; if (!this.state.focusedCell && this.state.selectedCell) { e.stopPropagation(); this.stateController.toggleOutput(this.state.selectedCell); } break; - case 'Enter': + this.pressedDOnce = false; if (e.shiftKey) { - this.submitCell(cellId, e); + this.submitCell(cellId, e, true); + } else if (e.ctrlKey) { + this.submitCell(cellId, e, false); + } else if (e.altKey) { + this.submitCell(cellId, e, false); + this.stateController.insertBelow(cellId, true); } else { this.enterCell(cellId, e); } break; - + case 'd': + if (this.pressedDOnce) { + this.stateController.deleteCell(cellId); + this.pressedDOnce = false; + } else { + this.pressedDOnce = true; + } + break; + case 'a': + this.pressedDOnce = false; + if (this.state.focusedCell === cellId && e.editorInfo && e.editorInfo.isLastLine && !e.editorInfo.isSuggesting) { + this.stateController.insertAbove(cellId, true); + } else if (!this.state.focusedCell) { + this.stateController.insertAbove(cellId, true); + } + break; + case 'b': + this.pressedDOnce = false; + if (this.state.focusedCell === cellId && e.editorInfo && e.editorInfo.isLastLine && !e.editorInfo.isSuggesting) { + this.stateController.insertBelow(cellId, true); + } else if (!this.state.focusedCell) { + this.stateController.insertBelow(cellId, true); + } + break; + case 'j': + this.pressedDOnce = false; + if (this.state.focusedCell === cellId && e.editorInfo && e.editorInfo.isFirstLine && !e.editorInfo.isSuggesting) { + this.arrowUpFromCell(cellId, e); + } else if (!this.state.focusedCell) { + this.arrowUpFromCell(cellId, e); + } + break; + case 'k': + this.pressedDOnce = false; + if (this.state.focusedCell === cellId && e.editorInfo && e.editorInfo.isFirstLine && !e.editorInfo.isSuggesting) { + this.arrowDownFromCell(cellId, e); + } else if (!this.state.focusedCell) { + this.arrowDownFromCell(cellId, e); + } + break; default: + this.pressedDOnce = false; break; } } @@ -361,7 +408,7 @@ export class NativeEditor extends React.Component { + private submitCell = (cellId: string, e: IKeyboardEvent, moveToNextCell: boolean) => { let content: string | undefined ; const cellVM = this.findCellViewModel(cellId); @@ -382,7 +429,7 @@ export class NativeEditor extends React.Component { + this.pressedDOnce = false; const focusedCell = cellId === this.state.focusedCell ? cellId : undefined; this.stateController.selectCell(cellId, focusedCell); } @@ -472,6 +520,24 @@ export class NativeEditor extends React.Component { + // const editedCells = this.state.cellVMs; + // const index = editedCells.findIndex(x => x.cell.id === cellId) + 1; + + // if (index > -1) { + // const textArea = document.createElement('textarea'); + // document.body.appendChild(textArea); + // textArea.select(); + // document.execCommand('Paste'); + // editedCells[index].cell.data.source = textArea.value.split(/\r?\n/); + // textArea.remove(); + // } + + // this.setState({ + // cellVMs: editedCells + // }); + // } + private moveCellUp = (cellId?: string) => { if (this.contentPanelRef.current && cellId) { const wasFocused = this.state.focusedCell; diff --git a/src/datascience-ui/native-editor/nativeEditorStateController.ts b/src/datascience-ui/native-editor/nativeEditorStateController.ts index 48aa1d67c683..7f2d0bd4c335 100644 --- a/src/datascience-ui/native-editor/nativeEditorStateController.ts +++ b/src/datascience-ui/native-editor/nativeEditorStateController.ts @@ -110,19 +110,19 @@ export class NativeEditorStateController extends MainStateController { } } - public insertAbove = (cellId?: string) => { + public insertAbove = (cellId?: string, isMonaco?: boolean) => { const cells = this.getState().cellVMs; const index = cells.findIndex(cvm => cvm.cell.id === cellId); if (index >= 0) { - this.insertCell(createEmptyCell(uuid(), null), index); + this.insertCell(createEmptyCell(uuid(), null), index, isMonaco); } } - public insertBelow = (cellId?: string) => { + public insertBelow = (cellId?: string, isMonaco?: boolean) => { const cells = this.getState().cellVMs; const index = cells.findIndex(cvm => cvm.cell.id === cellId); if (index >= 0) { - this.insertCell(createEmptyCell(uuid(), null), index + 1); + this.insertCell(createEmptyCell(uuid(), null), index + 1, isMonaco); } }