mirror of
https://github.com/gitui-org/gitui
synced 2026-05-23 08:58:21 +00:00
Copy text using OSC52 (#2548)
* Copy text using OSC52 if X/Wayland methods fail * Move Wayland/X string copying out of copy_string Copying logic seems too nested to comprehend with the introcution of two paths towards OSC52 otherwise. --------- Co-authored-by: Naseschwarz <naseschwarz@0x53a.de> Co-authored-by: extrawurst <776816+extrawurst@users.noreply.github.com>
This commit is contained in:
parent
381ab45d3a
commit
3c1e35eec7
4 changed files with 66 additions and 14 deletions
|
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Changed
|
||||
* improve syntax highlighting file detection [[@acuteenvy](https://github.com/acuteenvy)] ([#2524](https://github.com/extrawurst/gitui/pull/2524))
|
||||
* After commit: jump back to unstaged area [[@tommady](https://github.com/tommady)] ([#2476](https://github.com/extrawurst/gitui/issues/2476))
|
||||
* use OSC52 copying in case other methods fail [[@naseschwarz](https://github.com/naseschwarz)] ([#2366](https://github.com/gitui-org/gitui/issues/2366))
|
||||
|
||||
## [0.27.0] - 2024-01-14
|
||||
|
||||
|
|
|
|||
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1162,6 +1162,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"asyncgit",
|
||||
"backtrace",
|
||||
"base64",
|
||||
"bitflags 2.8.0",
|
||||
"bugreport",
|
||||
"bwrap",
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ build = "build.rs"
|
|||
anyhow = "1.0"
|
||||
asyncgit = { path = "./asyncgit", version = "0.27.0", default-features = false }
|
||||
backtrace = "0.3"
|
||||
base64 = "0.21"
|
||||
bitflags = "2.8"
|
||||
bugreport = "0.5.1"
|
||||
bwrap = { version = "1.3", features = ["use_std"] }
|
||||
|
|
|
|||
|
|
@ -63,33 +63,68 @@ fn is_wsl() -> bool {
|
|||
false
|
||||
}
|
||||
|
||||
// Copy text using escape sequence Ps = 5 2.
|
||||
// This enables copying even if there is no Wayland or X socket available,
|
||||
// e.g. via SSH, as long as it supported by the terminal.
|
||||
// See https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands
|
||||
#[cfg(any(
|
||||
all(target_family = "unix", not(target_os = "macos")),
|
||||
test
|
||||
))]
|
||||
fn copy_string_osc52(text: &str, out: &mut impl Write) -> Result<()> {
|
||||
use base64::prelude::{Engine, BASE64_STANDARD};
|
||||
const OSC52_DESTINATION_CLIPBOARD: char = 'c';
|
||||
write!(
|
||||
out,
|
||||
"\x1b]52;{destination};{encoded_text}\x07",
|
||||
destination = OSC52_DESTINATION_CLIPBOARD,
|
||||
encoded_text = BASE64_STANDARD.encode(text)
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
|
||||
pub fn copy_string(text: &str) -> Result<()> {
|
||||
if std::env::var("WAYLAND_DISPLAY").is_ok() {
|
||||
return exec_copy_with_args("wl-copy", &[], text, false);
|
||||
fn copy_string_wayland(text: &str) -> Result<()> {
|
||||
if exec_copy_with_args("wl-copy", &[], text, false).is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if is_wsl() {
|
||||
return exec_copy_with_args("clip.exe", &[], text, false);
|
||||
}
|
||||
copy_string_osc52(text, &mut std::io::stdout())
|
||||
}
|
||||
|
||||
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
|
||||
fn copy_string_x(text: &str) -> Result<()> {
|
||||
if exec_copy_with_args(
|
||||
"xclip",
|
||||
&["-selection", "clipboard"],
|
||||
text,
|
||||
false,
|
||||
)
|
||||
.is_err()
|
||||
.is_ok()
|
||||
{
|
||||
return exec_copy_with_args(
|
||||
"xsel",
|
||||
&["--clipboard"],
|
||||
text,
|
||||
true,
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
if exec_copy_with_args("xsel", &["--clipboard"], text, true)
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
copy_string_osc52(text, &mut std::io::stdout())
|
||||
}
|
||||
|
||||
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
|
||||
pub fn copy_string(text: &str) -> Result<()> {
|
||||
if std::env::var("WAYLAND_DISPLAY").is_ok() {
|
||||
return copy_string_wayland(text);
|
||||
}
|
||||
|
||||
if is_wsl() {
|
||||
return exec_copy_with_args("clip.exe", &[], text, false);
|
||||
}
|
||||
|
||||
copy_string_x(text)
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", windows))]
|
||||
|
|
@ -106,3 +141,17 @@ pub fn copy_string(text: &str) -> Result<()> {
|
|||
pub fn copy_string(text: &str) -> Result<()> {
|
||||
exec_copy("clip", text)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn test_copy_string_osc52() {
|
||||
let mut buffer = Vec::<u8>::new();
|
||||
{
|
||||
let mut cursor = std::io::Cursor::new(&mut buffer);
|
||||
super::copy_string_osc52("foo", &mut cursor).unwrap();
|
||||
}
|
||||
let output = String::from_utf8(buffer).unwrap();
|
||||
assert_eq!(output, "\x1b]52;c;Zm9v\x07");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue