This is an automated email from the ASF dual-hosted git repository.

voidmatcha pushed a commit to branch pr5339-rebase
in repository https://gitbox.apache.org/repos/asf/zeppelin.git

commit 077327bee10ada7145e5c1ffbd8c2bb3c44c9892
Author: YONGJAE LEE <[email protected]>
AuthorDate: Sun Aug 2 15:19:54 2026 +0900

    Keep Monaco shortcuts scoped to the focused paragraph
---
 .../keyboard/notebook-keyboard-shortcuts.spec.ts         | 16 ++++++++++------
 zeppelin-web-angular/src/app/key-binding/key-binder.ts   | 16 +++++++++++++---
 .../notebook-paragraph-keyboard-event-handler.ts         |  4 +---
 3 files changed, 24 insertions(+), 12 deletions(-)

diff --git 
a/zeppelin-web-angular/e2e/tests/notebook/keyboard/notebook-keyboard-shortcuts.spec.ts
 
b/zeppelin-web-angular/e2e/tests/notebook/keyboard/notebook-keyboard-shortcuts.spec.ts
index ee2fa5f481..a6c87814b1 100644
--- 
a/zeppelin-web-angular/e2e/tests/notebook/keyboard/notebook-keyboard-shortcuts.spec.ts
+++ 
b/zeppelin-web-angular/e2e/tests/notebook/keyboard/notebook-keyboard-shortcuts.spec.ts
@@ -461,18 +461,22 @@ test.describe.serial('Comprehensive Keyboard Shortcuts 
(ShortcutsMap)', () => {
   // ===== UI TOGGLE SHORTCUTS =====
 
   test.describe('ParagraphActions.SwitchEditor: Control+Alt+E', () => {
-    test('should toggle editor visibility with Control+Alt+E', async () => {
-      // Given: A paragraph with visible editor
-      await keyboardPage.tryFocusCodeEditor();
-      await keyboardPage.setCodeEditorContent('%python\nprint("Test editor 
toggle")');
+    test('should toggle the focused editor with Control+Alt+E', async () => {
+      await keyboardPage.tryFocusCodeEditor(0);
+      await keyboardPage.setCodeEditorContent('%python\nprint("First 
paragraph")', 0);
+      await keyboardPage.pressInsertBelow();
+      await keyboardPage.waitForParagraphCountChange(2);
+      await keyboardPage.tryFocusCodeEditor(1);
+      await keyboardPage.setCodeEditorContent('%python\nprint("Second 
paragraph")', 1);
+      await keyboardPage.tryFocusCodeEditor(0);
 
       const initialEditorVisibility = await keyboardPage.isEditorVisible(0);
+      const secondEditorVisibility = await keyboardPage.isEditorVisible(1);
 
-      // When: User presses Control+Alt+E
       await keyboardPage.pressSwitchEditor();
 
-      // Then: editor visibility toggles
       await expect.poll(() => keyboardPage.isEditorVisible(0), { timeout: 
10000 }).toBe(!initialEditorVisibility);
+      expect(await 
keyboardPage.isEditorVisible(1)).toBe(secondEditorVisibility);
     });
   });
 
diff --git a/zeppelin-web-angular/src/app/key-binding/key-binder.ts 
b/zeppelin-web-angular/src/app/key-binding/key-binder.ts
index 5267c78849..cfbec5b50b 100644
--- a/zeppelin-web-angular/src/app/key-binding/key-binder.ts
+++ b/zeppelin-web-angular/src/app/key-binding/key-binder.ts
@@ -18,14 +18,18 @@ import { map, mergeMap, takeUntil } from 'rxjs/operators';
 import { ShortcutService } from '@zeppelin/services';
 import { castArray, chain, isNil } from 'lodash';
 import { KeyCodeConverter } from './key-code-converter';
+import { MonacoHandledParagraphActions } from 
'./notebook-paragraph-keyboard-event-handler';
 import { ParagraphActions } from './paragraph-actions';
 import { ShortcutsMap } from './shortcuts-map';
 
 export class KeyBinder {
+  private static nextMonacoContextId = 0;
+
   private events$ = new Subject<{
     action: ParagraphActions;
     event: KeyboardEvent | null;
   }>();
+  private readonly monacoContext = 
`zeppelin.paragraphEditor.${KeyBinder.nextMonacoContextId++}`;
 
   constructor(
     private destroySubject: Observable<unknown>,
@@ -56,17 +60,23 @@ export class KeyBinder {
   }
 
   initKeyBindingsOnMonaco(editor: MonacoEditor.IStandaloneCodeEditor) {
+    editor.createContextKey(this.monacoContext, true);
     chain(ShortcutsMap)
       .toPairs()
+      .filter(([action]) => MonacoHandledParagraphActions.some(monacoAction => 
monacoAction === action))
       .flatMap(([action, keys]) => castArray(keys).map(key => ({ action, key 
})))
       .forEach(({ action, key }) => {
         const keyBinding = KeyCodeConverter.angularToMonacoKeyBinding(key);
         if (isNil(keyBinding)) {
           return;
         }
-        editor.addCommand(keyBinding, () => {
-          this.events$.next({ action: action as ParagraphActions, event: null 
});
-        });
+        editor.addCommand(
+          keyBinding,
+          () => {
+            this.events$.next({ action: action as ParagraphActions, event: 
null });
+          },
+          this.monacoContext
+        );
       })
       .value();
   }
diff --git 
a/zeppelin-web-angular/src/app/key-binding/notebook-paragraph-keyboard-event-handler.ts
 
b/zeppelin-web-angular/src/app/key-binding/notebook-paragraph-keyboard-event-handler.ts
index 3c6e8508c8..95cd4ec80f 100644
--- 
a/zeppelin-web-angular/src/app/key-binding/notebook-paragraph-keyboard-event-handler.ts
+++ 
b/zeppelin-web-angular/src/app/key-binding/notebook-paragraph-keyboard-event-handler.ts
@@ -71,9 +71,7 @@ export const ParagraphActionToHandlerName = {
   [ParagraphActions.FindInCode]: 'handleFindInCode'
 } as const satisfies Record<ParagraphActions, keyof 
NotebookParagraphKeyboardEventHandler>;
 
-// Referenced only via `typeof` below to derive a type; the runtime binding is 
intentionally unused.
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-const MonacoHandledParagraphActions = [
+export const MonacoHandledParagraphActions = [
   ParagraphActions.MoveCursorUp,
   ParagraphActions.MoveCursorDown,
   ParagraphActions.SwitchEditor,

Reply via email to