keys: n walks the search results, and a half-typed key shows

`n` / `N` move to the next / previous search result and open it beside the
results, so the next `n` goes on from there; a folder is only highlighted,
as going into it would end the search. Past the last result it starts
again at the first and says so, as vim's `wrapscan` does. Clearing the
search is left to `:noh` / `:clear`, as in vim, rather than to `n`.

After `g`, `d`, `]` or `[` the status line shows the key waiting for its
second half, like vim's `showcmd`, and forgets it after a second.
This commit is contained in:
nvrl committed 2026-10-20 15:17:31 +02:00
1 parent b3a60aa361
commit c72eccf86b
5 files changed
+42 -7

No files matched your search

+13 -2
View File
@@ -44,6 +44,7 @@
let importRoot = false
let shell = $state<HTMLDivElement>()
let overlayEl = $state<HTMLDivElement>()
/** The first half of `gg`, `dd`, `]]` …, shown until the second comes. */
let pending = $state('')
/** `F`: the pane whose links and buttons are wearing hints right now. */
let hintRoot = $state<HTMLElement | null>(null)
@@ -135,6 +136,13 @@
return () => clearTimeout(timer)
})
// A first half left alone is forgotten, as vim's `timeoutlen` does.
$effect(() => {
if (!pending) return
const timer = setTimeout(() => (pending = ''), 1000)
return () => clearTimeout(timer)
})
// Guard against losing a half-written entry to a stray refresh.
$effect(() => {
if (!workspace.dirty) return
@@ -775,8 +783,11 @@
})()
break
case 'n':
case 'N':
// Through the results, as vim's `n` goes through the matches; the
// search itself stays until `:noh`.
event.preventDefault()
if (workspace.query) void workspace.guard(() => workspace.search(''))
void workspace.guard(() => workspace.nextResult(key === 'n' ? 1 : -1))
break
case '/':
event.preventDefault()
@@ -864,7 +875,7 @@
{/key}
</main>
<StatusBar />
<StatusBar {pending} />
{#if cmdline !== null}
<CommandLine initial={cmdline} global={cmdGlobal} close={() => ((cmdline = null), (cmdGlobal = false))} />