Browse Source

Splits annotations and hovers

main
Eric Amodio 5 years ago
parent
commit
e88b960434
6 changed files with 205 additions and 203 deletions
  1. +3
    -187
      src/annotations/annotations.ts
  2. +5
    -8
      src/annotations/blameAnnotationProvider.ts
  3. +4
    -4
      src/annotations/recentChangesAnnotationProvider.ts
  4. +183
    -0
      src/hovers/hovers.ts
  5. +3
    -3
      src/hovers/lineHoverController.ts
  6. +7
    -1
      src/vsls/vsls.ts

+ 3
- 187
src/annotations/annotations.ts View File

@ -2,26 +2,14 @@
import {
DecorationInstanceRenderOptions,
DecorationOptions,
MarkdownString,
ThemableDecorationAttachmentRenderOptions,
ThemableDecorationRenderOptions,
ThemeColor
} from 'vscode';
import { DiffWithCommand, ShowQuickCommitDetailsCommand } from '../commands';
import { configuration, FileAnnotationType } from '../configuration';
import { configuration } from '../configuration';
import { GlyphChars } from '../constants';
import { Container } from '../container';
import {
CommitFormatOptions,
CommitFormatter,
GitBlameCommit,
GitCommit,
GitDiffHunkLine,
GitLogCommit,
GitService,
GitUri
} from '../git/gitService';
import { debug, Objects, Strings, timeout } from '../system';
import { CommitFormatOptions, CommitFormatter, GitCommit } from '../git/gitService';
import { Objects, Strings } from '../system';
import { toRgba } from '../webviews/apps/shared/colors';
export interface ComputedHeatmap {
@ -60,162 +48,6 @@ export class Annotations {
decoration.renderOptions!.before!.borderColor = color;
}
static async changesHoverMessage(
commit: GitBlameCommit,
uri: GitUri,
editorLine: number
): Promise<MarkdownString | undefined>;
static async changesHoverMessage(
commit: GitLogCommit,
uri: GitUri,
editorLine: number,
hunkLine: GitDiffHunkLine
): Promise<MarkdownString | undefined>;
static async changesHoverMessage(
commit: GitBlameCommit | GitLogCommit,
uri: GitUri,
editorLine: number,
hunkLine?: GitDiffHunkLine
): Promise<MarkdownString | undefined> {
const documentRef = uri.sha;
if (GitBlameCommit.is(commit)) {
// TODO: Figure out how to optimize this
let ref;
if (commit.isUncommitted) {
if (GitService.isUncommittedStaged(documentRef)) {
ref = documentRef;
}
} else {
ref = commit.sha;
}
const line = editorLine + 1;
const commitLine = commit.lines.find(l => l.line === line) || commit.lines[0];
let originalFileName = commit.originalFileName;
if (originalFileName === undefined) {
if (uri.fsPath !== commit.uri.fsPath) {
originalFileName = commit.fileName;
}
}
editorLine = commitLine.originalLine - 1;
hunkLine = await Container.git.getDiffForLine(uri, editorLine, ref, undefined, originalFileName);
// If we didn't find a diff & ref is undefined (meaning uncommitted), check for a staged diff
if (hunkLine === undefined && ref === undefined) {
hunkLine = await Container.git.getDiffForLine(
uri,
editorLine,
undefined,
GitService.uncommittedStagedSha,
originalFileName
);
}
}
if (hunkLine === undefined || commit.previousSha === undefined) return undefined;
const diff = this.getDiffFromHunkLine(hunkLine);
let message;
let previous;
let current;
if (commit.isUncommitted) {
const diffUris = await commit.getPreviousLineDiffUris(uri, editorLine, documentRef);
if (diffUris === undefined || diffUris.previous === undefined) {
return undefined;
}
message = `[\`Changes\`](${DiffWithCommand.getMarkdownCommandArgs({
lhs: {
sha: diffUris.previous.sha || '',
uri: diffUris.previous.documentUri()
},
rhs: {
sha: diffUris.current.sha || '',
uri: diffUris.current.documentUri()
},
repoPath: commit.repoPath,
line: editorLine
})} "Open Changes")`;
previous =
diffUris.previous.sha === undefined || diffUris.previous.isUncommitted
? `_${GitService.shortenSha(diffUris.previous.sha, {
strings: {
working: 'Working Tree'
}
})}_`
: `[\`${GitService.shortenSha(
diffUris.previous.sha || ''
)}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(
diffUris.previous.sha || ''
)} "Show Commit Details")`;
current =
diffUris.current.sha === undefined || diffUris.current.isUncommitted
? `_${GitService.shortenSha(diffUris.current.sha, {
strings: {
working: 'Working Tree'
}
})}_`
: `[\`${GitService.shortenSha(
diffUris.current.sha || ''
)}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(
diffUris.current.sha || ''
)} "Show Commit Details")`;
} else {
message = `[\`Changes\`](${DiffWithCommand.getMarkdownCommandArgs(commit, editorLine)} "Open Changes")`;
previous = `[\`${commit.previousShortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(
commit.previousSha
)} "Show Commit Details")`;
current = `[\`${commit.shortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(
commit.sha
)} "Show Commit Details")`;
}
message += ` &nbsp; ${GlyphChars.Dash} &nbsp; ${previous} &nbsp;${GlyphChars.ArrowLeftRightLong}&nbsp; ${current}\n${diff}`;
const markdown = new MarkdownString(message);
markdown.isTrusted = true;
return markdown;
}
static async detailsHoverMessage(
commit: GitCommit,
uri: GitUri,
editorLine: number,
dateFormat: string | null,
annotationType: FileAnnotationType | undefined
): Promise<MarkdownString> {
if (dateFormat === null) {
dateFormat = 'MMMM Do, YYYY h:mma';
}
const [presence, previousLineDiffUris, remotes] = await Promise.all([
Annotations.maybeGetPresence(commit.email).catch(reason => undefined),
commit.isUncommitted ? commit.getPreviousLineDiffUris(uri, editorLine, uri.sha) : undefined,
Container.git.getRemotes(commit.repoPath, { sort: true })
]);
const markdown = new MarkdownString(
CommitFormatter.fromTemplate(Container.config.hovers.detailsMarkdownFormat, commit, {
annotationType: annotationType,
dateFormat: dateFormat,
line: editorLine,
markdown: true,
presence: presence,
previousLineDiffUris: previousLineDiffUris,
remotes: remotes
})
);
markdown.isTrusted = true;
return markdown;
}
static gutter(
commit: GitCommit,
format: string,
@ -359,16 +191,6 @@ export class Annotations {
};
}
private static getDiffFromHunkLine(hunkLine: GitDiffHunkLine): string {
if (Container.config.hovers.changesDiff === 'hunk') {
return `\`\`\`diff\n${hunkLine.hunk.diff}\n\`\`\``;
}
return `\`\`\`diff${hunkLine.previous === undefined ? '' : `\n-${hunkLine.previous.line}`}${
hunkLine.current === undefined ? '' : `\n+${hunkLine.current.line}`
}\n\`\`\``;
}
private static getHeatmapColor(date: Date, heatmap: ComputedHeatmap) {
const baseColor = heatmap.cold ? heatmap.colors.cold : heatmap.colors.hot;
@ -390,10 +212,4 @@ export class Annotations {
return `rgba(${computedHeatmapColor.rgb}, ${(1 - age / 10).toFixed(2)})`;
}
@debug()
@timeout(250)
private static maybeGetPresence(email: string | undefined) {
return Container.vsls.getContactPresence(email);
}
}

+ 5
- 8
src/annotations/blameAnnotationProvider.ts View File

@ -10,12 +10,13 @@ import {
TextEditor,
TextEditorDecorationType
} from 'vscode';
import { AnnotationProviderBase } from './annotationProvider';
import { ComputedHeatmap } from './annotations';
import { Container } from '../container';
import { GitBlame, GitBlameCommit, GitCommit, GitUri } from '../git/gitService';
import { Hovers } from '../hovers/hovers';
import { Arrays, Iterables, log } from '../system';
import { GitDocumentState, TrackedDocument } from '../trackers/gitDocumentTracker';
import { AnnotationProviderBase } from './annotationProvider';
import { Annotations, ComputedHeatmap } from './annotations';
export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase {
protected _blame: Promise<GitBlame | undefined>;
@ -232,7 +233,7 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
const commitLine = commit.lines.find(l => l.line === line) || commit.lines[0];
editorLine = commitLine.originalLine - 1;
const message = await Annotations.detailsHoverMessage(
const message = await Hovers.detailsMessage(
logCommit || commit,
await GitUri.fromUri(document.uri),
editorLine,
@ -253,11 +254,7 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
const commit = await this.getCommitForHover(position);
if (commit === undefined) return undefined;
const message = await Annotations.changesHoverMessage(
commit,
await GitUri.fromUri(document.uri),
position.line
);
const message = await Hovers.changesMessage(commit, await GitUri.fromUri(document.uri), position.line);
if (message === undefined) return undefined;
return new Hover(

+ 4
- 4
src/annotations/recentChangesAnnotationProvider.ts View File

@ -8,14 +8,14 @@ import {
TextEditorDecorationType,
TextEditorRevealType
} from 'vscode';
import { AnnotationProviderBase } from './annotationProvider';
import { FileAnnotationType } from '../configuration';
import { Container } from '../container';
import { GitUri } from '../git/gitService';
import { Hovers } from '../hovers/hovers';
import { Logger } from '../logger';
import { log, Strings } from '../system';
import { GitDocumentState, TrackedDocument } from '../trackers/gitDocumentTracker';
import { AnnotationProviderBase } from './annotationProvider';
import { Annotations } from './annotations';
export class RecentChangesAnnotationProvider extends AnnotationProviderBase {
private readonly _uri: GitUri;
@ -90,7 +90,7 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase {
if (cfg.hovers.enabled && cfg.hovers.annotations.enabled) {
if (cfg.hovers.annotations.details) {
this.decorations.push({
hoverMessage: await Annotations.detailsHoverMessage(
hoverMessage: await Hovers.detailsMessage(
commit,
await GitUri.fromUri(this.editor.document.uri),
count,
@ -102,7 +102,7 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase {
}
if (cfg.hovers.annotations.changes) {
message = await Annotations.changesHoverMessage(commit, this._uri, count, hunkLine);
message = await Hovers.changesMessage(commit, this._uri, count, hunkLine);
if (message === undefined) continue;
}
}

+ 183
- 0
src/hovers/hovers.ts View File

@ -0,0 +1,183 @@
'use strict';
import { MarkdownString } from 'vscode';
import { DiffWithCommand, ShowQuickCommitDetailsCommand } from '../commands';
import { FileAnnotationType } from '../configuration';
import { GlyphChars } from '../constants';
import { Container } from '../container';
import {
CommitFormatter,
GitBlameCommit,
GitCommit,
GitDiffHunkLine,
GitLogCommit,
GitService,
GitUri
} from '../git/gitService';
export namespace Hovers {
export async function changesMessage(
commit: GitBlameCommit,
uri: GitUri,
editorLine: number
): Promise<MarkdownString | undefined>;
export async function changesMessage(
commit: GitLogCommit,
uri: GitUri,
editorLine: number,
hunkLine: GitDiffHunkLine
): Promise<MarkdownString | undefined>;
export async function changesMessage(
commit: GitBlameCommit | GitLogCommit,
uri: GitUri,
editorLine: number,
hunkLine?: GitDiffHunkLine
): Promise<MarkdownString | undefined> {
const documentRef = uri.sha;
if (GitBlameCommit.is(commit)) {
// TODO: Figure out how to optimize this
let ref;
if (commit.isUncommitted) {
if (GitService.isUncommittedStaged(documentRef)) {
ref = documentRef;
}
} else {
ref = commit.sha;
}
const line = editorLine + 1;
const commitLine = commit.lines.find(l => l.line === line) || commit.lines[0];
let originalFileName = commit.originalFileName;
if (originalFileName === undefined) {
if (uri.fsPath !== commit.uri.fsPath) {
originalFileName = commit.fileName;
}
}
editorLine = commitLine.originalLine - 1;
hunkLine = await Container.git.getDiffForLine(uri, editorLine, ref, undefined, originalFileName);
// If we didn't find a diff & ref is undefined (meaning uncommitted), check for a staged diff
if (hunkLine === undefined && ref === undefined) {
hunkLine = await Container.git.getDiffForLine(
uri,
editorLine,
undefined,
GitService.uncommittedStagedSha,
originalFileName
);
}
}
if (hunkLine === undefined || commit.previousSha === undefined) return undefined;
const diff = getDiffFromHunkLine(hunkLine);
let message;
let previous;
let current;
if (commit.isUncommitted) {
const diffUris = await commit.getPreviousLineDiffUris(uri, editorLine, documentRef);
if (diffUris === undefined || diffUris.previous === undefined) {
return undefined;
}
message = `[\`Changes\`](${DiffWithCommand.getMarkdownCommandArgs({
lhs: {
sha: diffUris.previous.sha || '',
uri: diffUris.previous.documentUri()
},
rhs: {
sha: diffUris.current.sha || '',
uri: diffUris.current.documentUri()
},
repoPath: commit.repoPath,
line: editorLine
})} "Open Changes")`;
previous =
diffUris.previous.sha === undefined || diffUris.previous.isUncommitted
? `_${GitService.shortenSha(diffUris.previous.sha, {
strings: {
working: 'Working Tree'
}
})}_`
: `[\`${GitService.shortenSha(
diffUris.previous.sha || ''
)}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(
diffUris.previous.sha || ''
)} "Show Commit Details")`;
current =
diffUris.current.sha === undefined || diffUris.current.isUncommitted
? `_${GitService.shortenSha(diffUris.current.sha, {
strings: {
working: 'Working Tree'
}
})}_`
: `[\`${GitService.shortenSha(
diffUris.current.sha || ''
)}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(
diffUris.current.sha || ''
)} "Show Commit Details")`;
} else {
message = `[\`Changes\`](${DiffWithCommand.getMarkdownCommandArgs(commit, editorLine)} "Open Changes")`;
previous = `[\`${commit.previousShortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(
commit.previousSha
)} "Show Commit Details")`;
current = `[\`${commit.shortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs(
commit.sha
)} "Show Commit Details")`;
}
message += ` &nbsp; ${GlyphChars.Dash} &nbsp; ${previous} &nbsp;${GlyphChars.ArrowLeftRightLong}&nbsp; ${current}\n${diff}`;
const markdown = new MarkdownString(message);
markdown.isTrusted = true;
return markdown;
}
export async function detailsMessage(
commit: GitCommit,
uri: GitUri,
editorLine: number,
dateFormat: string | null,
annotationType: FileAnnotationType | undefined
): Promise<MarkdownString> {
if (dateFormat === null) {
dateFormat = 'MMMM Do, YYYY h:mma';
}
const [presence, previousLineDiffUris, remotes] = await Promise.all([
Container.vsls.maybeGetPresence(commit.email).catch(reason => undefined),
commit.isUncommitted ? commit.getPreviousLineDiffUris(uri, editorLine, uri.sha) : undefined,
Container.git.getRemotes(commit.repoPath, { sort: true })
]);
const details = CommitFormatter.fromTemplate(Container.config.hovers.detailsMarkdownFormat, commit, {
annotationType: annotationType,
dateFormat: dateFormat,
line: editorLine,
markdown: true,
presence: presence,
previousLineDiffUris: previousLineDiffUris,
remotes: remotes
});
const markdown = new MarkdownString(details);
markdown.isTrusted = true;
return markdown;
}
function getDiffFromHunkLine(hunkLine: GitDiffHunkLine): string {
if (Container.config.hovers.changesDiff === 'hunk') {
return `\`\`\`diff\n${hunkLine.hunk.diff}\n\`\`\``;
}
return `\`\`\`diff${hunkLine.previous === undefined ? '' : `\n-${hunkLine.previous.line}`}${
hunkLine.current === undefined ? '' : `\n+${hunkLine.current.line}`
}\n\`\`\``;
}
}

+ 3
- 3
src/hovers/lineHoverController.ts View File

@ -12,9 +12,9 @@ import {
Uri,
window
} from 'vscode';
import { Annotations } from '../annotations/annotations';
import { configuration } from '../configuration';
import { Container } from '../container';
import { Hovers } from './hovers';
import { LinesChangeEvent } from '../trackers/gitLineTracker';
import { debug } from '../system';
import { UriComparer } from '../comparers';
@ -135,7 +135,7 @@ export class LineHoverController implements Disposable {
const trackedDocument = await Container.tracker.get(document);
if (trackedDocument === undefined) return undefined;
const message = await Annotations.detailsHoverMessage(
const message = await Hovers.detailsMessage(
logCommit || commit,
trackedDocument.uri,
editorLine,
@ -181,7 +181,7 @@ export class LineHoverController implements Disposable {
const trackedDocument = await Container.tracker.get(document);
if (trackedDocument === undefined) return undefined;
const message = await Annotations.changesHoverMessage(commit, trackedDocument.uri, position.line);
const message = await Hovers.changesMessage(commit, trackedDocument.uri, position.line);
if (message === undefined) return undefined;
return new Hover(message, range);

+ 7
- 1
src/vsls/vsls.ts View File

@ -6,7 +6,7 @@ import { Container } from '../container';
import { Logger } from '../logger';
import { VslsGuestService } from './guest';
import { VslsHostService } from './host';
import { debug } from '../system';
import { debug, timeout } from '../system';
export const vslsUriPrefixRegex = /^[/|\\]~(?:\d+?|external)(?:[/|\\]|$)/;
export const vslsUriRootRegex = /^[/|\\]~(?:\d+?|external)$/;
@ -150,6 +150,12 @@ export class VslsController implements Disposable {
);
}
@debug()
@timeout(250)
maybeGetPresence(email: string | undefined) {
return Container.vsls.getContactPresence(email);
}
async invite(email: string | undefined) {
if (email == null) return undefined;

Loading…
Cancel
Save