mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Merge pull request #67828 from hhu94/git-diff-links-simple
Add git diff terminal link handler
This commit is contained in:
@@ -63,6 +63,9 @@ export class TerminalLinkHandler {
|
||||
private _widgetManager: TerminalWidgetManager;
|
||||
private _processCwd: string;
|
||||
private _localLinkPattern: RegExp;
|
||||
private _gitDiffPreImagePattern: RegExp;
|
||||
private _gitDiffPostImagePattern: RegExp;
|
||||
private readonly _tooltipCallback: (event: MouseEvent, uri: string) => boolean | void;
|
||||
|
||||
constructor(
|
||||
private _xterm: any,
|
||||
@@ -75,8 +78,23 @@ export class TerminalLinkHandler {
|
||||
const baseLocalLinkClause = _platform === platform.Platform.Windows ? winLocalLinkClause : unixLocalLinkClause;
|
||||
// Append line and column number regex
|
||||
this._localLinkPattern = new RegExp(`${baseLocalLinkClause}(${lineAndColumnClause})`);
|
||||
// Matches '--- a/src/file1', capturing 'src/file1' in group 1
|
||||
this._gitDiffPreImagePattern = /^--- a\/(\S*)/;
|
||||
// Matches '+++ b/src/file1', capturing 'src/file1' in group 1
|
||||
this._gitDiffPostImagePattern = /^\+\+\+ b\/(\S*)/;
|
||||
|
||||
this._tooltipCallback = (e: MouseEvent) => {
|
||||
if (this._terminalService && this._terminalService.configHelper.config.rendererType === 'dom') {
|
||||
const target = (e.target as HTMLElement);
|
||||
this._widgetManager.showMessage(target.offsetLeft, target.offsetTop, this._getLinkHoverString());
|
||||
} else {
|
||||
this._widgetManager.showMessage(e.offsetX, e.offsetY, this._getLinkHoverString());
|
||||
}
|
||||
};
|
||||
|
||||
this.registerWebLinkHandler();
|
||||
this.registerLocalLinkHandler();
|
||||
this.registerGitDiffLinkHandlers();
|
||||
}
|
||||
|
||||
public setWidgetManager(widgetManager: TerminalWidgetManager): void {
|
||||
@@ -90,14 +108,7 @@ export class TerminalLinkHandler {
|
||||
public registerCustomLinkHandler(regex: RegExp, handler: (uri: string) => void, matchIndex?: number, validationCallback?: XtermLinkMatcherValidationCallback): number {
|
||||
const options: ILinkMatcherOptions = {
|
||||
matchIndex,
|
||||
tooltipCallback: (e: MouseEvent) => {
|
||||
if (this._terminalService && this._terminalService.configHelper.config.rendererType === 'dom') {
|
||||
const target = (e.target as HTMLElement);
|
||||
this._widgetManager.showMessage(target.offsetLeft, target.offsetTop, this._getLinkHoverString());
|
||||
} else {
|
||||
this._widgetManager.showMessage(e.offsetX, e.offsetY, this._getLinkHoverString());
|
||||
}
|
||||
},
|
||||
tooltipCallback: this._tooltipCallback,
|
||||
leaveCallback: () => this._widgetManager.closeMessage(),
|
||||
willLinkActivate: (e: MouseEvent) => this._isLinkActivationModifierDown(e),
|
||||
priority: CUSTOM_LINK_PRIORITY
|
||||
@@ -114,14 +125,7 @@ export class TerminalLinkHandler {
|
||||
});
|
||||
this._xterm.webLinksInit(wrappedHandler, {
|
||||
validationCallback: (uri: string, callback: (isValid: boolean) => void) => this._validateWebLink(uri, callback),
|
||||
tooltipCallback: (e: MouseEvent) => {
|
||||
if (this._terminalService && this._terminalService.configHelper.config.rendererType === 'dom') {
|
||||
const target = (e.target as HTMLElement);
|
||||
this._widgetManager.showMessage(target.offsetLeft, target.offsetTop, this._getLinkHoverString());
|
||||
} else {
|
||||
this._widgetManager.showMessage(e.offsetX, e.offsetY, this._getLinkHoverString());
|
||||
}
|
||||
},
|
||||
tooltipCallback: this._tooltipCallback,
|
||||
leaveCallback: () => this._widgetManager.closeMessage(),
|
||||
willLinkActivate: (e: MouseEvent) => this._isLinkActivationModifierDown(e)
|
||||
});
|
||||
@@ -133,20 +137,29 @@ export class TerminalLinkHandler {
|
||||
});
|
||||
this._xterm.registerLinkMatcher(this._localLinkRegex, wrappedHandler, {
|
||||
validationCallback: (uri: string, callback: (isValid: boolean) => void) => this._validateLocalLink(uri, callback),
|
||||
tooltipCallback: (e: MouseEvent) => {
|
||||
if (this._terminalService && this._terminalService.configHelper.config.rendererType === 'dom') {
|
||||
const target = (e.target as HTMLElement);
|
||||
this._widgetManager.showMessage(target.offsetLeft, target.offsetTop, this._getLinkHoverString());
|
||||
} else {
|
||||
this._widgetManager.showMessage(e.offsetX, e.offsetY, this._getLinkHoverString());
|
||||
}
|
||||
},
|
||||
tooltipCallback: this._tooltipCallback,
|
||||
leaveCallback: () => this._widgetManager.closeMessage(),
|
||||
willLinkActivate: (e: MouseEvent) => this._isLinkActivationModifierDown(e),
|
||||
priority: LOCAL_LINK_PRIORITY
|
||||
});
|
||||
}
|
||||
|
||||
public registerGitDiffLinkHandlers(): void {
|
||||
const wrappedHandler = this._wrapLinkHandler(url => {
|
||||
this._handleLocalLink(url);
|
||||
});
|
||||
const options = {
|
||||
matchIndex: 1,
|
||||
validationCallback: (uri: string, callback: (isValid: boolean) => void) => this._validateLocalLink(uri, callback),
|
||||
tooltipCallback: this._tooltipCallback,
|
||||
leaveCallback: () => this._widgetManager.closeMessage(),
|
||||
willLinkActivate: (e: MouseEvent) => this._isLinkActivationModifierDown(e),
|
||||
priority: LOCAL_LINK_PRIORITY
|
||||
};
|
||||
this._xterm.registerLinkMatcher(this._gitDiffPreImagePattern, wrappedHandler, options);
|
||||
this._xterm.registerLinkMatcher(this._gitDiffPostImagePattern, wrappedHandler, options);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._xterm = null;
|
||||
this._hoverDisposables = dispose(this._hoverDisposables);
|
||||
@@ -172,6 +185,14 @@ export class TerminalLinkHandler {
|
||||
return this._localLinkPattern;
|
||||
}
|
||||
|
||||
protected get _gitDiffPreImageRegex(): RegExp {
|
||||
return this._gitDiffPreImagePattern;
|
||||
}
|
||||
|
||||
protected get _gitDiffPostImageRegex(): RegExp {
|
||||
return this._gitDiffPostImagePattern;
|
||||
}
|
||||
|
||||
private _handleLocalLink(link: string): PromiseLike<any> {
|
||||
return this._resolvePath(link).then(resolvedLink => {
|
||||
if (!resolvedLink) {
|
||||
|
||||
@@ -14,6 +14,12 @@ class TestTerminalLinkHandler extends TerminalLinkHandler {
|
||||
public get localLinkRegex(): RegExp {
|
||||
return this._localLinkRegex;
|
||||
}
|
||||
public get gitDiffLinkPreImageRegex(): RegExp {
|
||||
return this._gitDiffPreImageRegex;
|
||||
}
|
||||
public get gitDiffLinkPostImageRegex(): RegExp {
|
||||
return this._gitDiffPostImageRegex;
|
||||
}
|
||||
public preprocessPath(link: string): string | null {
|
||||
return this._preprocessPath(link);
|
||||
}
|
||||
@@ -217,4 +223,30 @@ suite('Workbench - TerminalLinkHandler', () => {
|
||||
assert.equal(linkHandler.preprocessPath('/absolute/path/file3'), '/absolute/path/file3');
|
||||
});
|
||||
});
|
||||
|
||||
test('gitDiffLinkRegex', () => {
|
||||
// The platform is irrelevant because the links generated by Git are the same format regardless of platform
|
||||
const linkHandler = new TestTerminalLinkHandler(new TestXterm(), Platform.Linux, null!, null!, null!, null!);
|
||||
|
||||
function assertAreGoodMatches(matches: RegExpMatchArray | null) {
|
||||
if (matches) {
|
||||
assert.equal(matches.length, 2);
|
||||
assert.equal(matches[1], 'src/file1');
|
||||
} else {
|
||||
assert.fail();
|
||||
}
|
||||
}
|
||||
|
||||
// Happy cases
|
||||
assertAreGoodMatches('--- a/src/file1'.match(linkHandler.gitDiffLinkPreImageRegex));
|
||||
assertAreGoodMatches('--- a/src/file1 '.match(linkHandler.gitDiffLinkPreImageRegex));
|
||||
assertAreGoodMatches('+++ b/src/file1'.match(linkHandler.gitDiffLinkPostImageRegex));
|
||||
assertAreGoodMatches('+++ b/src/file1 '.match(linkHandler.gitDiffLinkPostImageRegex));
|
||||
|
||||
// Make sure /dev/null isn't a match
|
||||
assert.equal(linkHandler.gitDiffLinkPreImageRegex.test('--- /dev/null'), false);
|
||||
assert.equal(linkHandler.gitDiffLinkPreImageRegex.test('--- /dev/null '), false);
|
||||
assert.equal(linkHandler.gitDiffLinkPostImageRegex.test('+++ /dev/null'), false);
|
||||
assert.equal(linkHandler.gitDiffLinkPostImageRegex.test('+++ /dev/null '), false);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user