소스 검색

Adds better formatting/truncation to qp titles

Adds title context to stash push git command
main
Eric Amodio 4 년 전
부모
커밋
9bbf88fc75
14개의 변경된 파일155개의 추가작업 그리고 69개의 파일을 삭제
  1. +4
    -2
      src/commands/diffWithRevision.ts
  2. +3
    -2
      src/commands/diffWithRevisionFrom.ts
  3. +12
    -14
      src/commands/git/log.ts
  4. +18
    -5
      src/commands/git/stash.ts
  5. +4
    -2
      src/commands/openFileAtRevision.ts
  6. +3
    -2
      src/commands/openFileAtRevisionFrom.ts
  7. +18
    -12
      src/commands/quickCommand.steps.ts
  8. +2
    -0
      src/constants.ts
  9. +4
    -1
      src/git/formatters/statusFormatter.ts
  10. +60
    -24
      src/git/gitUri.ts
  11. +1
    -3
      src/git/models/commit.ts
  12. +1
    -1
      src/git/models/file.ts
  13. +1
    -1
      src/git/models/status.ts
  14. +24
    -0
      src/system/string.ts

+ 4
- 2
src/commands/diffWithRevision.ts 파일 보기

@ -1,7 +1,7 @@
'use strict';
import { TextDocumentShowOptions, TextEditor, Uri } from 'vscode';
import { ActiveEditorCommand, command, Commands, executeCommand, getCommandUri } from './common';
import { GlyphChars } from '../constants';
import { GlyphChars, quickPickTitleMaxChars } from '../constants';
import { Container } from '../container';
import { DiffWithCommandArgs } from './diffWith';
import { GitRevision } from '../git/git';
@ -44,10 +44,12 @@ export class DiffWithRevisionCommand extends ActiveEditorCommand {
: undefined),
);
const title = `Open Changes with Revision${Strings.pad(GlyphChars.Dot, 2, 2)}`;
const pick = await CommitPicker.show(
log,
`Open Changes with Revision${Strings.pad(GlyphChars.Dot, 2, 2)}${gitUri.getFormattedPath({
`${title}${gitUri.getFormattedFilename({
suffix: gitUri.sha ? `:${GitRevision.shorten(gitUri.sha)}` : undefined,
truncateTo: quickPickTitleMaxChars - title.length,
})}`,
'Choose a commit to compare with',
{

+ 3
- 2
src/commands/diffWithRevisionFrom.ts 파일 보기

@ -2,7 +2,7 @@
import * as paths from 'path';
import { TextDocumentShowOptions, TextEditor, Uri } from 'vscode';
import { ActiveEditorCommand, command, Commands, executeCommand, getCommandUri } from './common';
import { GlyphChars } from '../constants';
import { GlyphChars, quickPickTitleMaxChars } from '../constants';
import { Container } from '../container';
import { DiffWithCommandArgs } from './diffWith';
import { GitReference, GitRevision } from '../git/git';
@ -38,9 +38,10 @@ export class DiffWithRevisionFromCommand extends ActiveEditorCommand {
args.line = editor?.selection.active.line ?? 0;
}
const title = `Open Changes with Branch or Tag${Strings.pad(GlyphChars.Dot, 2, 2)}`;
const pick = await ReferencePicker.show(
gitUri.repoPath,
`Open Changes with Branch or Tag${Strings.pad(GlyphChars.Dot, 2, 2)}${gitUri.getFormattedPath()}`,
`${title}${gitUri.getFormattedFilename({ truncateTo: quickPickTitleMaxChars - title.length })}`,
'Choose a branch or tag to compare with',
{
allowEnteringRefs: true,

+ 12
- 14
src/commands/git/log.ts 파일 보기

@ -12,7 +12,7 @@ import {
StepResult,
StepState,
} from '../quickCommand';
import { GlyphChars } from '../../constants';
import { GlyphChars, quickPickTitleMaxChars } from '../../constants';
import { GitUri } from '../../git/gitUri';
import { Strings } from '../../system';
@ -128,19 +128,17 @@ export class LogGitCommand extends QuickCommand {
context.selectedBranchOrTag = state.reference;
}
context.title = `${this.title}${Strings.pad(GlyphChars.Dot, 2, 2)}${GitReference.toString(
context.selectedBranchOrTag,
{
icon: false,
},
)}${
state.fileName
? `${Strings.pad(GlyphChars.Dot, 2, 2)}${GitUri.getFormattedPath(state.fileName, {
relativeTo: state.repo.path,
truncateTo: 35,
})}`
: ''
}`;
context.title = `${this.title}${Strings.pad(
GlyphChars.Dot,
2,
2,
)}${GitReference.toString(context.selectedBranchOrTag, { icon: false })}`;
if (state.fileName) {
context.title += `${Strings.pad(GlyphChars.Dot, 2, 2)}${GitUri.getFormattedFilename(state.fileName, {
truncateTo: quickPickTitleMaxChars - context.title.length - 3,
})}`;
}
if (state.counter < 3 && context.selectedBranchOrTag != null) {
const ref = context.selectedBranchOrTag.ref;

+ 18
- 5
src/commands/git/stash.ts 파일 보기

@ -1,5 +1,6 @@
'use strict';
import { QuickInputButtons, QuickPickItem, Uri, window } from 'vscode';
import { GlyphChars } from '../../constants';
import { Container } from '../../container';
import { GitReference, GitStashCommit, GitStashReference, Repository } from '../../git/git';
import { GitUri } from '../../git/gitUri';
@ -21,6 +22,7 @@ import {
import { FlagsQuickPickItem, QuickPickItemOfT } from '../../quickpicks';
import { Logger } from '../../logger';
import { Messages } from '../../messages';
import { Strings } from '../../system';
interface Context {
repos: Repository[];
@ -506,7 +508,18 @@ export class StashGitCommand extends QuickCommand {
private async *pushCommandInputMessageStep(state: PushStepState, context: Context): StepResultGenerator<string> {
const step = QuickCommand.createInputStep({
title: appendReposToTitle(context.title, state, context),
title: appendReposToTitle(
context.title,
state,
context,
state.uris != null
? `${Strings.pad(GlyphChars.Dot, 2, 2)}${
state.uris.length === 1
? GitUri.getFormattedFilename(state.uris[0])
: `${state.uris.length} files`
}`
: undefined,
),
placeholder: 'Please provide a stash message',
value: state.message,
prompt: 'Enter stash message',
@ -546,17 +559,17 @@ export class StashGitCommand extends QuickCommand {
: [
FlagsQuickPickItem.create<PushFlags>(state.flags, [], {
label: context.title,
detail: `Will stash changes in ${
detail: `Will stash changes from ${
state.uris.length === 1
? GitUri.getFormattedPath(state.uris[0], { relativeTo: state.repo.path })
? GitUri.getFormattedFilename(state.uris[0])
: `${state.uris.length} files`
}`,
}),
FlagsQuickPickItem.create<PushFlags>(state.flags, ['--keep-index'], {
label: `${context.title} & Keep Staged`,
detail: `Will stash changes in ${
detail: `Will stash changes from ${
state.uris.length === 1
? GitUri.getFormattedPath(state.uris[0], { relativeTo: state.repo.path })
? GitUri.getFormattedFilename(state.uris[0])
: `${state.uris.length} files`
}, but will keep staged files intact`,
}),

+ 4
- 2
src/commands/openFileAtRevision.ts 파일 보기

@ -2,7 +2,7 @@
import { TextDocumentShowOptions, TextEditor, Uri } from 'vscode';
import { ActiveEditorCommand, command, Commands, getCommandUri } from './common';
import { FileAnnotationType } from '../configuration';
import { GlyphChars } from '../constants';
import { GlyphChars, quickPickTitleMaxChars } from '../constants';
import { Container } from '../container';
import { GitRevision } from '../git/git';
import { GitUri } from '../git/gitUri';
@ -72,10 +72,12 @@ export class OpenFileAtRevisionCommand extends ActiveEditorCommand {
: undefined),
);
const title = `Open File at Revision${Strings.pad(GlyphChars.Dot, 2, 2)}`;
const pick = await CommitPicker.show(
log,
`Open File at Revision${Strings.pad(GlyphChars.Dot, 2, 2)}${gitUri.getFormattedPath({
`${title}${gitUri.getFormattedFilename({
suffix: gitUri.sha ? `:${GitRevision.shorten(gitUri.sha)}` : undefined,
truncateTo: quickPickTitleMaxChars - title.length,
})}`,
'Choose a commit to open the file revision from',
{

+ 3
- 2
src/commands/openFileAtRevisionFrom.ts 파일 보기

@ -2,7 +2,7 @@
import { TextDocumentShowOptions, TextEditor, Uri } from 'vscode';
import { ActiveEditorCommand, command, Commands, getCommandUri } from './common';
import { FileAnnotationType } from '../configuration';
import { GlyphChars } from '../constants';
import { GlyphChars, quickPickTitleMaxChars } from '../constants';
import { GitReference } from '../git/git';
import { GitUri } from '../git/gitUri';
import { GitActions } from './gitCommands';
@ -40,9 +40,10 @@ export class OpenFileAtRevisionFromCommand extends ActiveEditorCommand {
}
if (args.reference == null) {
const title = `Open File at Revision${Strings.pad(GlyphChars.Dot, 2, 2)}`;
const pick = await ReferencePicker.show(
gitUri.repoPath,
`Open File at Revision${Strings.pad(GlyphChars.Dot, 2, 2)}${gitUri.getFormattedPath()}`,
`${title}${gitUri.getFormattedFilename({ truncateTo: quickPickTitleMaxChars - title.length })}`,
'Choose a branch or tag to open the file revision from',
{
allowEnteringRefs: true,

+ 18
- 12
src/commands/quickCommand.steps.ts 파일 보기

@ -3,7 +3,7 @@ import { QuickInputButton, QuickPick } from 'vscode';
import { Commands } from './common';
import { configuration } from '../configuration';
import { Container } from '../container';
import { GlyphChars } from '../constants';
import { GlyphChars, quickPickTitleMaxChars } from '../constants';
import {
GitBranch,
GitBranchReference,
@ -78,17 +78,26 @@ export function appendReposToTitle<
State extends { repo: Repository } | { repos: Repository[] },
Context extends { repos: Repository[] }
>(title: string, state: State, context: Context, additionalContext?: string) {
if (context.repos.length === 1) return `${title}${additionalContext ?? ''}`;
if (context.repos.length === 1) {
return `${title}${Strings.truncate(additionalContext ?? '', quickPickTitleMaxChars - title.length)}`;
}
let repoContext;
if ((state as { repo: Repository }).repo != null) {
return `${title}${Strings.pad(GlyphChars.Dot, 2, 2)}${(state as { repo: Repository }).repo.formattedName}`;
repoContext = `${additionalContext ?? ''}${Strings.pad(GlyphChars.Dot, 2, 2)}${
(state as { repo: Repository }).repo.formattedName
}`;
} else if ((state as { repos: Repository[] }).repos.length === 1) {
repoContext = `${additionalContext ?? ''}${Strings.pad(GlyphChars.Dot, 2, 2)}${
(state as { repos: Repository[] }).repos[0].formattedName
}`;
} else {
repoContext = `${Strings.pad(GlyphChars.Dot, 2, 2)}${
(state as { repos: Repository[] }).repos.length
} repositories`;
}
return `${title}${Strings.pad(GlyphChars.Dot, 2, 2)}${
(state as { repos: Repository[] }).repos.length === 1
? `${(state as { repos: Repository[] }).repos[0].formattedName}${additionalContext ?? ''}`
: `${(state as { repos: Repository[] }).repos.length} repositories`
}`;
return `${title}${Strings.truncate(repoContext, quickPickTitleMaxChars - title.length)}`;
}
export async function getBranches(
@ -1521,10 +1530,7 @@ export async function* showCommitOrStashFileStep<
}),
state,
context,
`${Strings.pad(GlyphChars.Dot, 2, 2)}${GitUri.getFormattedPath(state.fileName, {
relativeTo: state.repo.path,
truncateTo: 35,
})}`,
`${Strings.pad(GlyphChars.Dot, 2, 2)}${GitUri.getFormattedFilename(state.fileName)}`,
),
placeholder: `${GitUri.getFormattedPath(state.fileName, {
relativeTo: state.repo.path,

+ 2
- 0
src/constants.ts 파일 보기

@ -8,6 +8,8 @@ export const extensionOutputChannelName = 'GitLens';
export const extensionQualifiedId = `eamodio.${extensionId}`;
export const extensionTerminalName = 'GitLens';
export const quickPickTitleMaxChars = 80;
export enum BuiltInCommands {
CloseActiveEditor = 'workbench.action.closeActiveEditor',
CloseAllEditors = 'workbench.action.closeAllEditors',

+ 4
- 1
src/git/formatters/statusFormatter.ts 파일 보기

@ -31,7 +31,10 @@ export class StatusFileFormatter extends Formatter
}
get filePath() {
const filePath = GitFile.getFormattedPath(this._item, { relativeTo: this._options.relativePath });
const filePath = GitFile.getFormattedPath(this._item, {
relativeTo: this._options.relativePath,
truncateTo: this._options.tokenOptions.filePath?.truncateTo,
});
return this._padOrTruncate(filePath, this._options.tokenOptions.filePath);
}

+ 60
- 24
src/git/gitUri.ts 파일 보기

@ -2,7 +2,7 @@
import * as paths from 'path';
import { Uri } from 'vscode';
import { UriComparer } from '../comparers';
import { DocumentSchemes, GlyphChars } from '../constants';
import { DocumentSchemes } from '../constants';
import { Container } from '../container';
import { GitCommit, GitFile, GitRevision } from '../git/git';
import { Logger } from '../logger';
@ -180,15 +180,12 @@ export class GitUri extends ((Uri as any) as UriEx) {
return this.sha === (GitUri.is(uri) ? uri.sha : undefined);
}
getFormattedPath(options: { relativeTo?: string; separator?: string; suffix?: string } = {}): string {
const {
relativeTo = this.repoPath,
separator = Strings.pad(GlyphChars.Dot, 1, 1),
suffix = emptyStr,
} = options;
getFormattedFilename(options: { suffix?: string; truncateTo?: number } = {}): string {
return GitUri.getFormattedFilename(this.fsPath, options);
}
const directory = GitUri.getDirectory(this.fsPath, relativeTo);
return `${paths.basename(this.fsPath)}${suffix}${directory ? `${separator}${directory}` : emptyStr}`;
getFormattedPath(options: { relativeTo?: string; suffix?: string; truncateTo?: number } = {}): string {
return GitUri.getFormattedPath(this.fsPath, { relativeTo: this.repoPath, ...options });
}
@memoize()
@ -330,39 +327,78 @@ export class GitUri extends ((Uri as any) as UriEx) {
return directory == null || directory.length === 0 || directory === '.' ? emptyStr : directory;
}
static getFormattedPath(
static getFormattedFilename(
fileNameOrUri: string | Uri,
options: { relativeTo?: string; separator?: string; suffix?: string; truncateTo?: number },
options: {
suffix?: string;
truncateTo?: number;
} = {},
): string {
const { relativeTo, separator = Strings.pad(GlyphChars.Dot, 1, 1), suffix = emptyStr, truncateTo } = options;
const { suffix = emptyStr, truncateTo } = options;
let fileName: string;
if (fileNameOrUri instanceof Uri) {
if (GitUri.is(fileNameOrUri)) return fileNameOrUri.getFormattedPath(options);
fileName = fileNameOrUri.fsPath;
} else {
fileName = fileNameOrUri;
}
const file = `${paths.basename(fileName)}${suffix}`;
if (truncateTo != null && file.length > truncateTo) {
let file = paths.basename(fileName);
if (truncateTo != null && file.length >= truncateTo) {
return Strings.truncateMiddle(file, truncateTo);
}
let directory = GitUri.getDirectory(fileName, relativeTo);
if (!directory) {
return file;
if (suffix) {
if (truncateTo != null && file.length + suffix.length >= truncateTo) {
return `${Strings.truncateMiddle(file, truncateTo - suffix.length)}${suffix}`;
}
file += suffix;
}
return file;
}
static getFormattedPath(
fileNameOrUri: string | Uri,
options: {
relativeTo?: string;
suffix?: string;
truncateTo?: number;
},
): string {
const { relativeTo, suffix = emptyStr, truncateTo } = options;
let fileName: string;
if (fileNameOrUri instanceof Uri) {
fileName = fileNameOrUri.fsPath;
} else {
fileName = fileNameOrUri;
}
let file = paths.basename(fileName);
if (truncateTo != null && file.length >= truncateTo) {
return Strings.truncateMiddle(file, truncateTo);
}
if (truncateTo != null) {
const dirTruncateTo = truncateTo - (file.length + separator.length);
if (directory.length > dirTruncateTo) {
directory = Strings.truncateMiddle(directory, dirTruncateTo);
if (suffix) {
if (truncateTo != null && file.length + suffix.length >= truncateTo) {
return `${Strings.truncateMiddle(file, truncateTo - suffix.length)}${suffix}`;
}
file += suffix;
}
const directory = GitUri.getDirectory(fileName, relativeTo);
if (!directory) return file;
file = `/${file}`;
if (truncateTo != null && file.length + directory.length >= truncateTo) {
return `${Strings.truncateLeft(directory, truncateTo - file.length)}${file}`;
}
return `${file}${separator}${directory}`;
return `${directory}${file}`;
}
static relativeTo(fileNameOrUri: string | Uri, relativeTo: string | undefined): string {

+ 1
- 3
src/git/models/commit.ts 파일 보기

@ -213,9 +213,7 @@ export abstract class GitCommit implements GitRevisionReference {
return this.dateFormatter.fromNow();
}
getFormattedPath(
options: { relativeTo?: string; separator?: string; suffix?: string; truncateTo?: number } = {},
): string {
getFormattedPath(options: { relativeTo?: string; suffix?: string; truncateTo?: number } = {}): string {
return GitUri.getFormattedPath(this.fileName, options);
}

+ 1
- 1
src/git/models/file.ts 파일 보기

@ -44,7 +44,7 @@ export namespace GitFile {
export function getFormattedPath(
file: GitFile,
options: { relativeTo?: string; separator?: string; suffix?: string; truncateTo?: number } = {},
options: { relativeTo?: string; suffix?: string; truncateTo?: number } = {},
): string {
return GitUri.getFormattedPath(file.fileName, options);
}

+ 1
- 1
src/git/models/status.ts 파일 보기

@ -241,7 +241,7 @@ export class GitStatusFile implements GitFile {
return GitFile.getFormattedDirectory(this, includeOriginal);
}
getFormattedPath(options: { relativeTo?: string; separator?: string; suffix?: string } = {}): string {
getFormattedPath(options: { relativeTo?: string; suffix?: string; truncateTo?: number } = {}): string {
return GitFile.getFormattedPath(this, options);
}

+ 24
- 0
src/system/string.ts 파일 보기

@ -250,6 +250,7 @@ export namespace Strings {
export function truncate(s: string, truncateTo: number, ellipsis: string = '\u2026', width?: number) {
if (!s) return s;
if (truncateTo <= 1) return ellipsis;
width = width ?? getWidth(s);
if (width <= truncateTo) return s;
@ -269,8 +270,31 @@ export namespace Strings {
return `${s.substring(0, chars)}${ellipsis}`;
}
export function truncateLeft(s: string, truncateTo: number, ellipsis: string = '\u2026', width?: number) {
if (!s) return s;
if (truncateTo <= 1) return ellipsis;
width = width ?? getWidth(s);
if (width <= truncateTo) return s;
if (width === s.length) return `${ellipsis}${s.substring(width - truncateTo)}`;
// Skip ahead to start as far as we can by assuming all the double-width characters won't be truncated
let chars = Math.floor(truncateTo / (width / s.length));
let count = getWidth(s.substring(0, chars));
while (count < truncateTo) {
count += getWidth(s[chars++]);
}
if (count >= truncateTo) {
chars--;
}
return `${ellipsis}${s.substring(s.length - chars)}`;
}
export function truncateMiddle(s: string, truncateTo: number, ellipsis: string = '\u2026') {
if (!s) return s;
if (truncateTo <= 1) return ellipsis;
const width = getWidth(s);
if (width <= truncateTo) return s;

불러오는 중...
취소
저장