diff options
author | Daniel Hofstetter <daniel.hofstetter@42dh.com> | 2023-12-09 17:05:36 +0100 |
---|---|---|
committer | Daniel Hofstetter <daniel.hofstetter@42dh.com> | 2023-12-12 10:03:55 +0100 |
commit | 89cb4acb99593b6a85a9cc75e7623a3b1de82737 (patch) | |
tree | d81cd2990abd96ce0f1962f8f9d6f02a883d1efd | |
parent | 181cfc885b460bbcdf2cf1c866cb1ea48c3f6009 (diff) |
ls: encode path when using --hyperlink
-rw-r--r-- | src/uu/ls/src/ls.rs | 18 | ||||
-rw-r--r-- | tests/by-util/test_ls.rs | 32 |
2 files changed, 49 insertions, 1 deletions
diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index a5fe3d624..3cf848ae2 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -3019,7 +3019,23 @@ fn display_file_name( let absolute_path = fs::canonicalize(&path.p_buf).unwrap_or_default(); let absolute_path = absolute_path.to_string_lossy(); - // TODO encode path + #[cfg(not(target_os = "windows"))] + let unencoded_chars = "_-.:~/"; + #[cfg(target_os = "windows")] + let unencoded_chars = "_-.:~/\\"; + + // percentage encoding of path + let absolute_path: String = absolute_path + .chars() + .map(|c| { + if c.is_alphanumeric() || unencoded_chars.contains(c) { + c.to_string() + } else { + format!("%{:02x}", c as u8) + } + }) + .collect(); + // \x1b = ESC, \x07 = BEL name = format!("\x1b]8;;file://{hostname}{absolute_path}\x07{name}\x1b]8;;\x07"); } diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index c9f43028c..76cb0d216 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -3904,6 +3904,38 @@ fn test_ls_hyperlink() { .stdout_is(format!("{file}\n")); } +// spell-checker: disable +#[test] +fn test_ls_hyperlink_encode_link() { + let (at, mut ucmd) = at_and_ucmd!(); + + #[cfg(not(target_os = "windows"))] + { + at.touch("back\\slash"); + at.touch("ques?tion"); + } + at.touch("encoded%3Fquestion"); + at.touch("sp ace"); + + let result = ucmd.arg("--hyperlink").succeeds(); + #[cfg(not(target_os = "windows"))] + { + assert!(result + .stdout_str() + .contains("back%5cslash\x07back\\slash\x1b]8;;\x07")); + assert!(result + .stdout_str() + .contains("ques%3ftion\x07ques?tion\x1b]8;;\x07")); + } + assert!(result + .stdout_str() + .contains("encoded%253Fquestion\x07encoded%3Fquestion\x1b]8;;\x07")); + assert!(result + .stdout_str() + .contains("sp%20ace\x07sp ace\x1b]8;;\x07")); +} +// spell-checker: enable + #[test] fn test_ls_color_do_not_reset() { let scene: TestScenario = TestScenario::new(util_name!()); |