diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.html
index 9cca1743d2f..301ff35e4ae 100644
--- a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.html
+++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.html
@@ -23,6 +23,7 @@
[currentRevision]="currentRevision"
(tableHideChange)="setAllParagraphTableHide($event)"
(editorHideChange)="setAllParagraphEditorHide($event)"
+ #actionBar
>
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.ts
index 4bf9cae4f66..f7511cd75ca 100644
--- a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.ts
+++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.ts
@@ -198,6 +198,7 @@ export class NotebookComponent extends MessageListenersManager implements OnInit
// Call when next tick
setTimeout(() => {
scrollIntoViewIfNeeded(paragraphComponent.getElement());
+ paragraphComponent.focusEditor();
});
}
}
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.ts
index 415051d409c..e37dc3cb6ae 100644
--- a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.ts
+++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.ts
@@ -57,6 +57,7 @@ export class NotebookParagraphCodeEditorComponent implements OnChanges, OnDestro
@Output() readonly textChanged = new EventEmitter();
@Output() readonly editorBlur = new EventEmitter();
@Output() readonly editorFocus = new EventEmitter();
+ @Output() readonly toggleEditorShow = new EventEmitter();
private editor?: IStandaloneCodeEditor;
private monacoDisposables: IDisposable[] = [];
height = 18;
@@ -108,6 +109,72 @@ export class NotebookParagraphCodeEditorComponent implements OnChanges, OnDestro
}
}
+ // Handle Ctrl+Alt+E: Toggle editor show/hide
+ handleToggleEditorShow() {
+ this.toggleEditorShow.emit();
+ }
+
+ // Handle Ctrl+K: Cut current line to clipboard
+ async handleCutLine() {
+ if (!this.editor) {
+ return;
+ }
+
+ const position = this.editor.getPosition();
+ const model = this.editor.getModel();
+ if (!position || !model) {
+ return;
+ }
+
+ const lineNumber = position.lineNumber;
+ const lineContent = model.getLineContent(lineNumber);
+
+ if (!lineContent) {
+ return;
+ }
+
+ await navigator.clipboard.writeText(lineContent);
+
+ this.editor.executeEdits('cut-line', [
+ {
+ range: new monaco.Range(lineNumber, 1, lineNumber, lineContent.length + 1),
+ text: '',
+ forceMoveMarkers: true
+ }
+ ]);
+ }
+
+ // Handle Ctrl+Y: Paste from clipboard at current position
+ async handlePasteFromClipboard() {
+ if (!this.editor) {
+ return;
+ }
+
+ const text = await navigator.clipboard.readText();
+ const position = this.editor.getPosition();
+ if (position) {
+ this.editor.executeEdits('my-source', [
+ {
+ range: new monaco.Range(position.lineNumber, position.column, position.lineNumber, position.column),
+ text: text,
+ forceMoveMarkers: true
+ }
+ ]);
+ }
+ }
+
+ // Handle Ctrl+S: Show find widget
+ handleShowFind() {
+ if (this.editor) {
+ this.editor.getAction('actions.find').run();
+
+ // Focus on the find widget input field
+ const findInput = document.querySelector('.find-widget .input') as HTMLInputElement;
+ findInput.focus();
+ findInput.select();
+ }
+ }
+
initializedEditor(editor: IEditor) {
this.editor = editor as IStandaloneCodeEditor;
this.editor.addCommand(
@@ -119,6 +186,18 @@ export class NotebookParagraphCodeEditorComponent implements OnChanges, OnDestro
},
'!suggestWidgetVisible'
);
+ this.editor.addCommand(monaco.KeyMod.WinCtrl | monaco.KeyMod.Alt | monaco.KeyCode.KeyE, () => {
+ this.handleToggleEditorShow();
+ });
+ this.editor.addCommand(monaco.KeyMod.WinCtrl | monaco.KeyCode.KeyK, () => {
+ this.handleCutLine();
+ });
+ this.editor.addCommand(monaco.KeyMod.WinCtrl | monaco.KeyCode.KeyY, () => {
+ this.handlePasteFromClipboard();
+ });
+ this.editor.addCommand(monaco.KeyMod.WinCtrl | monaco.KeyCode.KeyS, () => {
+ this.handleShowFind();
+ });
this.updateEditorOptions(this.editor);
this.setParagraphMode();
@@ -160,6 +239,9 @@ export class NotebookParagraphCodeEditorComponent implements OnChanges, OnDestro
scrollbar: {
handleMouseWheel: false,
alwaysConsumeMouseWheel: false
+ },
+ find: {
+ addExtraSpaceOnTop: false
}
});
}
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.ts
index 3d39dcc1af4..741c9288c09 100644
--- a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.ts
+++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.ts
@@ -85,6 +85,14 @@ export class NotebookParagraphControlComponent implements OnInit, OnChanges {
trigger(): void;
}> = [];
+ formatShortcut(shortcut: string, isMac: boolean) {
+ if (isMac) {
+ return shortcut.replace('Alt', 'Option');
+ }
+
+ return shortcut;
+ }
+
updateListOfMenu() {
this.listOfMenu = [
{
@@ -93,7 +101,7 @@ export class NotebookParagraphControlComponent implements OnInit, OnChanges {
disabled: this.isEntireNoteRunning,
icon: 'play-circle',
trigger: () => this.trigger(this.runParagraph),
- shortCut: this.isMac ? '⇧+⌘+Enter' : 'Shift+Ctrl+Enter'
+ shortCut: this.formatShortcut('Shift+Enter', this.isMac)
},
{
label: 'Run all above',
@@ -101,7 +109,7 @@ export class NotebookParagraphControlComponent implements OnInit, OnChanges {
disabled: this.isEntireNoteRunning,
icon: 'up-square',
trigger: () => this.trigger(this.runAllAbove),
- shortCut: this.isMac ? '⇧+⌘+Enter' : 'Shift+Ctrl+Enter'
+ shortCut: this.formatShortcut('Shift+Ctrl+Up', this.isMac)
},
{
label: 'Run all below',
@@ -109,7 +117,7 @@ export class NotebookParagraphControlComponent implements OnInit, OnChanges {
disabled: this.isEntireNoteRunning,
icon: 'down-square',
trigger: () => this.trigger(this.runAllBelowAndCurrent),
- shortCut: this.isMac ? '⇧+⌘+Enter' : 'Shift+Ctrl+Enter'
+ shortCut: this.formatShortcut('Shift+Ctrl+Down', this.isMac)
},
{
label: 'Link this paragraph',
@@ -119,7 +127,7 @@ export class NotebookParagraphControlComponent implements OnInit, OnChanges {
trigger: () => {
this.openSingleParagraph.emit(this.pid);
},
- shortCut: this.isMac ? '⌥+⌘+T' : 'Alt+Ctrl+T'
+ shortCut: this.formatShortcut('Ctrl+Alt+W', this.isMac)
},
{
label: 'Clear output',
@@ -127,7 +135,7 @@ export class NotebookParagraphControlComponent implements OnInit, OnChanges {
disabled: this.isEntireNoteRunning,
icon: 'fire',
trigger: () => this.clearParagraphOutput(),
- shortCut: this.isMac ? '⌥+⌘+L' : 'Alt+Ctrl+L'
+ shortCut: this.formatShortcut('Ctrl+Alt+L', this.isMac)
},
{
label: 'Remove',
@@ -135,23 +143,23 @@ export class NotebookParagraphControlComponent implements OnInit, OnChanges {
disabled: this.isEntireNoteRunning,
icon: 'delete',
trigger: () => this.onRemoveParagraph(),
- shortCut: this.isMac ? '⇧+Del (Command)' : 'Shift+Del (Command)'
+ shortCut: this.formatShortcut('Ctrl+Alt+D', this.isMac)
},
{
- label: 'Move up',
+ label: 'Move paragraph up',
show: !this.first,
disabled: this.isEntireNoteRunning,
icon: 'up',
trigger: () => this.trigger(this.moveUp),
- shortCut: `${this.isMac ? '⌘' : 'Ctrl'}+K (Command)`
+ shortCut: this.formatShortcut('Ctrl+Alt+K', this.isMac)
},
{
- label: 'Move down',
+ label: 'Move paragraph down',
show: !this.last,
disabled: this.isEntireNoteRunning,
icon: 'down',
trigger: () => this.trigger(this.moveDown),
- shortCut: `${this.isMac ? '⌘' : 'Ctrl'}+J (Command)`
+ shortCut: this.formatShortcut('Ctrl+Alt+J', this.isMac)
},
{
label: 'Insert new',
@@ -159,7 +167,7 @@ export class NotebookParagraphControlComponent implements OnInit, OnChanges {
disabled: this.isEntireNoteRunning,
icon: 'plus',
trigger: () => this.trigger(this.insertNew),
- shortCut: `B (Command)`
+ shortCut: this.formatShortcut('Ctrl+Alt+B', this.isMac)
},
{
label: 'Clone paragraph',
@@ -167,7 +175,7 @@ export class NotebookParagraphControlComponent implements OnInit, OnChanges {
disabled: this.isEntireNoteRunning,
icon: 'copy',
trigger: () => this.trigger(this.cloneParagraph),
- shortCut: `C (Command)`
+ shortCut: this.formatShortcut('Shift+Ctrl+C', this.isMac)
},
{
label: this.title ? 'Hide Title' : 'Show Title',
@@ -175,7 +183,7 @@ export class NotebookParagraphControlComponent implements OnInit, OnChanges {
disabled: false,
icon: 'font-colors',
trigger: () => this.toggleTitle(),
- shortCut: `T (Command)`
+ shortCut: this.formatShortcut('Ctrl+Alt+T', this.isMac)
},
{
label: this.lineNumbers ? 'Hide line numbers' : 'Show line numbers',
@@ -183,7 +191,7 @@ export class NotebookParagraphControlComponent implements OnInit, OnChanges {
disabled: false,
icon: 'ordered-list',
trigger: () => this.toggleLineNumbers(),
- shortCut: `L (Command)`
+ shortCut: this.formatShortcut('Ctrl+Alt+M', this.isMac)
},
{
label: this.enabled ? 'Disable run' : 'Enable run',
@@ -191,7 +199,7 @@ export class NotebookParagraphControlComponent implements OnInit, OnChanges {
disabled: this.isEntireNoteRunning,
icon: 'api',
trigger: () => this.toggleEnabled(),
- shortCut: `R (Command)`
+ shortCut: this.formatShortcut('Ctrl+Alt+R', this.isMac)
}
];
}
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.html
index 5892aee5514..63ecfa5639e 100644
--- a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.html
+++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.html
@@ -82,6 +82,7 @@
(editorBlur)="onEditorBlur()"
(editorFocus)="onEditorFocus()"
(textChanged)="textChanged($event)"
+ (toggleEditorShow)="toggleEditorShow()"
>
();
@Output() readonly selected = new EventEmitter();
@Output() readonly selectAtIndex = new EventEmitter();
+ @Output() readonly searchCode = new EventEmitter();
private destroy$ = new Subject();
private mode: Mode = 'command';
@@ -155,6 +156,11 @@ export class NotebookParagraphComponent extends ParagraphBase implements OnInit,
}
}
+ toggleEditorShow() {
+ this.setEditorHide(!this.paragraph.config.editorHide);
+ this.commitParagraph();
+ }
+
saveParagraph() {
const dirtyText = this.paragraph.text;
if (dirtyText === undefined || dirtyText === this.originalText) {
@@ -356,7 +362,7 @@ export class NotebookParagraphComponent extends ParagraphBase implements OnInit,
this.cdr.markForCheck();
}
- moveUpParagraph() {
+ moveCursorUp() {
const newIndex = this.note.paragraphs.findIndex(p => p.id === this.paragraph.id) - 1;
if (newIndex < 0 || newIndex >= this.note.paragraphs.length) {
return;
@@ -369,7 +375,7 @@ export class NotebookParagraphComponent extends ParagraphBase implements OnInit,
this.messageService.moveParagraph(this.paragraph.id, newIndex);
}
- moveDownParagraph() {
+ moveCursorDown() {
const newIndex = this.note.paragraphs.findIndex(p => p.id === this.paragraph.id) + 1;
if (newIndex < 0 || newIndex >= this.note.paragraphs.length) {
return;
@@ -382,6 +388,28 @@ export class NotebookParagraphComponent extends ParagraphBase implements OnInit,
this.messageService.moveParagraph(this.paragraph.id, newIndex);
}
+ moveParagraphUp() {
+ const newIndex = this.note.paragraphs.findIndex(p => p.id === this.paragraph.id) - 1;
+ if (newIndex < 0 || newIndex >= this.note.paragraphs.length) {
+ return;
+ }
+ this.messageService.moveParagraph(this.paragraph.id, newIndex);
+ }
+
+ moveParagraphDown() {
+ const newIndex = this.note.paragraphs.findIndex(p => p.id === this.paragraph.id) + 1;
+ if (newIndex < 0 || newIndex >= this.note.paragraphs.length) {
+ return;
+ }
+ this.messageService.moveParagraph(this.paragraph.id, newIndex);
+ }
+
+ clearParagraphOutput() {
+ if (!this.isEntireNoteRunning) {
+ this.messageService.paragraphClearOutput(this.paragraph.id);
+ }
+ }
+
changeColWidth(needCommit: boolean, updateResult = true) {
if (needCommit) {
this.commitParagraph();
@@ -485,89 +513,15 @@ export class NotebookParagraphComponent extends ParagraphBase implements OnInit,
return; // ignore shortcut to make input work
}
- if (this.mode === 'command') {
- switch (action) {
- case ParagraphActions.InsertAbove:
- this.insertParagraph('above');
- break;
- case ParagraphActions.InsertBelow:
- this.insertParagraph('below');
- break;
- case ParagraphActions.SwitchEditorShow:
- this.setEditorHide(!this.paragraph.config.editorHide);
- this.commitParagraph();
- break;
- case ParagraphActions.SwitchOutputShow:
- this.setTableHide(!this.paragraph.config.tableHide);
- this.commitParagraph();
- break;
- case ParagraphActions.SwitchTitleShow:
- this.paragraph.config.title = !this.paragraph.config.title;
- this.commitParagraph();
- break;
- case ParagraphActions.SwitchLineNumber:
- this.paragraph.config.lineNumbers = !this.paragraph.config.lineNumbers;
- this.commitParagraph();
- break;
- case ParagraphActions.MoveToUp:
- event.preventDefault();
- this.moveUpParagraph();
- break;
- case ParagraphActions.MoveToDown:
- event.preventDefault();
- this.moveDownParagraph();
- break;
- case ParagraphActions.SwitchEnable:
- this.paragraph.config.enabled = !this.paragraph.config.enabled;
- this.commitParagraph();
- break;
- case ParagraphActions.ReduceWidth:
- if (!this.paragraph.config.colWidth) {
- throw new Error('colWidth is required');
- }
- this.paragraph.config.colWidth = Math.max(1, this.paragraph.config.colWidth - 1);
- this.cdr.markForCheck();
- this.changeColWidth(true);
- break;
- case ParagraphActions.IncreaseWidth:
- if (!this.paragraph.config.colWidth) {
- throw new Error('colWidth is required');
- }
- this.paragraph.config.colWidth = Math.min(12, this.paragraph.config.colWidth + 1);
- this.cdr.markForCheck();
- this.changeColWidth(true);
- break;
- case ParagraphActions.Delete:
- this.removeParagraph();
- break;
- case ParagraphActions.SelectAbove:
- event.preventDefault();
- this.selectAtIndex.emit(this.index - 1);
- break;
- case ParagraphActions.SelectBelow:
- event.preventDefault();
- this.selectAtIndex.emit(this.index + 1);
- break;
- default:
- break;
- }
- }
switch (action) {
- case ParagraphActions.Link:
- this.openSingleParagraph(this.paragraph.id);
- break;
- case ParagraphActions.EditMode:
- if (this.mode === 'command') {
- event.preventDefault();
- }
- if (!this.paragraph.config.editorHide) {
- this.switchMode('edit');
- }
- break;
case ParagraphActions.Run:
event.preventDefault();
this.runParagraph();
break;
+ case ParagraphActions.RunAbove:
+ this.waitConfirmFromEdit = true;
+ this.runAllAbove();
+ break;
case ParagraphActions.RunBelow:
this.waitConfirmFromEdit = true;
this.runAllBelowAndCurrent();
@@ -576,6 +530,75 @@ export class NotebookParagraphComponent extends ParagraphBase implements OnInit,
event.preventDefault();
this.cancelParagraph();
break;
+ case ParagraphActions.MoveCursorUp:
+ event.preventDefault();
+ this.moveCursorUp();
+ break;
+ case ParagraphActions.MoveCursorDown:
+ event.preventDefault();
+ this.moveCursorDown();
+ break;
+ case ParagraphActions.Delete:
+ this.removeParagraph();
+ break;
+ case ParagraphActions.InsertAbove:
+ this.insertParagraph('above');
+ break;
+ case ParagraphActions.InsertBelow:
+ this.insertParagraph('below');
+ break;
+ case ParagraphActions.InsertCopyOfParagraphBelow:
+ this.cloneParagraph('below');
+ break;
+ case ParagraphActions.MoveParagraphUp:
+ event.preventDefault();
+ this.moveParagraphUp();
+ break;
+ case ParagraphActions.MoveParagraphDown:
+ event.preventDefault();
+ this.moveParagraphDown();
+ break;
+ case ParagraphActions.SwitchEnable:
+ this.paragraph.config.enabled = !this.paragraph.config.enabled;
+ this.commitParagraph();
+ break;
+ case ParagraphActions.SwitchOutputShow:
+ this.setTableHide(!this.paragraph.config.tableHide);
+ this.commitParagraph();
+ break;
+ case ParagraphActions.SwitchLineNumber:
+ this.paragraph.config.lineNumbers = !this.paragraph.config.lineNumbers;
+ this.commitParagraph();
+ break;
+ case ParagraphActions.SwitchTitleShow:
+ this.paragraph.config.title = !this.paragraph.config.title;
+ this.commitParagraph();
+ break;
+ case ParagraphActions.Clear:
+ this.clearParagraphOutput();
+ break;
+ case ParagraphActions.Link:
+ this.openSingleParagraph(this.paragraph.id);
+ break;
+ case ParagraphActions.ReduceWidth:
+ if (!this.paragraph.config.colWidth) {
+ throw new Error('colWidth is required');
+ }
+ this.paragraph.config.colWidth = Math.max(1, this.paragraph.config.colWidth - 1);
+ this.cdr.markForCheck();
+ this.changeColWidth(true);
+ break;
+ case ParagraphActions.IncreaseWidth:
+ if (!this.paragraph.config.colWidth) {
+ throw new Error('colWidth is required');
+ }
+ this.paragraph.config.colWidth = Math.min(12, this.paragraph.config.colWidth + 1);
+ this.cdr.markForCheck();
+ this.changeColWidth(true);
+ break;
+ case ParagraphActions.FindInCode:
+ this.searchCode.emit();
+ break;
default:
break;
}
diff --git a/zeppelin-web-angular/src/app/services/shortcut.service.ts b/zeppelin-web-angular/src/app/services/shortcut.service.ts
index 135de343887..f3cdb96620b 100644
--- a/zeppelin-web-angular/src/app/services/shortcut.service.ts
+++ b/zeppelin-web-angular/src/app/services/shortcut.service.ts
@@ -16,56 +16,61 @@ import { EventManager } from '@angular/platform-browser';
import { Observable } from 'rxjs';
export enum ParagraphActions {
- EditMode = 'Paragraph:EditMode',
- CommandMode = 'Paragraph:CommandMode',
Run = 'Paragraph:Run',
+ RunAbove = 'Paragraph:RunAbove',
RunBelow = 'Paragraph:RunBelow',
Cancel = 'Paragraph:Cancel',
- Clear = 'Paragraph:Clear',
- ReduceWidth = 'Paragraph:ReduceWidth',
- IncreaseWidth = 'Paragraph:IncreaseWidth',
+ MoveCursorUp = 'Paragraph:MoveCursorUp',
+ MoveCursorDown = 'Paragraph:MoveCursorDown',
Delete = 'Paragraph:Delete',
- MoveToUp = 'Paragraph:MoveToUp',
- MoveToDown = 'Paragraph:MoveToDown',
- SelectAbove = 'Paragraph:SelectAbove',
- SelectBelow = 'Paragraph:SelectBelow',
InsertAbove = 'Paragraph:InsertAbove',
InsertBelow = 'Paragraph:InsertBelow',
+ InsertCopyOfParagraphBelow = 'Paragraph:InsertCopyOfParagraphBelow',
+ MoveParagraphUp = 'Paragraph:MoveParagraphUp',
+ MoveParagraphDown = 'Paragraph:MoveParagraphDown',
+ SwitchEnable = 'Paragraph:SwitchEnable',
+ SwitchOutputShow = 'Paragraph:SwitchOutputShow',
SwitchLineNumber = 'Paragraph:SwitchLineNumber',
SwitchTitleShow = 'Paragraph:SwitchTitleShow',
- SwitchOutputShow = 'Paragraph:SwitchOutputShow',
- SwitchEditorShow = 'Paragraph:SwitchEditorShow',
- SwitchEnable = 'Paragraph:SwitchEnable',
- Link = 'Paragraph:Link'
+ Clear = 'Paragraph:Clear',
+ Link = 'Paragraph:Link',
+ ReduceWidth = 'Paragraph:ReduceWidth',
+ IncreaseWidth = 'Paragraph:IncreaseWidth',
+ FindInCode = 'Paragraph:FindInCode'
}
+// On macOS, pressing Option(Alt) + a letter produces a non-ASCII character
+// Shortcuts must use this resulting character instead of the plain letter for macOS
export const ShortcutsMap = {
- [ParagraphActions.EditMode]: 'enter',
- [ParagraphActions.CommandMode]: 'esc',
- [ParagraphActions.Run]: 'shift.enter',
- [ParagraphActions.RunBelow]: 'shift.ctrlCmd.enter',
- [ParagraphActions.Cancel]: 'shift.ctrlCmd.c',
- // Need register special character `¬` in MacOS
- [ParagraphActions.Clear]: ['alt.ctrlCmd.l', 'alt.ctrlCmd.¬'],
- // Need register special character `†` in MacOS
- [ParagraphActions.Link]: ['alt.ctrlCmd.t', 'alt.ctrlCmd.†'],
- // Need register special character `®` in MacOS
- [ParagraphActions.SwitchEnable]: ['alt.ctrlCmd.r', 'alt.ctrlCmd.®'],
- // Need register special character `–` in MacOS
- [ParagraphActions.ReduceWidth]: ['alt.ctrlCmd.-', 'alt.ctrlCmd.–'],
- // Need register special character `≠` in MacOS
- [ParagraphActions.IncreaseWidth]: ['alt.ctrlCmd.+', 'alt.ctrlCmd.≠'],
- [ParagraphActions.Delete]: 'shift.delete',
- [ParagraphActions.MoveToUp]: ['ctrlCmd.k', 'ctrlCmd.arrowup', 'ctrlCmd.arrowleft'],
- [ParagraphActions.MoveToDown]: ['ctrlCmd.j', 'ctrlCmd.arrowdown', 'ctrlCmd.arrowright'],
- [ParagraphActions.SelectAbove]: ['k', 'arrowup', 'arrowleft'],
- [ParagraphActions.SelectBelow]: ['j', 'arrowdown', 'arrowright'],
- [ParagraphActions.SwitchLineNumber]: 'l',
- [ParagraphActions.SwitchTitleShow]: 't',
- [ParagraphActions.SwitchOutputShow]: 'o',
- [ParagraphActions.SwitchEditorShow]: 'e',
- [ParagraphActions.InsertAbove]: 'a',
- [ParagraphActions.InsertBelow]: 'b'
+ [ParagraphActions.Run]: 'shift.enter', // Run paragraph
+ [ParagraphActions.RunAbove]: 'control.shift.arrowup', // Run all above paragraphs (exclusive)
+ [ParagraphActions.RunBelow]: 'control.shift.arrowdown', // Run all below paragraphs (inclusive)
+ [ParagraphActions.Cancel]: ['control.alt.c', 'control.alt.ç'], // Cancel
+ [ParagraphActions.MoveCursorUp]: 'control.p', // Move cursor Up
+ [ParagraphActions.MoveCursorDown]: 'control.n', // Move cursor Down
+ [ParagraphActions.Delete]: ['control.alt.d', 'control.alt.∂'], // Remove paragraph
+ [ParagraphActions.InsertAbove]: ['control.alt.a', 'control.alt.å'], // Insert new paragraph above
+ [ParagraphActions.InsertBelow]: ['control.alt.b', 'control.alt.∫'], // Insert new paragraph below
+ [ParagraphActions.InsertCopyOfParagraphBelow]: 'control.shift.c', // Insert copy of paragraph below
+ [ParagraphActions.MoveParagraphUp]: ['control.alt.k', 'control.alt.˚'], // Move paragraph Up
+ [ParagraphActions.MoveParagraphDown]: ['control.alt.j', 'control.alt.∆'], // Move paragraph Down
+ [ParagraphActions.SwitchEnable]: ['control.alt.r', 'control.alt.®'], // Enable/Disable run paragraph
+ [ParagraphActions.SwitchOutputShow]: ['control.alt.o', 'control.alt.ø'], // Toggle output
+ // Toggle editor - Shortcut logic is implemented in the editor component
+ [ParagraphActions.SwitchLineNumber]: ['control.alt.m', 'control.alt.µ'], // Toggle line number
+ [ParagraphActions.SwitchTitleShow]: ['control.alt.t', 'control.alt.†'], // Toggle title
+ [ParagraphActions.Clear]: ['control.alt.l', 'control.alt.¬'], // Clear output
+ [ParagraphActions.Link]: ['control.alt.w', 'control.alt.∑'], // Link this paragraph
+ [ParagraphActions.ReduceWidth]: 'control.shift._', // Reduce paragraph width
+ [ParagraphActions.IncreaseWidth]: 'control.shift.=', // Increase paragraph width
+ // Auto-completion - No longer needed; always applied now
+ // Cut the line - Shortcut logic is implemented in the editor component
+ // Paste the line - Shortcut logic is implemented in the editor component
+ // Search inside the code - Shortcut logic is implemented in the editor component
+ // Move cursor to the beginning - System shortcut
+ // Move cursor at the end - System shortcut
+ // TODO: Check after the search code is implemented in action-bar.component.ts
+ [ParagraphActions.FindInCode]: ['control.alt.f', 'control.alt.ƒ'] // Find in code
};
export interface ShortcutEvent {
@@ -78,10 +83,6 @@ export interface ShortcutOption {
keybindings: string;
}
-function isMacOS() {
- return navigator.platform.indexOf('Mac') > -1;
-}
-
@Injectable({
providedIn: 'root'
})
@@ -99,9 +100,7 @@ export class ShortcutService {
bindShortcut(option: ShortcutOption): Observable {
const host = option.scope || this.element;
- // `ctrlCmd` is special symbol, will be replaced `meta` in MacOS, 'control' in Windows/Linux
- const keybindings = option.keybindings.replace(/ctrlCmd/g, isMacOS() ? 'meta' : 'control');
- const eventName = `keydown.${keybindings}`;
+ const eventName = `keydown.${option.keybindings}`;
// tslint:disable-next-line:ban-types
let dispose: Function;
return new Observable(observer => {
diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph-control.html b/zeppelin-web/src/app/notebook/paragraph/paragraph-control.html
index 81d711155d5..1621a174100 100644
--- a/zeppelin-web/src/app/notebook/paragraph/paragraph-control.html
+++ b/zeppelin-web/src/app/notebook/paragraph/paragraph-control.html
@@ -141,7 +141,7 @@
- Ctrl+Shift+Enter
+ Ctrl+Shift+Up
Run all above
@@ -150,7 +150,7 @@
- Ctrl+Shift+Enter
+ Ctrl+Shift+Down
Run all below
@@ -189,7 +189,7 @@
- Ctrl+ {{ isMac ? 'Option' : 'Alt'}}+R
+ Ctrl+{{ isMac ? 'Option' : 'Alt'}}+R
{{paragraph.config.enabled ? "Disable" : "Enable"}} run