From 559af16e709c2a87b6e319dcf18b2d8b2c400f1a Mon Sep 17 00:00:00 2001 From: Sven Efftinge Date: Wed, 15 May 2019 13:20:05 +0000 Subject: [PATCH] [terminal] activate links with cmd + click Signed-off-by: Sven Efftinge --- .../src/browser/terminal-widget-impl.ts | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/packages/terminal/src/browser/terminal-widget-impl.ts b/packages/terminal/src/browser/terminal-widget-impl.ts index 28fcd335ea695..a429a0921484e 100644 --- a/packages/terminal/src/browser/terminal-widget-impl.ts +++ b/packages/terminal/src/browser/terminal-widget-impl.ts @@ -60,6 +60,7 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget protected restored = false; protected closeOnDispose = true; protected waitForConnection: Deferred | undefined; + protected hoverMessage: HTMLDivElement; @inject(WorkspaceService) protected readonly workspaceService: WorkspaceService; @inject(WebSocketConnectionProvider) protected readonly webSocketConnectionProvider: WebSocketConnectionProvider; @@ -112,6 +113,25 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget }, }); + this.hoverMessage = document.createElement('div'); + if (isOSX) { + this.hoverMessage.textContent = 'Cmd + click to follow link'; + } else { + this.hoverMessage.textContent = 'Ctrl + click to follow link'; + } + this.hoverMessage.textContent = 'Cmd + click to follow link'; + this.hoverMessage.style.position = 'fixed'; + this.hoverMessage.style.color = 'var(--theia-ui-font-color1)'; + this.hoverMessage.style.backgroundColor = 'var(--theia-layout-color1)'; + this.hoverMessage.style.borderColor = 'var(--theia-layout-color3)'; + this.hoverMessage.style.borderWidth = '0.5px'; + this.hoverMessage.style.borderStyle = 'solid'; + this.hoverMessage.style.padding = '5px'; + this.hoverMessage.style.zIndex = '1'; + // initially invisible + this.hoverMessage.style.display = 'none'; + this.node.appendChild(this.hoverMessage); + this.toDispose.push(this.preferences.onPreferenceChanged(change => { const lastSeparator = change.preferenceName.lastIndexOf('.'); if (lastSeparator > 0) { @@ -169,7 +189,41 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget protected async registerLinkMatchers() { for (const linkMatcher of this.terminalLinkMatchers.getContributions()) { const regexp = await linkMatcher.getRegex(); - const matcherId = this.term.registerLinkMatcher(regexp, linkMatcher.handler, linkMatcher.options); + const isCmdClickBehavior = !linkMatcher.options || !linkMatcher.options.tooltipCallback; + let matcherId: number; + if (!isCmdClickBehavior) { + matcherId = this.term.registerLinkMatcher(regexp, (event, uri) => linkMatcher.handler(event, uri), linkMatcher.options); + } else { + const wrapped = (event: MouseEvent, uri: string) => { + event.preventDefault(); + if (this.isCommandPressed(event)) { + linkMatcher.handler(event, uri); + } else { + this.term.focus(); + } + }; + matcherId = this.term.registerLinkMatcher(regexp, wrapped, { + ...linkMatcher.options, + willLinkActivate: (event: MouseEvent, uri: string) => { + if (linkMatcher.options && linkMatcher.options.willLinkActivate) { + return linkMatcher.options.willLinkActivate(event, uri); + } + return this.isCommandPressed(event); + }, + tooltipCallback: (event: MouseEvent, uri: string) => { + this.showClickCommandHover(event); + if (linkMatcher.options && linkMatcher.options.tooltipCallback) { + linkMatcher.options.tooltipCallback(event, uri); + } + }, + leaveCallback: (event: MouseEvent, uri: string) => { + this.hideClickCommandHover(); + if (linkMatcher.options && linkMatcher.options.leaveCallback) { + linkMatcher.options.leaveCallback(event, uri); + } + } + }); + } this.toDispose.push({ dispose: () => { this.term.deregisterLinkMatcher(matcherId); @@ -178,6 +232,20 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget } } + protected showClickCommandHover(event: MouseEvent) { + this.hoverMessage.style.display = 'inline'; + this.hoverMessage.style.top = `${event.clientY - 30}px`; + this.hoverMessage.style.left = `${event.clientX - 60}px`; + } + + protected hideClickCommandHover() { + this.hoverMessage.style.display = 'none'; + } + + protected isCommandPressed(event: MouseEvent) { + return isOSX ? event.metaKey : event.ctrlKey; + } + get processId(): Promise { return (async () => { if (!IBaseTerminalServer.validateId(this.terminalId)) {