[Bug]: Copy to clipboard unsuccessful
ovv opened this issue · comments
What did you expect to happen?
Pressing ctrl-y
in the search view should copy the selected line to the clipboard
What happened?
Pressing ctrl-y
closes atuin but the clipboard content is not set
Atuin doctor output
atuin:
version: 18.2.0
sync:
cloud: false
records: true
auto_sync: true
last_sync: 2024-05-17 11:10:19.493442155 +00:00:00
shell:
name: fish
default: unknown
plugins:
- atuin
system:
os: Fedora Linux
arch: x86_64
version: '39'
disks:
- name: /dev/mapper/luks-a71d0523-7b8b-4cc2-9d60-a73e65041027
filesystem: btrfs
- name: /dev/mapper/luks-a71d0523-7b8b-4cc2-9d60-a73e65041027
filesystem: btrfs
- name: /dev/nvme0n1p2
filesystem: ext4
- name: /dev/nvme0n1p1
filesystem: vfat
Code of Conduct
- I agree to follow this project's Code of Conduct
Interestingly using this patch make it work. I'm quite confused how/why
diff --git a/crates/atuin/src/command/client/search/interactive.rs b/crates/atuin/src/command/client/search/interactive.rs
index 9185bc0f..5caedeb4 100644
--- a/crates/atuin/src/command/client/search/interactive.rs
+++ b/crates/atuin/src/command/client/search/interactive.rs
@@ -1174,7 +1174,8 @@ pub async fn history(
any(target_os = "windows", target_os = "macos", target_os = "linux")
))]
fn set_clipboard(s: String) {
- cli_clipboard::set_contents(s).unwrap();
+ cli_clipboard::set_contents(s.to_owned()).unwrap();
+ assert_eq!(cli_clipboard::get_contents().unwrap(), s);
}
#[cfg(not(all(
I was not able to reproduce this on macOS.
I think this is only an issue on Linux. What window manager/graphical env are you using?
I think this is only an issue on Linux. What window manager/graphical env are you using?
I'm using KDE Plasma, it reproduces on plasma 5 and 6
The cli_clipboard
crate documentation mention a different behavior on Linux.
This uses the platform default behavior for setting clipboard contents. Other users of the Wayland or X11 clipboard will only see the contents copied to the clipboard so long as the process copying to the clipboard exists. MacOS and Windows clipboard contents will stick around after your application exits.
I don't fully understand the so long as the process copying to the clipboard exists
since it seems to work if the process doesn't exit instantly. This code work, removing the sleep makes it fail.
use cli_clipboard;
use std::time::Duration;
use std::thread::sleep;
fn main() {
let the_string = "foobar";
cli_clipboard::set_contents(the_string.to_owned()).unwrap();
sleep(Duration::new(1, 0));
}
Looks like the bug is not directly related to atuin
Hi @ellie, I am working on packaging atuin
for Fedora (now there is only 1 dependency left, guess which), and I've encountered errors when testing cli_clipboard
. Upstream appears to encounter similar test failures. They also point to a few alternatives, primarily arboard and copypasta. The former seems to be the most active right now. Both are packaged right now, so it could be that these work better for linux. Will you consider trying either of these out?
I'd be pretty happy to switch to arboard - I'll likely get around to doing so fairly soon, unless anyone fancies making a PR
@LecrisUT #2067 works fine, but it has the same issue. Removing the
ctx.get_text().unwrap();
line result in the clipboard not being set.
Indeed, but I am not sure what would be an appropriate fix. From what I've tested the issue is that the clipboard must be consumed somewhere for it to be saved on the system, otherwise even with set_text().unwrap()
it doesn't seem to be propagated. Could be an upstream issue or it could be a misunderstanding on the API, not sure. I couldn't figure it out from reading the issues related to it, but maybe someone has better ideas.
But anything that does ctx.get_text().unwrap()
should be fine and it could be something like checking that the clipboard is set, otherwise try again n
times and give an error message that it failed afterwards. Dunno how to implement the latter part for that though
I can't test right now, but I'm curious to know if we need an explicity get_text
or if a sleep does it
From my testing, the sleep
also works, but it's finicky and it makes it slugish. get_text
is more responsive. In both cases though, there is no guarantee that the clipboard values was set (or even not overwritten) until we actually test for it
Hi there, maintainer/owner of arboard
here 👋:
From my testing, the sleep also works...
It might be possible that the clipboard manager is taking longer to respond then the data serving thread is willing to wait currently. If you enable trace
level logging for arboard
, you should be able to see if that is happening by viewing the steps of clipboard handoff.
I don't know about @ovv, but I am testing on wayland. Is there an equivalent there?
It doesn't look like wl-clipboard-rs
has much logging it it, so I think the answer is no :(. Most of what that crate does is a black box to arboard
for better or worse.
I've been struggling with this issue for a long time. Even in 18.4.0-beta.3, the problem still persists.
Environment: Ubuntu-2204, X11, Kitty, Zsh.
Calling external commands, while pretty ugly, does the trick. Sharing in case it helps someone.
crates/atuin/src/command/client/search/interactive.rs | 4 ++++
1 file changed, 4 insertions(+)
diff --git crates/atuin/src/command/client/search/interactive.rs crates/atuin/src/command/client/search/interactive.rs
index 777ec257..e0e615b3 100644
--- crates/atuin/src/command/client/search/interactive.rs
+++ crates/atuin/src/command/client/search/interactive.rs
@@ -1,5 +1,6 @@
use std::{
io::{stdout, Write},
+ process::Command,
time::Duration,
};
@@ -1197,6 +1198,9 @@ pub async fn history(
any(target_os = "windows", target_os = "macos", target_os = "linux")
))]
fn set_clipboard(s: String) {
+ let wtf = format!("copyq write text/plain '{}' && copyq select 0", s.clone());
+ Command::new("sh").arg("-c").arg(&wtf).output().expect("Failed to execute command");
+
let mut ctx = arboard::Clipboard::new().unwrap();
ctx.set_text(s).unwrap();
// Use the clipboard context to make sure it is saved
@s5unty I cannot reliably reproduce on my end, but if you can, could you check what you get when you try to compare ctx.get_text().unwrap()
with the input s
? My assumption is that doing this test n
times should make it more reliable. As for copyq
approach, can you elaborate more what is going on there?
IIUC, copyq
is a third-party clipboard manager, so it ~sort of makes sense that directly invoking it would provide more reliable results then going through X11, etc.
I would be curious to see if blocking atuin
's main thread from exiting for around 2 seconds also "fixes" the issue. That would confirm my hypothesis above that the process is just exiting before a clipboard handoff to the manager can complete. In comparison, the logic above blocks the process until the data is directly handed to copyq
and then put back on the clipboard.
I would be curious to see if blocking
atuin
's main thread from exiting for around 2 seconds also "fixes" the issue
When I tried @ovv approach there with the sleep, it indeed worked. But of course there is a difference between 2 seconds and 0.01 sec.
In comparison, the logic above blocks the process until the data is directly handed to
copyq
and then put back on the clipboard.
Well it's a bit weird because that command is run before the set_text
Well it's a bit weird because that command is run before the set_text
It likely has the same observable effect IIUC. Once atuin
stop's serving its data, the clipboard manager takes over serving data again (since that's how it can keep serving data after arbitrary numbers of processes/apps exit). Even though arboard
failed to hand the data over, identical data was already in the clipboard manager so the failure is papered over.
% git di
crates/atuin/src/command/client/search/interactive.rs | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git crates/atuin/src/command/client/search/interactive.rs crates/atuin/src/command/client/search/interactive.rs
index 777ec257..5bc91777 100644
--- crates/atuin/src/command/client/search/interactive.rs
+++ crates/atuin/src/command/client/search/interactive.rs
@@ -1,5 +1,7 @@
use std::{
io::{stdout, Write},
+ fs::write,
+ process::Command,
time::Duration,
};
@@ -1197,10 +1199,15 @@ pub async fn history(
any(target_os = "windows", target_os = "macos", target_os = "linux")
))]
fn set_clipboard(s: String) {
+ // let wtf = format!("copyq write text/plain '{}' && copyq select 0", s.clone());
+ // Command::new("sh").arg("-c").arg(&wtf).output().expect("Failed to execute command");
+
+ write("/tmp/debug1.log", s.clone()).expect("Unable to write to file");
let mut ctx = arboard::Clipboard::new().unwrap();
ctx.set_text(s).unwrap();
// Use the clipboard context to make sure it is saved
- ctx.get_text().unwrap();
+ let ret = ctx.get_text().unwrap();
+ write("/tmp/debug2.log", ret).expect("Unable to write to file");
}
#[cfg(not(all(
% cat /tmp/debug1.log; echo "###"; cat /tmp/debug2.log; echo "###"
lsb_release -a###
lsb_release -a###
copyq is a third-party tool that I usually keep running in the background to manage my clipboard.
I tried closing copyq, using Ctrl-Y to copy, and then observing with xclip.
# The "reproduce" here refers to the content that was in the clipboard before using Ctrl-Y.
2210% xclip -o -selection primary
reproduce%
2211% xclip -o -selection secondary
Error: target STRING not available
2212% xclip -o -selection clipboard
Error: target STRING not available
2213% xclip -o -selection buffer-cut
2214%