From f4a80ef0a51e31351a808fc539267053d1a15fe5 Mon Sep 17 00:00:00 2001 From: Daniel Brooks Date: Fri, 5 Jul 2024 06:47:53 -0700 Subject: [PATCH] print an OSC8 hyperlink around the filename when -n is specified This lets the user to open the file by clicking on or otherwise selecting the hyperlink in their terminal emulator. --- Cargo.lock | 18 ++++++++++++++++++ Cargo.toml | 2 ++ src/app.rs | 28 +++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index a1124b8..2335699 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + [[package]] name = "cfg-if" version = "1.0.0" @@ -319,6 +325,16 @@ dependencies = [ "spin", ] +[[package]] +name = "gethostname" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +dependencies = [ + "libc", + "windows-targets 0.48.5", +] + [[package]] name = "gif" version = "0.12.0" @@ -704,9 +720,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" name = "viu" version = "1.5.0" dependencies = [ + "bytes", "clap", "crossterm", "ctrlc", + "gethostname", "image", "viuer", ] diff --git a/Cargo.toml b/Cargo.toml index 6ff19e8..1ae6762 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,8 @@ crossterm = "0.27" viuer = "0.7.1" ctrlc = { version = "3.4", features = ["termination"] } image = "0.24" +gethostname = "0.4" +bytes = "1.6" [features] default = [] diff --git a/src/app.rs b/src/app.rs index 424bc6f..8db2791 100644 --- a/src/app.rs +++ b/src/app.rs @@ -116,7 +116,33 @@ fn view_directory(conf: &Config, dirname: &str, (tx, rx): TxRx) -> ViuResult { fn view_file(conf: &Config, filename: &str, (tx, rx): TxRx) -> ViuResult { if conf.name { - println!("{}:", filename); + if let Ok(path) = std::fs::canonicalize(filename) { + // In principle, we are doing this: + // println!("{osc}8;;file://{hostname}{path}{st}{filename}{osc}8;;{st}:", hostname=gethostname().to_string_lossy(), path=path.display()); + // but without ever putting anything into a utf8 string + use bytes::BufMut; + use std::os::unix::ffi::OsStrExt; + use std::io::Write; + let osc = b"\x1b]"; + let st = b"\x1b\\"; + let hostname = gethostname::gethostname(); + let path = path.into_os_string(); + let len = 23 + hostname.len() + path.len(); + let mut buf = bytes::BytesMut::with_capacity(len); + buf.extend_from_slice(osc); + buf.put(&b"8;;file://"[..]); + buf.put(hostname.as_bytes()); + buf.put(path.as_bytes()); + buf.extend_from_slice(st); + buf.put(filename.as_bytes()); + buf.extend_from_slice(osc); + buf.put(&b"8;;"[..]); + buf.extend_from_slice(st); + buf.put(&b":\n"[..]); + stdout().lock().write_all(&buf)?; + } else { + println!("{filename}:"); + } } let mut file_in = fs::File::open(filename)?;