Skip to content

[ZEPPELIN-6710] Keep Enter as a newline for no-op Monaco suggestions - #5490

Merged
voidmatcha merged 1 commit into
apache:masterfrom
HwangRock:ZEPPELIN-6710-monaco-enter-newline
Sep 20, 2026
Merged

voidmatcha merged 1 commit into
apache:masterfrom
HwangRock:ZEPPELIN-6710-monaco-enter-newline

Conversation

@HwangRock

@HwangRock HwangRock commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

What is this PR for?

In the New UI paragraph editor (Monaco), pressing Enter can be silently swallowed while the auto-suggest popup is open, dropping a line break so the next characters land on the current line instead of a new one.

The trigger is a no-op suggestion. When word-based suggestions offer a candidate identical to the word the user just finished typing, accepting it changes nothing. With Monaco's acceptSuggestionOnEnter left at its default ('on'), Enter accepts that no-op candidate instead of inserting a newline: the keystroke is consumed, the line break never lands, and rapid multi-line typing loses lines.

The fix sets acceptSuggestionOnEnter: 'smart' on the paragraph editor. The auto-suggest popup still appears; only the Enter behavior changes, and only for a focused candidate whose acceptance would not change the text.

Why 'smart' over the alternatives

  • wordBasedSuggestions: 'off' — removes the document-word completion feature entirely. That is heavier than the bug warrants, and it is not even the right lever: Monaco's built-in word-based provider already filters out an exact match of the current token (editorSimpleWorker.js, if (word === leadingWord) continue), so turning it off does not target the actual no-op source.
  • Filtering exact-match candidates in the interpreter completion provider (completion.service.ts) — the most surgical removal of the candidate, but it changes interpreter completion behavior, which ZEPPELIN-6710 explicitly lists as out of scope ("Changing interpreter completion behavior or the Ctrl+Space-then-Enter accept flow"). It also lives outside updateEditorOptions(), which the issue scopes the change to.
  • acceptSuggestionOnEnter: 'smart' — a one-line change inside updateEditorOptions(), keeps the completion feature intact, and defends the newline regardless of which provider produced the candidate. It matches the issue's scope ("Stop Enter from silently discarding a newline when the focused suggestion would make no textual change") exactly.

Trade-offs, and why they are not problems here

  • It defends Enter rather than removing the candidate. The no-op candidate still appears in the popup, and Tab/click still accept it. But accepting a no-op is inert (it changes nothing), so there is no harm left to prevent — only the silent newline loss mattered, and that is what 'smart' fixes.
  • acceptSuggestionOnEnter is editor-wide (within the paragraph code editor). Behavior only changes for the exact combination "no-op candidate + auto-triggered popup + Enter"; every other completion path — partial-word accept, Ctrl+Space, Tab — is unchanged. There is no scenario where turning a no-op accept into a newline is a regression.
  • 'smart' does not cover additionalTextEdits (auto-import) or snippet candidates — Monaco treats those as text-changing and still accepts them on Enter. This does not apply to Zeppelin: interpreter completions are mapped as plain-string insertText with no insertTextRules or additionalTextEdits (completion.service.ts), so those candidate shapes are never produced.

How 'smart' works internally

Monaco recomputes a context key suggestionMakesTextEdit whenever the focused suggestion changes. Under 'smart', it gates on: the popup was auto-triggered (state === Auto, i.e. not a manual Ctrl+Space), no additionalTextEdits, not a snippet, and the replace range length equals the insert-text length. When that gate passes, it compares the editor text against the candidate's insertText; if they are identical the key is set to false.

Enter is bound to acceptSelectedSuggestion, which requires Visible && textInputFocus && acceptSuggestionOnEnter && suggestionMakesTextEdit. With the key false, that binding no longer matches, so Enter falls through to the editor's default action — a newline. Ctrl+Space (a manual trigger) never enters the state === Auto gate, so interpreter completion's accept-on-Enter is unaffected; inline ghost-text is a separate registerInlineCompletionsProvider subsystem and is likewise untouched.

What type of PR is it?

Bug Fix

What is the Jira issue?

https://issues.apache.org/jira/browse/ZEPPELIN-6710

How should this be tested?

A new Playwright regression, zeppelin-web-angular/e2e/tests/notebook/monaco-enter-newline.spec.ts, drives the auto-suggest path (typing to let quickSuggestions open the popup, not a manual trigger, since 'smart' only applies to auto-triggered popups). It asserts:

  • a no-op exact-match candidate + Enter keeps the newline (foobar\nbaz, not foobarbaz);
  • a genuine partial-prefix candidate still accepts on Enter ('smart' only skips no-ops).

Verified: the test passes with the fix, and fails deterministically (foobar and baz merge onto one line) when the 'smart' line is removed — so the regression actually pins the bug. tsc, prettier, and eslint are clean.

Screenshots (if appropriate)

2026-09-19.8.42.44.mov

Questions:

  • Does the documentation need to be updated? No.

When word-based suggestions offer a candidate identical to the word just
typed, accepting it is a no-op. With acceptSuggestionOnEnter at its
default ('on'), Enter accepted that no-op suggestion and the newline was
swallowed, so rapid multi-line typing silently dropped line breaks.

Set acceptSuggestionOnEnter to 'smart' so Enter falls through as a
newline when the focused suggestion would not change the text.
Interpreter completion (Ctrl+Space, a manual trigger) and inline
ghost-text are a separate path and are unaffected.

Add an e2e regression covering the auto-suggest Enter path.

@ParkGyeongTae ParkGyeongTae left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. The change is focused, and the new E2E test passes locally.

@voidmatcha
voidmatcha merged commit 7076ea4 into apache:master Sep 20, 2026
24 checks passed
@voidmatcha

Copy link
Copy Markdown
Member

Merged into master (7076ea4).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants