@@ -7,6 +7,7 @@ import type { CancellationToken } from '../../../../../../base/common/cancellati
7
7
import { CancellationError } from '../../../../../../base/common/errors.js' ;
8
8
import { Event } from '../../../../../../base/common/event.js' ;
9
9
import { DisposableStore } from '../../../../../../base/common/lifecycle.js' ;
10
+ import { isNumber } from '../../../../../../base/common/types.js' ;
10
11
import type { ICommandDetectionCapability } from '../../../../../../platform/terminal/common/capabilities/capabilities.js' ;
11
12
import { ITerminalLogService } from '../../../../../../platform/terminal/common/terminal.js' ;
12
13
import type { ITerminalInstance } from '../../../../terminal/browser/terminal.js' ;
@@ -80,14 +81,22 @@ export class BasicExecuteStrategy implements ITerminalExecuteStrategy {
80
81
this . _logService . debug ( 'RunInTerminalTool#Basic: Waiting for idle' ) ;
81
82
await waitForIdle ( this . _instance . onData , 1000 ) ;
82
83
84
+ // Record where the command started. If the marker gets disposed, re-created it where
85
+ // the cursor is. This can happen in prompts where they clear the line and rerender it
86
+ // like powerlevel10k's transient prompt
87
+ let startMarker = store . add ( xterm . raw . registerMarker ( ) ) ;
88
+ store . add ( startMarker . onDispose ( ( ) => {
89
+ this . _logService . debug ( `RunInTerminalTool#Basic: Start marker was disposed, recreating` ) ;
90
+ startMarker = xterm . raw . registerMarker ( ) ;
91
+ } ) ) ;
92
+
83
93
// Execute the command
84
- const startMarker = store . add ( xterm . raw . registerMarker ( ) ) ;
85
94
this . _logService . debug ( `RunInTerminalTool#Basic: Executing command line \`${ commandLine } \`` ) ;
86
95
this . _instance . runCommand ( commandLine , true ) ;
87
96
88
97
// Wait for the next end execution event - note that this may not correspond to the actual
89
98
// execution requested
90
- const doneData = await onDone ;
99
+ const finishedCommand = await onDone ;
91
100
92
101
// Wait for the terminal to idle
93
102
this . _logService . debug ( 'RunInTerminalTool#Basic: Waiting for idle' ) ;
@@ -98,13 +107,36 @@ export class BasicExecuteStrategy implements ITerminalExecuteStrategy {
98
107
const endMarker = store . add ( xterm . raw . registerMarker ( ) ) ;
99
108
100
109
// Assemble final result
101
- let result = xterm . getContentsAsText ( startMarker , endMarker ) ;
102
- if ( doneData && typeof doneData . exitCode === 'number' && doneData . exitCode > 0 ) {
103
- result += `\n\nCommand exited with code ${ doneData . exitCode } ` ;
110
+ let result : string | undefined ;
111
+ if ( finishedCommand ) {
112
+ const commandOutput = finishedCommand ?. getOutput ( ) ;
113
+ if ( commandOutput !== undefined ) {
114
+ this . _logService . debug ( 'RunInTerminalTool#Basic: Fetched output via finished command' ) ;
115
+ result = commandOutput ;
116
+ }
117
+ }
118
+ if ( result === undefined ) {
119
+ try {
120
+ result = xterm . getContentsAsText ( startMarker , endMarker ) ;
121
+ this . _logService . debug ( 'RunInTerminalTool#Basic: Fetched output via markers' ) ;
122
+ } catch {
123
+ this . _logService . debug ( 'RunInTerminalTool#Basic: Failed to fetch output via markers' ) ;
124
+ result = 'Failed to retrieve command output' ;
125
+ }
126
+ }
127
+
128
+ if ( result . trim ( ) . length === 0 ) {
129
+ result = 'Command produced no output' ;
104
130
}
131
+
132
+ const exitCode = finishedCommand ?. exitCode ;
133
+ if ( isNumber ( exitCode ) && exitCode > 0 ) {
134
+ result += `\n\nCommand exited with code ${ exitCode } ` ;
135
+ }
136
+
105
137
return {
106
138
result,
107
- exitCode : doneData ?. exitCode ,
139
+ exitCode,
108
140
} ;
109
141
} finally {
110
142
store . dispose ( ) ;
0 commit comments