diff --git a/images/dark/icon-check.svg b/images/dark/icon-check.svg
new file mode 100644
index 0000000..e4094c5
--- /dev/null
+++ b/images/dark/icon-check.svg
@@ -0,0 +1,3 @@
+
diff --git a/images/dark/icon-no-check.svg b/images/dark/icon-no-check.svg
new file mode 100644
index 0000000..659bc34
--- /dev/null
+++ b/images/dark/icon-no-check.svg
@@ -0,0 +1,3 @@
+
diff --git a/images/light/icon-check.svg b/images/light/icon-check.svg
new file mode 100644
index 0000000..ef3c42c
--- /dev/null
+++ b/images/light/icon-check.svg
@@ -0,0 +1,3 @@
+
diff --git a/images/light/icon-no-check.svg b/images/light/icon-no-check.svg
new file mode 100644
index 0000000..f023f0c
--- /dev/null
+++ b/images/light/icon-no-check.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/commands/git/checkout.ts b/src/commands/git/checkout.ts
index 00dbd7d..08137a0 100644
--- a/src/commands/git/checkout.ts
+++ b/src/commands/git/checkout.ts
@@ -1,6 +1,6 @@
'use strict';
/* eslint-disable no-loop-func */
-import { ProgressLocation, QuickInputButtons, window } from 'vscode';
+import { ProgressLocation, QuickInputButton, window } from 'vscode';
import { Container } from '../../container';
import { GitBranch, GitReference, GitTag, Repository } from '../../git/gitService';
import { GlyphChars } from '../../constants';
@@ -9,22 +9,24 @@ import { ReferencesQuickPickItem, RefQuickPickItem, RepositoryQuickPickItem } fr
import { Strings } from '../../system';
import { Logger } from '../../logger';
+type Mutable = Omit & { -readonly [P in K]: T[P] };
+
interface State {
repos: Repository[];
branchOrTagOrRef: GitBranch | GitTag | GitReference;
createBranch?: string;
}
-export interface CommandArgs {
+export interface CheckoutGitCommandArgs {
readonly command: 'checkout';
state?: Partial;
- skipConfirmation?: boolean;
+ confirm?: boolean;
}
export class CheckoutGitCommand extends QuickCommandBase {
- constructor(args?: CommandArgs) {
- super('checkout', 'Checkout');
+ constructor(args?: CheckoutGitCommandArgs) {
+ super('checkout', 'checkout', 'Checkout');
if (args === undefined || args.state === undefined) return;
@@ -37,16 +39,9 @@ export class CheckoutGitCommand extends QuickCommandBase {
counter++;
}
- if (
- args.skipConfirmation === undefined &&
- Container.config.gitCommands.skipConfirmations.includes(this.label)
- ) {
- args.skipConfirmation = true;
- }
-
this._initialState = {
counter: counter,
- skipConfirmation: counter > 1 && args.skipConfirmation,
+ confirm: args.confirm,
...args.state
};
}
@@ -109,13 +104,22 @@ export class CheckoutGitCommand extends QuickCommandBase {
}
if (state.branchOrTagOrRef === undefined || state.counter < 2) {
- const includeTags = showTags || state.repos.length === 1;
+ showTags = state.repos.length === 1;
+
+ const toggleTagsButton: Mutable = {
+ iconPath: {
+ dark: Container.context.asAbsolutePath('images/dark/icon-tag.svg') as any,
+ light: Container.context.asAbsolutePath('images/light/icon-tag.svg') as any
+ },
+ tooltip: showTags ? 'Hide Tags' : 'Show Tags'
+ };
const items = await getBranchesAndOrTags(
state.repos,
- includeTags,
+ showTags,
state.repos.length === 1 ? undefined : { filterBranches: b => !b.remote }
);
+
const step = this.createPickStep({
title: `${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${
state.repos.length === 1
@@ -123,39 +127,30 @@ export class CheckoutGitCommand extends QuickCommandBase {
: `${state.repos.length} repositories`
}`,
placeholder: `Choose a branch${
- includeTags ? ' or tag' : ''
+ showTags ? ' or tag' : ''
} to checkout to${GlyphChars.Space.repeat(3)}(select or enter a reference)`,
matchOnDescription: true,
items: items,
selectedItems: state.branchOrTagOrRef
? items.filter(ref => ref.label === state.branchOrTagOrRef!.ref)
: undefined,
- buttons: includeTags
- ? [QuickInputButtons.Back]
- : [
- QuickInputButtons.Back,
- {
- iconPath: {
- dark: Container.context.asAbsolutePath('images/dark/icon-tag.svg') as any,
- light: Container.context.asAbsolutePath('images/light/icon-tag.svg') as any
- },
- tooltip: 'Show Tags'
- }
- ],
+ additionalButtons: [toggleTagsButton],
onDidClickButton: async (quickpick, button) => {
quickpick.busy = true;
quickpick.enabled = false;
- if (!showTags) {
- showTags = true;
- }
+ showTags = !showTags;
+ toggleTagsButton.tooltip = showTags ? 'Hide Tags' : 'Show Tags';
quickpick.placeholder = `Choose a branch${
showTags ? ' or tag' : ''
} to checkout to${GlyphChars.Space.repeat(3)}(select or enter a reference)`;
- quickpick.buttons = [QuickInputButtons.Back];
- quickpick.items = await getBranchesAndOrTags(state.repos!, showTags);
+ quickpick.items = await getBranchesAndOrTags(
+ state.repos!,
+ showTags,
+ state.repos!.length === 1 ? undefined : { filterBranches: b => !b.remote }
+ );
quickpick.busy = false;
quickpick.enabled = true;
@@ -228,7 +223,7 @@ export class CheckoutGitCommand extends QuickCommandBase {
}
}
- if (!state.skipConfirmation) {
+ if (this.confirm(state.confirm)) {
const step = this.createConfirmStep(
`Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${
state.repos.length === 1
diff --git a/src/commands/git/cherry-pick.ts b/src/commands/git/cherry-pick.ts
index 60da22c..7a3fb84 100644
--- a/src/commands/git/cherry-pick.ts
+++ b/src/commands/git/cherry-pick.ts
@@ -25,7 +25,7 @@ interface State {
export class CherryPickGitCommand extends QuickCommandBase {
constructor() {
- super('cherry-pick', 'Cherry Pick', { description: 'via Terminal' });
+ super('cherry-pick', 'cherry-pick', 'Cherry Pick', false, { description: 'via Terminal' });
}
execute(state: State) {
diff --git a/src/commands/git/fetch.ts b/src/commands/git/fetch.ts
index 365c00d..d1a5c10 100644
--- a/src/commands/git/fetch.ts
+++ b/src/commands/git/fetch.ts
@@ -12,16 +12,16 @@ interface State {
flags: string[];
}
-export interface CommandArgs {
+export interface FetchGitCommandArgs {
readonly command: 'fetch';
state?: Partial;
- skipConfirmation?: boolean;
+ confirm?: boolean;
}
export class FetchGitCommand extends QuickCommandBase {
- constructor(args?: CommandArgs) {
- super('fetch', 'Fetch');
+ constructor(args?: FetchGitCommandArgs) {
+ super('fetch', 'fetch', 'Fetch');
if (args === undefined || args.state === undefined) return;
@@ -30,16 +30,9 @@ export class FetchGitCommand extends QuickCommandBase {
counter++;
}
- if (
- args.skipConfirmation === undefined &&
- Container.config.gitCommands.skipConfirmations.includes(this.label)
- ) {
- args.skipConfirmation = true;
- }
-
this._initialState = {
counter: counter,
- skipConfirmation: counter > 0 && args.skipConfirmation,
+ confirm: args.confirm,
...args.state
};
}
@@ -94,10 +87,7 @@ export class FetchGitCommand extends QuickCommandBase {
}
}
- if (state.skipConfirmation) {
- state.flags = [];
- }
- else {
+ if (this.confirm(state.confirm)) {
const step = this.createConfirmStep>(
`Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${
state.repos.length === 1
@@ -159,6 +149,9 @@ export class FetchGitCommand extends QuickCommandBase {
state.flags = selection[0].item;
}
+ else {
+ state.flags = [];
+ }
this.execute(state as State);
break;
diff --git a/src/commands/git/merge.ts b/src/commands/git/merge.ts
index d5984cd..f7f5151 100644
--- a/src/commands/git/merge.ts
+++ b/src/commands/git/merge.ts
@@ -24,7 +24,7 @@ interface State {
export class MergeGitCommand extends QuickCommandBase {
constructor() {
- super('merge', 'Merge', { description: 'via Terminal' });
+ super('merge', 'merge', 'Merge', false, { description: 'via Terminal' });
}
execute(state: State) {
diff --git a/src/commands/git/pull.ts b/src/commands/git/pull.ts
index 34ecaa2..a1345a7 100644
--- a/src/commands/git/pull.ts
+++ b/src/commands/git/pull.ts
@@ -12,16 +12,16 @@ interface State {
flags: string[];
}
-export interface CommandArgs {
+export interface PullGitCommandArgs {
readonly command: 'pull';
state?: Partial;
- skipConfirmation?: boolean;
+ confirm?: boolean;
}
export class PullGitCommand extends QuickCommandBase {
- constructor(args?: CommandArgs) {
- super('pull', 'Pull');
+ constructor(args?: PullGitCommandArgs) {
+ super('pull', 'pull', 'Pull');
if (args === undefined || args.state === undefined) return;
@@ -30,16 +30,9 @@ export class PullGitCommand extends QuickCommandBase {
counter++;
}
- if (
- args.skipConfirmation === undefined &&
- Container.config.gitCommands.skipConfirmations.includes(this.label)
- ) {
- args.skipConfirmation = true;
- }
-
this._initialState = {
counter: counter,
- skipConfirmation: counter > 0 && args.skipConfirmation,
+ confirm: args.confirm,
...args.state
};
}
@@ -91,44 +84,51 @@ export class PullGitCommand extends QuickCommandBase {
}
}
- const step = this.createConfirmStep>(
- `Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${
- state.repos.length === 1 ? state.repos[0].formattedName : `${state.repos.length} repositories`
- }`,
- [
- {
- label: this.title,
- description: '',
- detail: `Will pull ${
- state.repos.length === 1
- ? state.repos[0].formattedName
- : `${state.repos.length} repositories`
- }`,
- item: []
- },
- {
- label: `${this.title} with Rebase`,
- description: '--rebase',
- detail: `Will pull with rebase ${
- state.repos.length === 1
- ? state.repos[0].formattedName
- : `${state.repos.length} repositories`
- }`,
- item: ['--rebase']
+ if (this.confirm(state.confirm)) {
+ const step = this.createConfirmStep>(
+ `Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${
+ state.repos.length === 1
+ ? state.repos[0].formattedName
+ : `${state.repos.length} repositories`
+ }`,
+ [
+ {
+ label: this.title,
+ description: '',
+ detail: `Will pull ${
+ state.repos.length === 1
+ ? state.repos[0].formattedName
+ : `${state.repos.length} repositories`
+ }`,
+ item: []
+ },
+ {
+ label: `${this.title} with Rebase`,
+ description: '--rebase',
+ detail: `Will pull with rebase ${
+ state.repos.length === 1
+ ? state.repos[0].formattedName
+ : `${state.repos.length} repositories`
+ }`,
+ item: ['--rebase']
+ }
+ ]
+ );
+ const selection = yield step;
+
+ if (!this.canMoveNext(step, state, selection)) {
+ if (oneRepo) {
+ break;
}
- ]
- );
- const selection = yield step;
- if (!this.canMoveNext(step, state, selection)) {
- if (oneRepo) {
- break;
+ continue;
}
- continue;
+ state.flags = selection[0].item;
+ }
+ else {
+ state.flags = [];
}
-
- state.flags = selection[0].item;
this.execute(state as State);
break;
diff --git a/src/commands/git/push.ts b/src/commands/git/push.ts
index f090ae9..43c8168 100644
--- a/src/commands/git/push.ts
+++ b/src/commands/git/push.ts
@@ -12,16 +12,16 @@ interface State {
flags: string[];
}
-export interface CommandArgs {
+export interface PushGitCommandArgs {
readonly command: 'push';
state?: Partial;
- skipConfirmation?: boolean;
+ confirm?: boolean;
}
export class PushGitCommand extends QuickCommandBase {
- constructor(args?: CommandArgs) {
- super('push', 'Push');
+ constructor(args?: PushGitCommandArgs) {
+ super('push', 'push', 'Push');
if (args === undefined || args.state === undefined) return;
@@ -30,16 +30,9 @@ export class PushGitCommand extends QuickCommandBase {
counter++;
}
- if (
- args.skipConfirmation === undefined &&
- Container.config.gitCommands.skipConfirmations.includes(this.label)
- ) {
- args.skipConfirmation = true;
- }
-
this._initialState = {
counter: counter,
- skipConfirmation: counter > 0 && args.skipConfirmation,
+ confirm: args.confirm,
...args.state
};
}
@@ -91,10 +84,7 @@ export class PushGitCommand extends QuickCommandBase {
}
}
- if (state.skipConfirmation) {
- state.flags = [];
- }
- else {
+ if (this.confirm(state.confirm)) {
const step = this.createConfirmStep(
`Confirm ${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${
state.repos.length === 1
@@ -136,6 +126,9 @@ export class PushGitCommand extends QuickCommandBase {
state.flags = selection[0].item;
}
+ else {
+ state.flags = [];
+ }
this.execute(state as State);
break;
diff --git a/src/commands/git/rebase.ts b/src/commands/git/rebase.ts
index 4a23639..032e880 100644
--- a/src/commands/git/rebase.ts
+++ b/src/commands/git/rebase.ts
@@ -24,7 +24,7 @@ interface State {
export class RebaseGitCommand extends QuickCommandBase {
constructor() {
- super('rebase', 'Rebase', { description: 'via Terminal' });
+ super('rebase', 'rebase', 'Rebase', false, { description: 'via Terminal' });
}
execute(state: State) {
diff --git a/src/commands/git/stash.ts b/src/commands/git/stash.ts
index 4e6433a..f5bda5c 100644
--- a/src/commands/git/stash.ts
+++ b/src/commands/git/stash.ts
@@ -1,5 +1,5 @@
'use strict';
-import { QuickPickItem, Uri, window } from 'vscode';
+import { QuickInputButtons, QuickPickItem, Uri, window } from 'vscode';
import { Container } from '../../container';
import { GitStashCommit, GitUri, Repository } from '../../git/gitService';
import { BreakQuickCommand, QuickCommandBase, QuickInputStep, QuickPickStep, StepState } from '../quickCommand';
@@ -45,18 +45,20 @@ interface PushState {
}
type State = ApplyState | DropState | PopState | PushState;
-type StashStepState = Partial & { counter: number; repo: Repository; skipConfirmation?: boolean };
+type StashStepState = StepState & { repo: Repository };
-export interface CommandArgs {
+export interface StashGitCommandArgs {
readonly command: 'stash';
state?: Partial;
- skipConfirmation?: boolean;
+ confirm?: boolean;
}
export class StashGitCommand extends QuickCommandBase {
- constructor(args?: CommandArgs) {
- super('stash', 'Stash');
+ private _subcommand: string | undefined;
+
+ constructor(args?: StashGitCommandArgs) {
+ super('stash', 'stash', 'Stash');
if (args === undefined || args.state === undefined) return;
@@ -86,20 +88,21 @@ export class StashGitCommand extends QuickCommandBase {
break;
}
- if (
- args.skipConfirmation === undefined &&
- Container.config.gitCommands.skipConfirmations.includes(`${this.label}-${args.state.subcommand}`)
- ) {
- args.skipConfirmation = true;
- }
-
this._initialState = {
counter: counter,
- skipConfirmation: counter > 0 && args.skipConfirmation,
+ confirm: args.confirm,
...args.state
};
}
+ get canSkipConfirm(): boolean {
+ return this._subcommand === 'drop' ? false : super.canSkipConfirm;
+ }
+
+ get confirmationKey() {
+ return this._subcommand === undefined ? undefined : `${super.confirmationKey}-${this._subcommand}`;
+ }
+
protected async *steps(): AsyncIterableIterator {
const state: StepState = this._initialState === undefined ? { counter: 0 } : this._initialState;
let oneRepo = false;
@@ -107,6 +110,8 @@ export class StashGitCommand extends QuickCommandBase {
while (true) {
try {
if (state.subcommand === undefined || state.counter < 1) {
+ this._subcommand = undefined;
+
const step = this.createPickStep>({
title: this.title,
placeholder: `Choose a ${this.label} command`,
@@ -131,7 +136,8 @@ export class StashGitCommand extends QuickCommandBase {
picked: state.subcommand === 'push',
item: 'push'
}
- ]
+ ],
+ buttons: [QuickInputButtons.Back]
});
const selection = yield step;
@@ -142,6 +148,8 @@ export class StashGitCommand extends QuickCommandBase {
state.subcommand = selection[0].item;
}
+ this._subcommand = state.subcommand;
+
if (state.repo === undefined || state.counter < 2) {
const repos = [...(await Container.git.getOrderedRepositories())];
@@ -289,10 +297,7 @@ export class StashGitCommand extends QuickCommandBase {
state.stash = selection[0].item;
}
- if (state.skipConfirmation) {
- state.flags = [];
- }
- else {
+ if (this.confirm(state.confirm)) {
const message =
state.stash.message.length > 80
? `${state.stash.message.substring(0, 80)}${GlyphChars.Ellipsis}`
@@ -344,6 +349,9 @@ export class StashGitCommand extends QuickCommandBase {
state.subcommand = selection[0].command;
state.flags = selection[0].item;
}
+ else {
+ state.flags = [];
+ }
void Container.git.stashApply(state.repo.path, state.stash!.stashName, state.subcommand === 'pop');
@@ -380,7 +388,7 @@ export class StashGitCommand extends QuickCommandBase {
}
)
)
- ]
+ ]
});
const selection = yield step;
@@ -391,10 +399,7 @@ export class StashGitCommand extends QuickCommandBase {
state.stash = selection[0].item;
}
- if (state.skipConfirmation) {
- state.flags = [];
- }
- else {
+ // if (this.confirm(state.confirm)) {
const message =
state.stash.message.length > 80
? `${state.stash.message.substring(0, 80)}${GlyphChars.Ellipsis}`
@@ -418,7 +423,7 @@ export class StashGitCommand extends QuickCommandBase {
if (!this.canMoveNext(step, state, selection)) {
break;
}
- }
+ // }
void Container.git.stashDelete(state.repo.path, state.stash.stashName);
@@ -448,10 +453,7 @@ export class StashGitCommand extends QuickCommandBase {
state.message = value;
}
- if (state.skipConfirmation) {
- state.flags = [];
- }
- else {
+ if (this.confirm(state.confirm)) {
const step = this.createConfirmStep>(
`Confirm ${this.title} ${state.subcommand}${Strings.pad(GlyphChars.Dot, 2, 2)}${
state.repo.formattedName
@@ -499,6 +501,9 @@ export class StashGitCommand extends QuickCommandBase {
state.flags = selection[0].item;
}
+ else {
+ state.flags = [];
+ }
void Container.git.stashSave(state.repo.path, state.message, state.uris, {
includeUntracked: state.flags.includes('--include-untracked'),
diff --git a/src/commands/gitCommands.ts b/src/commands/gitCommands.ts
index e797c4e..5d93d4d 100644
--- a/src/commands/gitCommands.ts
+++ b/src/commands/gitCommands.ts
@@ -1,26 +1,28 @@
'use strict';
-import { Disposable, InputBox, QuickInputButtons, QuickPick, QuickPickItem, window } from 'vscode';
+import { Disposable, InputBox, QuickInputButton, QuickInputButtons, QuickPick, QuickPickItem, window } from 'vscode';
import { command, Command, Commands } from './common';
import { log } from '../system';
import { isQuickInputStep, isQuickPickStep, QuickCommandBase, QuickInputStep, QuickPickStep } from './quickCommand';
import { Directive, DirectiveQuickPickItem } from '../quickpicks';
-import { CommandArgs as CheckoutCommandArgs, CheckoutGitCommand } from './git/checkout';
+import { CheckoutGitCommand, CheckoutGitCommandArgs } from './git/checkout';
import { CherryPickGitCommand } from './git/cherry-pick';
-import { CommandArgs as FetchCommandArgs, FetchGitCommand } from './git/fetch';
+import { FetchGitCommand, FetchGitCommandArgs } from './git/fetch';
import { MergeGitCommand } from './git/merge';
-import { CommandArgs as PullCommandArgs, PullGitCommand } from './git/pull';
-import { CommandArgs as PushCommandArgs, PushGitCommand } from './git/push';
+import { PullGitCommand, PullGitCommandArgs } from './git/pull';
+import { PushGitCommand, PushGitCommandArgs } from './git/push';
import { RebaseGitCommand } from './git/rebase';
-import { CommandArgs as StashCommandArgs, StashGitCommand } from './git/stash';
+import { StashGitCommand, StashGitCommandArgs } from './git/stash';
+import { Container } from '../container';
+import { configuration } from '../configuration';
const sanitizeLabel = /\$\(.+?\)|\W/g;
export type GitCommandsCommandArgs =
- | CheckoutCommandArgs
- | FetchCommandArgs
- | PullCommandArgs
- | PushCommandArgs
- | StashCommandArgs;
+ | CheckoutGitCommandArgs
+ | FetchGitCommandArgs
+ | PullGitCommandArgs
+ | PushGitCommandArgs
+ | StashGitCommandArgs;
class PickCommandStep implements QuickPickStep {
readonly buttons = [];
@@ -65,6 +67,32 @@ class PickCommandStep implements QuickPickStep {
@command()
export class GitCommandsCommand extends Command {
+ private readonly GitQuickInputButtons = class {
+ static readonly WillConfirm: QuickInputButton = {
+ iconPath: {
+ dark: Container.context.asAbsolutePath('images/dark/icon-check.svg') as any,
+ light: Container.context.asAbsolutePath('images/light/icon-check.svg') as any
+ },
+ tooltip: 'Will ask for confirmation at the end (click to toggle)'
+ };
+
+ static readonly WillConfirmForced: QuickInputButton = {
+ iconPath: {
+ dark: Container.context.asAbsolutePath('images/dark/icon-check.svg') as any,
+ light: Container.context.asAbsolutePath('images/light/icon-check.svg') as any
+ },
+ tooltip: 'Will ask for confirmation at the end (cannot be changed)'
+ };
+
+ static readonly WillSkipConfirm: QuickInputButton = {
+ iconPath: {
+ dark: Container.context.asAbsolutePath('images/dark/icon-no-check.svg') as any,
+ light: Container.context.asAbsolutePath('images/light/icon-no-check.svg') as any
+ },
+ tooltip: 'Will NOT ask for confirmation at the end (click to toggle)'
+ };
+ };
+
constructor() {
super(Commands.GitCommands);
}
@@ -123,11 +151,21 @@ export class GitCommandsCommand extends Command {
return;
}
- const step = commandsStep.command && commandsStep.command.value;
- if (step === undefined || !isQuickInputStep(step) || step.onDidClickButton === undefined)
+ if (e === this.GitQuickInputButtons.WillConfirmForced) return;
+ if (
+ e === this.GitQuickInputButtons.WillConfirm ||
+ e === this.GitQuickInputButtons.WillSkipConfirm
+ ) {
+ await this.toggleConfirmation(input, commandsStep.command);
+
return;
+ }
- step.onDidClickButton(input, e);
+ const step = commandsStep.command && commandsStep.command.value;
+ if (step !== undefined && isQuickInputStep(step) && step.onDidClickButton !== undefined) {
+ step.onDidClickButton(input, e);
+ input.buttons = this.getButtons(step, commandsStep.command);
+ }
}),
input.onDidChangeValue(async e => {
if (step.validate === undefined) return;
@@ -140,7 +178,7 @@ export class GitCommandsCommand extends Command {
})
);
- input.buttons = step.buttons || [QuickInputButtons.Back];
+ input.buttons = this.getButtons(step, commandsStep.command);
input.title = step.title;
input.placeholder = step.placeholder;
if (step.value !== undefined) {
@@ -184,10 +222,21 @@ export class GitCommandsCommand extends Command {
return;
}
- const step = commandsStep.command && commandsStep.command.value;
- if (step === undefined || !isQuickPickStep(step) || step.onDidClickButton === undefined) return;
+ if (e === this.GitQuickInputButtons.WillConfirmForced) return;
+ if (
+ e === this.GitQuickInputButtons.WillConfirm ||
+ e === this.GitQuickInputButtons.WillSkipConfirm
+ ) {
+ await this.toggleConfirmation(quickpick, commandsStep.command);
- step.onDidClickButton(quickpick, e);
+ return;
+ }
+
+ const step = commandsStep.command && commandsStep.command.value;
+ if (step !== undefined && isQuickPickStep(step) && step.onDidClickButton !== undefined) {
+ step.onDidClickButton(quickpick, e);
+ quickpick.buttons = this.getButtons(step, commandsStep.command);
+ }
}),
quickpick.onDidChangeValue(async e => {
if (!overrideItems) {
@@ -308,7 +357,6 @@ export class GitCommandsCommand extends Command {
})
);
- quickpick.buttons = step.buttons || [QuickInputButtons.Back];
quickpick.title = step.title;
quickpick.placeholder = step.placeholder;
quickpick.matchOnDescription = Boolean(step.matchOnDescription);
@@ -330,6 +378,9 @@ export class GitCommandsCommand extends Command {
commandsStep.command = undefined;
}
+ // Needs to be after we reset the command
+ quickpick.buttons = this.getButtons(step, commandsStep.command);
+
if (step.value !== undefined) {
quickpick.value = step.value;
}
@@ -343,6 +394,31 @@ export class GitCommandsCommand extends Command {
}
}
+ private getButtons(step: QuickInputStep | QuickPickStep, command?: QuickCommandBase) {
+ if (command === undefined) return [];
+
+ if (step.buttons !== undefined) return step.buttons;
+
+ const buttons = [QuickInputButtons.Back];
+
+ if (step.additionalButtons !== undefined) {
+ buttons.push(...step.additionalButtons);
+ }
+
+ if (command.canSkipConfirm) {
+ if (command.confirmationKey === undefined) return buttons;
+
+ buttons.push(
+ command.confirm() ? this.GitQuickInputButtons.WillConfirm : this.GitQuickInputButtons.WillSkipConfirm
+ );
+ }
+ else {
+ buttons.push(this.GitQuickInputButtons.WillConfirmForced);
+ }
+
+ return buttons;
+ }
+
private async nextStep(
quickInput: QuickPick | InputBox,
command: QuickCommandBase,
@@ -357,4 +433,29 @@ export class GitCommandsCommand extends Command {
quickInput.value = '';
return next.value;
}
+
+ private async toggleConfirmation(
+ input: InputBox | QuickPick,
+ command: QuickCommandBase | undefined
+ ) {
+ if (command === undefined || command.confirmationKey === undefined) return;
+
+ const section = configuration.name('gitCommands')('skipConfirmations').value;
+ const skipConfirmations = configuration.get(section) || [];
+
+ const index = skipConfirmations.indexOf(command.confirmationKey);
+ if (index !== -1) {
+ skipConfirmations.splice(index, 1);
+ }
+ else {
+ skipConfirmations.push(command.confirmationKey);
+ }
+
+ void (await configuration.updateEffective(
+ configuration.name('gitCommands')('skipConfirmations').value,
+ skipConfirmations
+ ));
+
+ input.buttons = this.getButtons(command.value!, command);
+ }
}
diff --git a/src/commands/quickCommand.ts b/src/commands/quickCommand.ts
index 0e13f08..ddd1f8e 100644
--- a/src/commands/quickCommand.ts
+++ b/src/commands/quickCommand.ts
@@ -1,7 +1,8 @@
'use strict';
-import { InputBox, QuickInputButton, QuickPick, QuickPickItem } from 'vscode';
+import { InputBox, QuickInputButton, QuickInputButtons, QuickPick, QuickPickItem } from 'vscode';
import { Promises } from '../system';
import { Directive, DirectiveQuickPickItem } from '../quickpicks';
+import { Container } from '../container';
export * from './quickCommand.helpers';
@@ -12,6 +13,7 @@ export class BreakQuickCommand extends Error {
}
export interface QuickInputStep {
+ additionalButtons?: QuickInputButton[];
buttons?: QuickInputButton[];
placeholder?: string;
title?: string;
@@ -26,6 +28,7 @@ export function isQuickInputStep(item: QuickPickStep | QuickInputStep): item is
}
export interface QuickPickStep {
+ additionalButtons?: QuickInputButton[];
buttons?: QuickInputButton[];
selectedItems?: QuickPickItem[];
items: (DirectiveQuickPickItem | T)[] | DirectiveQuickPickItem[];
@@ -46,7 +49,7 @@ export function isQuickPickStep(item: QuickPickStep | QuickInputStep): item is Q
return (item as QuickPickStep).items !== undefined;
}
-export type StepState = Partial & { counter: number; skipConfirmation?: boolean };
+export type StepState = Partial & { counter: number; confirm?: boolean };
export abstract class QuickCommandBase implements QuickPickItem {
static is(item: QuickPickItem): item is QuickCommandBase {
@@ -56,12 +59,16 @@ export abstract class QuickCommandBase implements QuickPickItem {
readonly description?: string;
readonly detail?: string;
+ protected _initialState?: StepState;
+
private _current: QuickPickStep | QuickInputStep | undefined;
private _stepsIterator: AsyncIterableIterator | undefined;
constructor(
+ public readonly key: string,
public readonly label: string,
public readonly title: string,
+ private readonly _canSkipConfirm: boolean = true,
options: {
description?: string;
detail?: string;
@@ -71,6 +78,14 @@ export abstract class QuickCommandBase implements QuickPickItem {
this.detail = options.detail;
}
+ get canSkipConfirm(): boolean {
+ return this._canSkipConfirm;
+ }
+
+ get confirmationKey(): string | undefined {
+ return this.key;
+ }
+
private _picked: boolean = false;
get picked() {
return this._picked;
@@ -79,7 +94,13 @@ export abstract class QuickCommandBase implements QuickPickItem {
this._picked = value;
}
- protected _initialState?: StepState;
+ confirm(override?: boolean) {
+ if (!this.canSkipConfirm || this.confirmationKey === undefined) return true;
+
+ return override !== undefined
+ ? override
+ : !Container.config.gitCommands.skipConfirmations.includes(this.confirmationKey);
+ }
protected abstract steps(): AsyncIterableIterator;
@@ -122,7 +143,8 @@ export abstract class QuickCommandBase implements QuickPickItem {
placeholder: placeholder || `Confirm ${this.title}`,
title: title,
items: [...confirmations, cancel || DirectiveQuickPickItem.create(Directive.Cancel)],
- selectedItems: [confirmations[0]]
+ selectedItems: [confirmations[0]],
+ buttons: [QuickInputButtons.Back]
});
}