aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJJ Liebig <jonathan.liebig@gmail.com>2026-08-17 22:29:47 +0200
committerGitHub <noreply@github.com>2026-08-17 23:29:47 +0300
commit19022d03c902de586009b1d156bc20b01ce48135 (patch)
treeb299bf56e5f3ab02cb900ada10ac3735661a3e05 /src
parent94093acb0aaefd7136108d402e25f3bdb86bde73 (diff)
fix: sync powershell process working directory (#2879)
Diffstat (limited to 'src')
-rw-r--r--src/pane.rs12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/pane.rs b/src/pane.rs
index a47e62eb..0b3edf7d 100644
--- a/src/pane.rs
+++ b/src/pane.rs
@@ -1474,8 +1474,8 @@ fn resolve_shell_for_login_mode(shell: &str) -> io::Result<String> {
/// wraps whatever `prompt` function the user's profile left behind so each
/// prompt render appends the cwd as OSC 9;9 — the sequence Windows Terminal
/// and ConEmu standardized for shell integration. PowerShell never updates
-/// its Win32 process cwd on `Set-Location`, so prompt-time reporting is the
-/// only reliable cwd source on Windows.
+/// its Win32 process cwd on `Set-Location`, so the prompt hook updates it when
+/// possible before reporting the cwd.
///
/// The snippet must not contain double quotes: powershell.exe parses its
/// command line with its own rules that disagree with the ArgvQuote escaping
@@ -1487,7 +1487,7 @@ fn resolve_shell_for_login_mode(shell: &str) -> io::Result<String> {
/// The original prompt must be invoked before any other statement in the
/// wrapper: anything that runs first resets `$?`, so a status-aware user
/// prompt would show success after a failed command (verified on 5.1).
-pub(crate) const WINDOWS_POWERSHELL_SHELL_INTEGRATION_COMMAND: &str = r"if ($null -eq $global:__HerdrOriginalPrompt) { $global:__HerdrOriginalPrompt = $function:prompt; function global:prompt { $out = @(& $global:__HerdrOriginalPrompt) -join ' '; $loc = $ExecutionContext.SessionState.Path.CurrentLocation; if ($loc.Provider.Name -eq 'FileSystem') { $esc = [string][char]27; $out += $esc + ']9;9;' + $loc.ProviderPath + $esc + '\' }; $out } }";
+pub(crate) const WINDOWS_POWERSHELL_SHELL_INTEGRATION_COMMAND: &str = r"if ($null -eq $global:__HerdrOriginalPrompt) { $global:__HerdrOriginalPrompt = $function:prompt; function global:prompt { $out = @(& $global:__HerdrOriginalPrompt) -join ' '; $loc = $ExecutionContext.SessionState.Path.CurrentLocation; if ($loc.Provider.Name -eq 'FileSystem') { try { [Environment]::CurrentDirectory = $loc.ProviderPath } catch {}; $esc = [string][char]27; $out += $esc + ']9;9;' + $loc.ProviderPath + $esc + '\' }; $out } }";
fn pane_shell_command_builder_for_target(
shell_config: PaneShellConfig<'_>,
@@ -3350,7 +3350,11 @@ mod tests {
}
let script = WINDOWS_POWERSHELL_SHELL_INTEGRATION_COMMAND;
- assert!(script.contains("]9;9;"), "missing OSC 9;9 emit: {script}");
+ let cwd_sync = script
+ .find("[Environment]::CurrentDirectory = $loc.ProviderPath")
+ .expect("wrapper must synchronize the Win32 process cwd");
+ let osc_report = script.find("]9;9;").expect("wrapper must emit OSC 9;9");
+ assert!(cwd_sync < osc_report, "cwd sync must precede OSC report");
assert!(
script.contains("$global:__HerdrOriginalPrompt = $function:prompt"),
"must wrap the profile-defined prompt: {script}"