feat(editor): always accept completions on Enter
Enter now accepts the highlighted item like Tab whenever the popup is open; dismiss with Escape first to insert a plain newline. Drops the `engaged` gate that only accepted after navigating the menu.
This commit is contained in:
@@ -19,10 +19,6 @@ const popup = ref({ left: 0, top: 0 })
|
|||||||
// Suppress the popup for one keystroke after Escape, so it doesn't pop straight
|
// Suppress the popup for one keystroke after Escape, so it doesn't pop straight
|
||||||
// back open while the author is still typing the word they just dismissed.
|
// back open while the author is still typing the word they just dismissed.
|
||||||
let justEscaped = false
|
let justEscaped = false
|
||||||
// Whether the author has moved the selection since the popup (re)opened. Tab
|
|
||||||
// always accepts; Enter only accepts once they've engaged with the menu — an
|
|
||||||
// untouched popup lets Enter do its normal job (a newline) rather than hijack it.
|
|
||||||
let engaged = false
|
|
||||||
// Pixel metrics of the (monospace, non-wrapping) textarea, measured once.
|
// Pixel metrics of the (monospace, non-wrapping) textarea, measured once.
|
||||||
let metrics = { charWidth: 8, lineHeight: 20, padLeft: 16, padTop: 14 }
|
let metrics = { charWidth: 8, lineHeight: 20, padLeft: 16, padTop: 14 }
|
||||||
|
|
||||||
@@ -64,7 +60,6 @@ function refresh() {
|
|||||||
if (!el) return
|
if (!el) return
|
||||||
completion.value = justEscaped ? null : getCompletions(el.value, el.selectionStart)
|
completion.value = justEscaped ? null : getCompletions(el.value, el.selectionStart)
|
||||||
selected.value = 0
|
selected.value = 0
|
||||||
engaged = false
|
|
||||||
if (completion.value) position()
|
if (completion.value) position()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +120,6 @@ function onKeydown(e: KeyboardEvent) {
|
|||||||
if (!ctx) return
|
if (!ctx) return
|
||||||
const move = (delta: number) => {
|
const move = (delta: number) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
engaged = true
|
|
||||||
selected.value = (selected.value + delta + ctx.items.length) % ctx.items.length
|
selected.value = (selected.value + delta + ctx.items.length) % ctx.items.length
|
||||||
}
|
}
|
||||||
// Ctrl+N / Ctrl+P mirror ArrowDown / ArrowUp (readline-style navigation).
|
// Ctrl+N / Ctrl+P mirror ArrowDown / ArrowUp (readline-style navigation).
|
||||||
@@ -140,19 +134,12 @@ function onKeydown(e: KeyboardEvent) {
|
|||||||
case "ArrowUp":
|
case "ArrowUp":
|
||||||
move(-1)
|
move(-1)
|
||||||
break
|
break
|
||||||
case "Tab":
|
|
||||||
e.preventDefault()
|
|
||||||
accept(selected.value)
|
|
||||||
break
|
|
||||||
case "Enter":
|
case "Enter":
|
||||||
// Only steal Enter once the author has navigated the menu; otherwise let
|
case "Tab":
|
||||||
// it insert a newline (onInput → refresh reopens the popup if warranted).
|
// Both accept the highlighted item whenever the popup is open. To insert a
|
||||||
if (engaged) {
|
// newline instead, dismiss the popup with Escape first, then press Enter.
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
accept(selected.value)
|
accept(selected.value)
|
||||||
} else {
|
|
||||||
completion.value = null
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
case "Escape":
|
case "Escape":
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|||||||
Reference in New Issue
Block a user