From 35b437afbf3517dc4f96ac50d65d9b8b3371c46d Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Tue, 27 Feb 2018 16:46:00 -0500 Subject: [PATCH] Renames files for better clarity --- src/commands/diffBranchWithBranch.ts | 2 +- src/commands/diffDirectory.ts | 2 +- src/commands/diffWithBranch.ts | 2 +- src/commands/diffWithRevision.ts | 2 +- src/commands/openBranchInRemote.ts | 2 +- src/commands/openFileRevision.ts | 2 +- src/commands/openInRemote.ts | 2 +- src/commands/showCommitSearch.ts | 2 +- src/commands/showQuickBranchHistory.ts | 2 +- src/commands/showQuickCommitDetails.ts | 4 +- src/commands/showQuickCommitFileDetails.ts | 4 +- src/commands/showQuickCurrentBranchHistory.ts | 2 +- src/commands/showQuickFileHistory.ts | 2 +- src/commands/showQuickRepoStatus.ts | 2 +- src/commands/showQuickStashList.ts | 2 +- src/commands/stashApply.ts | 2 +- src/commands/stashDelete.ts | 2 +- src/commands/stashSave.ts | 2 +- src/git/formatters/commit.ts | 64 ----- src/git/formatters/commitFormatter.ts | 64 +++++ src/git/formatters/formatters.ts | 4 + src/git/formatters/status.ts | 52 ---- src/git/formatters/statusFormatter.ts | 52 ++++ src/git/git.ts | 9 +- src/git/models/models.ts | 3 +- src/git/parsers/parsers.ts | 10 + src/gitService.ts | 3 +- src/quickPicks.ts | 14 -- src/quickPicks/branchHistory.ts | 139 ----------- src/quickPicks/branchHistoryQuickPick.ts | 139 +++++++++++ src/quickPicks/branches.ts | 42 ---- src/quickPicks/branchesAndTags.ts | 75 ------ src/quickPicks/branchesAndTagsQuickPick.ts | 75 ++++++ src/quickPicks/branchesQuickPick.ts | 42 ++++ src/quickPicks/commitDetails.ts | 320 ------------------------- src/quickPicks/commitFileDetails.ts | 324 ------------------------- src/quickPicks/commitFileQuickPick.ts | 324 +++++++++++++++++++++++++ src/quickPicks/commitQuickPick.ts | 320 +++++++++++++++++++++++++ src/quickPicks/commits.ts | 54 ----- src/quickPicks/commitsQuickPick.ts | 54 +++++ src/quickPicks/common.ts | 253 -------------------- src/quickPicks/commonQuickPicks.ts | 253 ++++++++++++++++++++ src/quickPicks/fileHistory.ts | 159 ------------- src/quickPicks/fileHistoryQuickPick.ts | 159 +++++++++++++ src/quickPicks/quickPicks.ts | 14 ++ src/quickPicks/remotes.ts | 139 ----------- src/quickPicks/remotesQuickPick.ts | 139 +++++++++++ src/quickPicks/repoStatus.ts | 327 -------------------------- src/quickPicks/repoStatusQuickPick.ts | 327 ++++++++++++++++++++++++++ src/quickPicks/repositories.ts | 46 ---- src/quickPicks/repositoriesQuickPick.ts | 46 ++++ src/quickPicks/stashList.ts | 64 ----- src/quickPicks/stashListQuickPick.ts | 64 +++++ 53 files changed, 2110 insertions(+), 2103 deletions(-) delete mode 100644 src/git/formatters/commit.ts create mode 100644 src/git/formatters/commitFormatter.ts create mode 100644 src/git/formatters/formatters.ts delete mode 100644 src/git/formatters/status.ts create mode 100644 src/git/formatters/statusFormatter.ts create mode 100644 src/git/parsers/parsers.ts delete mode 100644 src/quickPicks.ts delete mode 100644 src/quickPicks/branchHistory.ts create mode 100644 src/quickPicks/branchHistoryQuickPick.ts delete mode 100644 src/quickPicks/branches.ts delete mode 100644 src/quickPicks/branchesAndTags.ts create mode 100644 src/quickPicks/branchesAndTagsQuickPick.ts create mode 100644 src/quickPicks/branchesQuickPick.ts delete mode 100644 src/quickPicks/commitDetails.ts delete mode 100644 src/quickPicks/commitFileDetails.ts create mode 100644 src/quickPicks/commitFileQuickPick.ts create mode 100644 src/quickPicks/commitQuickPick.ts delete mode 100644 src/quickPicks/commits.ts create mode 100644 src/quickPicks/commitsQuickPick.ts delete mode 100644 src/quickPicks/common.ts create mode 100644 src/quickPicks/commonQuickPicks.ts delete mode 100644 src/quickPicks/fileHistory.ts create mode 100644 src/quickPicks/fileHistoryQuickPick.ts create mode 100644 src/quickPicks/quickPicks.ts delete mode 100644 src/quickPicks/remotes.ts create mode 100644 src/quickPicks/remotesQuickPick.ts delete mode 100644 src/quickPicks/repoStatus.ts create mode 100644 src/quickPicks/repoStatusQuickPick.ts delete mode 100644 src/quickPicks/repositories.ts create mode 100644 src/quickPicks/repositoriesQuickPick.ts delete mode 100644 src/quickPicks/stashList.ts create mode 100644 src/quickPicks/stashListQuickPick.ts diff --git a/src/commands/diffBranchWithBranch.ts b/src/commands/diffBranchWithBranch.ts index 7cf84c0..a5c6d8b 100644 --- a/src/commands/diffBranchWithBranch.ts +++ b/src/commands/diffBranchWithBranch.ts @@ -5,7 +5,7 @@ import { GlyphChars } from '../constants'; import { Container } from '../container'; import { Logger } from '../logger'; import { Messages } from '../messages'; -import { BranchesAndTagsQuickPick, CommandQuickPickItem } from '../quickPicks'; +import { BranchesAndTagsQuickPick, CommandQuickPickItem } from '../quickPicks/quickPicks'; export interface DiffBranchWithBranchCommandArgs { ref1?: string; diff --git a/src/commands/diffDirectory.ts b/src/commands/diffDirectory.ts index 3fcf44c..d69ce0a 100644 --- a/src/commands/diffDirectory.ts +++ b/src/commands/diffDirectory.ts @@ -7,7 +7,7 @@ import { Container } from '../container'; import { ComparisonResultsNode } from '../views/explorerNodes'; import { Logger } from '../logger'; import { Messages } from '../messages'; -import { BranchesAndTagsQuickPick, CommandQuickPickItem } from '../quickPicks'; +import { BranchesAndTagsQuickPick, CommandQuickPickItem } from '../quickPicks/quickPicks'; export interface DiffDirectoryCommandArgs { ref1?: string; diff --git a/src/commands/diffWithBranch.ts b/src/commands/diffWithBranch.ts index f05f37f..0479c4b 100644 --- a/src/commands/diffWithBranch.ts +++ b/src/commands/diffWithBranch.ts @@ -7,7 +7,7 @@ import { Container } from '../container'; import { DiffWithCommandArgs } from './diffWith'; import { GitUri } from '../gitService'; import { Messages } from '../messages'; -import { BranchesAndTagsQuickPick, CommandQuickPickItem } from '../quickPicks'; +import { BranchesAndTagsQuickPick, CommandQuickPickItem } from '../quickPicks/quickPicks'; import * as path from 'path'; export interface DiffWithBranchCommandArgs { diff --git a/src/commands/diffWithRevision.ts b/src/commands/diffWithRevision.ts index ba19ef0..dbded8a 100644 --- a/src/commands/diffWithRevision.ts +++ b/src/commands/diffWithRevision.ts @@ -8,7 +8,7 @@ import { DiffWithCommandArgs } from './diffWith'; import { GitUri } from '../gitService'; import { Logger } from '../logger'; import { Messages } from '../messages'; -import { CommandQuickPickItem, FileHistoryQuickPick, ShowBranchesAndTagsQuickPickItem } from '../quickPicks'; +import { CommandQuickPickItem, FileHistoryQuickPick, ShowBranchesAndTagsQuickPickItem } from '../quickPicks/quickPicks'; export interface DiffWithRevisionCommandArgs { maxCount?: number; diff --git a/src/commands/openBranchInRemote.ts b/src/commands/openBranchInRemote.ts index c1d696d..5c50e45 100644 --- a/src/commands/openBranchInRemote.ts +++ b/src/commands/openBranchInRemote.ts @@ -5,7 +5,7 @@ import { GlyphChars } from '../constants'; import { Container } from '../container'; import { GitUri } from '../gitService'; import { Logger } from '../logger'; -import { BranchesQuickPick, CommandQuickPickItem } from '../quickPicks'; +import { BranchesQuickPick, CommandQuickPickItem } from '../quickPicks/quickPicks'; import { OpenInRemoteCommandArgs } from './openInRemote'; export interface OpenBranchInRemoteCommandArgs { diff --git a/src/commands/openFileRevision.ts b/src/commands/openFileRevision.ts index 55eb0ff..15f6019 100644 --- a/src/commands/openFileRevision.ts +++ b/src/commands/openFileRevision.ts @@ -8,7 +8,7 @@ import { Container } from '../container'; import { GitUri } from '../gitService'; import { Logger } from '../logger'; import { Messages } from '../messages'; -import { CommandQuickPickItem, FileHistoryQuickPick, ShowBranchesAndTagsQuickPickItem } from '../quickPicks'; +import { CommandQuickPickItem, FileHistoryQuickPick, ShowBranchesAndTagsQuickPickItem } from '../quickPicks/quickPicks'; export interface OpenFileRevisionCommandArgs { uri?: Uri; diff --git a/src/commands/openInRemote.ts b/src/commands/openInRemote.ts index 0f89e0f..604071a 100644 --- a/src/commands/openInRemote.ts +++ b/src/commands/openInRemote.ts @@ -5,7 +5,7 @@ import { ActiveEditorCommand, Commands } from './common'; import { GlyphChars } from '../constants'; import { GitLogCommit, GitRemote, GitService, RemoteResource, RemoteResourceType } from '../gitService'; import { Logger } from '../logger'; -import { CommandQuickPickItem, OpenRemoteCommandQuickPickItem, RemotesQuickPick } from '../quickPicks'; +import { CommandQuickPickItem, OpenRemoteCommandQuickPickItem, RemotesQuickPick } from '../quickPicks/quickPicks'; export interface OpenInRemoteCommandArgs { remote?: string; diff --git a/src/commands/showCommitSearch.ts b/src/commands/showCommitSearch.ts index 8d515e1..f57075f 100644 --- a/src/commands/showCommitSearch.ts +++ b/src/commands/showCommitSearch.ts @@ -6,7 +6,7 @@ import { GlyphChars } from '../constants'; import { Container } from '../container'; import { GitRepoSearchBy, GitService, GitUri } from '../gitService'; import { Logger } from '../logger'; -import { CommandQuickPickItem, CommitsQuickPick, RepositoriesQuickPick, ShowCommitsSearchInResultsQuickPickItem } from '../quickPicks'; +import { CommandQuickPickItem, CommitsQuickPick, RepositoriesQuickPick, ShowCommitsSearchInResultsQuickPickItem } from '../quickPicks/quickPicks'; import { ShowQuickCommitDetailsCommandArgs } from './showQuickCommitDetails'; const searchByRegex = /^([@~=:#])/; diff --git a/src/commands/showQuickBranchHistory.ts b/src/commands/showQuickBranchHistory.ts index 659e565..3e3c581 100644 --- a/src/commands/showQuickBranchHistory.ts +++ b/src/commands/showQuickBranchHistory.ts @@ -7,7 +7,7 @@ import { Container } from '../container'; import { GitLog, GitUri } from '../gitService'; import { Logger } from '../logger'; import { Messages } from '../messages'; -import { BranchesQuickPick, BranchHistoryQuickPick, CommandQuickPickItem } from '../quickPicks'; +import { BranchesQuickPick, BranchHistoryQuickPick, CommandQuickPickItem } from '../quickPicks/quickPicks'; import { ShowQuickCommitDetailsCommandArgs } from './showQuickCommitDetails'; export interface ShowQuickBranchHistoryCommandArgs { diff --git a/src/commands/showQuickCommitDetails.ts b/src/commands/showQuickCommitDetails.ts index 080e372..a306fd0 100644 --- a/src/commands/showQuickCommitDetails.ts +++ b/src/commands/showQuickCommitDetails.ts @@ -5,7 +5,7 @@ import { ActiveEditorCachedCommand, CommandContext, Commands, getCommandUri, isC import { GlyphChars } from '../constants'; import { GitCommit, GitLog, GitLogCommit, GitUri } from '../gitService'; import { Logger } from '../logger'; -import { CommandQuickPickItem, CommitDetailsQuickPick, CommitWithFileStatusQuickPickItem } from '../quickPicks'; +import { CommandQuickPickItem, CommitQuickPick, CommitWithFileStatusQuickPickItem } from '../quickPicks/quickPicks'; import { ShowQuickCommitFileDetailsCommandArgs } from './showQuickCommitFileDetails'; import { Messages } from '../messages'; import * as path from 'path'; @@ -124,7 +124,7 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCachedCommand { args ]); - const pick = await CommitDetailsQuickPick.show(args.commit as GitLogCommit, uri, args.goBackCommand, currentCommand, args.repoLog); + const pick = await CommitQuickPick.show(args.commit as GitLogCommit, uri, args.goBackCommand, currentCommand, args.repoLog); if (pick === undefined) return undefined; if (!(pick instanceof CommitWithFileStatusQuickPickItem)) return pick.execute(); diff --git a/src/commands/showQuickCommitFileDetails.ts b/src/commands/showQuickCommitFileDetails.ts index 3df0385..f78fe47 100644 --- a/src/commands/showQuickCommitFileDetails.ts +++ b/src/commands/showQuickCommitFileDetails.ts @@ -5,7 +5,7 @@ import { ActiveEditorCachedCommand, CommandContext, Commands, getCommandUri, isC import { GlyphChars } from '../constants'; import { GitCommit, GitLog, GitLogCommit, GitService, GitUri } from '../gitService'; import { Logger } from '../logger'; -import { CommandQuickPickItem, CommitFileDetailsQuickPick } from '../quickPicks'; +import { CommandQuickPickItem, CommitFileQuickPick } from '../quickPicks/quickPicks'; import { ShowQuickCommitDetailsCommandArgs } from './showQuickCommitDetails'; import { Messages } from '../messages'; import * as path from 'path'; @@ -130,7 +130,7 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCachedCommand args ]); - const pick = await CommitFileDetailsQuickPick.show(args.commit as GitLogCommit, uri, args.goBackCommand, currentCommand, args.fileLog); + const pick = await CommitFileQuickPick.show(args.commit as GitLogCommit, uri, args.goBackCommand, currentCommand, args.fileLog); if (pick === undefined) return undefined; if (pick instanceof CommandQuickPickItem) return pick.execute(); diff --git a/src/commands/showQuickCurrentBranchHistory.ts b/src/commands/showQuickCurrentBranchHistory.ts index bba7de2..9a6852f 100644 --- a/src/commands/showQuickCurrentBranchHistory.ts +++ b/src/commands/showQuickCurrentBranchHistory.ts @@ -4,7 +4,7 @@ import { ActiveEditorCachedCommand, Commands, getCommandUri } from './common'; import { Container } from '../container'; import { Logger } from '../logger'; import { Messages } from '../messages'; -import { CommandQuickPickItem } from '../quickPicks'; +import { CommandQuickPickItem } from '../quickPicks/quickPicks'; import { ShowQuickBranchHistoryCommandArgs } from './showQuickBranchHistory'; export interface ShowQuickCurrentBranchHistoryCommandArgs { diff --git a/src/commands/showQuickFileHistory.ts b/src/commands/showQuickFileHistory.ts index b005fcc..b79b73a 100644 --- a/src/commands/showQuickFileHistory.ts +++ b/src/commands/showQuickFileHistory.ts @@ -6,7 +6,7 @@ import { GlyphChars } from '../constants'; import { Container } from '../container'; import { GitLog, GitUri } from '../gitService'; import { Logger } from '../logger'; -import { CommandQuickPickItem, FileHistoryQuickPick, ShowCommitsInResultsQuickPickItem } from '../quickPicks'; +import { CommandQuickPickItem, FileHistoryQuickPick, ShowCommitsInResultsQuickPickItem } from '../quickPicks/quickPicks'; import { ShowQuickCommitFileDetailsCommandArgs } from './showQuickCommitFileDetails'; import { Messages } from '../messages'; import * as path from 'path'; diff --git a/src/commands/showQuickRepoStatus.ts b/src/commands/showQuickRepoStatus.ts index f668f6a..2da1831 100644 --- a/src/commands/showQuickRepoStatus.ts +++ b/src/commands/showQuickRepoStatus.ts @@ -4,7 +4,7 @@ import { ActiveEditorCachedCommand, Commands, getCommandUri } from './common'; import { Container } from '../container'; import { Logger } from '../logger'; import { Messages } from '../messages'; -import { CommandQuickPickItem, RepoStatusQuickPick } from '../quickPicks'; +import { CommandQuickPickItem, RepoStatusQuickPick } from '../quickPicks/quickPicks'; export interface ShowQuickRepoStatusCommandArgs { goBackCommand?: CommandQuickPickItem; diff --git a/src/commands/showQuickStashList.ts b/src/commands/showQuickStashList.ts index 12b7107..23acfeb 100644 --- a/src/commands/showQuickStashList.ts +++ b/src/commands/showQuickStashList.ts @@ -6,7 +6,7 @@ import { GlyphChars } from '../constants'; import { Container } from '../container'; import { Logger } from '../logger'; import { Messages } from '../messages'; -import { CommandQuickPickItem, StashListQuickPick } from '../quickPicks'; +import { CommandQuickPickItem, StashListQuickPick } from '../quickPicks/quickPicks'; import { ShowQuickCommitDetailsCommandArgs } from './showQuickCommitDetails'; export interface ShowQuickStashListCommandArgs { diff --git a/src/commands/stashApply.ts b/src/commands/stashApply.ts index 6ad866c..5fcc335 100644 --- a/src/commands/stashApply.ts +++ b/src/commands/stashApply.ts @@ -6,7 +6,7 @@ import { GlyphChars } from '../constants'; import { Container } from '../container'; import { GitStashCommit } from '../gitService'; import { Logger } from '../logger'; -import { CommandQuickPickItem, RepositoriesQuickPick, StashListQuickPick } from '../quickPicks'; +import { CommandQuickPickItem, RepositoriesQuickPick, StashListQuickPick } from '../quickPicks/quickPicks'; export interface StashApplyCommandArgs { confirm?: boolean; diff --git a/src/commands/stashDelete.ts b/src/commands/stashDelete.ts index be71779..8a7492a 100644 --- a/src/commands/stashDelete.ts +++ b/src/commands/stashDelete.ts @@ -5,7 +5,7 @@ import { GlyphChars } from '../constants'; import { Container } from '../container'; import { GitStashCommit } from '../gitService'; import { Logger } from '../logger'; -import { CommandQuickPickItem } from '../quickPicks'; +import { CommandQuickPickItem } from '../quickPicks/quickPicks'; export interface StashDeleteCommandArgs { confirm?: boolean; diff --git a/src/commands/stashSave.ts b/src/commands/stashSave.ts index 182a729..b0d4f65 100644 --- a/src/commands/stashSave.ts +++ b/src/commands/stashSave.ts @@ -5,7 +5,7 @@ import { Command, Commands } from './common'; import { GlyphChars } from '../constants'; import { Container } from '../container'; import { Logger } from '../logger'; -import { CommandQuickPickItem, RepositoriesQuickPick } from '../quickPicks'; +import { CommandQuickPickItem, RepositoriesQuickPick } from '../quickPicks/quickPicks'; export interface StashSaveCommandArgs { message?: string; diff --git a/src/git/formatters/commit.ts b/src/git/formatters/commit.ts deleted file mode 100644 index abdb15b..0000000 --- a/src/git/formatters/commit.ts +++ /dev/null @@ -1,64 +0,0 @@ -'use strict'; -import { Strings } from '../../system'; -import { GitCommit } from '../models/commit'; -import { Formatter, IFormatOptions } from './formatter'; - -export interface ICommitFormatOptions extends IFormatOptions { - truncateMessageAtNewLine?: boolean; - - tokenOptions?: { - ago?: Strings.ITokenOptions; - author?: Strings.ITokenOptions; - authorAgo?: Strings.ITokenOptions; - date?: Strings.ITokenOptions; - message?: Strings.ITokenOptions; - }; -} - -export class CommitFormatter extends Formatter { - - get ago() { - const ago = this._item.fromNow(); - return this._padOrTruncate(ago, this._options.tokenOptions!.ago); - } - - get author() { - const author = this._item.author; - return this._padOrTruncate(author, this._options.tokenOptions!.author); - } - - get authorAgo() { - const authorAgo = `${this._item.author}, ${this._item.fromNow()}`; - return this._padOrTruncate(authorAgo, this._options.tokenOptions!.authorAgo); - } - - get date() { - const date = this._item.formatDate(this._options.dateFormat!); - return this._padOrTruncate(date, this._options.tokenOptions!.date); - } - - get id() { - if (this._item.isUncommitted && !this._item.isStagedUncommitted) return '00000000'; - return this._item.shortSha; - } - - get message() { - let message = this._item.isUncommitted ? 'Uncommitted change' : this._item.message; - if (this._options.truncateMessageAtNewLine) { - message = this._item.getShortMessage(); - } - - return this._padOrTruncate(message, this._options.tokenOptions!.message); - } - - get sha() { - return this.id; - } - - static fromTemplate(template: string, commit: GitCommit, dateFormat: string | null): string; - static fromTemplate(template: string, commit: GitCommit, options?: ICommitFormatOptions): string; - static fromTemplate(template: string, commit: GitCommit, dateFormatOrOptions?: string | null | ICommitFormatOptions): string; - static fromTemplate(template: string, commit: GitCommit, dateFormatOrOptions?: string | null | ICommitFormatOptions): string { - return super.fromTemplateCore(this, template, commit, dateFormatOrOptions); - } -} \ No newline at end of file diff --git a/src/git/formatters/commitFormatter.ts b/src/git/formatters/commitFormatter.ts new file mode 100644 index 0000000..abdb15b --- /dev/null +++ b/src/git/formatters/commitFormatter.ts @@ -0,0 +1,64 @@ +'use strict'; +import { Strings } from '../../system'; +import { GitCommit } from '../models/commit'; +import { Formatter, IFormatOptions } from './formatter'; + +export interface ICommitFormatOptions extends IFormatOptions { + truncateMessageAtNewLine?: boolean; + + tokenOptions?: { + ago?: Strings.ITokenOptions; + author?: Strings.ITokenOptions; + authorAgo?: Strings.ITokenOptions; + date?: Strings.ITokenOptions; + message?: Strings.ITokenOptions; + }; +} + +export class CommitFormatter extends Formatter { + + get ago() { + const ago = this._item.fromNow(); + return this._padOrTruncate(ago, this._options.tokenOptions!.ago); + } + + get author() { + const author = this._item.author; + return this._padOrTruncate(author, this._options.tokenOptions!.author); + } + + get authorAgo() { + const authorAgo = `${this._item.author}, ${this._item.fromNow()}`; + return this._padOrTruncate(authorAgo, this._options.tokenOptions!.authorAgo); + } + + get date() { + const date = this._item.formatDate(this._options.dateFormat!); + return this._padOrTruncate(date, this._options.tokenOptions!.date); + } + + get id() { + if (this._item.isUncommitted && !this._item.isStagedUncommitted) return '00000000'; + return this._item.shortSha; + } + + get message() { + let message = this._item.isUncommitted ? 'Uncommitted change' : this._item.message; + if (this._options.truncateMessageAtNewLine) { + message = this._item.getShortMessage(); + } + + return this._padOrTruncate(message, this._options.tokenOptions!.message); + } + + get sha() { + return this.id; + } + + static fromTemplate(template: string, commit: GitCommit, dateFormat: string | null): string; + static fromTemplate(template: string, commit: GitCommit, options?: ICommitFormatOptions): string; + static fromTemplate(template: string, commit: GitCommit, dateFormatOrOptions?: string | null | ICommitFormatOptions): string; + static fromTemplate(template: string, commit: GitCommit, dateFormatOrOptions?: string | null | ICommitFormatOptions): string { + return super.fromTemplateCore(this, template, commit, dateFormatOrOptions); + } +} \ No newline at end of file diff --git a/src/git/formatters/formatters.ts b/src/git/formatters/formatters.ts new file mode 100644 index 0000000..ff1a2c6 --- /dev/null +++ b/src/git/formatters/formatters.ts @@ -0,0 +1,4 @@ +'use strict'; + +export * from './commitFormatter'; +export * from './statusFormatter'; diff --git a/src/git/formatters/status.ts b/src/git/formatters/status.ts deleted file mode 100644 index fb7e2a9..0000000 --- a/src/git/formatters/status.ts +++ /dev/null @@ -1,52 +0,0 @@ -'use strict'; -import { Strings } from '../../system'; -import { GlyphChars } from '../../constants'; -import { Formatter, IFormatOptions } from './formatter'; -import { GitStatusFile, IGitStatusFile, IGitStatusFileWithCommit } from '../models/status'; -import * as path from 'path'; - -export interface IStatusFormatOptions extends IFormatOptions { - relativePath?: string; - - tokenOptions?: { - directory?: Strings.ITokenOptions; - file?: Strings.ITokenOptions; - filePath?: Strings.ITokenOptions; - path?: Strings.ITokenOptions; - }; -} - -export class StatusFileFormatter extends Formatter { - - get directory() { - const directory = GitStatusFile.getFormattedDirectory(this._item, false, this._options.relativePath); - return this._padOrTruncate(directory, this._options.tokenOptions!.file); - } - - get file() { - const file = path.basename(this._item.fileName); - return this._padOrTruncate(file, this._options.tokenOptions!.file); - } - - get filePath() { - const filePath = GitStatusFile.getFormattedPath(this._item, undefined, this._options.relativePath); - return this._padOrTruncate(filePath, this._options.tokenOptions!.filePath); - } - - get path() { - const directory = GitStatusFile.getRelativePath(this._item, this._options.relativePath); - return this._padOrTruncate(directory, this._options.tokenOptions!.file); - } - - get working() { - const commit = (this._item as IGitStatusFileWithCommit).commit; - return (commit !== undefined && commit.isUncommitted) ? `${GlyphChars.Pensil} ${GlyphChars.Space}` : ''; - } - - static fromTemplate(template: string, status: IGitStatusFile, dateFormat: string | null): string; - static fromTemplate(template: string, status: IGitStatusFile, options?: IStatusFormatOptions): string; - static fromTemplate(template: string, status: IGitStatusFile, dateFormatOrOptions?: string | null | IStatusFormatOptions): string; - static fromTemplate(template: string, status: IGitStatusFile, dateFormatOrOptions?: string | null | IStatusFormatOptions): string { - return super.fromTemplateCore(this, template, status, dateFormatOrOptions); - } -} \ No newline at end of file diff --git a/src/git/formatters/statusFormatter.ts b/src/git/formatters/statusFormatter.ts new file mode 100644 index 0000000..fb7e2a9 --- /dev/null +++ b/src/git/formatters/statusFormatter.ts @@ -0,0 +1,52 @@ +'use strict'; +import { Strings } from '../../system'; +import { GlyphChars } from '../../constants'; +import { Formatter, IFormatOptions } from './formatter'; +import { GitStatusFile, IGitStatusFile, IGitStatusFileWithCommit } from '../models/status'; +import * as path from 'path'; + +export interface IStatusFormatOptions extends IFormatOptions { + relativePath?: string; + + tokenOptions?: { + directory?: Strings.ITokenOptions; + file?: Strings.ITokenOptions; + filePath?: Strings.ITokenOptions; + path?: Strings.ITokenOptions; + }; +} + +export class StatusFileFormatter extends Formatter { + + get directory() { + const directory = GitStatusFile.getFormattedDirectory(this._item, false, this._options.relativePath); + return this._padOrTruncate(directory, this._options.tokenOptions!.file); + } + + get file() { + const file = path.basename(this._item.fileName); + return this._padOrTruncate(file, this._options.tokenOptions!.file); + } + + get filePath() { + const filePath = GitStatusFile.getFormattedPath(this._item, undefined, this._options.relativePath); + return this._padOrTruncate(filePath, this._options.tokenOptions!.filePath); + } + + get path() { + const directory = GitStatusFile.getRelativePath(this._item, this._options.relativePath); + return this._padOrTruncate(directory, this._options.tokenOptions!.file); + } + + get working() { + const commit = (this._item as IGitStatusFileWithCommit).commit; + return (commit !== undefined && commit.isUncommitted) ? `${GlyphChars.Pensil} ${GlyphChars.Space}` : ''; + } + + static fromTemplate(template: string, status: IGitStatusFile, dateFormat: string | null): string; + static fromTemplate(template: string, status: IGitStatusFile, options?: IStatusFormatOptions): string; + static fromTemplate(template: string, status: IGitStatusFile, dateFormatOrOptions?: string | null | IStatusFormatOptions): string; + static fromTemplate(template: string, status: IGitStatusFile, dateFormatOrOptions?: string | null | IStatusFormatOptions): string { + return super.fromTemplateCore(this, template, status, dateFormatOrOptions); + } +} \ No newline at end of file diff --git a/src/git/git.ts b/src/git/git.ts index c1cf415..80f9710 100644 --- a/src/git/git.ts +++ b/src/git/git.ts @@ -9,14 +9,7 @@ import * as path from 'path'; export { IGit }; export * from './models/models'; -export * from './parsers/blameParser'; -export * from './parsers/branchParser'; -export * from './parsers/diffParser'; -export * from './parsers/logParser'; -export * from './parsers/remoteParser'; -export * from './parsers/stashParser'; -export * from './parsers/statusParser'; -export * from './parsers/tagParser'; +export * from './parsers/parsers'; export * from './remotes/provider'; let git: IGit; diff --git a/src/git/models/models.ts b/src/git/models/models.ts index 5de9860..2c03bc9 100644 --- a/src/git/models/models.ts +++ b/src/git/models/models.ts @@ -1,4 +1,5 @@ 'use strict'; + export * from './blame'; export * from './blameCommit'; export * from './branch'; @@ -11,4 +12,4 @@ export * from './repository'; export * from './stash'; export * from './stashCommit'; export * from './status'; -export * from './tag'; \ No newline at end of file +export * from './tag'; diff --git a/src/git/parsers/parsers.ts b/src/git/parsers/parsers.ts new file mode 100644 index 0000000..1366911 --- /dev/null +++ b/src/git/parsers/parsers.ts @@ -0,0 +1,10 @@ +'use strict'; + +export * from './blameParser'; +export * from './branchParser'; +export * from './diffParser'; +export * from './logParser'; +export * from './remoteParser'; +export * from './stashParser'; +export * from './statusParser'; +export * from './tagParser'; diff --git a/src/gitService.ts b/src/gitService.ts index 1a92979..1d9b07b 100644 --- a/src/gitService.ts +++ b/src/gitService.ts @@ -14,8 +14,7 @@ import * as path from 'path'; export { GitUri, IGit, IGitCommitInfo }; export * from './git/models/models'; -export * from './git/formatters/commit'; -export * from './git/formatters/status'; +export * from './git/formatters/formatters'; export { getNameFromRemoteResource, RemoteProvider, RemoteResource, RemoteResourceType } from './git/remotes/provider'; export { RemoteProviderFactory } from './git/remotes/factory'; diff --git a/src/quickPicks.ts b/src/quickPicks.ts deleted file mode 100644 index 42b6c77..0000000 --- a/src/quickPicks.ts +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -export * from './quickPicks/common'; - -export * from './quickPicks/branches'; -export * from './quickPicks/branchesAndTags'; -export * from './quickPicks/commitDetails'; -export * from './quickPicks/commitFileDetails'; -export * from './quickPicks/commits'; -export * from './quickPicks/branchHistory'; -export * from './quickPicks/fileHistory'; -export * from './quickPicks/remotes'; -export * from './quickPicks/repositories'; -export * from './quickPicks/repoStatus'; -export * from './quickPicks/stashList'; \ No newline at end of file diff --git a/src/quickPicks/branchHistory.ts b/src/quickPicks/branchHistory.ts deleted file mode 100644 index 816b85e..0000000 --- a/src/quickPicks/branchHistory.ts +++ /dev/null @@ -1,139 +0,0 @@ -'use strict'; -import { Iterables, Strings } from '../system'; -import { CancellationTokenSource, QuickPickOptions, window } from 'vscode'; -import { Commands, ShowCommitSearchCommandArgs, ShowQuickBranchHistoryCommandArgs } from '../commands'; -import { CommandQuickPickItem, CommitQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress } from './common'; -import { GlyphChars } from '../constants'; -import { Container } from '../container'; -import { GitLog, GitUri, RemoteResource } from '../gitService'; -import { KeyNoopCommand } from '../keyboard'; -import { OpenRemotesCommandQuickPickItem } from './remotes'; - -export class BranchHistoryQuickPick { - - static showProgress(branch: string) { - return showQuickPickProgress(`${branch} history ${GlyphChars.Dash} search by commit message, filename, or commit id`, - { - left: KeyNoopCommand, - ',': KeyNoopCommand, - '.': KeyNoopCommand - }); - } - - static async show(log: GitLog, uri: GitUri | undefined, branch: string, progressCancellation: CancellationTokenSource, goBackCommand?: CommandQuickPickItem, nextPageCommand?: CommandQuickPickItem): Promise { - const items = Array.from(Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c))) as (CommitQuickPickItem | CommandQuickPickItem)[]; - - const currentCommand = new CommandQuickPickItem({ - label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to ${GlyphChars.Space}$(git-branch) ${branch} history` - }, Commands.ShowQuickBranchHistory, [ - uri, - { - branch, - log, - maxCount: log.maxCount, - goBackCommand - } as ShowQuickBranchHistoryCommandArgs - ]); - - const remotes = (await Container.git.getRemotes((uri && uri.repoPath) || log.repoPath)).filter(r => r.provider !== undefined); - if (remotes.length) { - items.splice(0, 0, new OpenRemotesCommandQuickPickItem(remotes, { - type: 'branch', - branch - } as RemoteResource, currentCommand)); - } - - items.splice(0, 0, new CommandQuickPickItem({ - label: `$(search) Show Commit Search`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} search for commits by message, author, files, or commit id` - }, Commands.ShowCommitSearch, [ - GitUri.fromRepoPath(log.repoPath), - { - goBackCommand: currentCommand - } as ShowCommitSearchCommandArgs - ])); - - let previousPageCommand: CommandQuickPickItem | undefined = undefined; - - if (log.truncated || log.sha) { - if (log.truncated) { - items.splice(0, 0, new CommandQuickPickItem({ - label: `$(sync) Show All Commits`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} this may take a while` - }, Commands.ShowQuickBranchHistory, [ - GitUri.fromRepoPath(log.repoPath), - { - branch, - maxCount: 0, - goBackCommand - } as ShowQuickBranchHistoryCommandArgs - ])); - } - - if (nextPageCommand) { - items.splice(0, 0, nextPageCommand); - } - - if (log.truncated) { - const npc = new CommandQuickPickItem({ - label: `$(arrow-right) Show Next Commits`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${log.maxCount} newer commits` - }, Commands.ShowQuickBranchHistory, [ - uri, - { - branch, - maxCount: log.maxCount, - nextPageCommand - } as ShowQuickBranchHistoryCommandArgs - ]); - - const last = Iterables.last(log.commits.values()); - if (last != null) { - previousPageCommand = new CommandQuickPickItem({ - label: `$(arrow-left) Show Previous Commits`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${log.maxCount} older commits` - }, Commands.ShowQuickBranchHistory, [ - new GitUri(uri ? uri : last.uri, last), - { - branch, - maxCount: log.maxCount, - goBackCommand, - nextPageCommand: npc - } as ShowQuickBranchHistoryCommandArgs - ]); - - items.splice(0, 0, previousPageCommand); - } - } - } - - if (goBackCommand) { - items.splice(0, 0, goBackCommand); - } - - if (progressCancellation.token.isCancellationRequested) return undefined; - - const scope = await Container.keyboard.beginScope({ - left: goBackCommand, - ',': previousPageCommand, - '.': nextPageCommand - }); - - progressCancellation.cancel(); - - const pick = await window.showQuickPick(items, { - matchOnDescription: true, - matchOnDetail: true, - placeHolder: `${branch} history ${GlyphChars.Dash} search by commit message, filename, or commit id`, - ignoreFocusOut: getQuickPickIgnoreFocusOut() - // onDidSelectItem: (item: QuickPickItem) => { - // scope.setKeyCommand('right', item); - // } - } as QuickPickOptions); - - await scope.dispose(); - - return pick; - } -} \ No newline at end of file diff --git a/src/quickPicks/branchHistoryQuickPick.ts b/src/quickPicks/branchHistoryQuickPick.ts new file mode 100644 index 0000000..6df569c --- /dev/null +++ b/src/quickPicks/branchHistoryQuickPick.ts @@ -0,0 +1,139 @@ +'use strict'; +import { Iterables, Strings } from '../system'; +import { CancellationTokenSource, QuickPickOptions, window } from 'vscode'; +import { Commands, ShowCommitSearchCommandArgs, ShowQuickBranchHistoryCommandArgs } from '../commands'; +import { CommandQuickPickItem, CommitQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress } from './commonQuickPicks'; +import { GlyphChars } from '../constants'; +import { Container } from '../container'; +import { GitLog, GitUri, RemoteResource } from '../gitService'; +import { KeyNoopCommand } from '../keyboard'; +import { OpenRemotesCommandQuickPickItem } from './remotesQuickPick'; + +export class BranchHistoryQuickPick { + + static showProgress(branch: string) { + return showQuickPickProgress(`${branch} history ${GlyphChars.Dash} search by commit message, filename, or commit id`, + { + left: KeyNoopCommand, + ',': KeyNoopCommand, + '.': KeyNoopCommand + }); + } + + static async show(log: GitLog, uri: GitUri | undefined, branch: string, progressCancellation: CancellationTokenSource, goBackCommand?: CommandQuickPickItem, nextPageCommand?: CommandQuickPickItem): Promise { + const items = Array.from(Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c))) as (CommitQuickPickItem | CommandQuickPickItem)[]; + + const currentCommand = new CommandQuickPickItem({ + label: `go back ${GlyphChars.ArrowBack}`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to ${GlyphChars.Space}$(git-branch) ${branch} history` + }, Commands.ShowQuickBranchHistory, [ + uri, + { + branch, + log, + maxCount: log.maxCount, + goBackCommand + } as ShowQuickBranchHistoryCommandArgs + ]); + + const remotes = (await Container.git.getRemotes((uri && uri.repoPath) || log.repoPath)).filter(r => r.provider !== undefined); + if (remotes.length) { + items.splice(0, 0, new OpenRemotesCommandQuickPickItem(remotes, { + type: 'branch', + branch + } as RemoteResource, currentCommand)); + } + + items.splice(0, 0, new CommandQuickPickItem({ + label: `$(search) Show Commit Search`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} search for commits by message, author, files, or commit id` + }, Commands.ShowCommitSearch, [ + GitUri.fromRepoPath(log.repoPath), + { + goBackCommand: currentCommand + } as ShowCommitSearchCommandArgs + ])); + + let previousPageCommand: CommandQuickPickItem | undefined = undefined; + + if (log.truncated || log.sha) { + if (log.truncated) { + items.splice(0, 0, new CommandQuickPickItem({ + label: `$(sync) Show All Commits`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} this may take a while` + }, Commands.ShowQuickBranchHistory, [ + GitUri.fromRepoPath(log.repoPath), + { + branch, + maxCount: 0, + goBackCommand + } as ShowQuickBranchHistoryCommandArgs + ])); + } + + if (nextPageCommand) { + items.splice(0, 0, nextPageCommand); + } + + if (log.truncated) { + const npc = new CommandQuickPickItem({ + label: `$(arrow-right) Show Next Commits`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${log.maxCount} newer commits` + }, Commands.ShowQuickBranchHistory, [ + uri, + { + branch, + maxCount: log.maxCount, + nextPageCommand + } as ShowQuickBranchHistoryCommandArgs + ]); + + const last = Iterables.last(log.commits.values()); + if (last != null) { + previousPageCommand = new CommandQuickPickItem({ + label: `$(arrow-left) Show Previous Commits`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${log.maxCount} older commits` + }, Commands.ShowQuickBranchHistory, [ + new GitUri(uri ? uri : last.uri, last), + { + branch, + maxCount: log.maxCount, + goBackCommand, + nextPageCommand: npc + } as ShowQuickBranchHistoryCommandArgs + ]); + + items.splice(0, 0, previousPageCommand); + } + } + } + + if (goBackCommand) { + items.splice(0, 0, goBackCommand); + } + + if (progressCancellation.token.isCancellationRequested) return undefined; + + const scope = await Container.keyboard.beginScope({ + left: goBackCommand, + ',': previousPageCommand, + '.': nextPageCommand + }); + + progressCancellation.cancel(); + + const pick = await window.showQuickPick(items, { + matchOnDescription: true, + matchOnDetail: true, + placeHolder: `${branch} history ${GlyphChars.Dash} search by commit message, filename, or commit id`, + ignoreFocusOut: getQuickPickIgnoreFocusOut() + // onDidSelectItem: (item: QuickPickItem) => { + // scope.setKeyCommand('right', item); + // } + } as QuickPickOptions); + + await scope.dispose(); + + return pick; + } +} \ No newline at end of file diff --git a/src/quickPicks/branches.ts b/src/quickPicks/branches.ts deleted file mode 100644 index 5a05122..0000000 --- a/src/quickPicks/branches.ts +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; -import { QuickPickItem, QuickPickOptions, window } from 'vscode'; -import { CommandQuickPickItem, getQuickPickIgnoreFocusOut } from './common'; -import { GlyphChars } from '../constants'; -import { GitBranch } from '../gitService'; - -export class BranchQuickPickItem implements QuickPickItem { - - label: string; - description: string; - detail: string | undefined; - - constructor( - public readonly branch: GitBranch - ) { - this.label = `${branch.current ? `$(check)${GlyphChars.Space}` : GlyphChars.Space.repeat(4)} ${branch.name}`; - this.description = branch.remote ? `${GlyphChars.Space.repeat(2)} remote branch` : ''; - } -} - -export class BranchesQuickPick { - - static async show(branches: GitBranch[], placeHolder: string, options: { goBackCommand?: CommandQuickPickItem} = {}): Promise { - const items = branches.map(b => new BranchQuickPickItem(b)) as (BranchQuickPickItem | CommandQuickPickItem)[]; - - if (options.goBackCommand !== undefined) { - items.splice(0, 0, options.goBackCommand); - } - - // const scope = await Container.keyboard.beginScope({ left: goBackCommand }); - - const pick = await window.showQuickPick(items, - { - placeHolder: placeHolder, - ignoreFocusOut: getQuickPickIgnoreFocusOut() - } as QuickPickOptions); - - // await scope.dispose(); - - return pick; - } -} \ No newline at end of file diff --git a/src/quickPicks/branchesAndTags.ts b/src/quickPicks/branchesAndTags.ts deleted file mode 100644 index e4a695f..0000000 --- a/src/quickPicks/branchesAndTags.ts +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; -import { CancellationTokenSource, QuickPickItem, QuickPickOptions, window } from 'vscode'; -import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress } from './common'; -import { GlyphChars } from '../constants'; -import { Container } from '../container'; -import { GitBranch, GitTag } from '../gitService'; -import { KeyNoopCommand } from '../keyboard'; - -export class BranchOrTagQuickPickItem implements QuickPickItem { - - label: string; - description: string; - detail: string | undefined; - - constructor( - public readonly branchOrTag: GitBranch | GitTag - ) { - if (branchOrTag instanceof GitBranch) { - this.label = `${branchOrTag.current ? `$(check)${GlyphChars.Space}` : GlyphChars.Space.repeat(4)} ${branchOrTag.name}`; - this.description = branchOrTag.remote ? `${GlyphChars.Space.repeat(2)} remote branch` : ''; - } - else { - this.label = `${GlyphChars.Space.repeat(4)} ${branchOrTag.name}`; - this.description = `${GlyphChars.Space.repeat(2)} tag`; - } - } - - get name() { - return this.branchOrTag.name; - } - - get remote() { - return this.branchOrTag instanceof GitBranch && this.branchOrTag.remote; - } -} - -export class BranchesAndTagsQuickPick { - - static showProgress(placeHolder: string) { - return showQuickPickProgress(placeHolder, - { - left: KeyNoopCommand, - ',': KeyNoopCommand, - '.': KeyNoopCommand - }); - } - - static async show(branches: GitBranch[], tags: GitTag[], placeHolder: string, options: { goBackCommand?: CommandQuickPickItem, progressCancellation?: CancellationTokenSource } = {}): Promise { - const items = [ - ...branches.filter(b => !b.remote).map(b => new BranchOrTagQuickPickItem(b)), - ...tags.map(t => new BranchOrTagQuickPickItem(t)), - ...branches.filter(b => b.remote).map(b => new BranchOrTagQuickPickItem(b)) - ] as (BranchOrTagQuickPickItem | CommandQuickPickItem)[]; - - if (options.goBackCommand !== undefined) { - items.splice(0, 0, options.goBackCommand); - } - - if (options.progressCancellation !== undefined && options.progressCancellation.token.isCancellationRequested) return undefined; - - const scope = await Container.keyboard.beginScope({ left: options.goBackCommand || KeyNoopCommand }); - - options.progressCancellation && options.progressCancellation.cancel(); - - const pick = await window.showQuickPick(items, - { - placeHolder: placeHolder, - ignoreFocusOut: getQuickPickIgnoreFocusOut() - } as QuickPickOptions); - - await scope.dispose(); - - return pick; - } -} \ No newline at end of file diff --git a/src/quickPicks/branchesAndTagsQuickPick.ts b/src/quickPicks/branchesAndTagsQuickPick.ts new file mode 100644 index 0000000..e14c2e2 --- /dev/null +++ b/src/quickPicks/branchesAndTagsQuickPick.ts @@ -0,0 +1,75 @@ +'use strict'; +import { CancellationTokenSource, QuickPickItem, QuickPickOptions, window } from 'vscode'; +import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress } from './commonQuickPicks'; +import { GlyphChars } from '../constants'; +import { Container } from '../container'; +import { GitBranch, GitTag } from '../gitService'; +import { KeyNoopCommand } from '../keyboard'; + +export class BranchOrTagQuickPickItem implements QuickPickItem { + + label: string; + description: string; + detail: string | undefined; + + constructor( + public readonly branchOrTag: GitBranch | GitTag + ) { + if (branchOrTag instanceof GitBranch) { + this.label = `${branchOrTag.current ? `$(check)${GlyphChars.Space}` : GlyphChars.Space.repeat(4)} ${branchOrTag.name}`; + this.description = branchOrTag.remote ? `${GlyphChars.Space.repeat(2)} remote branch` : ''; + } + else { + this.label = `${GlyphChars.Space.repeat(4)} ${branchOrTag.name}`; + this.description = `${GlyphChars.Space.repeat(2)} tag`; + } + } + + get name() { + return this.branchOrTag.name; + } + + get remote() { + return this.branchOrTag instanceof GitBranch && this.branchOrTag.remote; + } +} + +export class BranchesAndTagsQuickPick { + + static showProgress(placeHolder: string) { + return showQuickPickProgress(placeHolder, + { + left: KeyNoopCommand, + ',': KeyNoopCommand, + '.': KeyNoopCommand + }); + } + + static async show(branches: GitBranch[], tags: GitTag[], placeHolder: string, options: { goBackCommand?: CommandQuickPickItem, progressCancellation?: CancellationTokenSource } = {}): Promise { + const items = [ + ...branches.filter(b => !b.remote).map(b => new BranchOrTagQuickPickItem(b)), + ...tags.map(t => new BranchOrTagQuickPickItem(t)), + ...branches.filter(b => b.remote).map(b => new BranchOrTagQuickPickItem(b)) + ] as (BranchOrTagQuickPickItem | CommandQuickPickItem)[]; + + if (options.goBackCommand !== undefined) { + items.splice(0, 0, options.goBackCommand); + } + + if (options.progressCancellation !== undefined && options.progressCancellation.token.isCancellationRequested) return undefined; + + const scope = await Container.keyboard.beginScope({ left: options.goBackCommand || KeyNoopCommand }); + + options.progressCancellation && options.progressCancellation.cancel(); + + const pick = await window.showQuickPick(items, + { + placeHolder: placeHolder, + ignoreFocusOut: getQuickPickIgnoreFocusOut() + } as QuickPickOptions); + + await scope.dispose(); + + return pick; + } +} \ No newline at end of file diff --git a/src/quickPicks/branchesQuickPick.ts b/src/quickPicks/branchesQuickPick.ts new file mode 100644 index 0000000..c04453c --- /dev/null +++ b/src/quickPicks/branchesQuickPick.ts @@ -0,0 +1,42 @@ +'use strict'; +import { QuickPickItem, QuickPickOptions, window } from 'vscode'; +import { CommandQuickPickItem, getQuickPickIgnoreFocusOut } from './commonQuickPicks'; +import { GlyphChars } from '../constants'; +import { GitBranch } from '../gitService'; + +export class BranchQuickPickItem implements QuickPickItem { + + label: string; + description: string; + detail: string | undefined; + + constructor( + public readonly branch: GitBranch + ) { + this.label = `${branch.current ? `$(check)${GlyphChars.Space}` : GlyphChars.Space.repeat(4)} ${branch.name}`; + this.description = branch.remote ? `${GlyphChars.Space.repeat(2)} remote branch` : ''; + } +} + +export class BranchesQuickPick { + + static async show(branches: GitBranch[], placeHolder: string, options: { goBackCommand?: CommandQuickPickItem} = {}): Promise { + const items = branches.map(b => new BranchQuickPickItem(b)) as (BranchQuickPickItem | CommandQuickPickItem)[]; + + if (options.goBackCommand !== undefined) { + items.splice(0, 0, options.goBackCommand); + } + + // const scope = await Container.keyboard.beginScope({ left: goBackCommand }); + + const pick = await window.showQuickPick(items, + { + placeHolder: placeHolder, + ignoreFocusOut: getQuickPickIgnoreFocusOut() + } as QuickPickOptions); + + // await scope.dispose(); + + return pick; + } +} \ No newline at end of file diff --git a/src/quickPicks/commitDetails.ts b/src/quickPicks/commitDetails.ts deleted file mode 100644 index bb7f44f..0000000 --- a/src/quickPicks/commitDetails.ts +++ /dev/null @@ -1,320 +0,0 @@ -'use strict'; -import { Arrays, Iterables, Strings } from '../system'; -import { commands, QuickPickOptions, TextDocumentShowOptions, Uri, window } from 'vscode'; -import { Commands, CopyMessageToClipboardCommandArgs, CopyShaToClipboardCommandArgs, DiffDirectoryCommandArgs, DiffWithPreviousCommandArgs, ShowQuickCommitDetailsCommandArgs, StashApplyCommandArgs, StashDeleteCommandArgs } from '../commands'; -import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, KeyCommandQuickPickItem, OpenFileCommandQuickPickItem, OpenFilesCommandQuickPickItem, QuickPickItem, ShowCommitInResultsQuickPickItem } from './common'; -import { GlyphChars } from '../constants'; -import { Container } from '../container'; -import { getGitStatusOcticon, GitLog, GitLogCommit, GitStashCommit, GitStatusFile, GitStatusFileStatus, GitUri, IGitStatusFile, RemoteResource } from '../gitService'; -import { KeyCommand, KeyNoopCommand, Keys } from '../keyboard'; -import { OpenRemotesCommandQuickPickItem } from './remotes'; -import * as path from 'path'; - -export class CommitWithFileStatusQuickPickItem extends OpenFileCommandQuickPickItem { - - readonly status: GitStatusFileStatus; - - readonly commit: GitLogCommit; - - constructor( - commit: GitLogCommit, - status: IGitStatusFile - ) { - const octicon = getGitStatusOcticon(status.status); - const description = GitStatusFile.getFormattedDirectory(status, true); - - super(GitUri.toRevisionUri(commit.sha, status, commit.repoPath), { - label: `${Strings.pad(octicon, 4, 2)} ${path.basename(status.fileName)}`, - description: description - }); - - this.commit = commit.toFileCommit(status); - this.status = status.status; - } - - get sha(): string { - return this.commit.sha; - } - - onDidPressKey(key: Keys): Promise<{} | undefined> { - if (this.commit.previousSha === undefined) return super.onDidPressKey(key); - - return commands.executeCommand(Commands.DiffWithPrevious, - this.commit.toGitUri(), - { - commit: this.commit, - showOptions: { - preserveFocus: true, - preview: false - } as TextDocumentShowOptions - } as DiffWithPreviousCommandArgs) as Promise<{} | undefined>; - } -} - -export class OpenCommitFilesCommandQuickPickItem extends OpenFilesCommandQuickPickItem { - - constructor( - commit: GitLogCommit, - versioned: boolean = false, - item?: QuickPickItem - ) { - const repoPath = commit.repoPath; - const uris = Arrays.filterMap(commit.fileStatuses, - f => GitUri.fromFileStatus(f, repoPath)); - - super(uris, item || { - label: `$(file-symlink-file) Open Files`, - description: '' - // detail: `Opens all of the changed file in the working tree` - }); - } -} - -export class OpenCommitFileRevisionsCommandQuickPickItem extends OpenFilesCommandQuickPickItem { - - constructor( - commit: GitLogCommit, - item?: QuickPickItem - ) { - const uris = Arrays.filterMap(commit.fileStatuses, - f => GitUri.toRevisionUri(f.status === 'D' ? commit.previousFileSha : commit.sha, f, commit.repoPath)); - - super(uris, item || { - label: `$(file-symlink-file) Open Revisions`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} in ${GlyphChars.Space}$(git-commit) ${commit.shortSha}` - // detail: `Opens all of the changed files in $(git-commit) ${commit.shortSha}` - }); - } -} - -export class CommitDetailsQuickPick { - - static async show(commit: GitLogCommit, uri: Uri, goBackCommand?: CommandQuickPickItem, currentCommand?: CommandQuickPickItem, repoLog?: GitLog): Promise { - await commit.resolvePreviousFileSha(); - - const items: (CommitWithFileStatusQuickPickItem | CommandQuickPickItem)[] = commit.fileStatuses.map(fs => new CommitWithFileStatusQuickPickItem(commit, fs)); - - const stash = commit.isStash; - - let index = 0; - - if (stash) { - items.splice(index++, 0, new CommandQuickPickItem({ - label: `$(git-pull-request) Apply Stashed Changes`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`)}` - }, Commands.StashApply, [ - { - confirm: true, - deleteAfter: false, - stashItem: commit as GitStashCommit, - goBackCommand: currentCommand - } as StashApplyCommandArgs - ]) - ); - - items.splice(index++, 0, new CommandQuickPickItem({ - label: `$(x) Delete Stashed Changes`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`)}` - }, Commands.StashDelete, [ - { - confirm: true, - stashItem: commit as GitStashCommit, - goBackCommand: currentCommand - } as StashDeleteCommandArgs - ]) - ); - - items.splice(index++, 0, new ShowCommitInResultsQuickPickItem(commit)); - } - else { - items.splice(index++, 0, new ShowCommitInResultsQuickPickItem(commit)); - - const remotes = (await Container.git.getRemotes(commit.repoPath)).filter(r => r.provider !== undefined); - if (remotes.length) { - items.splice(index++, 0, new OpenRemotesCommandQuickPickItem(remotes, { - type: 'commit', - sha: commit.sha - } as RemoteResource, currentCommand)); - } - } - - items.splice(index++, 0, new OpenCommitFilesCommandQuickPickItem(commit)); - items.splice(index++, 0, new OpenCommitFileRevisionsCommandQuickPickItem(commit)); - - items.splice(index++, 0, new CommandQuickPickItem({ - label: `$(git-compare) Open Directory Compare with Previous Revision`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.previousFileShortSha} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}` - }, Commands.DiffDirectory, [ - commit.uri, - { - ref1: commit.previousFileSha, - ref2: commit.sha - } as DiffDirectoryCommandArgs - ]) - ); - - items.splice(index++, 0, new CommandQuickPickItem({ - label: `$(git-compare) Open Directory Compare with Working Tree`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.shortSha} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(file-directory) Working Tree` - }, Commands.DiffDirectory, [ - uri, - { - ref1: commit.sha - } as DiffDirectoryCommandArgs - ]) - ); - - if (!stash) { - items.splice(index++, 0, new CommandQuickPickItem({ - label: `$(clippy) Copy Commit ID to Clipboard`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.shortSha}` - }, Commands.CopyShaToClipboard, [ - uri, - { - sha: commit.sha - } as CopyShaToClipboardCommandArgs - ]) - ); - } - - items.splice(index++, 0, new CommandQuickPickItem({ - label: `$(clippy) Copy Commit Message to Clipboard`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`)}` - }, Commands.CopyMessageToClipboard, [ - uri, - { - message: commit.message, - sha: commit.sha - } as CopyMessageToClipboardCommandArgs - ]) - ); - - items.splice(index++, 0, new CommandQuickPickItem({ - label: `Changed Files`, - description: commit.getDiffStatus() - }, Commands.ShowQuickCommitDetails, [ - uri, - { - commit, - repoLog, - sha: commit.sha, - goBackCommand - } as ShowQuickCommitDetailsCommandArgs - ]) - ); - - if (goBackCommand) { - items.splice(0, 0, goBackCommand); - } - - let previousCommand: KeyCommand | (() => Promise) | undefined = undefined; - let nextCommand: KeyCommand | (() => Promise) | undefined = undefined; - if (!stash) { - // If we have the full history, we are good - if (repoLog !== undefined && !repoLog.truncated && repoLog.sha === undefined) { - previousCommand = commit.previousSha === undefined - ? undefined - : new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [ - commit.previousUri, - { - repoLog, - sha: commit.previousSha, - goBackCommand - } as ShowQuickCommitDetailsCommandArgs - ]); - - nextCommand = commit.nextSha === undefined - ? undefined - : new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [ - commit.nextUri, - { - repoLog, - sha: commit.nextSha, - goBackCommand - } as ShowQuickCommitDetailsCommandArgs - ]); - } - else { - previousCommand = async () => { - let log = repoLog; - let c = log && log.commits.get(commit.sha); - - // If we can't find the commit or the previous commit isn't available (since it isn't trustworthy) - if (c === undefined || c.previousSha === undefined) { - log = await Container.git.getLog(commit.repoPath, { maxCount: Container.config.advanced.maxListItems, ref: commit.sha }); - c = log && log.commits.get(commit.sha); - - if (c) { - // Copy over next info, since it is trustworthy at this point - c.nextSha = commit.nextSha; - } - } - - if (c === undefined || c.previousSha === undefined) return KeyNoopCommand; - - return new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [ - c.previousUri, - { - repoLog: log, - sha: c.previousSha, - goBackCommand - } as ShowQuickCommitDetailsCommandArgs - ]); - }; - - nextCommand = async () => { - let log = repoLog; - let c = log && log.commits.get(commit.sha); - - // If we can't find the commit or the next commit isn't available (since it isn't trustworthy) - if (c === undefined || c.nextSha === undefined) { - log = undefined; - c = undefined; - - // Try to find the next commit - const nextLog = await Container.git.getLog(commit.repoPath, { maxCount: 1, reverse: true, ref: commit.sha }); - const next = nextLog && Iterables.first(nextLog.commits.values()); - if (next !== undefined && next.sha !== commit.sha) { - c = commit; - c.nextSha = next.sha; - } - } - - if (c === undefined || c.nextSha === undefined) return KeyNoopCommand; - - return new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [ - c.nextUri, - { - repoLog: log, - sha: c.nextSha, - goBackCommand - } as ShowQuickCommitDetailsCommandArgs - ]); - }; - } - } - - const scope = await Container.keyboard.beginScope({ - left: goBackCommand, - ',': previousCommand, - '.': nextCommand - }); - - const pick = await window.showQuickPick(items, { - matchOnDescription: true, - matchOnDetail: true, - placeHolder: `${commit.shortSha} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.author ? `${commit.author}, ` : ''}${commit.formattedDate} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`)}`, - ignoreFocusOut: getQuickPickIgnoreFocusOut(), - onDidSelectItem: (item: QuickPickItem) => { - scope.setKeyCommand('right', item); - if (typeof item.onDidSelect === 'function') { - item.onDidSelect(); - } - } - } as QuickPickOptions); - - await scope.dispose(); - - return pick; - } -} \ No newline at end of file diff --git a/src/quickPicks/commitFileDetails.ts b/src/quickPicks/commitFileDetails.ts deleted file mode 100644 index e7557dc..0000000 --- a/src/quickPicks/commitFileDetails.ts +++ /dev/null @@ -1,324 +0,0 @@ -'use strict'; -import { Iterables, Strings } from '../system'; -import { QuickPickItem, QuickPickOptions, Uri, window } from 'vscode'; -import { Commands, CopyMessageToClipboardCommandArgs, CopyShaToClipboardCommandArgs, DiffWithPreviousCommandArgs, DiffWithWorkingCommandArgs, openEditor, ShowQuickCommitDetailsCommandArgs, ShowQuickCommitFileDetailsCommandArgs, ShowQuickFileHistoryCommandArgs } from '../commands'; -import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, KeyCommandQuickPickItem, OpenFileCommandQuickPickItem } from './common'; -import { GlyphChars } from '../constants'; -import { Container } from '../container'; -import { GitLog, GitLogCommit, GitUri, RemoteResource } from '../gitService'; -import { KeyCommand, KeyNoopCommand } from '../keyboard'; -import { OpenRemotesCommandQuickPickItem } from './remotes'; -import * as path from 'path'; - -export class ApplyCommitFileChangesCommandQuickPickItem extends CommandQuickPickItem { - constructor( - private readonly commit: GitLogCommit, - item?: QuickPickItem - ) { - super(item || { - label: `$(git-pull-request) Apply Changes`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(file-text) ${path.basename(commit.fileName)} in ${GlyphChars.Space}$(git-commit) ${commit.shortSha}` - }, undefined, undefined); - } - - async execute(): Promise<{} | undefined> { - const uri = this.commit.toGitUri(); - await Container.git.checkoutFile(uri); - return openEditor(uri, { preserveFocus: true, preview: false }); - } -} - -export class OpenCommitFileCommandQuickPickItem extends OpenFileCommandQuickPickItem { - - constructor( - commit: GitLogCommit, - item?: QuickPickItem - ) { - const uri = Uri.file(path.resolve(commit.repoPath, commit.fileName)); - super(uri, item || { - label: `$(file-symlink-file) Open File`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${path.basename(commit.fileName)}` - }); - } -} - -export class OpenCommitFileRevisionCommandQuickPickItem extends OpenFileCommandQuickPickItem { - - constructor( - commit: GitLogCommit, - item?: QuickPickItem - ) { - let description: string; - let uri: Uri; - if (commit.status === 'D') { - uri = GitUri.toRevisionUri(commit.previousFileSha, commit.previousUri.fsPath, commit.repoPath); - description = `${Strings.pad(GlyphChars.Dash, 2, 3)} ${path.basename(commit.fileName)} in ${GlyphChars.Space}$(git-commit) ${commit.previousShortSha} (deleted in ${GlyphChars.Space}$(git-commit) ${commit.shortSha})`; - } - else { - uri = GitUri.toRevisionUri(commit.sha, commit.uri.fsPath, commit.repoPath); - description = `${Strings.pad(GlyphChars.Dash, 2, 3)} ${path.basename(commit.fileName)} in ${GlyphChars.Space}$(git-commit) ${commit.shortSha}`; - } - super(uri, item || { - label: `$(file-symlink-file) Open Revision`, - description: description - }); - } -} - -export class CommitFileDetailsQuickPick { - - static async show(commit: GitLogCommit, uri: Uri, goBackCommand?: CommandQuickPickItem, currentCommand?: CommandQuickPickItem, fileLog?: GitLog): Promise { - const items: CommandQuickPickItem[] = []; - - const stash = commit.isStash; - - const workingName = (commit.workingFileName && path.basename(commit.workingFileName)) || path.basename(commit.fileName); - - const isUncommitted = commit.isUncommitted; - if (isUncommitted) { - // Since we can't trust the previous sha on an uncommitted commit, find the last commit for this file - const c = await Container.git.getRecentLogCommitForFile(undefined, commit.uri.fsPath); - if (c === undefined) return undefined; - - commit = c; - } - - await commit.resolvePreviousFileSha(); - - if (stash) { - items.push(new ApplyCommitFileChangesCommandQuickPickItem(commit)); - } - - if (commit.previousFileShortSha) { - items.push(new CommandQuickPickItem({ - label: `$(git-compare) Open Changes`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.previousFileShortSha} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}` - }, Commands.DiffWithPrevious, [ - commit.uri, - { - commit - } as DiffWithPreviousCommandArgs - ]) - ); - } - - if (commit.workingFileName) { - items.push(new CommandQuickPickItem({ - label: `$(git-compare) Open Changes with Working Tree`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.shortSha} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(file-text) ${workingName}` - }, Commands.DiffWithWorking, [ - Uri.file(path.resolve(commit.repoPath, commit.workingFileName)), - { - commit - } as DiffWithWorkingCommandArgs - ]) - ); - } - - if (commit.workingFileName && commit.status !== 'D') { - items.push(new OpenCommitFileCommandQuickPickItem(commit)); - } - items.push(new OpenCommitFileRevisionCommandQuickPickItem(commit)); - - const remotes = (await Container.git.getRemotes(commit.repoPath)).filter(r => r.provider !== undefined); - if (remotes.length) { - if (commit.workingFileName && commit.status !== 'D') { - const branch = await Container.git.getBranch(commit.repoPath); - items.push(new OpenRemotesCommandQuickPickItem(remotes, { - type: 'file', - fileName: commit.workingFileName, - branch: branch!.name - } as RemoteResource, currentCommand)); - } - - if (!stash) { - items.push(new OpenRemotesCommandQuickPickItem(remotes, { - type: 'revision', - fileName: commit.fileName, - commit - } as RemoteResource, currentCommand)); - } - } - - if (!stash) { - items.push(new ApplyCommitFileChangesCommandQuickPickItem(commit)); - - items.push(new CommandQuickPickItem({ - label: `$(clippy) Copy Commit ID to Clipboard`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.shortSha}` - }, Commands.CopyShaToClipboard, [ - uri, - { - sha: commit.sha - } as CopyShaToClipboardCommandArgs - ]) - ); - - items.push(new CommandQuickPickItem({ - label: `$(clippy) Copy Commit Message to Clipboard`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`)}` - }, Commands.CopyMessageToClipboard, [ - uri, - { - message: commit.message, - sha: commit.sha - } as CopyMessageToClipboardCommandArgs - ])); - } - - if (commit.workingFileName) { - items.push(new CommandQuickPickItem({ - label: `$(history) Show File History`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} of ${path.basename(commit.fileName)}` - }, Commands.ShowQuickFileHistory, [ - Uri.file(path.resolve(commit.repoPath, commit.workingFileName)), - { - fileLog, - goBackCommand: currentCommand - } as ShowQuickFileHistoryCommandArgs - ])); - } - - if (!stash) { - items.push(new CommandQuickPickItem({ - label: `$(history) Show ${commit.workingFileName ? 'Previous ' : ''}File History`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} of ${path.basename(commit.fileName)} ${Strings.pad(GlyphChars.Dot, 1, 1)} from ${GlyphChars.Space}$(git-commit) ${commit.shortSha}` - }, Commands.ShowQuickFileHistory, [ - commit.toGitUri(), - { - goBackCommand: currentCommand - } as ShowQuickFileHistoryCommandArgs - ])); - - items.push(new CommandQuickPickItem({ - label: `$(git-commit) Show Commit Details`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.shortSha}` - }, Commands.ShowQuickCommitDetails, [ - commit.toGitUri(), - { - commit, - sha: commit.sha, - goBackCommand: currentCommand - } as ShowQuickCommitDetailsCommandArgs - ]) - ); - } - - if (goBackCommand) { - items.splice(0, 0, goBackCommand); - } - - let previousCommand: KeyCommand | (() => Promise) | undefined = undefined; - let nextCommand: KeyCommand | (() => Promise) | undefined = undefined; - if (!stash) { - // If we have the full history, we are good - if (fileLog !== undefined && !fileLog.truncated && fileLog.sha === undefined) { - previousCommand = commit.previousSha === undefined - ? undefined - : new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [ - commit.previousUri, - { - fileLog, - sha: commit.previousSha, - goBackCommand - } as ShowQuickCommitFileDetailsCommandArgs - ]); - - nextCommand = commit.nextSha === undefined - ? undefined - : new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [ - commit.nextUri, - { - fileLog, - sha: commit.nextSha, - goBackCommand - } as ShowQuickCommitFileDetailsCommandArgs - ]); - } - else { - previousCommand = async () => { - let log = fileLog; - let c = log && log.commits.get(commit.sha); - - // If we can't find the commit or the previous commit isn't available (since it isn't trustworthy) - if (c === undefined || c.previousSha === undefined) { - log = await Container.git.getLogForFile(commit.repoPath, uri.fsPath, { maxCount: Container.config.advanced.maxListItems, ref: commit.sha, renames: true }); - if (log === undefined) return KeyNoopCommand; - - c = log && log.commits.get(commit.sha); - // Since we exclude merge commits in file log, just grab the first returned commit - if (c === undefined && commit.isMerge) { - c = Iterables.first(log.commits.values()); - } - - if (c) { - // Copy over next info, since it is trustworthy at this point - c.nextSha = commit.nextSha; - c.nextFileName = commit.nextFileName; - } - } - - if (c === undefined || c.previousSha === undefined) return KeyNoopCommand; - - return new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [ - c.previousUri, - { - fileLog: log, - sha: c.previousSha, - goBackCommand - } as ShowQuickCommitFileDetailsCommandArgs - ]); - }; - - nextCommand = async () => { - let log = fileLog; - let c = log && log.commits.get(commit.sha); - - // If we can't find the commit or the next commit isn't available (since it isn't trustworthy) - if (c === undefined || c.nextSha === undefined) { - log = undefined; - c = undefined; - - // Try to find the next commit - const next = await Container.git.findNextCommit(commit.repoPath, uri.fsPath, commit.sha); - if (next !== undefined && next.sha !== commit.sha) { - c = commit; - c.nextSha = next.sha; - c.nextFileName = next.originalFileName || next.fileName; - } - } - - if (c === undefined || c.nextSha === undefined) return KeyNoopCommand; - - return new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [ - c.nextUri, - { - fileLog: log, - sha: c.nextSha, - goBackCommand - } as ShowQuickCommitFileDetailsCommandArgs - ]); - }; - } - } - - const scope = await Container.keyboard.beginScope({ - left: goBackCommand, - ',': previousCommand, - '.': nextCommand - }); - - const pick = await window.showQuickPick(items, { - matchOnDescription: true, - placeHolder: `${commit.getFormattedPath()} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${isUncommitted ? `Uncommitted ${GlyphChars.ArrowRightHollow} ` : ''}${commit.shortSha} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.author}, ${commit.formattedDate} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`)}`, - ignoreFocusOut: getQuickPickIgnoreFocusOut(), - onDidSelectItem: (item: QuickPickItem) => { - scope.setKeyCommand('right', item as KeyCommand); - } - } as QuickPickOptions); - - await scope.dispose(); - - return pick; - } -} \ No newline at end of file diff --git a/src/quickPicks/commitFileQuickPick.ts b/src/quickPicks/commitFileQuickPick.ts new file mode 100644 index 0000000..bbf1729 --- /dev/null +++ b/src/quickPicks/commitFileQuickPick.ts @@ -0,0 +1,324 @@ +'use strict'; +import { Iterables, Strings } from '../system'; +import { QuickPickItem, QuickPickOptions, Uri, window } from 'vscode'; +import { Commands, CopyMessageToClipboardCommandArgs, CopyShaToClipboardCommandArgs, DiffWithPreviousCommandArgs, DiffWithWorkingCommandArgs, openEditor, ShowQuickCommitDetailsCommandArgs, ShowQuickCommitFileDetailsCommandArgs, ShowQuickFileHistoryCommandArgs } from '../commands'; +import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, KeyCommandQuickPickItem, OpenFileCommandQuickPickItem } from './commonQuickPicks'; +import { GlyphChars } from '../constants'; +import { Container } from '../container'; +import { GitLog, GitLogCommit, GitUri, RemoteResource } from '../gitService'; +import { KeyCommand, KeyNoopCommand } from '../keyboard'; +import { OpenRemotesCommandQuickPickItem } from './remotesQuickPick'; +import * as path from 'path'; + +export class ApplyCommitFileChangesCommandQuickPickItem extends CommandQuickPickItem { + constructor( + private readonly commit: GitLogCommit, + item?: QuickPickItem + ) { + super(item || { + label: `$(git-pull-request) Apply Changes`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(file-text) ${path.basename(commit.fileName)} in ${GlyphChars.Space}$(git-commit) ${commit.shortSha}` + }, undefined, undefined); + } + + async execute(): Promise<{} | undefined> { + const uri = this.commit.toGitUri(); + await Container.git.checkoutFile(uri); + return openEditor(uri, { preserveFocus: true, preview: false }); + } +} + +export class OpenCommitFileCommandQuickPickItem extends OpenFileCommandQuickPickItem { + + constructor( + commit: GitLogCommit, + item?: QuickPickItem + ) { + const uri = Uri.file(path.resolve(commit.repoPath, commit.fileName)); + super(uri, item || { + label: `$(file-symlink-file) Open File`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${path.basename(commit.fileName)}` + }); + } +} + +export class OpenCommitFileRevisionCommandQuickPickItem extends OpenFileCommandQuickPickItem { + + constructor( + commit: GitLogCommit, + item?: QuickPickItem + ) { + let description: string; + let uri: Uri; + if (commit.status === 'D') { + uri = GitUri.toRevisionUri(commit.previousFileSha, commit.previousUri.fsPath, commit.repoPath); + description = `${Strings.pad(GlyphChars.Dash, 2, 3)} ${path.basename(commit.fileName)} in ${GlyphChars.Space}$(git-commit) ${commit.previousShortSha} (deleted in ${GlyphChars.Space}$(git-commit) ${commit.shortSha})`; + } + else { + uri = GitUri.toRevisionUri(commit.sha, commit.uri.fsPath, commit.repoPath); + description = `${Strings.pad(GlyphChars.Dash, 2, 3)} ${path.basename(commit.fileName)} in ${GlyphChars.Space}$(git-commit) ${commit.shortSha}`; + } + super(uri, item || { + label: `$(file-symlink-file) Open Revision`, + description: description + }); + } +} + +export class CommitFileQuickPick { + + static async show(commit: GitLogCommit, uri: Uri, goBackCommand?: CommandQuickPickItem, currentCommand?: CommandQuickPickItem, fileLog?: GitLog): Promise { + const items: CommandQuickPickItem[] = []; + + const stash = commit.isStash; + + const workingName = (commit.workingFileName && path.basename(commit.workingFileName)) || path.basename(commit.fileName); + + const isUncommitted = commit.isUncommitted; + if (isUncommitted) { + // Since we can't trust the previous sha on an uncommitted commit, find the last commit for this file + const c = await Container.git.getRecentLogCommitForFile(undefined, commit.uri.fsPath); + if (c === undefined) return undefined; + + commit = c; + } + + await commit.resolvePreviousFileSha(); + + if (stash) { + items.push(new ApplyCommitFileChangesCommandQuickPickItem(commit)); + } + + if (commit.previousFileShortSha) { + items.push(new CommandQuickPickItem({ + label: `$(git-compare) Open Changes`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.previousFileShortSha} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}` + }, Commands.DiffWithPrevious, [ + commit.uri, + { + commit + } as DiffWithPreviousCommandArgs + ]) + ); + } + + if (commit.workingFileName) { + items.push(new CommandQuickPickItem({ + label: `$(git-compare) Open Changes with Working Tree`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.shortSha} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(file-text) ${workingName}` + }, Commands.DiffWithWorking, [ + Uri.file(path.resolve(commit.repoPath, commit.workingFileName)), + { + commit + } as DiffWithWorkingCommandArgs + ]) + ); + } + + if (commit.workingFileName && commit.status !== 'D') { + items.push(new OpenCommitFileCommandQuickPickItem(commit)); + } + items.push(new OpenCommitFileRevisionCommandQuickPickItem(commit)); + + const remotes = (await Container.git.getRemotes(commit.repoPath)).filter(r => r.provider !== undefined); + if (remotes.length) { + if (commit.workingFileName && commit.status !== 'D') { + const branch = await Container.git.getBranch(commit.repoPath); + items.push(new OpenRemotesCommandQuickPickItem(remotes, { + type: 'file', + fileName: commit.workingFileName, + branch: branch!.name + } as RemoteResource, currentCommand)); + } + + if (!stash) { + items.push(new OpenRemotesCommandQuickPickItem(remotes, { + type: 'revision', + fileName: commit.fileName, + commit + } as RemoteResource, currentCommand)); + } + } + + if (!stash) { + items.push(new ApplyCommitFileChangesCommandQuickPickItem(commit)); + + items.push(new CommandQuickPickItem({ + label: `$(clippy) Copy Commit ID to Clipboard`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.shortSha}` + }, Commands.CopyShaToClipboard, [ + uri, + { + sha: commit.sha + } as CopyShaToClipboardCommandArgs + ]) + ); + + items.push(new CommandQuickPickItem({ + label: `$(clippy) Copy Commit Message to Clipboard`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`)}` + }, Commands.CopyMessageToClipboard, [ + uri, + { + message: commit.message, + sha: commit.sha + } as CopyMessageToClipboardCommandArgs + ])); + } + + if (commit.workingFileName) { + items.push(new CommandQuickPickItem({ + label: `$(history) Show File History`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} of ${path.basename(commit.fileName)}` + }, Commands.ShowQuickFileHistory, [ + Uri.file(path.resolve(commit.repoPath, commit.workingFileName)), + { + fileLog, + goBackCommand: currentCommand + } as ShowQuickFileHistoryCommandArgs + ])); + } + + if (!stash) { + items.push(new CommandQuickPickItem({ + label: `$(history) Show ${commit.workingFileName ? 'Previous ' : ''}File History`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} of ${path.basename(commit.fileName)} ${Strings.pad(GlyphChars.Dot, 1, 1)} from ${GlyphChars.Space}$(git-commit) ${commit.shortSha}` + }, Commands.ShowQuickFileHistory, [ + commit.toGitUri(), + { + goBackCommand: currentCommand + } as ShowQuickFileHistoryCommandArgs + ])); + + items.push(new CommandQuickPickItem({ + label: `$(git-commit) Show Commit Details`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.shortSha}` + }, Commands.ShowQuickCommitDetails, [ + commit.toGitUri(), + { + commit, + sha: commit.sha, + goBackCommand: currentCommand + } as ShowQuickCommitDetailsCommandArgs + ]) + ); + } + + if (goBackCommand) { + items.splice(0, 0, goBackCommand); + } + + let previousCommand: KeyCommand | (() => Promise) | undefined = undefined; + let nextCommand: KeyCommand | (() => Promise) | undefined = undefined; + if (!stash) { + // If we have the full history, we are good + if (fileLog !== undefined && !fileLog.truncated && fileLog.sha === undefined) { + previousCommand = commit.previousSha === undefined + ? undefined + : new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [ + commit.previousUri, + { + fileLog, + sha: commit.previousSha, + goBackCommand + } as ShowQuickCommitFileDetailsCommandArgs + ]); + + nextCommand = commit.nextSha === undefined + ? undefined + : new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [ + commit.nextUri, + { + fileLog, + sha: commit.nextSha, + goBackCommand + } as ShowQuickCommitFileDetailsCommandArgs + ]); + } + else { + previousCommand = async () => { + let log = fileLog; + let c = log && log.commits.get(commit.sha); + + // If we can't find the commit or the previous commit isn't available (since it isn't trustworthy) + if (c === undefined || c.previousSha === undefined) { + log = await Container.git.getLogForFile(commit.repoPath, uri.fsPath, { maxCount: Container.config.advanced.maxListItems, ref: commit.sha, renames: true }); + if (log === undefined) return KeyNoopCommand; + + c = log && log.commits.get(commit.sha); + // Since we exclude merge commits in file log, just grab the first returned commit + if (c === undefined && commit.isMerge) { + c = Iterables.first(log.commits.values()); + } + + if (c) { + // Copy over next info, since it is trustworthy at this point + c.nextSha = commit.nextSha; + c.nextFileName = commit.nextFileName; + } + } + + if (c === undefined || c.previousSha === undefined) return KeyNoopCommand; + + return new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [ + c.previousUri, + { + fileLog: log, + sha: c.previousSha, + goBackCommand + } as ShowQuickCommitFileDetailsCommandArgs + ]); + }; + + nextCommand = async () => { + let log = fileLog; + let c = log && log.commits.get(commit.sha); + + // If we can't find the commit or the next commit isn't available (since it isn't trustworthy) + if (c === undefined || c.nextSha === undefined) { + log = undefined; + c = undefined; + + // Try to find the next commit + const next = await Container.git.findNextCommit(commit.repoPath, uri.fsPath, commit.sha); + if (next !== undefined && next.sha !== commit.sha) { + c = commit; + c.nextSha = next.sha; + c.nextFileName = next.originalFileName || next.fileName; + } + } + + if (c === undefined || c.nextSha === undefined) return KeyNoopCommand; + + return new KeyCommandQuickPickItem(Commands.ShowQuickCommitFileDetails, [ + c.nextUri, + { + fileLog: log, + sha: c.nextSha, + goBackCommand + } as ShowQuickCommitFileDetailsCommandArgs + ]); + }; + } + } + + const scope = await Container.keyboard.beginScope({ + left: goBackCommand, + ',': previousCommand, + '.': nextCommand + }); + + const pick = await window.showQuickPick(items, { + matchOnDescription: true, + placeHolder: `${commit.getFormattedPath()} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${isUncommitted ? `Uncommitted ${GlyphChars.ArrowRightHollow} ` : ''}${commit.shortSha} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.author}, ${commit.formattedDate} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`)}`, + ignoreFocusOut: getQuickPickIgnoreFocusOut(), + onDidSelectItem: (item: QuickPickItem) => { + scope.setKeyCommand('right', item as KeyCommand); + } + } as QuickPickOptions); + + await scope.dispose(); + + return pick; + } +} \ No newline at end of file diff --git a/src/quickPicks/commitQuickPick.ts b/src/quickPicks/commitQuickPick.ts new file mode 100644 index 0000000..01cd8ab --- /dev/null +++ b/src/quickPicks/commitQuickPick.ts @@ -0,0 +1,320 @@ +'use strict'; +import { Arrays, Iterables, Strings } from '../system'; +import { commands, QuickPickOptions, TextDocumentShowOptions, Uri, window } from 'vscode'; +import { Commands, CopyMessageToClipboardCommandArgs, CopyShaToClipboardCommandArgs, DiffDirectoryCommandArgs, DiffWithPreviousCommandArgs, ShowQuickCommitDetailsCommandArgs, StashApplyCommandArgs, StashDeleteCommandArgs } from '../commands'; +import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, KeyCommandQuickPickItem, OpenFileCommandQuickPickItem, OpenFilesCommandQuickPickItem, QuickPickItem, ShowCommitInResultsQuickPickItem } from './commonQuickPicks'; +import { GlyphChars } from '../constants'; +import { Container } from '../container'; +import { getGitStatusOcticon, GitLog, GitLogCommit, GitStashCommit, GitStatusFile, GitStatusFileStatus, GitUri, IGitStatusFile, RemoteResource } from '../gitService'; +import { KeyCommand, KeyNoopCommand, Keys } from '../keyboard'; +import { OpenRemotesCommandQuickPickItem } from './remotesQuickPick'; +import * as path from 'path'; + +export class CommitWithFileStatusQuickPickItem extends OpenFileCommandQuickPickItem { + + readonly status: GitStatusFileStatus; + + readonly commit: GitLogCommit; + + constructor( + commit: GitLogCommit, + status: IGitStatusFile + ) { + const octicon = getGitStatusOcticon(status.status); + const description = GitStatusFile.getFormattedDirectory(status, true); + + super(GitUri.toRevisionUri(commit.sha, status, commit.repoPath), { + label: `${Strings.pad(octicon, 4, 2)} ${path.basename(status.fileName)}`, + description: description + }); + + this.commit = commit.toFileCommit(status); + this.status = status.status; + } + + get sha(): string { + return this.commit.sha; + } + + onDidPressKey(key: Keys): Promise<{} | undefined> { + if (this.commit.previousSha === undefined) return super.onDidPressKey(key); + + return commands.executeCommand(Commands.DiffWithPrevious, + this.commit.toGitUri(), + { + commit: this.commit, + showOptions: { + preserveFocus: true, + preview: false + } as TextDocumentShowOptions + } as DiffWithPreviousCommandArgs) as Promise<{} | undefined>; + } +} + +export class OpenCommitFilesCommandQuickPickItem extends OpenFilesCommandQuickPickItem { + + constructor( + commit: GitLogCommit, + versioned: boolean = false, + item?: QuickPickItem + ) { + const repoPath = commit.repoPath; + const uris = Arrays.filterMap(commit.fileStatuses, + f => GitUri.fromFileStatus(f, repoPath)); + + super(uris, item || { + label: `$(file-symlink-file) Open Files`, + description: '' + // detail: `Opens all of the changed file in the working tree` + }); + } +} + +export class OpenCommitFileRevisionsCommandQuickPickItem extends OpenFilesCommandQuickPickItem { + + constructor( + commit: GitLogCommit, + item?: QuickPickItem + ) { + const uris = Arrays.filterMap(commit.fileStatuses, + f => GitUri.toRevisionUri(f.status === 'D' ? commit.previousFileSha : commit.sha, f, commit.repoPath)); + + super(uris, item || { + label: `$(file-symlink-file) Open Revisions`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} in ${GlyphChars.Space}$(git-commit) ${commit.shortSha}` + // detail: `Opens all of the changed files in $(git-commit) ${commit.shortSha}` + }); + } +} + +export class CommitQuickPick { + + static async show(commit: GitLogCommit, uri: Uri, goBackCommand?: CommandQuickPickItem, currentCommand?: CommandQuickPickItem, repoLog?: GitLog): Promise { + await commit.resolvePreviousFileSha(); + + const items: (CommitWithFileStatusQuickPickItem | CommandQuickPickItem)[] = commit.fileStatuses.map(fs => new CommitWithFileStatusQuickPickItem(commit, fs)); + + const stash = commit.isStash; + + let index = 0; + + if (stash) { + items.splice(index++, 0, new CommandQuickPickItem({ + label: `$(git-pull-request) Apply Stashed Changes`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`)}` + }, Commands.StashApply, [ + { + confirm: true, + deleteAfter: false, + stashItem: commit as GitStashCommit, + goBackCommand: currentCommand + } as StashApplyCommandArgs + ]) + ); + + items.splice(index++, 0, new CommandQuickPickItem({ + label: `$(x) Delete Stashed Changes`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`)}` + }, Commands.StashDelete, [ + { + confirm: true, + stashItem: commit as GitStashCommit, + goBackCommand: currentCommand + } as StashDeleteCommandArgs + ]) + ); + + items.splice(index++, 0, new ShowCommitInResultsQuickPickItem(commit)); + } + else { + items.splice(index++, 0, new ShowCommitInResultsQuickPickItem(commit)); + + const remotes = (await Container.git.getRemotes(commit.repoPath)).filter(r => r.provider !== undefined); + if (remotes.length) { + items.splice(index++, 0, new OpenRemotesCommandQuickPickItem(remotes, { + type: 'commit', + sha: commit.sha + } as RemoteResource, currentCommand)); + } + } + + items.splice(index++, 0, new OpenCommitFilesCommandQuickPickItem(commit)); + items.splice(index++, 0, new OpenCommitFileRevisionsCommandQuickPickItem(commit)); + + items.splice(index++, 0, new CommandQuickPickItem({ + label: `$(git-compare) Open Directory Compare with Previous Revision`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.previousFileShortSha} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}` + }, Commands.DiffDirectory, [ + commit.uri, + { + ref1: commit.previousFileSha, + ref2: commit.sha + } as DiffDirectoryCommandArgs + ]) + ); + + items.splice(index++, 0, new CommandQuickPickItem({ + label: `$(git-compare) Open Directory Compare with Working Tree`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.shortSha} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(file-directory) Working Tree` + }, Commands.DiffDirectory, [ + uri, + { + ref1: commit.sha + } as DiffDirectoryCommandArgs + ]) + ); + + if (!stash) { + items.splice(index++, 0, new CommandQuickPickItem({ + label: `$(clippy) Copy Commit ID to Clipboard`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.shortSha}` + }, Commands.CopyShaToClipboard, [ + uri, + { + sha: commit.sha + } as CopyShaToClipboardCommandArgs + ]) + ); + } + + items.splice(index++, 0, new CommandQuickPickItem({ + label: `$(clippy) Copy Commit Message to Clipboard`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`)}` + }, Commands.CopyMessageToClipboard, [ + uri, + { + message: commit.message, + sha: commit.sha + } as CopyMessageToClipboardCommandArgs + ]) + ); + + items.splice(index++, 0, new CommandQuickPickItem({ + label: `Changed Files`, + description: commit.getDiffStatus() + }, Commands.ShowQuickCommitDetails, [ + uri, + { + commit, + repoLog, + sha: commit.sha, + goBackCommand + } as ShowQuickCommitDetailsCommandArgs + ]) + ); + + if (goBackCommand) { + items.splice(0, 0, goBackCommand); + } + + let previousCommand: KeyCommand | (() => Promise) | undefined = undefined; + let nextCommand: KeyCommand | (() => Promise) | undefined = undefined; + if (!stash) { + // If we have the full history, we are good + if (repoLog !== undefined && !repoLog.truncated && repoLog.sha === undefined) { + previousCommand = commit.previousSha === undefined + ? undefined + : new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [ + commit.previousUri, + { + repoLog, + sha: commit.previousSha, + goBackCommand + } as ShowQuickCommitDetailsCommandArgs + ]); + + nextCommand = commit.nextSha === undefined + ? undefined + : new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [ + commit.nextUri, + { + repoLog, + sha: commit.nextSha, + goBackCommand + } as ShowQuickCommitDetailsCommandArgs + ]); + } + else { + previousCommand = async () => { + let log = repoLog; + let c = log && log.commits.get(commit.sha); + + // If we can't find the commit or the previous commit isn't available (since it isn't trustworthy) + if (c === undefined || c.previousSha === undefined) { + log = await Container.git.getLog(commit.repoPath, { maxCount: Container.config.advanced.maxListItems, ref: commit.sha }); + c = log && log.commits.get(commit.sha); + + if (c) { + // Copy over next info, since it is trustworthy at this point + c.nextSha = commit.nextSha; + } + } + + if (c === undefined || c.previousSha === undefined) return KeyNoopCommand; + + return new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [ + c.previousUri, + { + repoLog: log, + sha: c.previousSha, + goBackCommand + } as ShowQuickCommitDetailsCommandArgs + ]); + }; + + nextCommand = async () => { + let log = repoLog; + let c = log && log.commits.get(commit.sha); + + // If we can't find the commit or the next commit isn't available (since it isn't trustworthy) + if (c === undefined || c.nextSha === undefined) { + log = undefined; + c = undefined; + + // Try to find the next commit + const nextLog = await Container.git.getLog(commit.repoPath, { maxCount: 1, reverse: true, ref: commit.sha }); + const next = nextLog && Iterables.first(nextLog.commits.values()); + if (next !== undefined && next.sha !== commit.sha) { + c = commit; + c.nextSha = next.sha; + } + } + + if (c === undefined || c.nextSha === undefined) return KeyNoopCommand; + + return new KeyCommandQuickPickItem(Commands.ShowQuickCommitDetails, [ + c.nextUri, + { + repoLog: log, + sha: c.nextSha, + goBackCommand + } as ShowQuickCommitDetailsCommandArgs + ]); + }; + } + } + + const scope = await Container.keyboard.beginScope({ + left: goBackCommand, + ',': previousCommand, + '.': nextCommand + }); + + const pick = await window.showQuickPick(items, { + matchOnDescription: true, + matchOnDetail: true, + placeHolder: `${commit.shortSha} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.author ? `${commit.author}, ` : ''}${commit.formattedDate} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`)}`, + ignoreFocusOut: getQuickPickIgnoreFocusOut(), + onDidSelectItem: (item: QuickPickItem) => { + scope.setKeyCommand('right', item); + if (typeof item.onDidSelect === 'function') { + item.onDidSelect(); + } + } + } as QuickPickOptions); + + await scope.dispose(); + + return pick; + } +} \ No newline at end of file diff --git a/src/quickPicks/commits.ts b/src/quickPicks/commits.ts deleted file mode 100644 index c37a0e3..0000000 --- a/src/quickPicks/commits.ts +++ /dev/null @@ -1,54 +0,0 @@ -'use strict'; -import { Iterables } from '../system'; -import { CancellationTokenSource, QuickPickOptions, window } from 'vscode'; -import { Container } from '../container'; -import { GitLog } from '../gitService'; -import { KeyNoopCommand } from '../keyboard'; -import { CommandQuickPickItem, CommitQuickPickItem, getQuickPickIgnoreFocusOut, MessageQuickPickItem, showQuickPickProgress } from '../quickPicks'; - -export class CommitsQuickPick { - - static showProgress(message: string) { - return showQuickPickProgress(message, - { - left: KeyNoopCommand, - ',': KeyNoopCommand, - '.': KeyNoopCommand - }); - } - - static async show(log: GitLog | undefined, placeHolder: string, progressCancellation: CancellationTokenSource, options: { goBackCommand?: CommandQuickPickItem, showAllCommand?: CommandQuickPickItem, showInResultsExplorerCommand?: CommandQuickPickItem }): Promise { - const items = ((log && [...Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c))]) || [new MessageQuickPickItem('No results found')]) as (CommitQuickPickItem | CommandQuickPickItem)[]; - - if (options.showInResultsExplorerCommand !== undefined) { - items.splice(0, 0, options.showInResultsExplorerCommand); - } - - if (options.showAllCommand !== undefined) { - items.splice(0, 0, options.showAllCommand); - } - - if (options.goBackCommand !== undefined) { - items.splice(0, 0, options.goBackCommand); - } - - if (progressCancellation.token.isCancellationRequested) return undefined; - - const scope = await Container.keyboard.beginScope({ left: options.goBackCommand }); - - progressCancellation.cancel(); - - const pick = await window.showQuickPick(items, { - matchOnDescription: true, - placeHolder: placeHolder, - ignoreFocusOut: getQuickPickIgnoreFocusOut() - // onDidSelectItem: (item: QuickPickItem) => { - // scope.setKeyCommand('right', item); - // } - } as QuickPickOptions); - - await scope.dispose(); - - return pick; - } -} \ No newline at end of file diff --git a/src/quickPicks/commitsQuickPick.ts b/src/quickPicks/commitsQuickPick.ts new file mode 100644 index 0000000..d2d3b0c --- /dev/null +++ b/src/quickPicks/commitsQuickPick.ts @@ -0,0 +1,54 @@ +'use strict'; +import { Iterables } from '../system'; +import { CancellationTokenSource, QuickPickOptions, window } from 'vscode'; +import { Container } from '../container'; +import { GitLog } from '../gitService'; +import { KeyNoopCommand } from '../keyboard'; +import { CommandQuickPickItem, CommitQuickPickItem, getQuickPickIgnoreFocusOut, MessageQuickPickItem, showQuickPickProgress } from '../quickPicks/quickPicks'; + +export class CommitsQuickPick { + + static showProgress(message: string) { + return showQuickPickProgress(message, + { + left: KeyNoopCommand, + ',': KeyNoopCommand, + '.': KeyNoopCommand + }); + } + + static async show(log: GitLog | undefined, placeHolder: string, progressCancellation: CancellationTokenSource, options: { goBackCommand?: CommandQuickPickItem, showAllCommand?: CommandQuickPickItem, showInResultsExplorerCommand?: CommandQuickPickItem }): Promise { + const items = ((log && [...Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c))]) || [new MessageQuickPickItem('No results found')]) as (CommitQuickPickItem | CommandQuickPickItem)[]; + + if (options.showInResultsExplorerCommand !== undefined) { + items.splice(0, 0, options.showInResultsExplorerCommand); + } + + if (options.showAllCommand !== undefined) { + items.splice(0, 0, options.showAllCommand); + } + + if (options.goBackCommand !== undefined) { + items.splice(0, 0, options.goBackCommand); + } + + if (progressCancellation.token.isCancellationRequested) return undefined; + + const scope = await Container.keyboard.beginScope({ left: options.goBackCommand }); + + progressCancellation.cancel(); + + const pick = await window.showQuickPick(items, { + matchOnDescription: true, + placeHolder: placeHolder, + ignoreFocusOut: getQuickPickIgnoreFocusOut() + // onDidSelectItem: (item: QuickPickItem) => { + // scope.setKeyCommand('right', item); + // } + } as QuickPickOptions); + + await scope.dispose(); + + return pick; + } +} \ No newline at end of file diff --git a/src/quickPicks/common.ts b/src/quickPicks/common.ts deleted file mode 100644 index 74d304d..0000000 --- a/src/quickPicks/common.ts +++ /dev/null @@ -1,253 +0,0 @@ -'use strict'; -import { Strings } from '../system'; -import { CancellationTokenSource, commands, QuickPickItem, QuickPickOptions, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode'; -import { BranchesAndTagsQuickPick, BranchOrTagQuickPickItem } from './branchesAndTags'; -import { Commands, openEditor } from '../commands'; -import { configuration } from '../configuration'; -import { GlyphChars } from '../constants'; -import { Container } from '../container'; -import { GitLog, GitLogCommit, GitStashCommit } from '../gitService'; -import { KeyboardScope, KeyMapping, Keys } from '../keyboard'; - -export function getQuickPickIgnoreFocusOut() { - return !configuration.get(configuration.name('advanced')('quickPick')('closeOnFocusOut').value); -} - -export function showQuickPickProgress(message: string, mapping?: KeyMapping): CancellationTokenSource { - const cancellation = new CancellationTokenSource(); - _showQuickPickProgress(message, cancellation, mapping); - return cancellation; -} - -async function _showQuickPickProgress(message: string, cancellation: CancellationTokenSource, mapping?: KeyMapping) { - const scope: KeyboardScope | undefined = mapping && await Container.keyboard.beginScope(mapping); - - try { - await window.showQuickPick(_getInfiniteCancellablePromise(cancellation), { - placeHolder: message, - ignoreFocusOut: getQuickPickIgnoreFocusOut() - } as QuickPickOptions, cancellation.token); - } - catch (ex) { - // Not sure why this throws - } - finally { - cancellation.cancel(); - scope && scope.dispose(); - } -} - -function _getInfiniteCancellablePromise(cancellation: CancellationTokenSource) { - return new Promise((resolve, reject) => { - const disposable = cancellation.token.onCancellationRequested(() => { - disposable.dispose(); - resolve([]); - }); - }); -} - -export interface QuickPickItem extends QuickPickItem { - onDidSelect?(): void; - onDidPressKey?(key: Keys): Promise<{} | undefined>; -} - -export class CommandQuickPickItem implements QuickPickItem { - - label!: string; - description!: string; - detail?: string | undefined; - protected command: Commands | undefined; - protected args: any[] | undefined; - - constructor(item: QuickPickItem, args?: [Commands, any[]]); - constructor(item: QuickPickItem, command?: Commands, args?: any[]); - constructor(item: QuickPickItem, commandOrArgs?: Commands | [Commands, any[]], args?: any[]) { - if (commandOrArgs === undefined) { - this.command = undefined; - this.args = args; - } - else if (typeof commandOrArgs === 'string') { - this.command = commandOrArgs; - this.args = args; - } - else { - this.command = commandOrArgs[0]; - this.args = commandOrArgs.slice(1); - } - Object.assign(this, item); - } - - execute(): Promise<{} | undefined> { - if (this.command === undefined) return Promise.resolve(undefined); - - return commands.executeCommand(this.command, ...(this.args || [])) as Promise<{} | undefined>; - } - - onDidPressKey(key: Keys): Promise<{} | undefined> { - return this.execute(); - } -} - -export class MessageQuickPickItem extends CommandQuickPickItem { - - constructor(message: string) { - super({ label: message, description: '' } as QuickPickItem); - } -} - -export class KeyCommandQuickPickItem extends CommandQuickPickItem { - - constructor(command: Commands, args?: any[]) { - super({ label: '', description: '' } as QuickPickItem, command, args); - } -} - -export class OpenFileCommandQuickPickItem extends CommandQuickPickItem { - - constructor(public readonly uri: Uri, item: QuickPickItem) { - super(item, undefined, undefined); - } - - async execute(options?: TextDocumentShowOptions): Promise { - return openEditor(this.uri, options); - } - - // onDidSelect(): Promise<{} | undefined> { - // return this.execute({ - // preserveFocus: true, - // preview: true - // }); - // } - - onDidPressKey(key: Keys): Promise<{} | undefined> { - return this.execute({ - preserveFocus: true, - preview: false - }); - } -} - -export class OpenFilesCommandQuickPickItem extends CommandQuickPickItem { - - constructor(public readonly uris: Uri[], item: QuickPickItem) { - super(item, undefined, undefined); - } - - async execute(options: TextDocumentShowOptions = { preserveFocus: false, preview: false }): Promise<{} | undefined> { - for (const uri of this.uris) { - await openEditor(uri, options); - } - return undefined; - } - - async onDidPressKey(key: Keys): Promise<{} | undefined> { - return this.execute({ - preserveFocus: true, - preview: false - }); - } -} - -export class CommitQuickPickItem implements QuickPickItem { - - label: string; - description: string; - detail: string; - - constructor(public readonly commit: GitLogCommit) { - const message = commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`); - if (commit.isStash) { - this.label = message; - this.description = ''; - this.detail = `${GlyphChars.Space} ${(commit as GitStashCommit).stashName || commit.shortSha} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.formattedDate} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.getDiffStatus()}`; - } - else { - this.label = message; - this.description = `${Strings.pad('$(git-commit)', 1, 1)} ${commit.shortSha}`; - this.detail = `${GlyphChars.Space} ${commit.author}, ${commit.formattedDate}${commit.isFile ? '' : ` ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.getDiffStatus()}`}`; - } - } -} - -export class ShowCommitInResultsQuickPickItem extends CommandQuickPickItem { - constructor( - public readonly commit: GitLogCommit, - item: QuickPickItem = { - label: 'Show in Results', - description: `${Strings.pad(GlyphChars.Dash, 2, 2)} displays commit in the GitLens Results view` - } - ) { - super(item, undefined, undefined); - } - - async execute(options: TextDocumentShowOptions = { preserveFocus: false, preview: false }): Promise<{} | undefined> { - Container.resultsExplorer.showCommitInResults(this.commit); - return undefined; - } -} - -export class ShowCommitsInResultsQuickPickItem extends CommandQuickPickItem { - - constructor( - public readonly results: GitLog, - public readonly resultsLabel: string | { label: string, resultsType?: { singular: string, plural: string } }, - item: QuickPickItem = { - label: 'Show in Results', - description: `${Strings.pad(GlyphChars.Dash, 2, 2)} displays commits in the GitLens Results view` - } - ) { - super(item, undefined, undefined); - } - - async execute(options: TextDocumentShowOptions = { preserveFocus: false, preview: false }): Promise<{} | undefined> { - Container.resultsExplorer.showCommitsInResults(this.results, this.resultsLabel); - return undefined; - } -} - -export class ShowCommitsSearchInResultsQuickPickItem extends ShowCommitsInResultsQuickPickItem { - - constructor( - public readonly results: GitLog, - public readonly search: string, - item: QuickPickItem = { - label: 'Show in Results', - description: `${Strings.pad(GlyphChars.Dash, 2, 2)} displays results in the GitLens Results view` - } - ) { - super(results, { label: search }, item); - } -} - -export class ShowBranchesAndTagsQuickPickItem extends CommandQuickPickItem { - - constructor( - private readonly repoPath: string, - private readonly placeHolder: string, - private readonly goBackCommand?: CommandQuickPickItem, - item: QuickPickItem = { - label: 'Show Branches and Tags', - description: `${Strings.pad(GlyphChars.Dash, 2, 2)} displays branches and tags` - } - ) { - super(item, undefined, undefined); - } - - async execute(options: TextDocumentShowOptions = { preserveFocus: false, preview: false }): Promise { - const progressCancellation = BranchesAndTagsQuickPick.showProgress(this.placeHolder); - - try { - const [branches, tags] = await Promise.all([ - Container.git.getBranches(this.repoPath), - Container.git.getTags(this.repoPath) - ]); - - if (progressCancellation.token.isCancellationRequested) return undefined; - - return BranchesAndTagsQuickPick.show(branches, tags, this.placeHolder, { progressCancellation: progressCancellation, goBackCommand: this.goBackCommand }); - } - finally { - progressCancellation.dispose(); - } - } -} \ No newline at end of file diff --git a/src/quickPicks/commonQuickPicks.ts b/src/quickPicks/commonQuickPicks.ts new file mode 100644 index 0000000..3344946 --- /dev/null +++ b/src/quickPicks/commonQuickPicks.ts @@ -0,0 +1,253 @@ +'use strict'; +import { Strings } from '../system'; +import { CancellationTokenSource, commands, QuickPickItem, QuickPickOptions, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode'; +import { BranchesAndTagsQuickPick, BranchOrTagQuickPickItem } from './branchesAndTagsQuickPick'; +import { Commands, openEditor } from '../commands'; +import { configuration } from '../configuration'; +import { GlyphChars } from '../constants'; +import { Container } from '../container'; +import { GitLog, GitLogCommit, GitStashCommit } from '../gitService'; +import { KeyboardScope, KeyMapping, Keys } from '../keyboard'; + +export function getQuickPickIgnoreFocusOut() { + return !configuration.get(configuration.name('advanced')('quickPick')('closeOnFocusOut').value); +} + +export function showQuickPickProgress(message: string, mapping?: KeyMapping): CancellationTokenSource { + const cancellation = new CancellationTokenSource(); + _showQuickPickProgress(message, cancellation, mapping); + return cancellation; +} + +async function _showQuickPickProgress(message: string, cancellation: CancellationTokenSource, mapping?: KeyMapping) { + const scope: KeyboardScope | undefined = mapping && await Container.keyboard.beginScope(mapping); + + try { + await window.showQuickPick(_getInfiniteCancellablePromise(cancellation), { + placeHolder: message, + ignoreFocusOut: getQuickPickIgnoreFocusOut() + } as QuickPickOptions, cancellation.token); + } + catch (ex) { + // Not sure why this throws + } + finally { + cancellation.cancel(); + scope && scope.dispose(); + } +} + +function _getInfiniteCancellablePromise(cancellation: CancellationTokenSource) { + return new Promise((resolve, reject) => { + const disposable = cancellation.token.onCancellationRequested(() => { + disposable.dispose(); + resolve([]); + }); + }); +} + +export interface QuickPickItem extends QuickPickItem { + onDidSelect?(): void; + onDidPressKey?(key: Keys): Promise<{} | undefined>; +} + +export class CommandQuickPickItem implements QuickPickItem { + + label!: string; + description!: string; + detail?: string | undefined; + protected command: Commands | undefined; + protected args: any[] | undefined; + + constructor(item: QuickPickItem, args?: [Commands, any[]]); + constructor(item: QuickPickItem, command?: Commands, args?: any[]); + constructor(item: QuickPickItem, commandOrArgs?: Commands | [Commands, any[]], args?: any[]) { + if (commandOrArgs === undefined) { + this.command = undefined; + this.args = args; + } + else if (typeof commandOrArgs === 'string') { + this.command = commandOrArgs; + this.args = args; + } + else { + this.command = commandOrArgs[0]; + this.args = commandOrArgs.slice(1); + } + Object.assign(this, item); + } + + execute(): Promise<{} | undefined> { + if (this.command === undefined) return Promise.resolve(undefined); + + return commands.executeCommand(this.command, ...(this.args || [])) as Promise<{} | undefined>; + } + + onDidPressKey(key: Keys): Promise<{} | undefined> { + return this.execute(); + } +} + +export class MessageQuickPickItem extends CommandQuickPickItem { + + constructor(message: string) { + super({ label: message, description: '' } as QuickPickItem); + } +} + +export class KeyCommandQuickPickItem extends CommandQuickPickItem { + + constructor(command: Commands, args?: any[]) { + super({ label: '', description: '' } as QuickPickItem, command, args); + } +} + +export class OpenFileCommandQuickPickItem extends CommandQuickPickItem { + + constructor(public readonly uri: Uri, item: QuickPickItem) { + super(item, undefined, undefined); + } + + async execute(options?: TextDocumentShowOptions): Promise { + return openEditor(this.uri, options); + } + + // onDidSelect(): Promise<{} | undefined> { + // return this.execute({ + // preserveFocus: true, + // preview: true + // }); + // } + + onDidPressKey(key: Keys): Promise<{} | undefined> { + return this.execute({ + preserveFocus: true, + preview: false + }); + } +} + +export class OpenFilesCommandQuickPickItem extends CommandQuickPickItem { + + constructor(public readonly uris: Uri[], item: QuickPickItem) { + super(item, undefined, undefined); + } + + async execute(options: TextDocumentShowOptions = { preserveFocus: false, preview: false }): Promise<{} | undefined> { + for (const uri of this.uris) { + await openEditor(uri, options); + } + return undefined; + } + + async onDidPressKey(key: Keys): Promise<{} | undefined> { + return this.execute({ + preserveFocus: true, + preview: false + }); + } +} + +export class CommitQuickPickItem implements QuickPickItem { + + label: string; + description: string; + detail: string; + + constructor(public readonly commit: GitLogCommit) { + const message = commit.getShortMessage(`${GlyphChars.Space}$(ellipsis)`); + if (commit.isStash) { + this.label = message; + this.description = ''; + this.detail = `${GlyphChars.Space} ${(commit as GitStashCommit).stashName || commit.shortSha} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.formattedDate} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.getDiffStatus()}`; + } + else { + this.label = message; + this.description = `${Strings.pad('$(git-commit)', 1, 1)} ${commit.shortSha}`; + this.detail = `${GlyphChars.Space} ${commit.author}, ${commit.formattedDate}${commit.isFile ? '' : ` ${Strings.pad(GlyphChars.Dot, 1, 1)} ${commit.getDiffStatus()}`}`; + } + } +} + +export class ShowCommitInResultsQuickPickItem extends CommandQuickPickItem { + constructor( + public readonly commit: GitLogCommit, + item: QuickPickItem = { + label: 'Show in Results', + description: `${Strings.pad(GlyphChars.Dash, 2, 2)} displays commit in the GitLens Results view` + } + ) { + super(item, undefined, undefined); + } + + async execute(options: TextDocumentShowOptions = { preserveFocus: false, preview: false }): Promise<{} | undefined> { + Container.resultsExplorer.showCommitInResults(this.commit); + return undefined; + } +} + +export class ShowCommitsInResultsQuickPickItem extends CommandQuickPickItem { + + constructor( + public readonly results: GitLog, + public readonly resultsLabel: string | { label: string, resultsType?: { singular: string, plural: string } }, + item: QuickPickItem = { + label: 'Show in Results', + description: `${Strings.pad(GlyphChars.Dash, 2, 2)} displays commits in the GitLens Results view` + } + ) { + super(item, undefined, undefined); + } + + async execute(options: TextDocumentShowOptions = { preserveFocus: false, preview: false }): Promise<{} | undefined> { + Container.resultsExplorer.showCommitsInResults(this.results, this.resultsLabel); + return undefined; + } +} + +export class ShowCommitsSearchInResultsQuickPickItem extends ShowCommitsInResultsQuickPickItem { + + constructor( + public readonly results: GitLog, + public readonly search: string, + item: QuickPickItem = { + label: 'Show in Results', + description: `${Strings.pad(GlyphChars.Dash, 2, 2)} displays results in the GitLens Results view` + } + ) { + super(results, { label: search }, item); + } +} + +export class ShowBranchesAndTagsQuickPickItem extends CommandQuickPickItem { + + constructor( + private readonly repoPath: string, + private readonly placeHolder: string, + private readonly goBackCommand?: CommandQuickPickItem, + item: QuickPickItem = { + label: 'Show Branches and Tags', + description: `${Strings.pad(GlyphChars.Dash, 2, 2)} displays branches and tags` + } + ) { + super(item, undefined, undefined); + } + + async execute(options: TextDocumentShowOptions = { preserveFocus: false, preview: false }): Promise { + const progressCancellation = BranchesAndTagsQuickPick.showProgress(this.placeHolder); + + try { + const [branches, tags] = await Promise.all([ + Container.git.getBranches(this.repoPath), + Container.git.getTags(this.repoPath) + ]); + + if (progressCancellation.token.isCancellationRequested) return undefined; + + return BranchesAndTagsQuickPick.show(branches, tags, this.placeHolder, { progressCancellation: progressCancellation, goBackCommand: this.goBackCommand }); + } + finally { + progressCancellation.dispose(); + } + } +} \ No newline at end of file diff --git a/src/quickPicks/fileHistory.ts b/src/quickPicks/fileHistory.ts deleted file mode 100644 index 98104aa..0000000 --- a/src/quickPicks/fileHistory.ts +++ /dev/null @@ -1,159 +0,0 @@ -'use strict'; -import { Iterables, Strings } from '../system'; -import { CancellationTokenSource, QuickPickOptions, Uri, window } from 'vscode'; -import { Commands, ShowQuickCurrentBranchHistoryCommandArgs, ShowQuickFileHistoryCommandArgs } from '../commands'; -import { CommandQuickPickItem, CommitQuickPickItem, getQuickPickIgnoreFocusOut, ShowBranchesAndTagsQuickPickItem, showQuickPickProgress } from './common'; -import { GlyphChars } from '../constants'; -import { Container } from '../container'; -import { GitLog, GitUri, RemoteResource } from '../gitService'; -import { KeyNoopCommand } from '../keyboard'; -import { OpenRemotesCommandQuickPickItem } from './remotes'; -import * as path from 'path'; - -export class FileHistoryQuickPick { - - static showProgress(placeHolder: string) { - return showQuickPickProgress(placeHolder, - { - left: KeyNoopCommand, - ',': KeyNoopCommand, - '.': KeyNoopCommand - }); - } - - static async show(log: GitLog, uri: GitUri, placeHolder: string, options: { currentCommand?: CommandQuickPickItem, goBackCommand?: CommandQuickPickItem, nextPageCommand?: CommandQuickPickItem, previousPageCommand?: CommandQuickPickItem, pickerOnly?: boolean, progressCancellation?: CancellationTokenSource, showAllCommand?: CommandQuickPickItem, showInResultsExplorerCommand?: CommandQuickPickItem } = {}): Promise { - options = { pickerOnly: false, ...options }; - - const items = Array.from(Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c))) as (CommitQuickPickItem | CommandQuickPickItem)[]; - - let index = 0; - - if (options.pickerOnly) { - index++; - items.splice(0, 0, new ShowBranchesAndTagsQuickPickItem(log.repoPath, placeHolder, options.currentCommand)); - } - - if (options.showInResultsExplorerCommand !== undefined) { - index++; - items.splice(0, 0, options.showInResultsExplorerCommand); - } - - if (log.truncated || log.sha) { - if (options.showAllCommand !== undefined) { - index++; - items.splice(0, 0, options.showAllCommand); - } - else if (!options.pickerOnly) { - const [workingFileName] = await Container.git.findWorkingFileName(path.relative(log.repoPath, uri.fsPath), log.repoPath); - if (workingFileName) { - index++; - items.splice(0, 0, new CommandQuickPickItem({ - label: `$(history) Show File History`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} of ${path.basename(workingFileName)}` - }, Commands.ShowQuickFileHistory, [ - Uri.file(path.resolve(log.repoPath, workingFileName)), - { - goBackCommand: new CommandQuickPickItem({ - label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to history of ${GlyphChars.Space}$(file-text) ${path.basename(uri.fsPath)}${uri.sha ? ` from ${GlyphChars.Space}$(git-commit) ${uri.shortSha}` : ''}` - }, Commands.ShowQuickFileHistory, [ - uri, - { - log: log, - maxCount: log.maxCount, - range: log.range, - goBackCommand: options.goBackCommand - } as ShowQuickFileHistoryCommandArgs - ]) - } as ShowQuickFileHistoryCommandArgs - ])); - } - } - - if (options.nextPageCommand !== undefined) { - index++; - items.splice(0, 0, options.nextPageCommand); - } - - if (options.previousPageCommand !== undefined) { - index++; - items.splice(0, 0, options.previousPageCommand); - } - } - - if (!options.pickerOnly) { - const branch = await Container.git.getBranch(uri.repoPath!); - - const currentCommand = new CommandQuickPickItem({ - label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to history of ${GlyphChars.Space}$(file-text) ${path.basename(uri.fsPath)}${uri.sha ? ` from ${GlyphChars.Space}$(git-commit) ${uri.shortSha}` : ''}` - }, Commands.ShowQuickFileHistory, [ - uri, - { - log, - maxCount: log.maxCount, - range: log.range - } as ShowQuickFileHistoryCommandArgs - ]); - - // Only show the full repo option if we are the root - if (options.goBackCommand === undefined) { - items.splice(index++, 0, new CommandQuickPickItem({ - label: `$(history) Show Branch History`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${GlyphChars.Space}$(git-branch) ${branch!.name} history` - }, Commands.ShowQuickCurrentBranchHistory, - [ - undefined, - { - goBackCommand: currentCommand - } as ShowQuickCurrentBranchHistoryCommandArgs - ])); - } - - const remotes = (await Container.git.getRemotes(uri.repoPath!)).filter(r => r.provider !== undefined); - if (remotes.length) { - const resource = uri.sha !== undefined - ? { - type: 'revision', - branch: branch!.name, - fileName: uri.getRelativePath(), - sha: uri.sha - } as RemoteResource - : { - type: 'file', - branch: branch!.name, - fileName: uri.getRelativePath() - } as RemoteResource; - items.splice(index++, 0, new OpenRemotesCommandQuickPickItem(remotes, resource, currentCommand)); - } - - if (options.goBackCommand) { - items.splice(0, 0, options.goBackCommand); - } - } - - if (options.progressCancellation !== undefined && options.progressCancellation.token.isCancellationRequested) return undefined; - - const scope = await Container.keyboard.beginScope({ - left: options.goBackCommand, - ',': options.previousPageCommand, - '.': options.nextPageCommand - }); - - options.progressCancellation && options.progressCancellation.cancel(); - - const pick = await window.showQuickPick(items, { - matchOnDescription: true, - matchOnDetail: true, - placeHolder: placeHolder, - ignoreFocusOut: getQuickPickIgnoreFocusOut() - // onDidSelectItem: (item: QuickPickItem) => { - // scope.setKeyCommand('right', item); - // } - } as QuickPickOptions); - - await scope.dispose(); - - return pick; - } -} \ No newline at end of file diff --git a/src/quickPicks/fileHistoryQuickPick.ts b/src/quickPicks/fileHistoryQuickPick.ts new file mode 100644 index 0000000..4450b48 --- /dev/null +++ b/src/quickPicks/fileHistoryQuickPick.ts @@ -0,0 +1,159 @@ +'use strict'; +import { Iterables, Strings } from '../system'; +import { CancellationTokenSource, QuickPickOptions, Uri, window } from 'vscode'; +import { Commands, ShowQuickCurrentBranchHistoryCommandArgs, ShowQuickFileHistoryCommandArgs } from '../commands'; +import { CommandQuickPickItem, CommitQuickPickItem, getQuickPickIgnoreFocusOut, ShowBranchesAndTagsQuickPickItem, showQuickPickProgress } from './commonQuickPicks'; +import { GlyphChars } from '../constants'; +import { Container } from '../container'; +import { GitLog, GitUri, RemoteResource } from '../gitService'; +import { KeyNoopCommand } from '../keyboard'; +import { OpenRemotesCommandQuickPickItem } from './remotesQuickPick'; +import * as path from 'path'; + +export class FileHistoryQuickPick { + + static showProgress(placeHolder: string) { + return showQuickPickProgress(placeHolder, + { + left: KeyNoopCommand, + ',': KeyNoopCommand, + '.': KeyNoopCommand + }); + } + + static async show(log: GitLog, uri: GitUri, placeHolder: string, options: { currentCommand?: CommandQuickPickItem, goBackCommand?: CommandQuickPickItem, nextPageCommand?: CommandQuickPickItem, previousPageCommand?: CommandQuickPickItem, pickerOnly?: boolean, progressCancellation?: CancellationTokenSource, showAllCommand?: CommandQuickPickItem, showInResultsExplorerCommand?: CommandQuickPickItem } = {}): Promise { + options = { pickerOnly: false, ...options }; + + const items = Array.from(Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c))) as (CommitQuickPickItem | CommandQuickPickItem)[]; + + let index = 0; + + if (options.pickerOnly) { + index++; + items.splice(0, 0, new ShowBranchesAndTagsQuickPickItem(log.repoPath, placeHolder, options.currentCommand)); + } + + if (options.showInResultsExplorerCommand !== undefined) { + index++; + items.splice(0, 0, options.showInResultsExplorerCommand); + } + + if (log.truncated || log.sha) { + if (options.showAllCommand !== undefined) { + index++; + items.splice(0, 0, options.showAllCommand); + } + else if (!options.pickerOnly) { + const [workingFileName] = await Container.git.findWorkingFileName(path.relative(log.repoPath, uri.fsPath), log.repoPath); + if (workingFileName) { + index++; + items.splice(0, 0, new CommandQuickPickItem({ + label: `$(history) Show File History`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} of ${path.basename(workingFileName)}` + }, Commands.ShowQuickFileHistory, [ + Uri.file(path.resolve(log.repoPath, workingFileName)), + { + goBackCommand: new CommandQuickPickItem({ + label: `go back ${GlyphChars.ArrowBack}`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to history of ${GlyphChars.Space}$(file-text) ${path.basename(uri.fsPath)}${uri.sha ? ` from ${GlyphChars.Space}$(git-commit) ${uri.shortSha}` : ''}` + }, Commands.ShowQuickFileHistory, [ + uri, + { + log: log, + maxCount: log.maxCount, + range: log.range, + goBackCommand: options.goBackCommand + } as ShowQuickFileHistoryCommandArgs + ]) + } as ShowQuickFileHistoryCommandArgs + ])); + } + } + + if (options.nextPageCommand !== undefined) { + index++; + items.splice(0, 0, options.nextPageCommand); + } + + if (options.previousPageCommand !== undefined) { + index++; + items.splice(0, 0, options.previousPageCommand); + } + } + + if (!options.pickerOnly) { + const branch = await Container.git.getBranch(uri.repoPath!); + + const currentCommand = new CommandQuickPickItem({ + label: `go back ${GlyphChars.ArrowBack}`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to history of ${GlyphChars.Space}$(file-text) ${path.basename(uri.fsPath)}${uri.sha ? ` from ${GlyphChars.Space}$(git-commit) ${uri.shortSha}` : ''}` + }, Commands.ShowQuickFileHistory, [ + uri, + { + log, + maxCount: log.maxCount, + range: log.range + } as ShowQuickFileHistoryCommandArgs + ]); + + // Only show the full repo option if we are the root + if (options.goBackCommand === undefined) { + items.splice(index++, 0, new CommandQuickPickItem({ + label: `$(history) Show Branch History`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows ${GlyphChars.Space}$(git-branch) ${branch!.name} history` + }, Commands.ShowQuickCurrentBranchHistory, + [ + undefined, + { + goBackCommand: currentCommand + } as ShowQuickCurrentBranchHistoryCommandArgs + ])); + } + + const remotes = (await Container.git.getRemotes(uri.repoPath!)).filter(r => r.provider !== undefined); + if (remotes.length) { + const resource = uri.sha !== undefined + ? { + type: 'revision', + branch: branch!.name, + fileName: uri.getRelativePath(), + sha: uri.sha + } as RemoteResource + : { + type: 'file', + branch: branch!.name, + fileName: uri.getRelativePath() + } as RemoteResource; + items.splice(index++, 0, new OpenRemotesCommandQuickPickItem(remotes, resource, currentCommand)); + } + + if (options.goBackCommand) { + items.splice(0, 0, options.goBackCommand); + } + } + + if (options.progressCancellation !== undefined && options.progressCancellation.token.isCancellationRequested) return undefined; + + const scope = await Container.keyboard.beginScope({ + left: options.goBackCommand, + ',': options.previousPageCommand, + '.': options.nextPageCommand + }); + + options.progressCancellation && options.progressCancellation.cancel(); + + const pick = await window.showQuickPick(items, { + matchOnDescription: true, + matchOnDetail: true, + placeHolder: placeHolder, + ignoreFocusOut: getQuickPickIgnoreFocusOut() + // onDidSelectItem: (item: QuickPickItem) => { + // scope.setKeyCommand('right', item); + // } + } as QuickPickOptions); + + await scope.dispose(); + + return pick; + } +} \ No newline at end of file diff --git a/src/quickPicks/quickPicks.ts b/src/quickPicks/quickPicks.ts new file mode 100644 index 0000000..db0e185 --- /dev/null +++ b/src/quickPicks/quickPicks.ts @@ -0,0 +1,14 @@ +'use strict'; + +export * from './branchesAndTagsQuickPick'; +export * from './branchesQuickPick'; +export * from './branchHistoryQuickPick'; +export * from './commitFileQuickPick'; +export * from './commitQuickPick'; +export * from './commitsQuickPick'; +export * from './commonQuickPicks'; +export * from './fileHistoryQuickPick'; +export * from './remotesQuickPick'; +export * from './repositoriesQuickPick'; +export * from './repoStatusQuickPick'; +export * from './stashListQuickPick'; diff --git a/src/quickPicks/remotes.ts b/src/quickPicks/remotes.ts deleted file mode 100644 index 5e7b229..0000000 --- a/src/quickPicks/remotes.ts +++ /dev/null @@ -1,139 +0,0 @@ -'use strict'; -import { Strings } from '../system'; -import { QuickPickOptions, window } from 'vscode'; -import { Commands, OpenInRemoteCommandArgs } from '../commands'; -import { CommandQuickPickItem, getQuickPickIgnoreFocusOut } from './common'; -import { GlyphChars } from '../constants'; -import { getNameFromRemoteResource, GitLogCommit, GitRemote, GitService, RemoteResource, RemoteResourceType } from '../gitService'; -import * as path from 'path'; - -export class OpenRemoteCommandQuickPickItem extends CommandQuickPickItem { - - private remote: GitRemote; - private resource: RemoteResource; - - constructor( - remote: GitRemote, - resource: RemoteResource - ) { - super({ - label: `$(link-external) Open ${getNameFromRemoteResource(resource)} in ${remote.provider!.name}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(repo) ${remote.provider!.path}` - }, undefined, undefined); - - this.remote = remote; - this.resource = resource; - } - - async execute(): Promise<{} | undefined> { - return this.remote.provider!.open(this.resource); - } -} - -export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem { - - constructor( - remotes: GitRemote[], - resource: RemoteResource, - goBackCommand?: CommandQuickPickItem - ) { - const name = getNameFromRemoteResource(resource); - - let description = ''; - switch (resource.type) { - case RemoteResourceType.Branch: - description = `$(git-branch) ${resource.branch}`; - break; - - case RemoteResourceType.Branches: - description = `$(git-branch) Branches`; - break; - - case RemoteResourceType.Commit: - const shortSha = GitService.shortenSha(resource.sha); - description = `$(git-commit) ${shortSha}`; - break; - - case RemoteResourceType.File: - description = `$(file-text) ${path.basename(resource.fileName)}`; - break; - - case RemoteResourceType.Repo: - description = `$(repo) Repository`; - break; - - case RemoteResourceType.Revision: - if (resource.commit !== undefined && resource.commit instanceof GitLogCommit) { - if (resource.commit.status === 'D') { - resource.sha = resource.commit.previousSha; - description = `$(file-text) ${path.basename(resource.fileName)} in ${GlyphChars.Space}$(git-commit) ${resource.commit.previousShortSha} (deleted in ${GlyphChars.Space}$(git-commit) ${resource.commit.shortSha})`; - } - else { - resource.sha = resource.commit.sha; - description = `$(file-text) ${path.basename(resource.fileName)} in ${GlyphChars.Space}$(git-commit) ${resource.commit.shortSha}`; - } - } - else { - const shortFileSha = resource.sha === undefined ? '' : GitService.shortenSha(resource.sha); - description = `$(file-text) ${path.basename(resource.fileName)}${shortFileSha ? ` in ${GlyphChars.Space}$(git-commit) ${shortFileSha}` : ''}`; - } - break; - } - - const remote = remotes[0]; - if (remotes.length === 1) { - super({ - label: `$(link-external) Open ${name} in ${remote.provider!.name}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(repo) ${remote.provider!.path} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${description}` - }, Commands.OpenInRemote, [ - undefined, - { - remotes, - resource, - goBackCommand - } as OpenInRemoteCommandArgs - ]); - - return; - } - - const provider = remotes.every(r => r.provider !== undefined && r.provider.name === remote.provider!.name) - ? remote.provider!.name - : 'Remote'; - - super({ - label: `$(link-external) Open ${name} in ${provider}${GlyphChars.Ellipsis}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${description}` - }, Commands.OpenInRemote, [ - undefined, - { - remotes, - resource, - goBackCommand - } as OpenInRemoteCommandArgs - ]); - } -} - -export class RemotesQuickPick { - - static async show(remotes: GitRemote[], placeHolder: string, resource: RemoteResource, goBackCommand?: CommandQuickPickItem): Promise { - const items = remotes.map(r => new OpenRemoteCommandQuickPickItem(r, resource)) as (OpenRemoteCommandQuickPickItem | CommandQuickPickItem)[]; - - if (goBackCommand) { - items.splice(0, 0, goBackCommand); - } - - // const scope = await Container.keyboard.beginScope({ left: goBackCommand }); - - const pick = await window.showQuickPick(items, { - placeHolder: placeHolder, - ignoreFocusOut: getQuickPickIgnoreFocusOut() - } as QuickPickOptions); - if (pick === undefined) return undefined; - - // await scope.dispose(); - - return pick; - } -} \ No newline at end of file diff --git a/src/quickPicks/remotesQuickPick.ts b/src/quickPicks/remotesQuickPick.ts new file mode 100644 index 0000000..752108a --- /dev/null +++ b/src/quickPicks/remotesQuickPick.ts @@ -0,0 +1,139 @@ +'use strict'; +import { Strings } from '../system'; +import { QuickPickOptions, window } from 'vscode'; +import { Commands, OpenInRemoteCommandArgs } from '../commands'; +import { CommandQuickPickItem, getQuickPickIgnoreFocusOut } from './commonQuickPicks'; +import { GlyphChars } from '../constants'; +import { getNameFromRemoteResource, GitLogCommit, GitRemote, GitService, RemoteResource, RemoteResourceType } from '../gitService'; +import * as path from 'path'; + +export class OpenRemoteCommandQuickPickItem extends CommandQuickPickItem { + + private remote: GitRemote; + private resource: RemoteResource; + + constructor( + remote: GitRemote, + resource: RemoteResource + ) { + super({ + label: `$(link-external) Open ${getNameFromRemoteResource(resource)} in ${remote.provider!.name}`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(repo) ${remote.provider!.path}` + }, undefined, undefined); + + this.remote = remote; + this.resource = resource; + } + + async execute(): Promise<{} | undefined> { + return this.remote.provider!.open(this.resource); + } +} + +export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem { + + constructor( + remotes: GitRemote[], + resource: RemoteResource, + goBackCommand?: CommandQuickPickItem + ) { + const name = getNameFromRemoteResource(resource); + + let description = ''; + switch (resource.type) { + case RemoteResourceType.Branch: + description = `$(git-branch) ${resource.branch}`; + break; + + case RemoteResourceType.Branches: + description = `$(git-branch) Branches`; + break; + + case RemoteResourceType.Commit: + const shortSha = GitService.shortenSha(resource.sha); + description = `$(git-commit) ${shortSha}`; + break; + + case RemoteResourceType.File: + description = `$(file-text) ${path.basename(resource.fileName)}`; + break; + + case RemoteResourceType.Repo: + description = `$(repo) Repository`; + break; + + case RemoteResourceType.Revision: + if (resource.commit !== undefined && resource.commit instanceof GitLogCommit) { + if (resource.commit.status === 'D') { + resource.sha = resource.commit.previousSha; + description = `$(file-text) ${path.basename(resource.fileName)} in ${GlyphChars.Space}$(git-commit) ${resource.commit.previousShortSha} (deleted in ${GlyphChars.Space}$(git-commit) ${resource.commit.shortSha})`; + } + else { + resource.sha = resource.commit.sha; + description = `$(file-text) ${path.basename(resource.fileName)} in ${GlyphChars.Space}$(git-commit) ${resource.commit.shortSha}`; + } + } + else { + const shortFileSha = resource.sha === undefined ? '' : GitService.shortenSha(resource.sha); + description = `$(file-text) ${path.basename(resource.fileName)}${shortFileSha ? ` in ${GlyphChars.Space}$(git-commit) ${shortFileSha}` : ''}`; + } + break; + } + + const remote = remotes[0]; + if (remotes.length === 1) { + super({ + label: `$(link-external) Open ${name} in ${remote.provider!.name}`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(repo) ${remote.provider!.path} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${description}` + }, Commands.OpenInRemote, [ + undefined, + { + remotes, + resource, + goBackCommand + } as OpenInRemoteCommandArgs + ]); + + return; + } + + const provider = remotes.every(r => r.provider !== undefined && r.provider.name === remote.provider!.name) + ? remote.provider!.name + : 'Remote'; + + super({ + label: `$(link-external) Open ${name} in ${provider}${GlyphChars.Ellipsis}`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${description}` + }, Commands.OpenInRemote, [ + undefined, + { + remotes, + resource, + goBackCommand + } as OpenInRemoteCommandArgs + ]); + } +} + +export class RemotesQuickPick { + + static async show(remotes: GitRemote[], placeHolder: string, resource: RemoteResource, goBackCommand?: CommandQuickPickItem): Promise { + const items = remotes.map(r => new OpenRemoteCommandQuickPickItem(r, resource)) as (OpenRemoteCommandQuickPickItem | CommandQuickPickItem)[]; + + if (goBackCommand) { + items.splice(0, 0, goBackCommand); + } + + // const scope = await Container.keyboard.beginScope({ left: goBackCommand }); + + const pick = await window.showQuickPick(items, { + placeHolder: placeHolder, + ignoreFocusOut: getQuickPickIgnoreFocusOut() + } as QuickPickOptions); + if (pick === undefined) return undefined; + + // await scope.dispose(); + + return pick; + } +} \ No newline at end of file diff --git a/src/quickPicks/repoStatus.ts b/src/quickPicks/repoStatus.ts deleted file mode 100644 index 112d168..0000000 --- a/src/quickPicks/repoStatus.ts +++ /dev/null @@ -1,327 +0,0 @@ -'use strict'; -import { Iterables, Strings } from '../system'; -import { commands, QuickPickOptions, TextDocumentShowOptions, window } from 'vscode'; -import { Commands, DiffWithPreviousCommandArgs, OpenChangedFilesCommandArgs, ShowQuickBranchHistoryCommandArgs, ShowQuickRepoStatusCommandArgs, ShowQuickStashListCommandArgs } from '../commands'; -import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, OpenFileCommandQuickPickItem, QuickPickItem } from './common'; -import { GlyphChars } from '../constants'; -import { Container } from '../container'; -import { GitCommitType, GitLogCommit, GitService, GitStatus, GitStatusFile, GitStatusFileStatus, GitUri } from '../gitService'; -import { Keys } from '../keyboard'; -import * as path from 'path'; - -export class OpenStatusFileCommandQuickPickItem extends OpenFileCommandQuickPickItem { - - public readonly status: GitStatusFile; - private readonly commit: GitLogCommit; - - constructor( - status: GitStatusFile, - realIndexStatus?: GitStatusFileStatus, - item?: QuickPickItem - ) { - const octicon = status.getOcticon(); - const description = status.getFormattedDirectory(true); - - super(status.uri, item || { - label: `${status.staged ? '$(check)' : GlyphChars.Space.repeat(3)}${Strings.pad(octicon, 2, 2)} ${path.basename(status.fileName)}`, - description: description - }); - - this.status = status; - if (status.indexStatus !== undefined) { - this.commit = new GitLogCommit(GitCommitType.File, status.repoPath, GitService.stagedUncommittedSha, 'You', undefined, new Date(), '', status.fileName, [status], status.status, status.originalFileName, 'HEAD', status.fileName); - } - else { - this.commit = new GitLogCommit(GitCommitType.File, status.repoPath, GitService.uncommittedSha, 'You', undefined, new Date(), '', status.fileName, [status], status.status, status.originalFileName, realIndexStatus !== undefined ? GitService.stagedUncommittedSha : 'HEAD', status.fileName); - } - } - - onDidPressKey(key: Keys): Promise<{} | undefined> { - return commands.executeCommand(Commands.DiffWithPrevious, - GitUri.fromFileStatus(this.status, this.status.repoPath), - { - commit: this.commit, - line: 0, - showOptions: { - preserveFocus: true, - preview: false - } as TextDocumentShowOptions - } as DiffWithPreviousCommandArgs) as Promise<{} | undefined>; - } -} - -export class OpenStatusFilesCommandQuickPickItem extends CommandQuickPickItem { - - constructor( - statuses: GitStatusFile[], - item?: QuickPickItem - ) { - const uris = statuses.map(f => f.uri); - - super(item || { - label: `$(file-symlink-file) Open Changed Files`, - description: '' - // detail: `Opens all of the changed files in the repository` - }, Commands.OpenChangedFiles, [ - undefined, - { - uris - } as OpenChangedFilesCommandArgs - ] - ); - } -} - -interface ComputedStatus { - staged: number; - stagedAddsAndChanges: GitStatusFile[]; - stagedStatus: string; - - unstaged: number; - unstagedAddsAndChanges: GitStatusFile[]; - unstagedStatus: string; -} - -export class RepoStatusQuickPick { - - private static computeStatus(files: GitStatusFile[]): ComputedStatus { - let stagedAdds = 0; - let unstagedAdds = 0; - let stagedChanges = 0; - let unstagedChanges = 0; - let stagedDeletes = 0; - let unstagedDeletes = 0; - - const stagedAddsAndChanges: GitStatusFile[] = []; - const unstagedAddsAndChanges: GitStatusFile[] = []; - - for (const f of files) { - switch (f.indexStatus) { - case 'A': - case '?': - stagedAdds++; - stagedAddsAndChanges.push(f); - break; - - case 'D': - stagedDeletes++; - break; - - case undefined: - break; - - default: - stagedChanges++; - stagedAddsAndChanges.push(f); - break; - } - - switch (f.workTreeStatus) { - case 'A': - case '?': - unstagedAdds++; - unstagedAddsAndChanges.push(f); - break; - - case 'D': - unstagedDeletes++; - break; - - case undefined: - break; - - default: - unstagedChanges++; - unstagedAddsAndChanges.push(f); - break; - } - } - - const staged = stagedAdds + stagedChanges + stagedDeletes; - const unstaged = unstagedAdds + unstagedChanges + unstagedDeletes; - - return { - staged: staged, - stagedStatus: staged > 0 ? `+${stagedAdds} ~${stagedChanges} -${stagedDeletes}` : '', - stagedAddsAndChanges: stagedAddsAndChanges, - unstaged: unstaged, - unstagedStatus: unstaged > 0 ? `+${unstagedAdds} ~${unstagedChanges} -${unstagedDeletes}` : '', - unstagedAddsAndChanges: unstagedAddsAndChanges - }; - } - - static async show(status: GitStatus, goBackCommand?: CommandQuickPickItem): Promise { - const items = [ - ...Iterables.flatMap(status.files, s => { - if (s.workTreeStatus !== undefined && s.indexStatus !== undefined) { - return [ - new OpenStatusFileCommandQuickPickItem(s.with({ indexStatus: null }), s.indexStatus), - new OpenStatusFileCommandQuickPickItem(s.with({ workTreeStatus: null })) - ]; - } - else { - return [new OpenStatusFileCommandQuickPickItem(s)]; - } - }) - ] as (OpenStatusFileCommandQuickPickItem | OpenStatusFilesCommandQuickPickItem | CommandQuickPickItem)[]; - - // Sort the status by staged and then filename - items.sort((a, b) => ((a as OpenStatusFileCommandQuickPickItem).status.staged ? -1 : 1) - ((b as OpenStatusFileCommandQuickPickItem).status.staged ? -1 : 1) || - (a as OpenStatusFileCommandQuickPickItem).status.fileName.localeCompare((b as OpenStatusFileCommandQuickPickItem).status.fileName)); - - const currentCommand = new CommandQuickPickItem({ - label: `go back ${GlyphChars.ArrowBack}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to ${GlyphChars.Space}$(git-branch) ${status.branch} status` - }, Commands.ShowQuickRepoStatus, [ - undefined, - { - goBackCommand - } as ShowQuickRepoStatusCommandArgs - ] - ); - - const computed = this.computeStatus(status.files); - if (computed.staged > 0) { - let index = 0; - const unstagedIndex = computed.unstaged > 0 ? status.files.findIndex(f => !f.staged) : -1; - if (unstagedIndex > -1) { - items.splice(unstagedIndex, 0, new CommandQuickPickItem({ - label: `Unstaged Files`, - description: computed.unstagedStatus - }, Commands.ShowQuickRepoStatus, [ - undefined, - { - goBackCommand - } as ShowQuickRepoStatusCommandArgs - ]) - ); - - items.splice(unstagedIndex, 0, new OpenStatusFilesCommandQuickPickItem(computed.stagedAddsAndChanges, { - label: `${GlyphChars.Space.repeat(4)} $(file-symlink-file) Open Staged Files`, - description: '' - })); - - items.push(new OpenStatusFilesCommandQuickPickItem(computed.unstagedAddsAndChanges, { - label: `${GlyphChars.Space.repeat(4)} $(file-symlink-file) Open Unstaged Files`, - description: '' - })); - } - - items.splice(index++, 0, new CommandQuickPickItem({ - label: `Staged Files`, - description: computed.stagedStatus - }, Commands.ShowQuickRepoStatus, [ - undefined, - { - goBackCommand - } as ShowQuickRepoStatusCommandArgs - ]) - ); - } - else if (status.files.some(f => !f.staged)) { - items.splice(0, 0, new CommandQuickPickItem({ - label: `Unstaged Files`, - description: computed.unstagedStatus - }, Commands.ShowQuickRepoStatus, [ - undefined, - { - goBackCommand - } as ShowQuickRepoStatusCommandArgs - ]) - ); - } - - if (status.files.length) { - items.push(new OpenStatusFilesCommandQuickPickItem(computed.stagedAddsAndChanges.concat(computed.unstagedAddsAndChanges))); - items.push(new CommandQuickPickItem({ - label: '$(x) Close Unchanged Files', - description: '' - }, Commands.CloseUnchangedFiles)); - } - else { - items.push(new CommandQuickPickItem({ - label: `No changes in the working tree`, - description: '' - }, Commands.ShowQuickRepoStatus, [ - undefined, - { - goBackCommand - } as ShowQuickRepoStatusCommandArgs - ]) - ); - } - - items.splice(0, 0, new CommandQuickPickItem({ - label: `$(inbox) Show Stashed Changes`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows stashed changes in the repository` - }, Commands.ShowQuickStashList, [ - GitUri.fromRepoPath(status.repoPath), - { - goBackCommand: currentCommand - } as ShowQuickStashListCommandArgs - ]) - ); - - if (status.upstream && status.state.ahead) { - items.splice(0, 0, new CommandQuickPickItem({ - label: `$(cloud-upload)${GlyphChars.Space} ${status.state.ahead} Commit${status.state.ahead > 1 ? 's' : ''} ahead of ${GlyphChars.Space}$(git-branch) ${status.upstream}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows commits in ${GlyphChars.Space}$(git-branch) ${status.branch} but not ${GlyphChars.Space}$(git-branch) ${status.upstream}` - }, Commands.ShowQuickBranchHistory, [ - GitUri.fromRepoPath(status.repoPath, `${status.upstream}..${status.branch}`), - { - branch: status.branch, - maxCount: 0, - goBackCommand: currentCommand - } as ShowQuickBranchHistoryCommandArgs - ]) - ); - } - - if (status.upstream && status.state.behind) { - items.splice(0, 0, new CommandQuickPickItem({ - label: `$(cloud-download)${GlyphChars.Space} ${status.state.behind} Commit${status.state.behind > 1 ? 's' : ''} behind ${GlyphChars.Space}$(git-branch) ${status.upstream}`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows commits in ${GlyphChars.Space}$(git-branch) ${status.upstream} but not ${GlyphChars.Space}$(git-branch) ${status.branch}${status.sha ? ` (since ${GlyphChars.Space}$(git-commit) ${GitService.shortenSha(status.sha)})` : ''}` - }, Commands.ShowQuickBranchHistory, [ - GitUri.fromRepoPath(status.repoPath, `${status.branch}..${status.upstream}`), - { - branch: status.upstream, - maxCount: 0, - goBackCommand: currentCommand - } as ShowQuickBranchHistoryCommandArgs - ]) - ); - } - - if (status.upstream && !status.state.ahead && !status.state.behind) { - items.splice(0, 0, new CommandQuickPickItem({ - label: `$(git-branch) ${status.branch} is up-to-date with ${GlyphChars.Space}$(git-branch) ${status.upstream}`, - description: '' - }, Commands.ShowQuickRepoStatus, [ - undefined, - { - goBackCommand - } as ShowQuickRepoStatusCommandArgs - ]) - ); - } - - if (goBackCommand) { - items.splice(0, 0, goBackCommand); - } - - const scope = await Container.keyboard.beginScope({ left: goBackCommand }); - - const pick = await window.showQuickPick(items, { - matchOnDescription: true, - placeHolder: `status of ${status.branch}${status.upstream ? ` ${Strings.pad(GlyphChars.ArrowLeftRight, 1, 1)} ${status.upstream}` : ''}`, - ignoreFocusOut: getQuickPickIgnoreFocusOut(), - onDidSelectItem: (item: QuickPickItem) => { - scope.setKeyCommand('right', item); - } - } as QuickPickOptions); - - await scope.dispose(); - - return pick; - } -} \ No newline at end of file diff --git a/src/quickPicks/repoStatusQuickPick.ts b/src/quickPicks/repoStatusQuickPick.ts new file mode 100644 index 0000000..06d4336 --- /dev/null +++ b/src/quickPicks/repoStatusQuickPick.ts @@ -0,0 +1,327 @@ +'use strict'; +import { Iterables, Strings } from '../system'; +import { commands, QuickPickOptions, TextDocumentShowOptions, window } from 'vscode'; +import { Commands, DiffWithPreviousCommandArgs, OpenChangedFilesCommandArgs, ShowQuickBranchHistoryCommandArgs, ShowQuickRepoStatusCommandArgs, ShowQuickStashListCommandArgs } from '../commands'; +import { CommandQuickPickItem, getQuickPickIgnoreFocusOut, OpenFileCommandQuickPickItem, QuickPickItem } from './commonQuickPicks'; +import { GlyphChars } from '../constants'; +import { Container } from '../container'; +import { GitCommitType, GitLogCommit, GitService, GitStatus, GitStatusFile, GitStatusFileStatus, GitUri } from '../gitService'; +import { Keys } from '../keyboard'; +import * as path from 'path'; + +export class OpenStatusFileCommandQuickPickItem extends OpenFileCommandQuickPickItem { + + public readonly status: GitStatusFile; + private readonly commit: GitLogCommit; + + constructor( + status: GitStatusFile, + realIndexStatus?: GitStatusFileStatus, + item?: QuickPickItem + ) { + const octicon = status.getOcticon(); + const description = status.getFormattedDirectory(true); + + super(status.uri, item || { + label: `${status.staged ? '$(check)' : GlyphChars.Space.repeat(3)}${Strings.pad(octicon, 2, 2)} ${path.basename(status.fileName)}`, + description: description + }); + + this.status = status; + if (status.indexStatus !== undefined) { + this.commit = new GitLogCommit(GitCommitType.File, status.repoPath, GitService.stagedUncommittedSha, 'You', undefined, new Date(), '', status.fileName, [status], status.status, status.originalFileName, 'HEAD', status.fileName); + } + else { + this.commit = new GitLogCommit(GitCommitType.File, status.repoPath, GitService.uncommittedSha, 'You', undefined, new Date(), '', status.fileName, [status], status.status, status.originalFileName, realIndexStatus !== undefined ? GitService.stagedUncommittedSha : 'HEAD', status.fileName); + } + } + + onDidPressKey(key: Keys): Promise<{} | undefined> { + return commands.executeCommand(Commands.DiffWithPrevious, + GitUri.fromFileStatus(this.status, this.status.repoPath), + { + commit: this.commit, + line: 0, + showOptions: { + preserveFocus: true, + preview: false + } as TextDocumentShowOptions + } as DiffWithPreviousCommandArgs) as Promise<{} | undefined>; + } +} + +export class OpenStatusFilesCommandQuickPickItem extends CommandQuickPickItem { + + constructor( + statuses: GitStatusFile[], + item?: QuickPickItem + ) { + const uris = statuses.map(f => f.uri); + + super(item || { + label: `$(file-symlink-file) Open Changed Files`, + description: '' + // detail: `Opens all of the changed files in the repository` + }, Commands.OpenChangedFiles, [ + undefined, + { + uris + } as OpenChangedFilesCommandArgs + ] + ); + } +} + +interface ComputedStatus { + staged: number; + stagedAddsAndChanges: GitStatusFile[]; + stagedStatus: string; + + unstaged: number; + unstagedAddsAndChanges: GitStatusFile[]; + unstagedStatus: string; +} + +export class RepoStatusQuickPick { + + private static computeStatus(files: GitStatusFile[]): ComputedStatus { + let stagedAdds = 0; + let unstagedAdds = 0; + let stagedChanges = 0; + let unstagedChanges = 0; + let stagedDeletes = 0; + let unstagedDeletes = 0; + + const stagedAddsAndChanges: GitStatusFile[] = []; + const unstagedAddsAndChanges: GitStatusFile[] = []; + + for (const f of files) { + switch (f.indexStatus) { + case 'A': + case '?': + stagedAdds++; + stagedAddsAndChanges.push(f); + break; + + case 'D': + stagedDeletes++; + break; + + case undefined: + break; + + default: + stagedChanges++; + stagedAddsAndChanges.push(f); + break; + } + + switch (f.workTreeStatus) { + case 'A': + case '?': + unstagedAdds++; + unstagedAddsAndChanges.push(f); + break; + + case 'D': + unstagedDeletes++; + break; + + case undefined: + break; + + default: + unstagedChanges++; + unstagedAddsAndChanges.push(f); + break; + } + } + + const staged = stagedAdds + stagedChanges + stagedDeletes; + const unstaged = unstagedAdds + unstagedChanges + unstagedDeletes; + + return { + staged: staged, + stagedStatus: staged > 0 ? `+${stagedAdds} ~${stagedChanges} -${stagedDeletes}` : '', + stagedAddsAndChanges: stagedAddsAndChanges, + unstaged: unstaged, + unstagedStatus: unstaged > 0 ? `+${unstagedAdds} ~${unstagedChanges} -${unstagedDeletes}` : '', + unstagedAddsAndChanges: unstagedAddsAndChanges + }; + } + + static async show(status: GitStatus, goBackCommand?: CommandQuickPickItem): Promise { + const items = [ + ...Iterables.flatMap(status.files, s => { + if (s.workTreeStatus !== undefined && s.indexStatus !== undefined) { + return [ + new OpenStatusFileCommandQuickPickItem(s.with({ indexStatus: null }), s.indexStatus), + new OpenStatusFileCommandQuickPickItem(s.with({ workTreeStatus: null })) + ]; + } + else { + return [new OpenStatusFileCommandQuickPickItem(s)]; + } + }) + ] as (OpenStatusFileCommandQuickPickItem | OpenStatusFilesCommandQuickPickItem | CommandQuickPickItem)[]; + + // Sort the status by staged and then filename + items.sort((a, b) => ((a as OpenStatusFileCommandQuickPickItem).status.staged ? -1 : 1) - ((b as OpenStatusFileCommandQuickPickItem).status.staged ? -1 : 1) || + (a as OpenStatusFileCommandQuickPickItem).status.fileName.localeCompare((b as OpenStatusFileCommandQuickPickItem).status.fileName)); + + const currentCommand = new CommandQuickPickItem({ + label: `go back ${GlyphChars.ArrowBack}`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} to ${GlyphChars.Space}$(git-branch) ${status.branch} status` + }, Commands.ShowQuickRepoStatus, [ + undefined, + { + goBackCommand + } as ShowQuickRepoStatusCommandArgs + ] + ); + + const computed = this.computeStatus(status.files); + if (computed.staged > 0) { + let index = 0; + const unstagedIndex = computed.unstaged > 0 ? status.files.findIndex(f => !f.staged) : -1; + if (unstagedIndex > -1) { + items.splice(unstagedIndex, 0, new CommandQuickPickItem({ + label: `Unstaged Files`, + description: computed.unstagedStatus + }, Commands.ShowQuickRepoStatus, [ + undefined, + { + goBackCommand + } as ShowQuickRepoStatusCommandArgs + ]) + ); + + items.splice(unstagedIndex, 0, new OpenStatusFilesCommandQuickPickItem(computed.stagedAddsAndChanges, { + label: `${GlyphChars.Space.repeat(4)} $(file-symlink-file) Open Staged Files`, + description: '' + })); + + items.push(new OpenStatusFilesCommandQuickPickItem(computed.unstagedAddsAndChanges, { + label: `${GlyphChars.Space.repeat(4)} $(file-symlink-file) Open Unstaged Files`, + description: '' + })); + } + + items.splice(index++, 0, new CommandQuickPickItem({ + label: `Staged Files`, + description: computed.stagedStatus + }, Commands.ShowQuickRepoStatus, [ + undefined, + { + goBackCommand + } as ShowQuickRepoStatusCommandArgs + ]) + ); + } + else if (status.files.some(f => !f.staged)) { + items.splice(0, 0, new CommandQuickPickItem({ + label: `Unstaged Files`, + description: computed.unstagedStatus + }, Commands.ShowQuickRepoStatus, [ + undefined, + { + goBackCommand + } as ShowQuickRepoStatusCommandArgs + ]) + ); + } + + if (status.files.length) { + items.push(new OpenStatusFilesCommandQuickPickItem(computed.stagedAddsAndChanges.concat(computed.unstagedAddsAndChanges))); + items.push(new CommandQuickPickItem({ + label: '$(x) Close Unchanged Files', + description: '' + }, Commands.CloseUnchangedFiles)); + } + else { + items.push(new CommandQuickPickItem({ + label: `No changes in the working tree`, + description: '' + }, Commands.ShowQuickRepoStatus, [ + undefined, + { + goBackCommand + } as ShowQuickRepoStatusCommandArgs + ]) + ); + } + + items.splice(0, 0, new CommandQuickPickItem({ + label: `$(inbox) Show Stashed Changes`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows stashed changes in the repository` + }, Commands.ShowQuickStashList, [ + GitUri.fromRepoPath(status.repoPath), + { + goBackCommand: currentCommand + } as ShowQuickStashListCommandArgs + ]) + ); + + if (status.upstream && status.state.ahead) { + items.splice(0, 0, new CommandQuickPickItem({ + label: `$(cloud-upload)${GlyphChars.Space} ${status.state.ahead} Commit${status.state.ahead > 1 ? 's' : ''} ahead of ${GlyphChars.Space}$(git-branch) ${status.upstream}`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows commits in ${GlyphChars.Space}$(git-branch) ${status.branch} but not ${GlyphChars.Space}$(git-branch) ${status.upstream}` + }, Commands.ShowQuickBranchHistory, [ + GitUri.fromRepoPath(status.repoPath, `${status.upstream}..${status.branch}`), + { + branch: status.branch, + maxCount: 0, + goBackCommand: currentCommand + } as ShowQuickBranchHistoryCommandArgs + ]) + ); + } + + if (status.upstream && status.state.behind) { + items.splice(0, 0, new CommandQuickPickItem({ + label: `$(cloud-download)${GlyphChars.Space} ${status.state.behind} Commit${status.state.behind > 1 ? 's' : ''} behind ${GlyphChars.Space}$(git-branch) ${status.upstream}`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} shows commits in ${GlyphChars.Space}$(git-branch) ${status.upstream} but not ${GlyphChars.Space}$(git-branch) ${status.branch}${status.sha ? ` (since ${GlyphChars.Space}$(git-commit) ${GitService.shortenSha(status.sha)})` : ''}` + }, Commands.ShowQuickBranchHistory, [ + GitUri.fromRepoPath(status.repoPath, `${status.branch}..${status.upstream}`), + { + branch: status.upstream, + maxCount: 0, + goBackCommand: currentCommand + } as ShowQuickBranchHistoryCommandArgs + ]) + ); + } + + if (status.upstream && !status.state.ahead && !status.state.behind) { + items.splice(0, 0, new CommandQuickPickItem({ + label: `$(git-branch) ${status.branch} is up-to-date with ${GlyphChars.Space}$(git-branch) ${status.upstream}`, + description: '' + }, Commands.ShowQuickRepoStatus, [ + undefined, + { + goBackCommand + } as ShowQuickRepoStatusCommandArgs + ]) + ); + } + + if (goBackCommand) { + items.splice(0, 0, goBackCommand); + } + + const scope = await Container.keyboard.beginScope({ left: goBackCommand }); + + const pick = await window.showQuickPick(items, { + matchOnDescription: true, + placeHolder: `status of ${status.branch}${status.upstream ? ` ${Strings.pad(GlyphChars.ArrowLeftRight, 1, 1)} ${status.upstream}` : ''}`, + ignoreFocusOut: getQuickPickIgnoreFocusOut(), + onDidSelectItem: (item: QuickPickItem) => { + scope.setKeyCommand('right', item); + } + } as QuickPickOptions); + + await scope.dispose(); + + return pick; + } +} \ No newline at end of file diff --git a/src/quickPicks/repositories.ts b/src/quickPicks/repositories.ts deleted file mode 100644 index e06eb6f..0000000 --- a/src/quickPicks/repositories.ts +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; -import { Iterables } from '../system'; -import { QuickPickItem, QuickPickOptions, window } from 'vscode'; -import { Container } from '../container'; -import { Repository } from '../gitService'; -import { CommandQuickPickItem, getQuickPickIgnoreFocusOut } from '../quickPicks'; - -export class RepositoryQuickPickItem implements QuickPickItem { - - label: string; - description: string; - detail: string | undefined; - - constructor( - public readonly repository: Repository - ) { - this.label = repository.name; - this.description = repository.path; - } - - get repoPath(): string { - return this.repository.path; - } -} - -export class RepositoriesQuickPick { - - static async show(placeHolder: string, goBackCommand?: CommandQuickPickItem): Promise { - const items = ([...Iterables.map(await Container.git.getRepositories(), r => new RepositoryQuickPickItem(r))]) as (RepositoryQuickPickItem | CommandQuickPickItem)[]; - - if (goBackCommand !== undefined) { - items.splice(0, 0, goBackCommand); - } - - // const scope = await Container.keyboard.beginScope({ left: goBackCommand }); - - const pick = await window.showQuickPick(items, { - placeHolder: placeHolder, - ignoreFocusOut: getQuickPickIgnoreFocusOut() - } as QuickPickOptions); - - // await scope.dispose(); - - return pick; - } -} \ No newline at end of file diff --git a/src/quickPicks/repositoriesQuickPick.ts b/src/quickPicks/repositoriesQuickPick.ts new file mode 100644 index 0000000..5f4fa72 --- /dev/null +++ b/src/quickPicks/repositoriesQuickPick.ts @@ -0,0 +1,46 @@ +'use strict'; +import { Iterables } from '../system'; +import { QuickPickItem, QuickPickOptions, window } from 'vscode'; +import { CommandQuickPickItem, getQuickPickIgnoreFocusOut } from './commonQuickPicks'; +import { Container } from '../container'; +import { Repository } from '../gitService'; + +export class RepositoryQuickPickItem implements QuickPickItem { + + label: string; + description: string; + detail: string | undefined; + + constructor( + public readonly repository: Repository + ) { + this.label = repository.name; + this.description = repository.path; + } + + get repoPath(): string { + return this.repository.path; + } +} + +export class RepositoriesQuickPick { + + static async show(placeHolder: string, goBackCommand?: CommandQuickPickItem): Promise { + const items = ([...Iterables.map(await Container.git.getRepositories(), r => new RepositoryQuickPickItem(r))]) as (RepositoryQuickPickItem | CommandQuickPickItem)[]; + + if (goBackCommand !== undefined) { + items.splice(0, 0, goBackCommand); + } + + // const scope = await Container.keyboard.beginScope({ left: goBackCommand }); + + const pick = await window.showQuickPick(items, { + placeHolder: placeHolder, + ignoreFocusOut: getQuickPickIgnoreFocusOut() + } as QuickPickOptions); + + // await scope.dispose(); + + return pick; + } +} \ No newline at end of file diff --git a/src/quickPicks/stashList.ts b/src/quickPicks/stashList.ts deleted file mode 100644 index 7c28a7b..0000000 --- a/src/quickPicks/stashList.ts +++ /dev/null @@ -1,64 +0,0 @@ -'use strict'; -import { Iterables, Strings } from '../system'; -import { CancellationTokenSource, QuickPickOptions, window } from 'vscode'; -import { Commands, StashSaveCommandArgs } from '../commands'; -import { GlyphChars } from '../constants'; -import { Container } from '../container'; -import { GitStash } from '../gitService'; -import { KeyNoopCommand } from '../keyboard'; -import { CommandQuickPickItem, CommitQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress } from '../quickPicks'; - -export class StashListQuickPick { - - static showProgress(mode: 'list' | 'apply') { - const message = mode === 'apply' - ? `Apply stashed changes to your working tree${GlyphChars.Ellipsis}` - : `stashed changes ${GlyphChars.Dash} search by message, filename, or commit id`; - return showQuickPickProgress(message, - { - left: KeyNoopCommand, - ',': KeyNoopCommand, - '.': KeyNoopCommand - }); - } - - static async show(stash: GitStash, mode: 'list' | 'apply', progressCancellation: CancellationTokenSource, goBackCommand?: CommandQuickPickItem, currentCommand?: CommandQuickPickItem): Promise { - const items = ((stash && Array.from(Iterables.map(stash.commits.values(), c => new CommitQuickPickItem(c)))) || []) as (CommitQuickPickItem | CommandQuickPickItem)[]; - - if (mode === 'list') { - items.splice(0, 0, new CommandQuickPickItem({ - label: `$(plus) Stash Changes`, - description: `${Strings.pad(GlyphChars.Dash, 2, 3)} stashes all changes` - }, Commands.StashSave, [ - { - goBackCommand: currentCommand - } as StashSaveCommandArgs - ])); - } - - if (goBackCommand) { - items.splice(0, 0, goBackCommand); - } - - if (progressCancellation.token.isCancellationRequested) return undefined; - - const scope = await Container.keyboard.beginScope({ left: goBackCommand }); - - progressCancellation.cancel(); - - const pick = await window.showQuickPick(items, { - matchOnDescription: true, - placeHolder: mode === 'apply' - ? `Apply stashed changes to your working tree${GlyphChars.Ellipsis}` - : `stashed changes ${GlyphChars.Dash} search by message, filename, or commit id`, - ignoreFocusOut: getQuickPickIgnoreFocusOut() - // onDidSelectItem: (item: QuickPickItem) => { - // scope.setKeyCommand('right', item); - // } - } as QuickPickOptions); - - await scope.dispose(); - - return pick; - } -} \ No newline at end of file diff --git a/src/quickPicks/stashListQuickPick.ts b/src/quickPicks/stashListQuickPick.ts new file mode 100644 index 0000000..846eb14 --- /dev/null +++ b/src/quickPicks/stashListQuickPick.ts @@ -0,0 +1,64 @@ +'use strict'; +import { Iterables, Strings } from '../system'; +import { CancellationTokenSource, QuickPickOptions, window } from 'vscode'; +import { Commands, StashSaveCommandArgs } from '../commands'; +import { GlyphChars } from '../constants'; +import { Container } from '../container'; +import { GitStash } from '../gitService'; +import { KeyNoopCommand } from '../keyboard'; +import { CommandQuickPickItem, CommitQuickPickItem, getQuickPickIgnoreFocusOut, showQuickPickProgress } from '../quickPicks/quickPicks'; + +export class StashListQuickPick { + + static showProgress(mode: 'list' | 'apply') { + const message = mode === 'apply' + ? `Apply stashed changes to your working tree${GlyphChars.Ellipsis}` + : `stashed changes ${GlyphChars.Dash} search by message, filename, or commit id`; + return showQuickPickProgress(message, + { + left: KeyNoopCommand, + ',': KeyNoopCommand, + '.': KeyNoopCommand + }); + } + + static async show(stash: GitStash, mode: 'list' | 'apply', progressCancellation: CancellationTokenSource, goBackCommand?: CommandQuickPickItem, currentCommand?: CommandQuickPickItem): Promise { + const items = ((stash && Array.from(Iterables.map(stash.commits.values(), c => new CommitQuickPickItem(c)))) || []) as (CommitQuickPickItem | CommandQuickPickItem)[]; + + if (mode === 'list') { + items.splice(0, 0, new CommandQuickPickItem({ + label: `$(plus) Stash Changes`, + description: `${Strings.pad(GlyphChars.Dash, 2, 3)} stashes all changes` + }, Commands.StashSave, [ + { + goBackCommand: currentCommand + } as StashSaveCommandArgs + ])); + } + + if (goBackCommand) { + items.splice(0, 0, goBackCommand); + } + + if (progressCancellation.token.isCancellationRequested) return undefined; + + const scope = await Container.keyboard.beginScope({ left: goBackCommand }); + + progressCancellation.cancel(); + + const pick = await window.showQuickPick(items, { + matchOnDescription: true, + placeHolder: mode === 'apply' + ? `Apply stashed changes to your working tree${GlyphChars.Ellipsis}` + : `stashed changes ${GlyphChars.Dash} search by message, filename, or commit id`, + ignoreFocusOut: getQuickPickIgnoreFocusOut() + // onDidSelectItem: (item: QuickPickItem) => { + // scope.setKeyCommand('right', item); + // } + } as QuickPickOptions); + + await scope.dispose(); + + return pick; + } +} \ No newline at end of file