From 1fcb5fa57586d09ab550085e53ec203a2ba82e43 Mon Sep 17 00:00:00 2001 From: Andy Dixon Date: Mon, 12 Oct 2026 18:40:11 +0100 Subject: [PATCH] feat: the SFTP browser opens in the shell's current directory (OSC 7) When the remote shell reports its working directory (OSC 7: fish, or the bash/zsh hook in the manual), opening the SFTP browser from that terminal goes there, including when it was already open elsewhere. Without it the browser still falls back to the exec'd 'pwd' (the login directory) and then the SFTP home. The File menu entry now goes through the same request as the toolbar and palette. --- rust/app/src/app.rs | 8 +++++++- rust/app/src/chrome.rs | 2 +- rust/app/src/sftp.rs | 15 +++++++++++++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/rust/app/src/app.rs b/rust/app/src/app.rs index dc6b315..82a167a 100644 --- a/rust/app/src/app.rs +++ b/rust/app/src/app.rs @@ -614,7 +614,13 @@ impl App { } Request::ExportEncrypted(ids) => self.transfer.export_encrypted(ids), Request::ImportEncrypted => self.transfer.import_encrypted(), - Request::Sftp(id) => self.sftp.toggle(&id), + Request::Sftp(id) => { + let at = match self.s.pane(&id).map(|p| &p.view) { + Some(View::Terminal(t)) => t.reported_cwd.as_ref().map(|c| c.1.clone()), + _ => None, + }; + self.sftp.toggle(&id, at); + } Request::SendToActive(text) => match self.s.focused_session() { Some(id) if self.s.session_state(&id) == Some(SessionState::Connected) => self.send_input(&id, text.as_bytes()), _ => self.s.error("No active connected session"), diff --git a/rust/app/src/chrome.rs b/rust/app/src/chrome.rs index e37c346..caf7d05 100644 --- a/rust/app/src/chrome.rs +++ b/rust/app/src/chrome.rs @@ -132,7 +132,7 @@ pub fn title_bar(app: &mut App, ui: &mut Ui) { if item(ui, icon::FOLDER_OPEN, "SFTP browser", "") && let Some(f) = focused.clone() { - app.sftp.toggle(&f); + app.s.request(crate::state::Request::Sftp(f)); } if item(ui, icon::ARROWS_LEFT_RIGHT, "Port forwards", "") && let Some(f) = focused.clone() diff --git a/rust/app/src/sftp.rs b/rust/app/src/sftp.rs index 3b37ff1..344d44a 100644 --- a/rust/app/src/sftp.rs +++ b/rust/app/src/sftp.rs @@ -109,6 +109,8 @@ pub struct Sftp { /// Profile id (or host:port for quick connects) → bookmarked paths. Loaded on first use. bookmarks: Option>>, inbox: Arc>>, + /// Where a browser opened from a terminal should start: the directory its shell reported. + start_at: HashMap, } // --- path helpers --------------------------------------------------------------------------- @@ -215,11 +217,16 @@ fn state_line(ui: &mut Ui, loading: bool, error: Option<&str>) -> bool { } impl Sftp { - pub fn toggle(&mut self, session: &str) { + /// Opens (or closes) the browser for `session`; `at` is the shell's reported directory, which + /// the browser goes to when it opens. + pub fn toggle(&mut self, session: &str, at: Option) { if self.open_for.as_deref() == Some(session) { self.close(session); } else { self.open_for = Some(session.into()); + if let Some(dir) = at.filter(|d| d.starts_with('/')) { + self.start_at.insert(session.into(), dir); + } } } @@ -488,7 +495,11 @@ impl Sftp { let Some(session) = self.open_for.clone() else { return; }; - if !self.panels.contains_key(&session) { + if let Some(dir) = self.start_at.remove(&session) { + if self.panels.get(&session).is_none_or(|p| p.cwd != dir) { + self.navigate(s, &session, Some(dir)); + } + } else if !self.panels.contains_key(&session) { self.navigate(s, &session, None); } let t = Tokens::get(ui.ctx());