Skip to content

Commit

Permalink
Allows seek to accept more than one keypress.
Browse files Browse the repository at this point in the history
The new argument `inputLength` (which defaults to 1) determines how many
characters the `seek` command accepts. This uses the newly implemented
`keyCount` argument (which also defaults to 1) to accept multiples
keypresses.

The most immediate use for this is to implement the equivalent of
vim-sneak. Sneak accepts two key presses, and like `t`, sneak jumps the
cursor right before the next match of the input.

This also includes some shortcut commands for easily sneaking with the
`s` key in normal mode using select.orSneak.
  • Loading branch information
haberdashPI committed Aug 1, 2023
1 parent e15330a commit 05bfdd8
Show file tree
Hide file tree
Showing 9 changed files with 295 additions and 198 deletions.
30 changes: 30 additions & 0 deletions package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 27 additions & 3 deletions src/api/data/commands.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2480,6 +2480,7 @@ selections.select:
| Title | Identifier | Keybinding | Command |
| -------------- | --------------- | --------------------- | ------------------------------------------------------------------------------------------------- |
| Leap or select | `select.orLeap` | `s` (kakoune: normal) | `[".ifEmpty", { then: [[".seek.leap", { ... }]], otherwise: [[".selections.select", { ... }]] }]` |
| Leap or select | `select.orSneak` | `s` (kakoune: normal) | `[".ifEmpty", { then: [[".seek", { inputLength: 2, ... }]], otherwise: [[".selections.select", { ... }]] }]` |
selections.select.orLeap:
title:
Expand All @@ -2492,6 +2493,17 @@ selections.select.orLeap:
qwerty: |-
`s` (kakoune: normal)
selections.select.orSneak:
title:
en: Leap or select

commands: |-
[".ifEmpty", { then: [[".seek", { inputLength: 2, $exclude: [] }]], otherwise: [[".selections.select", { $exclude: [] }]] }]
keys:
qwerty: |-
`s` (kakoune: normal)
selections.showIndices:
title:
en: Show selection indices
Expand Down Expand Up @@ -2530,9 +2542,10 @@ selections.splitLines:
#### Variants
| Title | Identifier | Keybinding | Command |
| ----------------------- | ---------------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------- |
| Leap or select backward | `splitLines.orLeap.backward` | `a-s` (kakoune: normal) | `[".ifEmpty", { then: [[".seek.leap", { direction: -1, ... }]], otherwise: [[".selections.splitLines", { ... }]] }]` |
| Title | Identifier | Keybinding | Command |
| ------------------------ | ----------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Leap or select backward | `splitLines.orLeap.backward` | `a-s` (kakoune: normal) | `[".ifEmpty", { then: [[".seek.leap", { direction: -1, ... }]], otherwise: [[".selections.splitLines", { ... }]] }]` |
| Sneak or select backward | `splitLines.orSneak.backward` | `a-s` (kakoune: normal) | `[".ifEmpty", { then: [[".seek", { inputLength: 2, direction: -1, ... }]], otherwise: [[".selections.splitLines", { ... }]] }]` |
selections.splitLines.orLeap.backward:
title:
Expand All @@ -2545,6 +2558,17 @@ selections.splitLines.orLeap.backward:
qwerty: |-
`a-s` (kakoune: normal)
selections.splitLines.orSneak.backward:
title:
en: Sneak or select backward

commands: |-
[".ifEmpty", { then: [[".seek", { inputLength: 2, direction: -1, $exclude: [] }]], otherwise: [[".selections.splitLines", { $exclude: [] }]] }]
keys:
qwerty: |-
`a-s` (kakoune: normal)
selections.toggleIndices:
title:
en: Toggle selection indices
Expand Down
13 changes: 9 additions & 4 deletions src/api/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,9 +466,11 @@ export function notifyPromptActionRequested(action: "next" | "previous" | "clear
}

/**
* Awaits a keypress from the user and returns the entered key.
* Awaits for one or more keypresses from the user and returns the entered keys.
*
* `keyCount`: determines the number of keypresses to wait for (defaults to 1)
*/
export async function keypress(context = Context.current): Promise<string> {
export async function keypress(context = Context.current, keyCount: number = 1): Promise<string> {
if (context.cancellationToken.isCancellationRequested) {
return Promise.reject(new CancellationError(CancellationError.Reason.CancellationToken));
}
Expand All @@ -479,12 +481,15 @@ export async function keypress(context = Context.current): Promise<string> {

return await new Promise<string>((resolve, reject) => {
try {
let keys = "";
const subscriptions = [
vscode.commands.registerCommand("type", ({ text }: { text: string; }) => {
if (subscriptions.length > 0) {
keys += text;
if (subscriptions.length > 0 && keys.length >= keyCount) {
subscriptions.splice(0).forEach((s) => s.dispose());

context.switchToMode(previousMode).then(() => resolve(text));
context.switchToMode(previousMode)
.then(() => resolve(keys.slice(0, keyCount)));
}
}),

Expand Down
Loading

0 comments on commit 05bfdd8

Please sign in to comment.