|
3 | 3 | * Licensed under the MIT License. See License.txt in the project root for license information. |
4 | 4 | *--------------------------------------------------------------------------------------------*/ |
5 | 5 |
|
6 | | -import { DeferredPromise, disposableTimeout, timeout } from '../../../../../base/common/async.js'; |
| 6 | +import { DeferredPromise, disposableTimeout } from '../../../../../base/common/async.js'; |
7 | 7 | import type { CancellationToken } from '../../../../../base/common/cancellation.js'; |
8 | 8 | import { Codicon } from '../../../../../base/common/codicons.js'; |
9 | 9 | import { CancellationError } from '../../../../../base/common/errors.js'; |
10 | | -import { DisposableStore } from '../../../../../base/common/lifecycle.js'; |
| 10 | +import { DisposableStore, MutableDisposable } from '../../../../../base/common/lifecycle.js'; |
11 | 11 | import { ThemeIcon } from '../../../../../base/common/themables.js'; |
12 | 12 | import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js'; |
13 | 13 | import { TerminalCapability } from '../../../../../platform/terminal/common/capabilities/capabilities.js'; |
@@ -95,61 +95,52 @@ export class ToolTerminalCreator { |
95 | 95 | instance: ITerminalInstance, |
96 | 96 | timeoutMs: number |
97 | 97 | ): Promise<ShellIntegrationQuality> { |
98 | | - const dataFinished = new DeferredPromise<void>(); |
| 98 | + const store = new DisposableStore(); |
| 99 | + const result = new DeferredPromise<ShellIntegrationQuality>(); |
99 | 100 |
|
100 | | - const deferred = new DeferredPromise<ShellIntegrationQuality>(); |
101 | | - const timer = disposableTimeout(() => deferred.complete(ShellIntegrationQuality.None), timeoutMs); |
| 101 | + const siNoneTimer = store.add(new MutableDisposable()); |
| 102 | + siNoneTimer.value = disposableTimeout(() => result.complete(ShellIntegrationQuality.None), timeoutMs); |
102 | 103 |
|
103 | 104 | if (instance.capabilities.get(TerminalCapability.CommandDetection)?.hasRichCommandDetection) { |
104 | | - timer.dispose(); |
105 | | - deferred.complete(ShellIntegrationQuality.Rich); |
| 105 | + // Rich command detection is available immediately. |
| 106 | + siNoneTimer.clear(); |
| 107 | + result.complete(ShellIntegrationQuality.Rich); |
106 | 108 | } else { |
107 | | - const onSetRichCommandDetection = this._terminalService.createOnInstanceCapabilityEvent(TerminalCapability.CommandDetection, e => e.onSetRichCommandDetection); |
108 | | - |
109 | | - const richCommandDetectionListener = onSetRichCommandDetection.event((e) => { |
| 109 | + const onSetRichCommandDetection = store.add(this._terminalService.createOnInstanceCapabilityEvent(TerminalCapability.CommandDetection, e => e.onSetRichCommandDetection)); |
| 110 | + store.add(onSetRichCommandDetection.event((e) => { |
110 | 111 | if (e.instance !== instance) { |
111 | 112 | return; |
112 | 113 | } |
113 | | - deferred.complete(ShellIntegrationQuality.Rich); |
114 | | - }); |
115 | | - |
116 | | - const store = new DisposableStore(); |
| 114 | + siNoneTimer.clear(); |
| 115 | + // Rich command detection becomes available some time after the terminal is created. |
| 116 | + result.complete(ShellIntegrationQuality.Rich); |
| 117 | + })); |
117 | 118 |
|
118 | 119 | const commandDetection = instance.capabilities.get(TerminalCapability.CommandDetection); |
119 | 120 | if (commandDetection) { |
120 | | - timer.dispose(); |
| 121 | + siNoneTimer.clear(); |
121 | 122 | // When command detection lights up, allow up to 200ms for the rich command |
122 | 123 | // detection sequence to come in before declaring it as basic shell integration. |
123 | | - // up. |
124 | | - Promise.race([ |
125 | | - dataFinished.p, |
126 | | - timeout(200) |
127 | | - ]).then(() => { |
128 | | - if (!deferred.isResolved) { |
129 | | - deferred.complete(ShellIntegrationQuality.Basic); |
130 | | - } |
131 | | - }); |
| 124 | + store.add(disposableTimeout(() => { |
| 125 | + result.complete(ShellIntegrationQuality.Basic); |
| 126 | + }, 200)); |
132 | 127 | } else { |
133 | 128 | store.add(instance.capabilities.onDidAddCapabilityType(e => { |
134 | 129 | if (e === TerminalCapability.CommandDetection) { |
135 | | - timer.dispose(); |
| 130 | + siNoneTimer.clear(); |
136 | 131 | // When command detection lights up, allow up to 200ms for the rich command |
137 | | - // detection sequence to come in before declaring it as basic shell integration. |
138 | | - // up. |
139 | | - Promise.race([ |
140 | | - dataFinished.p, |
141 | | - timeout(200) |
142 | | - ]).then(() => deferred.complete(ShellIntegrationQuality.Basic)); |
| 132 | + // detection sequence to come in before declaring it as basic shell |
| 133 | + // integration. |
| 134 | + store.add(disposableTimeout(() => { |
| 135 | + result.complete(ShellIntegrationQuality.Basic); |
| 136 | + }, 200)); |
143 | 137 | } |
144 | 138 | })); |
145 | 139 | } |
146 | | - |
147 | | - deferred.p.finally(() => { |
148 | | - store.dispose(); |
149 | | - richCommandDetectionListener.dispose(); |
150 | | - }); |
151 | 140 | } |
152 | 141 |
|
153 | | - return deferred.p; |
| 142 | + result.p.finally(() => store.dispose()); |
| 143 | + |
| 144 | + return result.p; |
154 | 145 | } |
155 | 146 | } |
0 commit comments