From 8e4de5d5251e9c411271c1f1b06ee401cf4bab8a Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Sun, 16 Aug 2026 00:40:19 +0800 Subject: [PATCH] fix(ui): route every home lookup through the one that knows Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `path_display` opens by calling itself the one place a path is measured against `~`, because three rows spelling that check their own way is what #544 was. Three sites in src/ui had since gone back to reading the environment directly, and two of them read only `HOME` — the variable #544 recorded as "often unset" on Windows: - the file tree's fallback root, so a Windows window with no resolved root drew an empty tree instead of the home directory; - `expand_path`, so a `~/`-prefixed theme in config fell through to `themes_dir().join("~/theme.json")` — a path that cannot exist, and no error to say why. The third (the SFTP download directory) already checked `USERPROFILE`, but as a second copy of the canonical lookup under the same name, minus its empty-string filter: `HOME=` set-but-empty resolved downloads to a relative `Downloads`. It keeps its `.` last resort, which is a real difference worth stating rather than deleting — a download has to be offered somewhere, while every other caller wants the `None`. No behaviour change on Unix, where `HOME` was already the answer. --- src/ui/file_tree.rs | 4 ++-- src/ui/presets.rs | 4 ++-- src/ui/sftp.rs | 11 +++++++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/ui/file_tree.rs b/src/ui/file_tree.rs index 2eedc38d..07dcf014 100644 --- a/src/ui/file_tree.rs +++ b/src/ui/file_tree.rs @@ -782,9 +782,9 @@ impl Tty7App { } if roots.is_empty() && id.is_local() - && let Some(home) = std::env::var_os("HOME") + && let Some(home) = crate::ui::path_display::local_home() { - roots.push(PathBuf::from(home)); + roots.push(home); } let _ = window; let Some(code) = self.tab_code_mut_or_init() else { diff --git a/src/ui/presets.rs b/src/ui/presets.rs index d6b3a1e3..084642b9 100644 --- a/src/ui/presets.rs +++ b/src/ui/presets.rs @@ -941,9 +941,9 @@ impl FillFile { fn expand_path(p: &str) -> PathBuf { let p = p.trim(); if let Some(rest) = p.strip_prefix("~/") - && let Some(home) = std::env::var_os("HOME") + && let Some(home) = crate::ui::path_display::local_home() { - return PathBuf::from(home).join(rest); + return home.join(rest); } let path = PathBuf::from(p); if path.is_absolute() { diff --git a/src/ui/sftp.rs b/src/ui/sftp.rs index e723fd15..ba369bf5 100644 --- a/src/ui/sftp.rs +++ b/src/ui/sftp.rs @@ -310,11 +310,14 @@ fn mode_string(mode: u32) -> String { ) } +/// Where a download lands when nothing else says. +/// +/// The relative `.` is a last resort rather than a failure because a +/// download has to be offered somewhere; every other caller of +/// [`path_display::local_home`](crate::ui::path_display::local_home) wants +/// the `None` and shows the path whole instead. fn local_home() -> PathBuf { - std::env::var_os("HOME") - .or_else(|| std::env::var_os("USERPROFILE")) - .map(PathBuf::from) - .unwrap_or_else(|| PathBuf::from(".")) + crate::ui::path_display::local_home().unwrap_or_else(|| PathBuf::from(".")) } fn local_download_dir() -> PathBuf {