mirror of
https://github.com/gitui-org/gitui
synced 2026-05-24 09:28: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
|
### Changed
|
||||||
* improve syntax highlighting file detection [[@acuteenvy](https://github.com/acuteenvy)] ([#2524](https://github.com/extrawurst/gitui/pull/2524))
|
* 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))
|
* 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
|
## [0.27.0] - 2024-01-14
|
||||||
|
|
||||||
|
|
|
||||||
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1162,6 +1162,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"asyncgit",
|
"asyncgit",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
|
"base64",
|
||||||
"bitflags 2.8.0",
|
"bitflags 2.8.0",
|
||||||
"bugreport",
|
"bugreport",
|
||||||
"bwrap",
|
"bwrap",
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ build = "build.rs"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
asyncgit = { path = "./asyncgit", version = "0.27.0", default-features = false }
|
asyncgit = { path = "./asyncgit", version = "0.27.0", default-features = false }
|
||||||
backtrace = "0.3"
|
backtrace = "0.3"
|
||||||
|
base64 = "0.21"
|
||||||
bitflags = "2.8"
|
bitflags = "2.8"
|
||||||
bugreport = "0.5.1"
|
bugreport = "0.5.1"
|
||||||
bwrap = { version = "1.3", features = ["use_std"] }
|
bwrap = { version = "1.3", features = ["use_std"] }
|
||||||
|
|
|
||||||
|
|
@ -63,33 +63,68 @@ fn is_wsl() -> bool {
|
||||||
false
|
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")))]
|
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
|
||||||
pub fn copy_string(text: &str) -> Result<()> {
|
fn copy_string_wayland(text: &str) -> Result<()> {
|
||||||
if std::env::var("WAYLAND_DISPLAY").is_ok() {
|
if exec_copy_with_args("wl-copy", &[], text, false).is_ok() {
|
||||||
return exec_copy_with_args("wl-copy", &[], text, false);
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_wsl() {
|
copy_string_osc52(text, &mut std::io::stdout())
|
||||||
return exec_copy_with_args("clip.exe", &[], text, false);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
|
||||||
|
fn copy_string_x(text: &str) -> Result<()> {
|
||||||
if exec_copy_with_args(
|
if exec_copy_with_args(
|
||||||
"xclip",
|
"xclip",
|
||||||
&["-selection", "clipboard"],
|
&["-selection", "clipboard"],
|
||||||
text,
|
text,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.is_err()
|
.is_ok()
|
||||||
{
|
{
|
||||||
return exec_copy_with_args(
|
return Ok(());
|
||||||
"xsel",
|
|
||||||
&["--clipboard"],
|
|
||||||
text,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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))]
|
#[cfg(any(target_os = "macos", windows))]
|
||||||
|
|
@ -106,3 +141,17 @@ pub fn copy_string(text: &str) -> Result<()> {
|
||||||
pub fn copy_string(text: &str) -> Result<()> {
|
pub fn copy_string(text: &str) -> Result<()> {
|
||||||
exec_copy("clip", text)
|
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