From 3c9a78ac9f81917c53db6273e491ca5206a5c8f0 Mon Sep 17 00:00:00 2001 From: chris-010 <10660568+chris-010@users.noreply.github.com> Date: Mon, 17 Aug 2026 13:16:09 +0200 Subject: [PATCH] fix: accept a URI typed into the location bar from any location The location bar inherits its type from the tab's current location (Message::EditLocationEnable), and the view has exactly two branches, next to the existing "TODO: allow editing other locations": a Location::Network is edited through with_uri, anything else through with_path. Typing smb://server/share while standing in a local folder therefore produced Path("smb://server/share"), which is not a directory, and the navigation was dropped. The reverse direction was broken the same way: from the Networks view a local path was passed to with_uri and became a bogus network location. EditLocationSubmit now decides by parsing the text instead of by the location it came from: * parses as a URL with a scheme other than "file" and has a host -> Location::Network, using url::Url::as_str(), which also normalizes away surrounding whitespace. * fails to parse and the current location is a Network -> Location::Path, with the text untrimmed, because a directory name may legitimately end in a space. * anything else is left as it was, so network:/// and foo:bar keep behaving exactly as before. The reliable indicator for "this is a path" is that parsing fails, not that the host is missing: network:/// and file:///home both parse with has_host() == false. Verified against url 2.5.8. An unmounted share cannot be resolved, since Tab::resolve sends network locations through mounter.dir_info, so resolve() returns None and the navigation would be dropped again. Navigating there is what triggers the mount, because Cmd::NetworkScan mounts the location it is asked to scan, so the typed URI is used as a fallback. That fallback is restricted to input recognised by the first rule above; applying it to any network location would let unparseable text through, and because with_uri keeps the display name and path of the previous location, the window would look normal while the listing stayed empty. Known cosmetic side effect: while the share is not mounted, resolve() yields nothing and the tab shows the raw URI as its name. It is replaced by the proper name as soon as the mount completes. Drafted with AI assistance (Claude Code); the change was reviewed, built and tested by me on real hardware as described. Signed-off-by: chris-010 <10660568+chris-010@users.noreply.github.com> --- src/tab.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/tab.rs b/src/tab.rs index 337ba6b..0da0db2 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -3861,6 +3861,28 @@ impl Tab { } Message::EditLocationSubmit => { if let Some(mut edit_location) = self.edit_location.take() { + let typed_opt = match &edit_location.location { + Location::Path(path) => path.to_str().map(str::to_string), + Location::Network(uri, ..) => Some(uri.clone()), + _ => None, + }; + let mut typed_uri = false; + if let Some(typed) = typed_opt { + match typed.trim().parse::() { + Ok(url) if url.scheme() != "file" && url.has_host() => { + let uri = url.as_str().to_string(); + edit_location = + Location::Network(uri.clone(), uri, None).normalize().into(); + typed_uri = true; + } + Err(_) if matches!(edit_location.location, Location::Network(..)) => { + edit_location = + Location::Path(PathBuf::from(typed)).normalize().into(); + } + _ => {} + } + } + // Select first completion if current location does not exist if edit_location.selected.is_none() && edit_location @@ -3876,6 +3898,9 @@ impl Tab { } cd = edit_location.resolve(); + if cd.is_none() && typed_uri { + cd = Some(edit_location.location); + } } } Message::EditLocationTab => {