mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-30 16:50:30 -04:00
Merge from vscode 79a1f5a5ca0c6c53db617aa1fa5a2396d2caebe2
This commit is contained in:
@@ -93,10 +93,12 @@ export function convertBufferRangeToViewport(bufferRange: IBufferRange, viewport
|
||||
};
|
||||
}
|
||||
|
||||
export function getXtermLineContent(buffer: IBuffer, lineStart: number, lineEnd: number): string {
|
||||
export function getXtermLineContent(buffer: IBuffer, lineStart: number, lineEnd: number, cols: number): string {
|
||||
let line = '';
|
||||
for (let i = lineStart; i <= lineEnd; i++) {
|
||||
line += buffer.getLine(i)?.translateToString(true);
|
||||
// Make sure only 0 to cols are considered as resizing when windows mode is enabled will
|
||||
// retain buffer data outside of the terminal width as reflow is disabled.
|
||||
line += buffer.getLine(i)!.translateToString(true, 0, cols);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
@@ -5,69 +5,30 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { DisposableStore, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ITerminalProcessManager, ITerminalConfigHelper, ITerminalConfiguration, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ITerminalProcessManager, ITerminalConfiguration, TERMINAL_CONFIG_SECTION } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ITextEditorSelection } from 'vs/platform/editor/common/editor';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { Terminal, ILinkMatcherOptions, IViewportRange, ITerminalAddon } from 'xterm';
|
||||
import { Terminal, IViewportRange } from 'xterm';
|
||||
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { posix, win32 } from 'vs/base/common/path';
|
||||
import { ITerminalInstanceService, ITerminalBeforeHandleLinkEvent, LINK_INTERCEPT_THRESHOLD } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ITerminalBeforeHandleLinkEvent, LINK_INTERCEPT_THRESHOLD } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { OperatingSystem, isMacintosh, OS } from 'vs/base/common/platform';
|
||||
import { IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { TerminalProtocolLinkProvider } from 'vs/workbench/contrib/terminal/browser/links/terminalProtocolLinkProvider';
|
||||
import { TerminalValidatedLocalLinkProvider } from 'vs/workbench/contrib/terminal/browser/links/terminalValidatedLocalLinkProvider';
|
||||
import { TerminalValidatedLocalLinkProvider, lineAndColumnClause, unixLocalLinkClause, winLocalLinkClause, winDrivePrefix, winLineAndColumnMatchIndex, unixLineAndColumnMatchIndex, lineAndColumnClauseGroupCount } from 'vs/workbench/contrib/terminal/browser/links/terminalValidatedLocalLinkProvider';
|
||||
import { TerminalWordLinkProvider } from 'vs/workbench/contrib/terminal/browser/links/terminalWordLinkProvider';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { XTermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private';
|
||||
import { TerminalHover, ILinkHoverTargetOptions } from 'vs/workbench/contrib/terminal/browser/widgets/terminalHoverWidget';
|
||||
import { TerminalLink } from 'vs/workbench/contrib/terminal/browser/links/terminalLink';
|
||||
|
||||
const pathPrefix = '(\\.\\.?|\\~)';
|
||||
const pathSeparatorClause = '\\/';
|
||||
// '":; are allowed in paths but they are often separators so ignore them
|
||||
// Also disallow \\ to prevent a catastropic backtracking case #24798
|
||||
const excludedPathCharactersClause = '[^\\0\\s!$`&*()\\[\\]+\'":;\\\\]';
|
||||
/** A regex that matches paths in the form /foo, ~/foo, ./foo, ../foo, foo/bar */
|
||||
const unixLocalLinkClause = '((' + pathPrefix + '|(' + excludedPathCharactersClause + ')+)?(' + pathSeparatorClause + '(' + excludedPathCharactersClause + ')+)+)';
|
||||
|
||||
// Valid absolute formats: C:, \\?\C: and \\?\%VAR%
|
||||
const winDrivePrefix = '(?:\\\\\\\\\\?\\\\)?[a-zA-Z]:';
|
||||
const winPathPrefix = '(' + winDrivePrefix + '|\\.\\.?|\\~)';
|
||||
const winPathSeparatorClause = '(\\\\|\\/)';
|
||||
const winExcludedPathCharactersClause = '[^\\0<>\\?\\|\\/\\s!$`&*()\\[\\]+\'":;]';
|
||||
/** A regex that matches paths in the form \\?\c:\foo c:\foo, ~\foo, .\foo, ..\foo, foo\bar */
|
||||
const winLocalLinkClause = '((' + winPathPrefix + '|(' + winExcludedPathCharactersClause + ')+)?(' + winPathSeparatorClause + '(' + winExcludedPathCharactersClause + ')+)+)';
|
||||
|
||||
/** As xterm reads from DOM, space in that case is nonbreaking char ASCII code - 160,
|
||||
replacing space with nonBreakningSpace or space ASCII code - 32. */
|
||||
const lineAndColumnClause = [
|
||||
'((\\S*)", line ((\\d+)( column (\\d+))?))', // "(file path)", line 45 [see #40468]
|
||||
'((\\S*)",((\\d+)(:(\\d+))?))', // "(file path)",45 [see #78205]
|
||||
'((\\S*) on line ((\\d+)(, column (\\d+))?))', // (file path) on line 8, column 13
|
||||
'((\\S*):line ((\\d+)(, column (\\d+))?))', // (file path):line 8, column 13
|
||||
'(([^\\s\\(\\)]*)(\\s?[\\(\\[](\\d+)(,\\s?(\\d+))?)[\\)\\]])', // (file path)(45), (file path) (45), (file path)(45,18), (file path) (45,18), (file path)(45, 18), (file path) (45, 18), also with []
|
||||
'(([^:\\s\\(\\)<>\'\"\\[\\]]*)(:(\\d+))?(:(\\d+))?)' // (file path):336, (file path):336:9
|
||||
].join('|').replace(/ /g, `[${'\u00A0'} ]`);
|
||||
|
||||
// Changing any regex may effect this value, hence changes this as well if required.
|
||||
const winLineAndColumnMatchIndex = 12;
|
||||
const unixLineAndColumnMatchIndex = 11;
|
||||
|
||||
// Each line and column clause have 6 groups (ie no. of expressions in round brackets)
|
||||
const lineAndColumnClauseGroupCount = 6;
|
||||
|
||||
/** Higher than local link, lower than hypertext */
|
||||
const CUSTOM_LINK_PRIORITY = -1;
|
||||
/** Lowest */
|
||||
const LOCAL_LINK_PRIORITY = -2;
|
||||
|
||||
export type XtermLinkMatcherHandler = (event: MouseEvent | undefined, link: string) => Promise<void>;
|
||||
export type XtermLinkMatcherValidationCallback = (uri: string, callback: (isValid: boolean) => void) => void;
|
||||
|
||||
@@ -82,10 +43,6 @@ interface IPath {
|
||||
export class TerminalLinkManager extends DisposableStore {
|
||||
private _widgetManager: TerminalWidgetManager | undefined;
|
||||
private _processCwd: string | undefined;
|
||||
private _gitDiffPreImagePattern: RegExp;
|
||||
private _gitDiffPostImagePattern: RegExp;
|
||||
private _linkMatchers: number[] = [];
|
||||
private _webLinksAddon: ITerminalAddon | undefined;
|
||||
private _linkProviders: IDisposable[] = [];
|
||||
private _hasBeforeHandleLinkListeners = false;
|
||||
|
||||
@@ -106,62 +63,16 @@ export class TerminalLinkManager extends DisposableStore {
|
||||
constructor(
|
||||
private _xterm: Terminal,
|
||||
private readonly _processManager: ITerminalProcessManager,
|
||||
private readonly _configHelper: ITerminalConfigHelper,
|
||||
@IOpenerService private readonly _openerService: IOpenerService,
|
||||
@IEditorService private readonly _editorService: IEditorService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService,
|
||||
@IFileService private readonly _fileService: IFileService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService
|
||||
) {
|
||||
super();
|
||||
|
||||
// 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*)/;
|
||||
|
||||
if (this._configHelper.config.experimentalLinkProvider) {
|
||||
this.registerLinkProvider();
|
||||
} else {
|
||||
this._registerLinkMatchers();
|
||||
}
|
||||
|
||||
this._configurationService?.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('terminal.integrated.experimentalLinkProvider')) {
|
||||
if (this._configHelper.config.experimentalLinkProvider) {
|
||||
this._deregisterLinkMatchers();
|
||||
this.registerLinkProvider();
|
||||
} else {
|
||||
dispose(this._linkProviders);
|
||||
this._linkProviders.length = 0;
|
||||
this._registerLinkMatchers();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _tooltipCallback(linkText: string, viewportRange: IViewportRange, linkHandler: (url: string) => void) {
|
||||
if (!this._widgetManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
const core = (this._xterm as any)._core as XTermCore;
|
||||
const cellDimensions = {
|
||||
width: core._renderService.dimensions.actualCellWidth,
|
||||
height: core._renderService.dimensions.actualCellHeight
|
||||
};
|
||||
const terminalDimensions = {
|
||||
width: this._xterm.cols,
|
||||
height: this._xterm.rows
|
||||
};
|
||||
|
||||
this._showHover({
|
||||
viewportRange,
|
||||
cellDimensions,
|
||||
terminalDimensions
|
||||
}, this._getLinkHoverString(linkText, undefined), linkHandler);
|
||||
this.registerLinkProvider();
|
||||
}
|
||||
|
||||
private _tooltipCallback2(link: TerminalLink, viewportRange: IViewportRange, modifierDownCallback?: () => void, modifierUpCallback?: () => void) {
|
||||
@@ -204,24 +115,6 @@ export class TerminalLinkManager extends DisposableStore {
|
||||
}
|
||||
}
|
||||
|
||||
private _registerLinkMatchers() {
|
||||
this.registerWebLinkHandler();
|
||||
if (this._processManager) {
|
||||
if (this._configHelper.config.enableFileLinks) {
|
||||
this.registerLocalLinkHandler();
|
||||
}
|
||||
this.registerGitDiffLinkHandlers();
|
||||
}
|
||||
}
|
||||
|
||||
private _deregisterLinkMatchers() {
|
||||
this._webLinksAddon?.dispose();
|
||||
|
||||
this._linkMatchers.forEach(matcherId => {
|
||||
this._xterm.deregisterLinkMatcher(matcherId);
|
||||
});
|
||||
}
|
||||
|
||||
public setWidgetManager(widgetManager: TerminalWidgetManager): void {
|
||||
this._widgetManager = widgetManager;
|
||||
}
|
||||
@@ -230,71 +123,6 @@ export class TerminalLinkManager extends DisposableStore {
|
||||
this._processCwd = processCwd;
|
||||
}
|
||||
|
||||
public registerCustomLinkHandler(regex: RegExp, handler: (event: MouseEvent | undefined, uri: string) => void, matchIndex?: number, validationCallback?: XtermLinkMatcherValidationCallback): number {
|
||||
const tooltipCallback = (_: MouseEvent, linkText: string, location: IViewportRange) => {
|
||||
this._tooltipCallback(linkText, location, text => handler(undefined, text));
|
||||
};
|
||||
const options: ILinkMatcherOptions = {
|
||||
matchIndex,
|
||||
tooltipCallback,
|
||||
willLinkActivate: (e: MouseEvent) => this._isLinkActivationModifierDown(e),
|
||||
priority: CUSTOM_LINK_PRIORITY
|
||||
};
|
||||
if (validationCallback) {
|
||||
options.validationCallback = (uri: string, callback: (isValid: boolean) => void) => validationCallback(uri, callback);
|
||||
}
|
||||
return this._xterm.registerLinkMatcher(regex, this._wrapLinkHandler(handler), options);
|
||||
}
|
||||
|
||||
public registerWebLinkHandler(): void {
|
||||
this._terminalInstanceService.getXtermWebLinksConstructor().then((WebLinksAddon) => {
|
||||
if (!this._xterm) {
|
||||
return;
|
||||
}
|
||||
const wrappedHandler = this._wrapLinkHandler((_, link) => this._handleHypertextLink(link));
|
||||
const tooltipCallback = (_: MouseEvent, linkText: string, location: IViewportRange) => {
|
||||
this._tooltipCallback(linkText, location, this._handleHypertextLink.bind(this));
|
||||
};
|
||||
this._webLinksAddon = new WebLinksAddon(wrappedHandler, {
|
||||
validationCallback: (uri: string, callback: (isValid: boolean) => void) => this._validateWebLink(callback),
|
||||
tooltipCallback,
|
||||
willLinkActivate: (e: MouseEvent) => this._isLinkActivationModifierDown(e)
|
||||
});
|
||||
this._xterm.loadAddon(this._webLinksAddon);
|
||||
});
|
||||
}
|
||||
|
||||
public registerLocalLinkHandler(): void {
|
||||
const wrappedHandler = this._wrapLinkHandler((_, url) => this._handleLocalLink(url));
|
||||
const tooltipCallback = (event: MouseEvent, linkText: string, location: IViewportRange) => {
|
||||
this._tooltipCallback(linkText, location, this._handleLocalLink.bind(this));
|
||||
};
|
||||
this._linkMatchers.push(this._xterm.registerLinkMatcher(this._localLinkRegex, wrappedHandler, {
|
||||
validationCallback: (uri: string, callback: (isValid: boolean) => void) => this._validateLocalLink(uri, callback),
|
||||
tooltipCallback,
|
||||
willLinkActivate: (e: MouseEvent) => this._isLinkActivationModifierDown(e),
|
||||
priority: LOCAL_LINK_PRIORITY
|
||||
}));
|
||||
}
|
||||
|
||||
public registerGitDiffLinkHandlers(): void {
|
||||
const wrappedHandler = this._wrapLinkHandler((_, url) => {
|
||||
this._handleLocalLink(url);
|
||||
});
|
||||
const tooltipCallback = (event: MouseEvent, linkText: string, location: IViewportRange) => {
|
||||
this._tooltipCallback(linkText, location, this._handleLocalLink.bind(this));
|
||||
};
|
||||
const options = {
|
||||
matchIndex: 1,
|
||||
validationCallback: (uri: string, callback: (isValid: boolean) => void) => this._validateLocalLink(uri, callback),
|
||||
tooltipCallback,
|
||||
willLinkActivate: (e: MouseEvent) => this._isLinkActivationModifierDown(e),
|
||||
priority: LOCAL_LINK_PRIORITY
|
||||
};
|
||||
this._linkMatchers.push(this._xterm.registerLinkMatcher(this._gitDiffPreImagePattern, wrappedHandler, options));
|
||||
this._linkMatchers.push(this._xterm.registerLinkMatcher(this._gitDiffPostImagePattern, wrappedHandler, options));
|
||||
}
|
||||
|
||||
public registerLinkProvider(): void {
|
||||
// Protocol links
|
||||
const wrappedActivateCallback = this._wrapLinkHandler((_, link) => this._handleProtocolLink(link));
|
||||
@@ -370,14 +198,6 @@ export class TerminalLinkManager extends DisposableStore {
|
||||
return new RegExp(`${baseLocalLinkClause}(${lineAndColumnClause})`);
|
||||
}
|
||||
|
||||
protected get _gitDiffPreImageRegex(): RegExp {
|
||||
return this._gitDiffPreImagePattern;
|
||||
}
|
||||
|
||||
protected get _gitDiffPostImageRegex(): RegExp {
|
||||
return this._gitDiffPostImagePattern;
|
||||
}
|
||||
|
||||
private async _handleLocalLink(link: string): Promise<void> {
|
||||
// TODO: This gets resolved again but doesn't need to as it's already validated
|
||||
const resolvedLink = await this._resolvePath(link);
|
||||
@@ -392,14 +212,6 @@ export class TerminalLinkManager extends DisposableStore {
|
||||
await this._editorService.openEditor({ resource: resolvedLink.uri, options: { pinned: true, selection } });
|
||||
}
|
||||
|
||||
private _validateLocalLink(link: string, callback: (isValid: boolean) => void): void {
|
||||
this._resolvePath(link).then(resolvedLink => callback(!!resolvedLink));
|
||||
}
|
||||
|
||||
private _validateWebLink(callback: (isValid: boolean) => void): void {
|
||||
callback(true);
|
||||
}
|
||||
|
||||
private _handleHypertextLink(url: string): void {
|
||||
this._openerService.open(url, { allowTunneling: !!(this._processManager && this._processManager.remoteAuthority) });
|
||||
}
|
||||
|
||||
@@ -69,6 +69,6 @@ class TerminalLinkAdapter implements ILinkComputerTarget {
|
||||
}
|
||||
|
||||
getLineContent(): string {
|
||||
return getXtermLineContent(this._xterm.buffer.active, this._lineStart, this._lineEnd);
|
||||
return getXtermLineContent(this._xterm.buffer.active, this._lineStart, this._lineEnd, this._xterm.cols);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,18 +22,18 @@ const pathSeparatorClause = '\\/';
|
||||
// Also disallow \\ to prevent a catastropic backtracking case #24798
|
||||
const excludedPathCharactersClause = '[^\\0\\s!$`&*()\\[\\]+\'":;\\\\]';
|
||||
/** A regex that matches paths in the form /foo, ~/foo, ./foo, ../foo, foo/bar */
|
||||
const unixLocalLinkClause = '((' + pathPrefix + '|(' + excludedPathCharactersClause + ')+)?(' + pathSeparatorClause + '(' + excludedPathCharactersClause + ')+)+)';
|
||||
export const unixLocalLinkClause = '((' + pathPrefix + '|(' + excludedPathCharactersClause + ')+)?(' + pathSeparatorClause + '(' + excludedPathCharactersClause + ')+)+)';
|
||||
|
||||
const winDrivePrefix = '(?:\\\\\\\\\\?\\\\)?[a-zA-Z]:';
|
||||
export const winDrivePrefix = '(?:\\\\\\\\\\?\\\\)?[a-zA-Z]:';
|
||||
const winPathPrefix = '(' + winDrivePrefix + '|\\.\\.?|\\~)';
|
||||
const winPathSeparatorClause = '(\\\\|\\/)';
|
||||
const winExcludedPathCharactersClause = '[^\\0<>\\?\\|\\/\\s!$`&*()\\[\\]+\'":;]';
|
||||
/** A regex that matches paths in the form \\?\c:\foo c:\foo, ~\foo, .\foo, ..\foo, foo\bar */
|
||||
const winLocalLinkClause = '((' + winPathPrefix + '|(' + winExcludedPathCharactersClause + ')+)?(' + winPathSeparatorClause + '(' + winExcludedPathCharactersClause + ')+)+)';
|
||||
export const winLocalLinkClause = '((' + winPathPrefix + '|(' + winExcludedPathCharactersClause + ')+)?(' + winPathSeparatorClause + '(' + winExcludedPathCharactersClause + ')+)+)';
|
||||
|
||||
/** As xterm reads from DOM, space in that case is nonbreaking char ASCII code - 160,
|
||||
replacing space with nonBreakningSpace or space ASCII code - 32. */
|
||||
const lineAndColumnClause = [
|
||||
export const lineAndColumnClause = [
|
||||
'((\\S*)", line ((\\d+)( column (\\d+))?))', // "(file path)", line 45 [see #40468]
|
||||
'((\\S*)",((\\d+)(:(\\d+))?))', // "(file path)",45 [see #78205]
|
||||
'((\\S*) on line ((\\d+)(, column (\\d+))?))', // (file path) on line 8, column 13
|
||||
@@ -42,6 +42,13 @@ const lineAndColumnClause = [
|
||||
'(([^:\\s\\(\\)<>\'\"\\[\\]]*)(:(\\d+))?(:(\\d+))?)' // (file path):336, (file path):336:9
|
||||
].join('|').replace(/ /g, `[${'\u00A0'} ]`);
|
||||
|
||||
// Changing any regex may effect this value, hence changes this as well if required.
|
||||
export const winLineAndColumnMatchIndex = 12;
|
||||
export const unixLineAndColumnMatchIndex = 11;
|
||||
|
||||
// Each line and column clause have 6 groups (ie no. of expressions in round brackets)
|
||||
export const lineAndColumnClauseGroupCount = 6;
|
||||
|
||||
export class TerminalValidatedLocalLinkProvider extends TerminalBaseLinkProvider {
|
||||
constructor(
|
||||
private readonly _xterm: Terminal,
|
||||
@@ -77,7 +84,7 @@ export class TerminalValidatedLocalLinkProvider extends TerminalBaseLinkProvider
|
||||
endLine++;
|
||||
}
|
||||
|
||||
const text = getXtermLineContent(this._xterm.buffer.active, startLine, endLine);
|
||||
const text = getXtermLineContent(this._xterm.buffer.active, startLine, endLine, this._xterm.cols);
|
||||
|
||||
// clone regex to do a global search on text
|
||||
const rex = new RegExp(this._localLinkRegex, 'g');
|
||||
|
||||
@@ -119,8 +119,8 @@
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .pane-body.integrated-terminal .xterm.focus::before,
|
||||
.hc-black .monaco-workbench .pane-body.integrated-terminal .xterm:focus::before {
|
||||
.monaco-workbench.hc-black .pane-body.integrated-terminal .xterm.focus::before,
|
||||
.monaco-workbench.hc-black .pane-body.integrated-terminal .xterm:focus::before {
|
||||
display: block;
|
||||
content: "";
|
||||
border: 1px solid;
|
||||
@@ -132,8 +132,8 @@
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .pane-body.integrated-terminal .monaco-split-view2.horizontal .split-view-view:not(:only-child) .xterm.focus::before,
|
||||
.hc-black .monaco-workbench .pane-body.integrated-terminal .monaco-split-view2.horizontal .split-view-view:not(:only-child) .xterm:focus::before {
|
||||
.monaco-workbench.hc-black .pane-body.integrated-terminal .monaco-split-view2.horizontal .split-view-view:not(:only-child) .xterm.focus::before,
|
||||
.monaco-workbench.hc-black .pane-body.integrated-terminal .monaco-split-view2.horizontal .split-view-view:not(:only-child) .xterm:focus::before {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
@@ -147,8 +147,8 @@
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench.mac .pane-body.integrated-terminal .terminal-outer-container:not(.alt-active) .terminal:not(.enable-mouse-events),
|
||||
.hc-black .monaco-workbench.mac .pane-body.integrated-terminal .terminal-outer-container:not(.alt-active) .terminal:not(.enable-mouse-events) {
|
||||
.monaco-workbench.vs-dark.mac .pane-body.integrated-terminal .terminal-outer-container:not(.alt-active) .terminal:not(.enable-mouse-events),
|
||||
.monaco-workbench.hc-black.mac .pane-body.integrated-terminal .terminal-outer-container:not(.alt-active) .terminal:not(.enable-mouse-events) {
|
||||
cursor: -webkit-image-set(url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAL0lEQVQoz2NgCD3x//9/BhBYBWdhgFVAiVW4JBFKGIa4AqD0//9D3pt4I4tAdAMAHTQ/j5Zom30AAAAASUVORK5CYII=') 1x, url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAAz0lEQVRIx2NgYGBY/R8I/vx5eelX3n82IJ9FxGf6tksvf/8FiTMQAcAGQMDvSwu09abffY8QYSAScNk45G198eX//yev73/4///701eh//kZSARckrNBRvz//+8+6ZohwCzjGNjdgQxkAg7B9WADeBjIBqtJCbhRA0YNoIkBSNmaPEMoNmA0FkYNoFKhapJ6FGyAH3nauaSmPfwI0v/3OukVi0CIZ+F25KrtYcx/CTIy0e+rC7R1Z4KMICVTQQ14feVXIbR695u14+Ir4gwAAD49E54wc1kWAAAAAElFTkSuQmCC') 2x) 5 8, text;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import { Terminal as XTermTerminal } from 'xterm';
|
||||
import { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
|
||||
import { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode11';
|
||||
import { WebLinksAddon as XTermWebLinksAddon } from 'xterm-addon-web-links';
|
||||
import { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl';
|
||||
import { IWindowsShellHelper, ITerminalConfigHelper, ITerminalChildProcess, IShellLaunchConfig, IDefaultShellAndArgsRequest, ISpawnExtHostProcessRequest, IStartExtensionTerminalRequest, IAvailableShellsRequest, ITerminalProcessExtHostProxy, ICommandTracker, INavigationMode, TitleEventSource, ITerminalDimensions } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -33,7 +32,6 @@ export interface ITerminalInstanceService {
|
||||
getXtermConstructor(): Promise<typeof XTermTerminal>;
|
||||
getXtermSearchConstructor(): Promise<typeof XTermSearchAddon>;
|
||||
getXtermUnicode11Constructor(): Promise<typeof XTermUnicode11Addon>;
|
||||
getXtermWebLinksConstructor(): Promise<typeof XTermWebLinksAddon>;
|
||||
getXtermWebglConstructor(): Promise<typeof XTermWebglAddon>;
|
||||
createWindowsShellHelper(shellProcessId: number, xterm: XTermTerminal): IWindowsShellHelper;
|
||||
createTerminalProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, windowsEnableConpty: boolean): ITerminalChildProcess;
|
||||
@@ -338,26 +336,6 @@ export interface ITerminalInstance {
|
||||
*/
|
||||
forceRedraw(): void;
|
||||
|
||||
/**
|
||||
* Registers a link matcher, allowing custom link patterns to be matched and handled.
|
||||
* @param regex The regular expression the search for, specifically this searches the
|
||||
* textContent of the rows. You will want to use \s to match a space ' ' character for example.
|
||||
* @param handler The callback when the link is called.
|
||||
* @param matchIndex The index of the link from the regex.match(html) call. This defaults to 0
|
||||
* (for regular expressions without capture groups).
|
||||
* @param validationCallback A callback which can be used to validate the link after it has been
|
||||
* added to the DOM.
|
||||
* @return The ID of the new matcher, this can be used to deregister.
|
||||
*/
|
||||
registerLinkMatcher(regex: RegExp, handler: (url: string) => void, matchIndex?: number, validationCallback?: (uri: string, callback: (isValid: boolean) => void) => void): number;
|
||||
|
||||
/**
|
||||
* Deregisters a link matcher if it has been registered.
|
||||
* @param matcherId The link matcher's ID (returned after register)
|
||||
* @return Whether a link matcher was found and deregistered.
|
||||
*/
|
||||
deregisterLinkMatcher(matcherId: number): void;
|
||||
|
||||
/**
|
||||
* Check if anything is selected in terminal.
|
||||
*/
|
||||
|
||||
@@ -26,7 +26,7 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { ITerminalInstance, ITerminalService, Direction } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { Action2, registerAction2, ILocalizedString } from 'vs/platform/actions/common/actions';
|
||||
import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminalQuickAccess';
|
||||
import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions';
|
||||
import { IViewsService, IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
@@ -236,7 +236,7 @@ export class SplitTerminalAction extends Action {
|
||||
super(id, label, SplitTerminalAction.HORIZONTAL_CLASS);
|
||||
}
|
||||
|
||||
public async run(event?: any): Promise<any> {
|
||||
public async run(): Promise<any> {
|
||||
await this._terminalService.doWithActiveInstance(async t => {
|
||||
const cwd = await getCwdForSplit(this._terminalService.configHelper, t, this._workspaceContextService.getWorkspace().folders, this._commandService);
|
||||
if (cwd === undefined) {
|
||||
@@ -343,7 +343,7 @@ export class SwitchTerminalActionViewItem extends SelectActionViewItem {
|
||||
@IThemeService private readonly _themeService: IThemeService,
|
||||
@IContextViewService contextViewService: IContextViewService
|
||||
) {
|
||||
super(null, action, getTerminalSelectOpenItems(_terminalService), _terminalService.activeTabIndex, contextViewService, { ariaLabel: localize('terminals', 'Open Terminals.') });
|
||||
super(null, action, getTerminalSelectOpenItems(_terminalService), _terminalService.activeTabIndex, contextViewService, { ariaLabel: localize('terminals', 'Open Terminals.'), optionsAsChildren: true });
|
||||
|
||||
this._register(_terminalService.onInstancesChanged(this._updateItems, this));
|
||||
this._register(_terminalService.onActiveTabChanged(this._updateItems, this));
|
||||
@@ -393,13 +393,13 @@ export class ClearTerminalAction extends Action {
|
||||
}
|
||||
|
||||
export function registerTerminalActions() {
|
||||
const category = TERMINAL_ACTION_CATEGORY;
|
||||
const category: ILocalizedString = { value: TERMINAL_ACTION_CATEGORY, original: 'Terminal' };
|
||||
|
||||
registerAction2(class extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.NEW_IN_ACTIVE_WORKSPACE,
|
||||
title: localize('workbench.action.terminal.newInActiveWorkspace', "Create New Integrated Terminal (In Active Workspace)"),
|
||||
title: { value: localize('workbench.action.terminal.newInActiveWorkspace', "Create New Integrated Terminal (In Active Workspace)"), original: 'Create New Integrated Terminal (In Active Workspace)' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
@@ -418,7 +418,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.FOCUS_PREVIOUS_PANE,
|
||||
title: localize('workbench.action.terminal.focusPreviousPane', "Focus Previous Pane"),
|
||||
title: { value: localize('workbench.action.terminal.focusPreviousPane', "Focus Previous Pane"), original: 'Focus Previous Pane' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -443,7 +443,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.FOCUS_NEXT_PANE,
|
||||
title: localize('workbench.action.terminal.focusNextPane', "Focus Next Pane"),
|
||||
title: { value: localize('workbench.action.terminal.focusNextPane', "Focus Next Pane"), original: 'Focus Next Pane' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -468,7 +468,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.RESIZE_PANE_LEFT,
|
||||
title: localize('workbench.action.terminal.resizePaneLeft', "Resize Pane Left"),
|
||||
title: { value: localize('workbench.action.terminal.resizePaneLeft', "Resize Pane Left"), original: 'Resize Pane Left' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -487,7 +487,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.RESIZE_PANE_RIGHT,
|
||||
title: localize('workbench.action.terminal.resizePaneRight', "Resize Pane Right"),
|
||||
title: { value: localize('workbench.action.terminal.resizePaneRight', "Resize Pane Right"), original: 'Resize Pane Right' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -506,7 +506,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.RESIZE_PANE_UP,
|
||||
title: localize('workbench.action.terminal.resizePaneUp', "Resize Pane Up"),
|
||||
title: { value: localize('workbench.action.terminal.resizePaneUp', "Resize Pane Up"), original: 'Resize Pane Up' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -524,7 +524,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.RESIZE_PANE_DOWN,
|
||||
title: localize('workbench.action.terminal.resizePaneDown', "Resize Pane Down"),
|
||||
title: { value: localize('workbench.action.terminal.resizePaneDown', "Resize Pane Down"), original: 'Resize Pane Down' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -542,7 +542,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.FOCUS,
|
||||
title: localize('workbench.action.terminal.focus', "Focus Terminal"),
|
||||
title: { value: localize('workbench.action.terminal.focus', "Focus Terminal"), original: 'Focus Terminal' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
@@ -561,7 +561,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.FOCUS_NEXT,
|
||||
title: localize('workbench.action.terminal.focusNext', "Focus Next Terminal"),
|
||||
title: { value: localize('workbench.action.terminal.focusNext', "Focus Next Terminal"), original: 'Focus Next Terminal' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
@@ -576,7 +576,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.FOCUS_PREVIOUS,
|
||||
title: localize('workbench.action.terminal.focusPrevious', "Focus Previous Terminal"),
|
||||
title: { value: localize('workbench.action.terminal.focusPrevious', "Focus Previous Terminal"), original: 'Focus Previous Terminal' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
@@ -591,7 +591,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.RUN_SELECTED_TEXT,
|
||||
title: localize('workbench.action.terminal.runSelectedText', "Run Selected Text In Active Terminal"),
|
||||
title: { value: localize('workbench.action.terminal.runSelectedText', "Run Selected Text In Active Terminal"), original: 'Run Selected Text In Active Terminal' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
@@ -621,7 +621,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.RUN_ACTIVE_FILE,
|
||||
title: localize('workbench.action.terminal.runActiveFile', "Run Active File In Active Terminal"),
|
||||
title: { value: localize('workbench.action.terminal.runActiveFile', "Run Active File In Active Terminal"), original: 'Run Active File In Active Terminal' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
@@ -655,7 +655,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SCROLL_DOWN_LINE,
|
||||
title: localize('workbench.action.terminal.scrollDown', "Scroll Down (Line)"),
|
||||
title: { value: localize('workbench.action.terminal.scrollDown', "Scroll Down (Line)"), original: 'Scroll Down (Line)' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -674,7 +674,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SCROLL_DOWN_PAGE,
|
||||
title: localize('workbench.action.terminal.scrollDownPage', "Scroll Down (Page)"),
|
||||
title: { value: localize('workbench.action.terminal.scrollDownPage', "Scroll Down (Page)"), original: 'Scroll Down (Page)' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -693,7 +693,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SCROLL_TO_BOTTOM,
|
||||
title: localize('workbench.action.terminal.scrollToBottom', "Scroll to Bottom"),
|
||||
title: { value: localize('workbench.action.terminal.scrollToBottom', "Scroll to Bottom"), original: 'Scroll to Bottom' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -712,7 +712,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SCROLL_UP_LINE,
|
||||
title: localize('workbench.action.terminal.scrollUp', "Scroll Up (Line)"),
|
||||
title: { value: localize('workbench.action.terminal.scrollUp', "Scroll Up (Line)"), original: 'Scroll Up (Line)' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -731,7 +731,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SCROLL_UP_PAGE,
|
||||
title: localize('workbench.action.terminal.scrollUpPage', "Scroll Up (Page)"),
|
||||
title: { value: localize('workbench.action.terminal.scrollUpPage', "Scroll Up (Page)"), original: 'Scroll Up (Page)' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -750,7 +750,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SCROLL_TO_TOP,
|
||||
title: localize('workbench.action.terminal.scrollToTop', "Scroll to Top"),
|
||||
title: { value: localize('workbench.action.terminal.scrollToTop', "Scroll to Top"), original: 'Scroll to Top' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -769,7 +769,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.NAVIGATION_MODE_EXIT,
|
||||
title: localize('workbench.action.terminal.navigationModeExit', "Exit Navigation Mode"),
|
||||
title: { value: localize('workbench.action.terminal.navigationModeExit', "Exit Navigation Mode"), original: 'Exit Navigation Mode' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -787,7 +787,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.NAVIGATION_MODE_FOCUS_PREVIOUS,
|
||||
title: localize('workbench.action.terminal.navigationModeFocusPrevious', "Focus Previous Line (Navigation Mode)"),
|
||||
title: { value: localize('workbench.action.terminal.navigationModeFocusPrevious', "Focus Previous Line (Navigation Mode)"), original: 'Focus Previous Line (Navigation Mode)' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -808,7 +808,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.NAVIGATION_MODE_FOCUS_NEXT,
|
||||
title: localize('workbench.action.terminal.navigationModeFocusNext', "Focus Next Line (Navigation Mode)"),
|
||||
title: { value: localize('workbench.action.terminal.navigationModeFocusNext', "Focus Next Line (Navigation Mode)"), original: 'Focus Next Line (Navigation Mode)' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -829,7 +829,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.CLEAR_SELECTION,
|
||||
title: localize('workbench.action.terminal.clearSelection', "Clear Selection"),
|
||||
title: { value: localize('workbench.action.terminal.clearSelection', "Clear Selection"), original: 'Clear Selection' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -850,7 +850,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.MANAGE_WORKSPACE_SHELL_PERMISSIONS,
|
||||
title: localize('workbench.action.terminal.manageWorkspaceShellPermissions', "Manage Workspace Shell Permissions"),
|
||||
title: { value: localize('workbench.action.terminal.manageWorkspaceShellPermissions', "Manage Workspace Shell Permissions"), original: 'Manage Workspace Shell Permissions' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
@@ -863,7 +863,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.RENAME,
|
||||
title: localize('workbench.action.terminal.rename', "Rename"),
|
||||
title: { value: localize('workbench.action.terminal.rename', "Rename"), original: 'Rename' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
@@ -884,7 +884,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.FIND_FOCUS,
|
||||
title: localize('workbench.action.terminal.focusFind', "Focus Find"),
|
||||
title: { value: localize('workbench.action.terminal.focusFind', "Focus Find"), original: 'Focus Find' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -902,7 +902,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.FIND_HIDE,
|
||||
title: localize('workbench.action.terminal.hideFind', "Hide Find"),
|
||||
title: { value: localize('workbench.action.terminal.hideFind', "Hide Find"), original: 'Hide Find' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -921,7 +921,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.QUICK_OPEN_TERM,
|
||||
title: localize('quickAccessTerminal', "Switch Active Terminal"),
|
||||
title: { value: localize('quickAccessTerminal', "Switch Active Terminal"), original: 'Switch Active Terminal' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
@@ -934,7 +934,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SCROLL_TO_PREVIOUS_COMMAND,
|
||||
title: localize('workbench.action.terminal.scrollToPreviousCommand', "Scroll To Previous Command"),
|
||||
title: { value: localize('workbench.action.terminal.scrollToPreviousCommand', "Scroll To Previous Command"), original: 'Scroll To Previous Command' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -955,7 +955,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SCROLL_TO_NEXT_COMMAND,
|
||||
title: localize('workbench.action.terminal.scrollToNextCommand', "Scroll To Next Command"),
|
||||
title: { value: localize('workbench.action.terminal.scrollToNextCommand', "Scroll To Next Command"), original: 'Scroll To Next Command' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -976,7 +976,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SELECT_TO_PREVIOUS_COMMAND,
|
||||
title: localize('workbench.action.terminal.selectToPreviousCommand', "Select To Previous Command"),
|
||||
title: { value: localize('workbench.action.terminal.selectToPreviousCommand', "Select To Previous Command"), original: 'Select To Previous Command' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -997,7 +997,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SELECT_TO_NEXT_COMMAND,
|
||||
title: localize('workbench.action.terminal.selectToNextCommand', "Select To Next Command"),
|
||||
title: { value: localize('workbench.action.terminal.selectToNextCommand', "Select To Next Command"), original: 'Select To Next Command' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -1018,7 +1018,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SELECT_TO_PREVIOUS_LINE,
|
||||
title: localize('workbench.action.terminal.selectToPreviousLine', "Select To Previous Line"),
|
||||
title: { value: localize('workbench.action.terminal.selectToPreviousLine', "Select To Previous Line"), original: 'Select To Previous Line' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
@@ -1034,7 +1034,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SELECT_TO_NEXT_LINE,
|
||||
title: localize('workbench.action.terminal.selectToNextLine', "Select To Next Line"),
|
||||
title: { value: localize('workbench.action.terminal.selectToNextLine', "Select To Next Line"), original: 'Select To Next Line' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
@@ -1050,7 +1050,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.TOGGLE_ESCAPE_SEQUENCE_LOGGING,
|
||||
title: localize('workbench.action.terminal.toggleEscapeSequenceLogging', "Toggle Escape Sequence Logging"),
|
||||
title: { value: localize('workbench.action.terminal.toggleEscapeSequenceLogging', "Toggle Escape Sequence Logging"), original: 'Toggle Escape Sequence Logging' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
@@ -1064,7 +1064,7 @@ export function registerTerminalActions() {
|
||||
const title = localize('workbench.action.terminal.sendSequence', "Send Custom Sequence To Terminal");
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SEND_SEQUENCE,
|
||||
title,
|
||||
title: { value: title, original: 'Send Custom Sequence To Terminal' },
|
||||
category,
|
||||
description: {
|
||||
description: title,
|
||||
@@ -1090,7 +1090,7 @@ export function registerTerminalActions() {
|
||||
const title = localize('workbench.action.terminal.newWithCwd', "Create New Integrated Terminal Starting in a Custom Working Directory");
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.NEW_WITH_CWD,
|
||||
title,
|
||||
title: { value: title, original: 'Create New Integrated Terminal Starting in a Custom Working Directory' },
|
||||
category,
|
||||
description: {
|
||||
description: title,
|
||||
@@ -1125,7 +1125,7 @@ export function registerTerminalActions() {
|
||||
const title = localize('workbench.action.terminal.renameWithArg', "Rename the Currently Active Terminal");
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.RENAME_WITH_ARG,
|
||||
title,
|
||||
title: { value: title, original: 'Rename the Currently Active Terminal' },
|
||||
category,
|
||||
description: {
|
||||
description: title,
|
||||
@@ -1159,7 +1159,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.TOGGLE_FIND_REGEX,
|
||||
title: localize('workbench.action.terminal.toggleFindRegex', "Toggle Find Using Regex"),
|
||||
title: { value: localize('workbench.action.terminal.toggleFindRegex', "Toggle Find Using Regex"), original: 'Toggle Find Using Regex' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -1179,7 +1179,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.TOGGLE_FIND_WHOLE_WORD,
|
||||
title: localize('workbench.action.terminal.toggleFindWholeWord', "Toggle Find Using Whole Word"),
|
||||
title: { value: localize('workbench.action.terminal.toggleFindWholeWord', "Toggle Find Using Whole Word"), original: 'Toggle Find Using Whole Word' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -1199,7 +1199,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.TOGGLE_FIND_CASE_SENSITIVE,
|
||||
title: localize('workbench.action.terminal.toggleFindCaseSensitive', "Toggle Find Using Case Sensitive"),
|
||||
title: { value: localize('workbench.action.terminal.toggleFindCaseSensitive', "Toggle Find Using Case Sensitive"), original: 'Toggle Find Using Case Sensitive' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
@@ -1219,7 +1219,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.FIND_NEXT,
|
||||
title: localize('workbench.action.terminal.findNext', "Find Next"),
|
||||
title: { value: localize('workbench.action.terminal.findNext', "Find Next"), original: 'Find Next' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: [
|
||||
@@ -1245,7 +1245,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.FIND_PREVIOUS,
|
||||
title: localize('workbench.action.terminal.findPrevious', "Find Previous"),
|
||||
title: { value: localize('workbench.action.terminal.findPrevious', "Find Previous"), original: 'Find Previous' },
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: [
|
||||
@@ -1271,7 +1271,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.RELAUNCH,
|
||||
title: localize('workbench.action.terminal.relaunch', "Relaunch Active Terminal"),
|
||||
title: { value: localize('workbench.action.terminal.relaunch', "Relaunch Active Terminal"), original: 'Relaunch Active Terminal' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
@@ -1284,7 +1284,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TERMINAL_COMMAND_ID.SHOW_ENVIRONMENT_INFORMATION,
|
||||
title: localize('workbench.action.terminal.showEnvironmentInformation', "Show Environment Information"),
|
||||
title: { value: localize('workbench.action.terminal.showEnvironmentInformation', "Show Environment Information"), original: 'Show Environment Information' },
|
||||
f1: true,
|
||||
category
|
||||
});
|
||||
|
||||
@@ -408,7 +408,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
this._linkManager = this._instantiationService.createInstance(TerminalLinkManager, xterm, this._processManager!, this._configHelper);
|
||||
this._linkManager = this._instantiationService.createInstance(TerminalLinkManager, xterm, this._processManager!);
|
||||
this._linkManager.onBeforeHandleLink(e => {
|
||||
e.terminal = this;
|
||||
this._onBeforeHandleLink.fire(e);
|
||||
@@ -656,14 +656,6 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
};
|
||||
}
|
||||
|
||||
public registerLinkMatcher(regex: RegExp, handler: (url: string) => void, matchIndex?: number, validationCallback?: (uri: string, callback: (isValid: boolean) => void) => void): number {
|
||||
return this._linkManager!.registerCustomLinkHandler(regex, (_, url) => handler(url), matchIndex, validationCallback);
|
||||
}
|
||||
|
||||
public deregisterLinkMatcher(linkMatcherId: number): void {
|
||||
this._xtermReadyPromise.then(xterm => xterm.deregisterLinkMatcher(linkMatcherId));
|
||||
}
|
||||
|
||||
public hasSelection(): boolean {
|
||||
return this._xterm ? this._xterm.hasSelection() : false;
|
||||
}
|
||||
@@ -1484,8 +1476,8 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
||||
const border = theme.getColor(activeContrastBorder);
|
||||
if (border) {
|
||||
collector.addRule(`
|
||||
.hc-black .monaco-workbench .pane-body.integrated-terminal .xterm.focus::before,
|
||||
.hc-black .monaco-workbench .pane-body.integrated-terminal .xterm:focus::before { border-color: ${border}; }`
|
||||
.monaco-workbench.hc-black .pane-body.integrated-terminal .xterm.focus::before,
|
||||
.monaco-workbench.hc-black .pane-body.integrated-terminal .xterm:focus::before { border-color: ${border}; }`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import { IWindowsShellHelper, ITerminalChildProcess, IDefaultShellAndArgsRequest
|
||||
import { Terminal as XTermTerminal } from 'xterm';
|
||||
import { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
|
||||
import { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode11';
|
||||
import { WebLinksAddon as XTermWebLinksAddon } from 'xterm-addon-web-links';
|
||||
import { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl';
|
||||
import { IProcessEnvironment } from 'vs/base/common/platform';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
@@ -17,7 +16,6 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
let Terminal: typeof XTermTerminal;
|
||||
let SearchAddon: typeof XTermSearchAddon;
|
||||
let Unicode11Addon: typeof XTermUnicode11Addon;
|
||||
let WebLinksAddon: typeof XTermWebLinksAddon;
|
||||
let WebglAddon: typeof XTermWebglAddon;
|
||||
|
||||
export class TerminalInstanceService implements ITerminalInstanceService {
|
||||
@@ -47,13 +45,6 @@ export class TerminalInstanceService implements ITerminalInstanceService {
|
||||
return Unicode11Addon;
|
||||
}
|
||||
|
||||
public async getXtermWebLinksConstructor(): Promise<typeof XTermWebLinksAddon> {
|
||||
if (!WebLinksAddon) {
|
||||
WebLinksAddon = (await import('xterm-addon-web-links')).WebLinksAddon;
|
||||
}
|
||||
return WebLinksAddon;
|
||||
}
|
||||
|
||||
public async getXtermWebglConstructor(): Promise<typeof XTermWebglAddon> {
|
||||
if (!WebglAddon) {
|
||||
WebglAddon = (await import('xterm-addon-webgl')).WebglAddon;
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { renderMarkdown } from 'vs/base/browser/markdownRenderer';
|
||||
import { Widget } from 'vs/base/browser/ui/widget';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { editorHoverHighlight, editorHoverBackground, editorHoverBorder, textLinkForeground, editorHoverForeground, editorHoverStatusBarBackground, textCodeBlockBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
@@ -14,23 +13,23 @@ import * as dom from 'vs/base/browser/dom';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IHoverTarget, HorizontalAnchorSide, VerticalAnchorSide } from 'vs/workbench/contrib/terminal/browser/widgets/widgets';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { EDITOR_FONT_DEFAULTS, IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { HoverWidget as BaseHoverWidget, renderHoverAction } from 'vs/base/browser/ui/hover/hoverWidget';
|
||||
import { Widget } from 'vs/base/browser/ui/widget';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
export class HoverWidget extends Widget {
|
||||
private readonly _containerDomNode: HTMLElement;
|
||||
private readonly _domNode: HTMLElement;
|
||||
private readonly _messageListeners = new DisposableStore();
|
||||
private readonly _mouseTracker: CompositeMouseTracker;
|
||||
private readonly _scrollbar: DomScrollableElement;
|
||||
|
||||
private readonly _hover: BaseHoverWidget;
|
||||
|
||||
private _isDisposed: boolean = false;
|
||||
|
||||
get isDisposed(): boolean { return this._isDisposed; }
|
||||
get domNode(): HTMLElement { return this._containerDomNode; }
|
||||
get domNode(): HTMLElement { return this._hover.containerDomNode; }
|
||||
|
||||
private readonly _onDispose = new Emitter<void>();
|
||||
get onDispose(): Event<void> { return this._onDispose.event; }
|
||||
@@ -45,24 +44,16 @@ export class HoverWidget extends Widget {
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService
|
||||
) {
|
||||
super();
|
||||
this._containerDomNode = document.createElement('div');
|
||||
this._containerDomNode.classList.add('terminal-hover-widget', 'fadeIn', 'monaco-editor-hover', 'xterm-hover');
|
||||
this._containerDomNode.tabIndex = 0;
|
||||
this._containerDomNode.setAttribute('role', 'tooltip');
|
||||
|
||||
this._domNode = document.createElement('div');
|
||||
this._domNode.className = 'monaco-editor-hover-content';
|
||||
|
||||
this._scrollbar = new DomScrollableElement(this._domNode, {});
|
||||
this._register(this._scrollbar);
|
||||
this._containerDomNode.appendChild(this._scrollbar.getDomNode());
|
||||
this._hover = this._register(new BaseHoverWidget());
|
||||
this._hover.containerDomNode.classList.add('terminal-hover-widget', 'fadeIn', 'xterm-hover');
|
||||
|
||||
// Don't allow mousedown out of the widget, otherwise preventDefault will call and text will
|
||||
// not be selected.
|
||||
this.onmousedown(this._containerDomNode, e => e.stopPropagation());
|
||||
this.onmousedown(this._hover.containerDomNode, e => e.stopPropagation());
|
||||
|
||||
// Hide hover on escape
|
||||
this.onkeydown(this._containerDomNode, e => {
|
||||
this.onkeydown(this._hover.containerDomNode, e => {
|
||||
if (e.equals(KeyCode.Escape)) {
|
||||
this.dispose();
|
||||
}
|
||||
@@ -86,96 +77,85 @@ export class HoverWidget extends Widget {
|
||||
});
|
||||
contentsElement.appendChild(markdownElement);
|
||||
rowElement.appendChild(contentsElement);
|
||||
this._domNode.appendChild(rowElement);
|
||||
this._hover.contentsDomNode.appendChild(rowElement);
|
||||
|
||||
if (this._actions && this._actions.length > 0) {
|
||||
const statusBarElement = $('div.hover-row.status-bar');
|
||||
const actionsElement = $('div.actions');
|
||||
this._actions.forEach(action => this._renderAction(actionsElement, action));
|
||||
this._actions.forEach(action => {
|
||||
const keybinding = this._keybindingService.lookupKeybinding(action.commandId);
|
||||
const keybindingLabel = keybinding ? keybinding.getLabel() : null;
|
||||
renderHoverAction(actionsElement, action, keybindingLabel);
|
||||
});
|
||||
statusBarElement.appendChild(actionsElement);
|
||||
this._containerDomNode.appendChild(statusBarElement);
|
||||
this._hover.containerDomNode.appendChild(statusBarElement);
|
||||
}
|
||||
|
||||
this._mouseTracker = new CompositeMouseTracker([this._containerDomNode, ..._target.targetElements]);
|
||||
this._mouseTracker = new CompositeMouseTracker([this._hover.containerDomNode, ..._target.targetElements]);
|
||||
this._register(this._mouseTracker.onMouseOut(() => this.dispose()));
|
||||
this._register(this._mouseTracker);
|
||||
|
||||
this._container.appendChild(this._containerDomNode);
|
||||
this._container.appendChild(this._hover.containerDomNode);
|
||||
|
||||
this.layout();
|
||||
}
|
||||
|
||||
private _renderAction(parent: HTMLElement, actionOptions: { label: string, iconClass?: string, run: (target: HTMLElement) => void, commandId: string }): IDisposable {
|
||||
const actionContainer = dom.append(parent, $('div.action-container'));
|
||||
const action = dom.append(actionContainer, $('a.action'));
|
||||
action.setAttribute('href', '#');
|
||||
action.setAttribute('role', 'button');
|
||||
if (actionOptions.iconClass) {
|
||||
dom.append(action, $(`span.icon.${actionOptions.iconClass}`));
|
||||
}
|
||||
const label = dom.append(action, $('span'));
|
||||
const keybinding = this._keybindingService.lookupKeybinding(actionOptions.commandId);
|
||||
const keybindingLabel = keybinding ? keybinding.getLabel() : null;
|
||||
label.textContent = keybindingLabel ? `${actionOptions.label} (${keybindingLabel})` : actionOptions.label;
|
||||
return dom.addDisposableListener(actionContainer, dom.EventType.CLICK, e => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
actionOptions.run(actionContainer);
|
||||
});
|
||||
}
|
||||
|
||||
public layout(): void {
|
||||
const anchor = this._target.anchor;
|
||||
|
||||
this._containerDomNode.classList.remove('right-aligned');
|
||||
this._domNode.style.maxHeight = '';
|
||||
this._hover.containerDomNode.classList.remove('right-aligned');
|
||||
this._hover.contentsDomNode.style.maxHeight = '';
|
||||
if (anchor.horizontalAnchorSide === HorizontalAnchorSide.Left) {
|
||||
if (anchor.x + this._containerDomNode.clientWidth > document.documentElement.clientWidth) {
|
||||
if (anchor.x + this._hover.containerDomNode.clientWidth > document.documentElement.clientWidth) {
|
||||
// Shift the hover to the left when part of it would get cut off
|
||||
const width = Math.round(this._containerDomNode.clientWidth);
|
||||
this._containerDomNode.style.width = `${width - 1}px`;
|
||||
this._containerDomNode.style.maxWidth = '';
|
||||
const width = Math.round(this._hover.containerDomNode.clientWidth);
|
||||
this._hover.containerDomNode.style.width = `${width - 1}px`;
|
||||
this._hover.containerDomNode.style.maxWidth = '';
|
||||
const left = document.documentElement.clientWidth - width - 1;
|
||||
this._containerDomNode.style.left = `${left}px`;
|
||||
this._hover.containerDomNode.style.left = `${left}px`;
|
||||
// Right align if the right edge is closer to the anchor than the left edge
|
||||
if (left + width / 2 < anchor.x) {
|
||||
this._containerDomNode.classList.add('right-aligned');
|
||||
this._hover.containerDomNode.classList.add('right-aligned');
|
||||
}
|
||||
} else {
|
||||
this._containerDomNode.style.width = '';
|
||||
this._containerDomNode.style.maxWidth = `${document.documentElement.clientWidth - anchor.x - 1}px`;
|
||||
this._containerDomNode.style.left = `${anchor.x}px`;
|
||||
this._hover.containerDomNode.style.width = '';
|
||||
this._hover.containerDomNode.style.maxWidth = `${document.documentElement.clientWidth - anchor.x - 1}px`;
|
||||
this._hover.containerDomNode.style.left = `${anchor.x}px`;
|
||||
}
|
||||
} else {
|
||||
this._containerDomNode.style.right = `${anchor.x}px`;
|
||||
this._hover.containerDomNode.style.right = `${anchor.x}px`;
|
||||
}
|
||||
// Use fallback y value if there is not enough vertical space
|
||||
if (anchor.verticalAnchorSide === VerticalAnchorSide.Bottom) {
|
||||
if (anchor.y + this._containerDomNode.clientHeight > document.documentElement.clientHeight) {
|
||||
this._containerDomNode.style.top = `${anchor.fallbackY}px`;
|
||||
this._domNode.style.maxHeight = `${document.documentElement.clientHeight - anchor.fallbackY}px`;
|
||||
if (anchor.y + this._hover.containerDomNode.clientHeight > document.documentElement.clientHeight) {
|
||||
this._hover.containerDomNode.style.top = `${anchor.fallbackY}px`;
|
||||
this._hover.contentsDomNode.style.maxHeight = `${document.documentElement.clientHeight - anchor.fallbackY}px`;
|
||||
} else {
|
||||
this._containerDomNode.style.bottom = `${anchor.y}px`;
|
||||
this._containerDomNode.style.maxHeight = '';
|
||||
this._hover.containerDomNode.style.bottom = `${anchor.y}px`;
|
||||
this._hover.containerDomNode.style.maxHeight = '';
|
||||
}
|
||||
} else {
|
||||
if (anchor.y + this._containerDomNode.clientHeight > document.documentElement.clientHeight) {
|
||||
this._containerDomNode.style.bottom = `${anchor.fallbackY}px`;
|
||||
if (anchor.y + this._hover.containerDomNode.clientHeight > document.documentElement.clientHeight) {
|
||||
this._hover.containerDomNode.style.bottom = `${anchor.fallbackY}px`;
|
||||
} else {
|
||||
this._containerDomNode.style.top = `${anchor.y}px`;
|
||||
this._hover.containerDomNode.style.top = `${anchor.y}px`;
|
||||
}
|
||||
}
|
||||
this._scrollbar.scanDomNode();
|
||||
this._hover.onContentsChanged();
|
||||
}
|
||||
|
||||
public focus() {
|
||||
this._containerDomNode.focus();
|
||||
this._hover.containerDomNode.focus();
|
||||
}
|
||||
|
||||
public hide(): void {
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
if (!this._isDisposed) {
|
||||
this._onDispose.fire();
|
||||
this._containerDomNode.parentElement?.removeChild(this.domNode);
|
||||
this._hover.containerDomNode.parentElement?.removeChild(this.domNode);
|
||||
this._messageListeners.dispose();
|
||||
this._target.dispose();
|
||||
super.dispose();
|
||||
@@ -238,29 +218,29 @@ registerThemingParticipant((theme, collector) => {
|
||||
}
|
||||
const hoverBackground = theme.getColor(editorHoverBackground);
|
||||
if (hoverBackground) {
|
||||
collector.addRule(`.integrated-terminal .monaco-editor-hover { background-color: ${hoverBackground}; }`);
|
||||
collector.addRule(`.integrated-terminal .monaco-hover { background-color: ${hoverBackground}; }`);
|
||||
}
|
||||
const hoverBorder = theme.getColor(editorHoverBorder);
|
||||
if (hoverBorder) {
|
||||
collector.addRule(`.integrated-terminal .monaco-editor-hover { border: 1px solid ${hoverBorder}; }`);
|
||||
collector.addRule(`.integrated-terminal .monaco-editor-hover .hover-row:not(:first-child):not(:empty) { border-top: 1px solid ${hoverBorder.transparent(0.5)}; }`);
|
||||
collector.addRule(`.integrated-terminal .monaco-editor-hover hr { border-top: 1px solid ${hoverBorder.transparent(0.5)}; }`);
|
||||
collector.addRule(`.integrated-terminal .monaco-editor-hover hr { border-bottom: 0px solid ${hoverBorder.transparent(0.5)}; }`);
|
||||
collector.addRule(`.integrated-terminal .monaco-hover { border: 1px solid ${hoverBorder}; }`);
|
||||
collector.addRule(`.integrated-terminal .monaco-hover .hover-row:not(:first-child):not(:empty) { border-top: 1px solid ${hoverBorder.transparent(0.5)}; }`);
|
||||
collector.addRule(`.integrated-terminal .monaco-hover hr { border-top: 1px solid ${hoverBorder.transparent(0.5)}; }`);
|
||||
collector.addRule(`.integrated-terminal .monaco-hover hr { border-bottom: 0px solid ${hoverBorder.transparent(0.5)}; }`);
|
||||
}
|
||||
const link = theme.getColor(textLinkForeground);
|
||||
if (link) {
|
||||
collector.addRule(`.integrated-terminal .monaco-editor-hover a { color: ${link}; }`);
|
||||
collector.addRule(`.integrated-terminal .monaco-hover a { color: ${link}; }`);
|
||||
}
|
||||
const hoverForeground = theme.getColor(editorHoverForeground);
|
||||
if (hoverForeground) {
|
||||
collector.addRule(`.integrated-terminal .monaco-editor-hover { color: ${hoverForeground}; }`);
|
||||
collector.addRule(`.integrated-terminal .monaco-hover { color: ${hoverForeground}; }`);
|
||||
}
|
||||
const actionsBackground = theme.getColor(editorHoverStatusBarBackground);
|
||||
if (actionsBackground) {
|
||||
collector.addRule(`.integrated-terminal .monaco-editor-hover .hover-row .actions { background-color: ${actionsBackground}; }`);
|
||||
collector.addRule(`.integrated-terminal .monaco-hover .hover-row .actions { background-color: ${actionsBackground}; }`);
|
||||
}
|
||||
const codeBackground = theme.getColor(textCodeBlockBackground);
|
||||
if (codeBackground) {
|
||||
collector.addRule(`.integrated-terminal .monaco-editor-hover code { background-color: ${codeBackground}; }`);
|
||||
collector.addRule(`.integrated-terminal .monaco-hover code { background-color: ${codeBackground}; }`);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -16,17 +16,26 @@ export const terminalConfiguration: IConfigurationNode = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
'terminal.integrated.automationShell.linux': {
|
||||
markdownDescription: localize('terminal.integrated.automationShell.linux', "A path that when set will override {0} and ignore {1} values for automation-related terminal usage like tasks and debug.", '`terminal.integrated.shell.linux`', '`shellArgs`'),
|
||||
markdownDescription: localize({
|
||||
key: 'terminal.integrated.automationShell.linux',
|
||||
comment: ['{0} and {1} are the `shell` and `shellArgs` settings keys']
|
||||
}, "A path that when set will override {0} and ignore {1} values for automation-related terminal usage like tasks and debug.", '`terminal.integrated.shell.linux`', '`shellArgs`'),
|
||||
type: ['string', 'null'],
|
||||
default: null
|
||||
},
|
||||
'terminal.integrated.automationShell.osx': {
|
||||
markdownDescription: localize('terminal.integrated.automationShell.osx', "A path that when set will override {0} and ignore {1} values for automation-related terminal usage like tasks and debug.", '`terminal.integrated.shell.osx`', '`shellArgs`'),
|
||||
markdownDescription: localize({
|
||||
key: 'terminal.integrated.automationShell.osx',
|
||||
comment: ['{0} and {1} are the `shell` and `shellArgs` settings keys']
|
||||
}, "A path that when set will override {0} and ignore {1} values for automation-related terminal usage like tasks and debug.", '`terminal.integrated.shell.osx`', '`shellArgs`'),
|
||||
type: ['string', 'null'],
|
||||
default: null
|
||||
},
|
||||
'terminal.integrated.automationShell.windows': {
|
||||
markdownDescription: localize('terminal.integrated.automationShell.windows', "A path that when set will override {0} and ignore {1} values for automation-related terminal usage like tasks and debug.", '`terminal.integrated.shell.windows`', '`shellArgs`'),
|
||||
markdownDescription: localize({
|
||||
key: 'terminal.integrated.automationShell.windows',
|
||||
comment: ['{0} and {1} are the `shell` and `shellArgs` settings keys']
|
||||
}, "A path that when set will override {0} and ignore {1} values for automation-related terminal usage like tasks and debug.", '`terminal.integrated.shell.windows`', '`shellArgs`'),
|
||||
type: ['string', 'null'],
|
||||
default: null
|
||||
},
|
||||
@@ -209,7 +218,7 @@ export const terminalConfiguration: IConfigurationNode = {
|
||||
default: false
|
||||
},
|
||||
'terminal.integrated.commandsToSkipShell': {
|
||||
markdownDescription: localize('terminal.integrated.commandsToSkipShell', "A set of command IDs whose keybindings will not be sent to the shell and instead always be handled by Code. This allows the use of keybindings that would normally be consumed by the shell to act the same as when the terminal is not focused, for example ctrl+p to launch Quick Open.\nDefault Skipped Commands:\n\n{0}", DEFAULT_COMMANDS_TO_SKIP_SHELL.sort().map(command => `- ${command}`).join('\n')),
|
||||
markdownDescription: localize('terminal.integrated.commandsToSkipShell', "A set of command IDs whose keybindings will not be sent to the shell and instead always be handled by Code. This allows the use of keybindings that would normally be consumed by the shell to act the same as when the terminal is not focused, for example ctrl+p to launch Quick Open. Use the command prefixed with `-` to remove default commands from the list.\nDefault Skipped Commands:\n\n{0}", DEFAULT_COMMANDS_TO_SKIP_SHELL.sort().map(command => `- ${command}`).join('\n')),
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string'
|
||||
|
||||
@@ -13,7 +13,6 @@ import { getSystemShell } from 'vs/workbench/contrib/terminal/node/terminal';
|
||||
import { Terminal as XTermTerminal } from 'xterm';
|
||||
import { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
|
||||
import { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode11';
|
||||
import { WebLinksAddon as XTermWebLinksAddon } from 'xterm-addon-web-links';
|
||||
import { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { getDefaultShell, getDefaultShellArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
|
||||
@@ -27,7 +26,6 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
let Terminal: typeof XTermTerminal;
|
||||
let SearchAddon: typeof XTermSearchAddon;
|
||||
let Unicode11Addon: typeof XTermUnicode11Addon;
|
||||
let WebLinksAddon: typeof XTermWebLinksAddon;
|
||||
let WebglAddon: typeof XTermWebglAddon;
|
||||
|
||||
export class TerminalInstanceService implements ITerminalInstanceService {
|
||||
@@ -51,13 +49,6 @@ export class TerminalInstanceService implements ITerminalInstanceService {
|
||||
return Terminal;
|
||||
}
|
||||
|
||||
public async getXtermWebLinksConstructor(): Promise<typeof XTermWebLinksAddon> {
|
||||
if (!WebLinksAddon) {
|
||||
WebLinksAddon = (await import('xterm-addon-web-links')).WebLinksAddon;
|
||||
}
|
||||
return WebLinksAddon;
|
||||
}
|
||||
|
||||
public async getXtermSearchConstructor(): Promise<typeof XTermSearchAddon> {
|
||||
if (!SearchAddon) {
|
||||
SearchAddon = (await import('xterm-addon-search')).SearchAddon;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ipcRenderer as ipc } from 'electron';
|
||||
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
|
||||
import { IOpenFileRequest } from 'vs/platform/windows/common/windows';
|
||||
import { ITerminalNativeService, LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -31,8 +31,8 @@ export class TerminalNativeService implements ITerminalNativeService {
|
||||
@IInstantiationService readonly instantiationService: IInstantiationService,
|
||||
@IRemoteAgentService remoteAgentService: IRemoteAgentService
|
||||
) {
|
||||
ipc.on('vscode:openFiles', (_event: any, request: IOpenFileRequest) => this._onOpenFileRequest.fire(request));
|
||||
ipc.on('vscode:osResume', () => this._onOsResume.fire());
|
||||
ipcRenderer.on('vscode:openFiles', (event: unknown, request: IOpenFileRequest) => this._onOpenFileRequest.fire(request));
|
||||
ipcRenderer.on('vscode:osResume', () => this._onOsResume.fire());
|
||||
|
||||
const connection = remoteAgentService.getConnection();
|
||||
if (connection && connection.remoteAuthority) {
|
||||
|
||||
@@ -29,7 +29,7 @@ export class CreateNewLocalTerminalAction extends Action {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
public run(event?: any): Promise<any> {
|
||||
public run(): Promise<any> {
|
||||
const instance = this.terminalService.createTerminal({ cwd: URI.file(homedir()) });
|
||||
if (!instance) {
|
||||
return Promise.resolve(undefined);
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { OperatingSystem } from 'vs/base/common/platform';
|
||||
import { TerminalLinkManager, LineColumnInfo, XtermLinkMatcherHandler } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { TerminalLinkManager, XtermLinkMatcherHandler } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager';
|
||||
import { Terminal as XtermTerminal } from 'xterm';
|
||||
import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { ITerminalConfigHelper } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { TestPathService, TestEnvironmentService } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||
import { IPathService } from 'vs/workbench/services/path/common/pathService';
|
||||
@@ -21,12 +20,6 @@ class TestTerminalLinkManager extends TerminalLinkManager {
|
||||
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);
|
||||
}
|
||||
@@ -39,11 +32,6 @@ class TestTerminalLinkManager extends TerminalLinkManager {
|
||||
}
|
||||
}
|
||||
|
||||
class TestXterm {
|
||||
public loadAddon() { }
|
||||
public registerLinkMatcher() { }
|
||||
}
|
||||
|
||||
class MockTerminalInstanceService implements ITerminalInstanceService {
|
||||
onRequestDefaultShellAndArgs?: Event<any> | undefined;
|
||||
getDefaultShellAndArgs(): Promise<{ shell: string; args: string | string[] | undefined; }> {
|
||||
@@ -59,9 +47,6 @@ class MockTerminalInstanceService implements ITerminalInstanceService {
|
||||
getXtermUnicode11Constructor(): Promise<any> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
async getXtermWebLinksConstructor(): Promise<any> {
|
||||
return (await import('xterm-addon-web-links')).WebLinksAddon;
|
||||
}
|
||||
getXtermWebglConstructor(): Promise<any> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
@@ -76,180 +61,26 @@ class MockTerminalInstanceService implements ITerminalInstanceService {
|
||||
}
|
||||
}
|
||||
|
||||
interface LinkFormatInfo {
|
||||
urlFormat: string;
|
||||
line?: string;
|
||||
column?: string;
|
||||
}
|
||||
|
||||
const testConfigHelper: ITerminalConfigHelper = <any>{
|
||||
config: {
|
||||
enableFileLinks: true
|
||||
}
|
||||
};
|
||||
|
||||
suite('Workbench - TerminalLinkHandler', () => {
|
||||
suite('Workbench - TerminalLinkManager', () => {
|
||||
let instantiationService: TestInstantiationService;
|
||||
|
||||
setup(() => {
|
||||
setup(async () => {
|
||||
const configurationService = new TestConfigurationService();
|
||||
await configurationService.setUserConfiguration('terminal', { integrated: { enableFileLinks: true } });
|
||||
|
||||
instantiationService = new TestInstantiationService();
|
||||
instantiationService.stub(IEnvironmentService, TestEnvironmentService);
|
||||
instantiationService.stub(IPathService, new TestPathService());
|
||||
instantiationService.stub(ITerminalInstanceService, new MockTerminalInstanceService());
|
||||
instantiationService.stub(IConfigurationService, new TestConfigurationService());
|
||||
});
|
||||
|
||||
suite('localLinkRegex', () => {
|
||||
test('Windows', () => {
|
||||
const terminalLinkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new TestXterm(), {
|
||||
os: OperatingSystem.Windows,
|
||||
userHome: ''
|
||||
} as any, testConfigHelper);
|
||||
function testLink(link: string, linkUrl: string, lineNo?: string, columnNo?: string) {
|
||||
assert.equal(terminalLinkHandler.extractLinkUrl(link), linkUrl);
|
||||
assert.equal(terminalLinkHandler.extractLinkUrl(`:${link}:`), linkUrl);
|
||||
assert.equal(terminalLinkHandler.extractLinkUrl(`;${link};`), linkUrl);
|
||||
assert.equal(terminalLinkHandler.extractLinkUrl(`(${link})`), linkUrl);
|
||||
|
||||
if (lineNo) {
|
||||
const lineColumnInfo: LineColumnInfo = terminalLinkHandler.extractLineColumnInfo(link);
|
||||
assert.equal(lineColumnInfo.lineNumber, lineNo, `For link ${link}, expected line number ${lineNo}, actual ${lineColumnInfo.lineNumber}`);
|
||||
|
||||
if (columnNo) {
|
||||
assert.equal(lineColumnInfo.columnNumber, columnNo, `For link ${link}, expected column number ${columnNo}, actual ${lineColumnInfo.columnNumber}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function generateAndTestLinks() {
|
||||
const linkUrls = [
|
||||
'c:\\foo',
|
||||
'\\\\?\\c:\\foo',
|
||||
'c:/foo',
|
||||
'.\\foo',
|
||||
'./foo',
|
||||
'..\\foo',
|
||||
'~\\foo',
|
||||
'~/foo',
|
||||
'c:/a/long/path',
|
||||
'c:\\a\\long\\path',
|
||||
'c:\\mixed/slash\\path',
|
||||
'a/relative/path',
|
||||
'plain/path',
|
||||
'plain\\path'
|
||||
];
|
||||
|
||||
const supportedLinkFormats: LinkFormatInfo[] = [
|
||||
{ urlFormat: '{0}' },
|
||||
{ urlFormat: '{0} on line {1}', line: '5' },
|
||||
{ urlFormat: '{0} on line {1}, column {2}', line: '5', column: '3' },
|
||||
{ urlFormat: '{0}:line {1}', line: '5' },
|
||||
{ urlFormat: '{0}:line {1}, column {2}', line: '5', column: '3' },
|
||||
{ urlFormat: '{0}({1})', line: '5' },
|
||||
{ urlFormat: '{0} ({1})', line: '5' },
|
||||
{ urlFormat: '{0}({1},{2})', line: '5', column: '3' },
|
||||
{ urlFormat: '{0} ({1},{2})', line: '5', column: '3' },
|
||||
{ urlFormat: '{0}({1}, {2})', line: '5', column: '3' },
|
||||
{ urlFormat: '{0} ({1}, {2})', line: '5', column: '3' },
|
||||
{ urlFormat: '{0}:{1}', line: '5' },
|
||||
{ urlFormat: '{0}:{1}:{2}', line: '5', column: '3' },
|
||||
{ urlFormat: '{0}[{1}]', line: '5' },
|
||||
{ urlFormat: '{0} [{1}]', line: '5' },
|
||||
{ urlFormat: '{0}[{1},{2}]', line: '5', column: '3' },
|
||||
{ urlFormat: '{0} [{1},{2}]', line: '5', column: '3' },
|
||||
{ urlFormat: '{0}[{1}, {2}]', line: '5', column: '3' },
|
||||
{ urlFormat: '{0} [{1}, {2}]', line: '5', column: '3' },
|
||||
{ urlFormat: '"{0}",{1}', line: '5' }
|
||||
];
|
||||
|
||||
linkUrls.forEach(linkUrl => {
|
||||
supportedLinkFormats.forEach(linkFormatInfo => {
|
||||
testLink(
|
||||
strings.format(linkFormatInfo.urlFormat, linkUrl, linkFormatInfo.line, linkFormatInfo.column),
|
||||
linkUrl,
|
||||
linkFormatInfo.line,
|
||||
linkFormatInfo.column
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
generateAndTestLinks();
|
||||
});
|
||||
|
||||
test('Linux', () => {
|
||||
const terminalLinkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new TestXterm(), {
|
||||
os: OperatingSystem.Linux,
|
||||
userHome: ''
|
||||
} as any, testConfigHelper);
|
||||
function testLink(link: string, linkUrl: string, lineNo?: string, columnNo?: string) {
|
||||
assert.equal(terminalLinkHandler.extractLinkUrl(link), linkUrl);
|
||||
assert.equal(terminalLinkHandler.extractLinkUrl(`:${link}:`), linkUrl);
|
||||
assert.equal(terminalLinkHandler.extractLinkUrl(`;${link};`), linkUrl);
|
||||
assert.equal(terminalLinkHandler.extractLinkUrl(`(${link})`), linkUrl);
|
||||
|
||||
if (lineNo) {
|
||||
const lineColumnInfo: LineColumnInfo = terminalLinkHandler.extractLineColumnInfo(link);
|
||||
assert.equal(lineColumnInfo.lineNumber, lineNo, `For link ${link}, expected line number ${lineNo}, actual ${lineColumnInfo.lineNumber}`);
|
||||
|
||||
if (columnNo) {
|
||||
assert.equal(lineColumnInfo.columnNumber, columnNo, `For link ${link}, expected column number ${columnNo}, actual ${lineColumnInfo.columnNumber}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function generateAndTestLinks() {
|
||||
const linkUrls = [
|
||||
'/foo',
|
||||
'~/foo',
|
||||
'./foo',
|
||||
'../foo',
|
||||
'/a/long/path',
|
||||
'a/relative/path'
|
||||
];
|
||||
|
||||
const supportedLinkFormats: LinkFormatInfo[] = [
|
||||
{ urlFormat: '{0}' },
|
||||
{ urlFormat: '{0} on line {1}', line: '5' },
|
||||
{ urlFormat: '{0} on line {1}, column {2}', line: '5', column: '3' },
|
||||
{ urlFormat: '{0}:line {1}', line: '5' },
|
||||
{ urlFormat: '{0}:line {1}, column {2}', line: '5', column: '3' },
|
||||
{ urlFormat: '{0}({1})', line: '5' },
|
||||
{ urlFormat: '{0} ({1})', line: '5' },
|
||||
{ urlFormat: '{0}({1},{2})', line: '5', column: '3' },
|
||||
{ urlFormat: '{0} ({1},{2})', line: '5', column: '3' },
|
||||
{ urlFormat: '{0}:{1}', line: '5' },
|
||||
{ urlFormat: '{0}:{1}:{2}', line: '5', column: '3' },
|
||||
{ urlFormat: '{0}[{1}]', line: '5' },
|
||||
{ urlFormat: '{0} [{1}]', line: '5' },
|
||||
{ urlFormat: '{0}[{1},{2}]', line: '5', column: '3' },
|
||||
{ urlFormat: '{0} [{1},{2}]', line: '5', column: '3' },
|
||||
{ urlFormat: '"{0}",{1}', line: '5' }
|
||||
];
|
||||
|
||||
linkUrls.forEach(linkUrl => {
|
||||
supportedLinkFormats.forEach(linkFormatInfo => {
|
||||
// console.log('linkFormatInfo: ', linkFormatInfo);
|
||||
testLink(
|
||||
strings.format(linkFormatInfo.urlFormat, linkUrl, linkFormatInfo.line, linkFormatInfo.column),
|
||||
linkUrl,
|
||||
linkFormatInfo.line,
|
||||
linkFormatInfo.column
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
generateAndTestLinks();
|
||||
});
|
||||
instantiationService.stub(IConfigurationService, configurationService);
|
||||
});
|
||||
|
||||
suite('preprocessPath', () => {
|
||||
test('Windows', () => {
|
||||
const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new TestXterm() as any, {
|
||||
const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new XtermTerminal() as any, {
|
||||
os: OperatingSystem.Windows,
|
||||
userHome: 'C:\\Users\\Me'
|
||||
} as any, testConfigHelper);
|
||||
} as any);
|
||||
linkHandler.processCwd = 'C:\\base';
|
||||
|
||||
assert.equal(linkHandler.preprocessPath('./src/file1'), 'C:\\base\\src\\file1');
|
||||
@@ -260,10 +91,10 @@ suite('Workbench - TerminalLinkHandler', () => {
|
||||
assert.equal(linkHandler.preprocessPath('\\\\?\\C:\\absolute\\path\\extended\\file6'), 'C:\\absolute\\path\\extended\\file6');
|
||||
});
|
||||
test('Windows - spaces', () => {
|
||||
const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new TestXterm() as any, {
|
||||
const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new XtermTerminal() as any, {
|
||||
os: OperatingSystem.Windows,
|
||||
userHome: 'C:\\Users\\M e'
|
||||
} as any, testConfigHelper);
|
||||
} as any);
|
||||
linkHandler.processCwd = 'C:\\base dir';
|
||||
|
||||
assert.equal(linkHandler.preprocessPath('./src/file1'), 'C:\\base dir\\src\\file1');
|
||||
@@ -274,10 +105,10 @@ suite('Workbench - TerminalLinkHandler', () => {
|
||||
});
|
||||
|
||||
test('Linux', () => {
|
||||
const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new TestXterm() as any, {
|
||||
const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new XtermTerminal() as any, {
|
||||
os: OperatingSystem.Linux,
|
||||
userHome: '/home/me'
|
||||
} as any, testConfigHelper);
|
||||
} as any);
|
||||
linkHandler.processCwd = '/base';
|
||||
|
||||
assert.equal(linkHandler.preprocessPath('./src/file1'), '/base/src/file1');
|
||||
@@ -287,10 +118,10 @@ suite('Workbench - TerminalLinkHandler', () => {
|
||||
});
|
||||
|
||||
test('No Workspace', () => {
|
||||
const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new TestXterm() as any, {
|
||||
const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new XtermTerminal() as any, {
|
||||
os: OperatingSystem.Linux,
|
||||
userHome: '/home/me'
|
||||
} as any, testConfigHelper);
|
||||
} as any);
|
||||
|
||||
assert.equal(linkHandler.preprocessPath('./src/file1'), null);
|
||||
assert.equal(linkHandler.preprocessPath('src/file2'), null);
|
||||
@@ -299,43 +130,14 @@ suite('Workbench - TerminalLinkHandler', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('gitDiffLinkRegex', () => {
|
||||
// The platform is irrelevant because the links generated by Git are the same format regardless of platform
|
||||
const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new TestXterm() as any, {
|
||||
os: OperatingSystem.Linux,
|
||||
userHome: ''
|
||||
} as any, testConfigHelper);
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
suite('wrapLinkHandler', () => {
|
||||
const nullMouseEvent: any = Object.freeze({ preventDefault: () => { } });
|
||||
|
||||
test('should allow intercepting of links with onBeforeHandleLink', async () => {
|
||||
const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new TestXterm() as any, {
|
||||
const linkHandler: TestTerminalLinkManager = instantiationService.createInstance(TestTerminalLinkManager, new XtermTerminal() as any, {
|
||||
os: OperatingSystem.Linux,
|
||||
userHome: ''
|
||||
} as any, testConfigHelper);
|
||||
} as any);
|
||||
linkHandler.onBeforeHandleLink(e => {
|
||||
if (e.link === 'https://www.microsoft.com') {
|
||||
intercepted = true;
|
||||
|
||||
Reference in New Issue
Block a user