|
5 | 5 |
|
6 | 6 | import * as vscode from 'vscode'; |
7 | 7 | import * as util from 'util'; |
| 8 | +import * as nls from 'vscode-nls'; |
| 9 | + |
| 10 | +const localize = nls.loadMessageBundle(); |
8 | 11 |
|
9 | 12 | const PATTERN = 'listening on.* (https?://\\S+|[0-9]+)'; // matches "listening on port 3000" or "Now listening on: https://localhost:5001" |
10 | 13 | const URI_FORMAT = 'http://localhost:%s'; |
@@ -85,24 +88,44 @@ class ServerReadyDetector extends vscode.Disposable { |
85 | 88 | detectPattern(s: string): void { |
86 | 89 |
|
87 | 90 | if (!this.hasFired) { |
88 | | - const result = this.regexp.exec(s); |
89 | | - if (result && result.length === 2) { |
90 | | - this.openExternalWithString(this.session, result[1]); |
| 91 | + const matches = this.regexp.exec(s); |
| 92 | + if (matches && matches.length >= 1) { |
| 93 | + this.openExternalWithString(this.session, matches.length > 1 ? matches[1] : ''); |
91 | 94 | this.hasFired = true; |
92 | 95 | this.internalDispose(); |
93 | 96 | } |
94 | 97 | } |
95 | 98 | } |
96 | 99 |
|
97 | | - private openExternalWithString(session: vscode.DebugSession, portOrUriString: string) { |
| 100 | + private openExternalWithString(session: vscode.DebugSession, captureString: string) { |
98 | 101 |
|
99 | | - if (portOrUriString) { |
100 | | - if (/^[0-9]+$/.test(portOrUriString)) { |
101 | | - const args: ServerReadyAction = session.configuration.serverReadyAction; |
102 | | - portOrUriString = util.format(args.uriFormat || URI_FORMAT, portOrUriString); |
| 102 | + const args: ServerReadyAction = session.configuration.serverReadyAction; |
| 103 | + const format = args.uriFormat || URI_FORMAT; |
| 104 | + |
| 105 | + if (captureString === '') { |
| 106 | + // nothing captured by reg exp -> use the uriFormat as the target url without substitution |
| 107 | + // verify that format does not contain '%s' |
| 108 | + if (format.indexOf('%s') >= 0) { |
| 109 | + const errMsg = localize('server.ready.nocapture.error', "Format uri ('{0}') uses a substitution placeholder but pattern did not capture anything.", format); |
| 110 | + vscode.window.showErrorMessage(errMsg, { modal: true }).then(_ => undefined); |
| 111 | + return; |
103 | 112 | } |
104 | | - this.openExternalWithUri(session, portOrUriString); |
| 113 | + captureString = format; |
| 114 | + } else if (/^[0-9]+$/.test(captureString)) { |
| 115 | + // looks like a port number -> use the uriFormat and substitute a single "%s" with the port |
| 116 | + // verify that format only contains a single '%s' |
| 117 | + const s = format.split('%s'); |
| 118 | + if (s.length !== 2) { |
| 119 | + const errMsg = localize('server.ready.placeholder.error', "Format uri ('{0}') must contain exactly one substitution placeholder.", format); |
| 120 | + vscode.window.showErrorMessage(errMsg, { modal: true }).then(_ => undefined); |
| 121 | + return; |
| 122 | + } |
| 123 | + captureString = util.format(format, captureString); |
| 124 | + } else { |
| 125 | + // use the string as is |
105 | 126 | } |
| 127 | + |
| 128 | + this.openExternalWithUri(session, captureString); |
106 | 129 | } |
107 | 130 |
|
108 | 131 | private openExternalWithUri(session: vscode.DebugSession, uri: string) { |
|
0 commit comments