Skip to content

Commit 20575d1

Browse files
committed
refactor: simplify shell behavior for exec commands
- Remove interactive prompt setup for CMD and PowerShell when using exec commands. - Update CMD to use `/c` instead of `/k` for proper shell exit after exec commands. - Adjust PowerShell arguments to omit `-NoExit` for seamless shell termination post-execution. - Refactor script generation to streamline flow and exit behavior. fix: prevent prompt activity corruption during inactivity timeout - Stop activity monitor immediately upon detecting terminal inactivity to lock the last activity frame. - Ensure prompt isn't incorrectly recorded during the EndBuffer wait period.
1 parent 26ad787 commit 20575d1

2 files changed

Lines changed: 15 additions & 23 deletions

File tree

src/VcrSharp.Infrastructure/Processes/TtydProcess.cs

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,20 @@ public async Task StartAsync()
104104
args.Add(_shellCommand[0]); // Shell executable (e.g., "bash", "pwsh", "cmd")
105105

106106
// PowerShell: use script file to avoid command line length limits
107+
// Don't use -NoExit when we have Exec commands - shell should exit after commands complete
107108
if (shellName is "pwsh" or "powershell")
108109
{
109110
args.Add("-NoLogo");
110111
args.Add("-NoProfile");
111-
args.Add("-NoExit");
112112
_startupScriptPath = CreateStartupScriptFile(script, shellName);
113113
args.Add("-File");
114114
args.Add(_startupScriptPath);
115115
}
116116
else
117117
{
118-
args.Add(_shellConfig.ExecutionFlag); // Shell-specific flag (-c, /k)
118+
// For CMD, use /c (run and exit) instead of /k (run and remain) with Exec commands
119+
var execFlag = (shellName is "cmd" or "cmd.exe") ? "/c" : _shellConfig.ExecutionFlag;
120+
args.Add(execFlag);
119121
args.Add(script);
120122
}
121123
}
@@ -244,28 +246,11 @@ private string BuildStartupScript()
244246
// Generate shell-specific sleep command
245247
var sleepCommand = GetShellSpecificSleepCommand(_execStartDelay.TotalSeconds);
246248

247-
// Build the full script: sleep → prompt setup → exec commands
248-
// Exec commands must be LAST as they are the content being recorded
249+
// Build the full script: sleep → exec commands
250+
// Shell exits after commands complete (no return to interactive mode)
249251
var script = sleepCommand;
250252

251-
// Add prompt setup BEFORE exec commands
252-
if (!string.IsNullOrEmpty(_shellConfig.InteractiveReturnCommand))
253-
{
254-
script += $"{separator}{_shellConfig.InteractiveReturnCommand}";
255-
}
256-
else if (isCmd)
257-
{
258-
// CMD with /k stays interactive but needs prompt setup
259-
script += $"{separator}prompt $G$S";
260-
}
261-
else if (isPowerShell)
262-
{
263-
// PowerShell with -NoExit stays interactive, add prompt function
264-
script += $"{separator}Set-PSReadLineOption -HistorySaveStyle SaveNothing -PredictionSource None";
265-
script += $"{separator}function prompt {{ '> ' }}";
266-
}
267-
268-
// Exec commands run LAST (the content being recorded)
253+
// Exec commands run and then shell exits
269254
script += $"{separator}{commandChain}";
270255

271256
return script;

src/VcrSharp.Infrastructure/Session/VcrSession.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,9 +451,16 @@ private async Task WaitForInactivityAsync(CancellationToken cancellationToken)
451451
if (inactiveDuration >= inactivityTimeout)
452452
{
453453
// Terminal has been inactive long enough
454-
VcrLogger.Logger.Debug("Terminal inactive for {InactiveDuration}s, waiting end buffer",
454+
VcrLogger.Logger.Debug("Terminal inactive for {InactiveDuration}s, stopping activity monitor before end buffer",
455455
inactiveDuration.TotalSeconds);
456456

457+
// Stop activity monitor NOW to lock in the last activity frame
458+
// This prevents the prompt from being counted as activity during EndBuffer wait
459+
if (_activityMonitor != null)
460+
{
461+
await _activityMonitor.StopAsync();
462+
}
463+
457464
// Wait end buffer to capture final frames
458465
await Task.Delay(_options.EndBuffer, cancellationToken);
459466
break;

0 commit comments

Comments
 (0)