Skip to content

Commit

Permalink
Improves quickpick keyboard navigation
Browse files Browse the repository at this point in the history
 - Avoids breaking ctrl+[left|right] in input
 - Introduces structured `keyboard` object to handle keypress event bindings and actions
  • Loading branch information
eamodio committed Dec 6, 2023
1 parent 6935b4c commit 7981bd5
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 83 deletions.
32 changes: 17 additions & 15 deletions src/commands/diffWithRevision.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,23 @@ export class DiffWithRevisionCommand extends ActiveEditorCommand {
'Choose a commit to compare with',
{
picked: gitUri.sha,
keys: ['right', 'alt+right', 'ctrl+right'],
onDidPressKey: async (key, item) => {
void (await executeCommand<DiffWithCommandArgs>(Commands.DiffWith, {
repoPath: gitUri.repoPath,
lhs: {
sha: item.item.ref,
uri: gitUri,
},
rhs: {
sha: '',
uri: gitUri,
},
line: args!.line,
showOptions: args!.showOptions,
}));
keyboard: {
keys: ['right', 'alt+right', 'ctrl+right'],
onDidPressKey: async (key, item) => {
await executeCommand<DiffWithCommandArgs>(Commands.DiffWith, {
repoPath: gitUri.repoPath,
lhs: {
sha: item.item.ref,
uri: gitUri,
},
rhs: {
sha: '',
uri: gitUri,
},
line: args!.line,
showOptions: args!.showOptions,
});
},
},
showOtherReferences: [
CommandQuickPickItem.fromCommand('Choose a Branch or Tag...', Commands.DiffWithRevisionFrom),
Expand Down
14 changes: 10 additions & 4 deletions src/commands/gitCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,9 @@ export class GitCommandsCommand extends Command {

const scope = this.container.keyboard.createScope(mapping);
void scope.start();
if (step.value != null) {
void scope.pause(['left', 'ctrl+left', 'right', 'ctrl+right']);
}

disposables.push(
scope,
Expand Down Expand Up @@ -404,9 +407,9 @@ export class GitCommandsCommand extends Command {
if (scope != null) {
// Pause the left/right keyboard commands if there is a value, otherwise the left/right arrows won't work in the input properly
if (e.length !== 0) {
await scope.pause(['left', 'right']);
void scope.pause(['left', 'ctrl+left', 'right', 'ctrl+right']);
} else {
await scope.resume();
void scope.resume();
}
}

Expand Down Expand Up @@ -521,6 +524,9 @@ export class GitCommandsCommand extends Command {

const scope = this.container.keyboard.createScope(mapping);
void scope.start();
if (step.value != null) {
void scope.pause(['left', 'ctrl+left', 'right', 'ctrl+right']);
}

let overrideItems = false;

Expand Down Expand Up @@ -592,9 +598,9 @@ export class GitCommandsCommand extends Command {
if (scope != null) {
// Pause the left/right keyboard commands if there is a value, otherwise the left/right arrows won't work in the input properly
if (e.length !== 0) {
await scope.pause(['left', 'right']);
void scope.pause(['left', 'ctrl+left', 'right', 'ctrl+right']);
} else {
await scope.resume();
void scope.resume();
}
}

Expand Down
18 changes: 10 additions & 8 deletions src/commands/openFileAtRevision.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,16 @@ export class OpenFileAtRevisionCommand extends ActiveEditorCommand {
`Choose a commit to ${args.annotationType === 'blame' ? 'blame' : 'open'} the file revision from`,
{
picked: gitUri.sha,
keys: ['right', 'alt+right', 'ctrl+right'],
onDidPressKey: async (key, item) => {
await openFileAtRevision(item.item.file!, item.item, {
annotationType: args!.annotationType,
line: args!.line,
preserveFocus: true,
preview: false,
});
keyboard: {
keys: ['right', 'alt+right', 'ctrl+right'],
onDidPressKey: async (key, item) => {
await openFileAtRevision(item.item.file!, item.item, {
annotationType: args!.annotationType,
line: args!.line,
preserveFocus: true,
preview: true,
});
},
},
showOtherReferences: [
CommandQuickPickItem.fromCommand(
Expand Down
11 changes: 5 additions & 6 deletions src/commands/openFileAtRevisionFrom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,19 @@ export class OpenFileAtRevisionFromCommand extends ActiveEditorCommand {
'Choose a branch or tag to open the file revision from',
{
allowEnteringRefs: true,
keys: ['right', 'alt+right', 'ctrl+right'],
onDidPressKey: async (key, quickpick) => {
const [item] = quickpick.activeItems;
if (item != null) {
keyboard: {
keys: ['right', 'alt+right', 'ctrl+right'],
onDidPressKey: async (key, item) => {
await openFileAtRevision(
this.container.git.getRevisionUri(item.ref, gitUri.fsPath, gitUri.repoPath!),
{
annotationType: args!.annotationType,
line: args!.line,
preserveFocus: true,
preview: false,
preview: true,
},
);
}
},
},
},
);
Expand Down
56 changes: 36 additions & 20 deletions src/quickpicks/commitPicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ export async function showCommitPicker(
placeholder: string,
options?: {
picked?: string;
keys?: Keys[];
onDidPressKey?(key: Keys, item: CommitQuickPickItem): void | Promise<void>;
keyboard?: {
keys: Keys[];
onDidPressKey(key: Keys, item: CommitQuickPickItem): void | Promise<void>;
};
showOtherReferences?: CommandQuickPickItem[];
},
): Promise<GitCommit | undefined> {
Expand Down Expand Up @@ -98,17 +100,23 @@ export async function showCommitPicker(
const disposables: Disposable[] = [];

let scope: KeyboardScope | undefined;
if (options?.keys != null && options.keys.length !== 0 && options?.onDidPressKey !== null) {
if (options?.keyboard != null) {
const { keyboard } = options;
scope = Container.instance.keyboard.createScope(
Object.fromEntries(
options.keys.map(key => [
keyboard.keys.map(key => [
key,
{
onDidPressKey: key => {
onDidPressKey: async key => {
if (quickpick.activeItems.length !== 0) {
const [item] = quickpick.activeItems;
if (item != null && !isDirectiveQuickPickItem(item) && !CommandQuickPickItem.is(item)) {
void options.onDidPressKey!(key, item);
const ignoreFocusOut = quickpick.ignoreFocusOut;
quickpick.ignoreFocusOut = true;

await keyboard.onDidPressKey(key, item);

quickpick.ignoreFocusOut = ignoreFocusOut;
}
}
},
Expand Down Expand Up @@ -143,14 +151,14 @@ export async function showCommitPicker(
resolve(item);
}
}),
quickpick.onDidChangeValue(async e => {
quickpick.onDidChangeValue(value => {
if (scope == null) return;

// Pause the left/right keyboard commands if there is a value, otherwise the left/right arrows won't work in the input properly
if (e.length !== 0) {
await scope.pause(['left', 'right']);
if (value.length !== 0) {
void scope.pause(['left', 'ctrl+left', 'right', 'ctrl+right']);
} else {
await scope.resume();
void scope.resume();
}
}),
);
Expand Down Expand Up @@ -182,8 +190,10 @@ export async function showStashPicker(
options?: {
empty?: string;
filter?: (c: GitStashCommit) => boolean;
keys?: Keys[];
onDidPressKey?(key: Keys, item: CommitQuickPickItem<GitStashCommit>): void | Promise<void>;
keyboard?: {
keys: Keys[];
onDidPressKey(key: Keys, item: CommitQuickPickItem<GitStashCommit>): void | Promise<void>;
};
picked?: string;
showOtherReferences?: CommandQuickPickItem[];
},
Expand Down Expand Up @@ -231,17 +241,23 @@ export async function showStashPicker(
const disposables: Disposable[] = [];

let scope: KeyboardScope | undefined;
if (options?.keys != null && options.keys.length !== 0 && options?.onDidPressKey !== null) {
if (options?.keyboard != null) {
const { keyboard } = options;
scope = Container.instance.keyboard.createScope(
Object.fromEntries(
options.keys.map(key => [
keyboard.keys.map(key => [
key,
{
onDidPressKey: key => {
onDidPressKey: async key => {
if (quickpick.activeItems.length !== 0) {
const [item] = quickpick.activeItems;
if (item != null && !isDirectiveQuickPickItem(item) && !CommandQuickPickItem.is(item)) {
void options.onDidPressKey!(key, item);
const ignoreFocusOut = quickpick.ignoreFocusOut;
quickpick.ignoreFocusOut = true;

await keyboard.onDidPressKey(key, item);

quickpick.ignoreFocusOut = ignoreFocusOut;
}
}
},
Expand Down Expand Up @@ -270,14 +286,14 @@ export async function showStashPicker(
resolve(item);
}
}),
quickpick.onDidChangeValue(async e => {
quickpick.onDidChangeValue(value => {
if (scope == null) return;

// Pause the left/right keyboard commands if there is a value, otherwise the left/right arrows won't work in the input properly
if (e.length !== 0) {
await scope.pause(['left', 'right']);
if (value.length !== 0) {
void scope.pause(['left', 'ctrl+left', 'right', 'ctrl+right']);
} else {
await scope.resume();
void scope.resume();
}
}),
);
Expand Down
Loading

0 comments on commit 7981bd5

Please sign in to comment.