bugaevc / wl-clipboard

Command-line copy/paste utilities for Wayland
GNU General Public License v3.0
1.62k stars 60 forks source link

Double newline added on paste #63

Closed louib closed 5 years ago

louib commented 5 years ago

I'm not convinced about the newline handling on this one:

$ echo "hello" | wl-copy 
$ wl-paste 
hello

$ wl-copy --version
wl-clipboard 2.0.0-beta
Copyright (C) 2019 Sergey Bugaev
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Why is there a second newline appended? From the manpage:

       -n, --no-newline
              Do  not  append a newline character after the pasted clipboard content. This option is automatically enabled for non-text content
              types and when using the --watch mode.

So I guess I could be using the -n option, I just don't understand why that would not be the default in that case.

Thanks!!

bugaevc commented 5 years ago

The reason for this more philosophical than technical. The default conventions are different between the "Unix commands" and "GUI clipboard" worlds, and wl-clipboard has to bridge between them.

In Unix commands, the convention is that everything always ends with a \n, including command output. For example, if you run echo "hello", it does actually call write("hello\n"), because that's the convention, to always end your output with a newline. And echo has an -n option to turn this off too, if you know what you're doing. Many Unix programs treat newline as a line separator rather than as a character in its own right. For example, if you use grep '^$', you're asking it to look for "empty" lines, not lines containing just a '\n' character.

In the GUI clipboard world, the convention is for clipboard to contain the exact thing you want to copy, without an extra newline at the end. For example, if I select this word hello and press Ctrl-C, my clipboard will contain hello, not hello\n. If your selection happens to contain a newline character, it is copied, cut and pasted just like other characters.

wl-clipboard exists between these worlds, and it tries to do its best to be a good citizen of both. If you copy hello and then wl-paste it, wl-clipboard will append a \n, just like echo, giving you the expected output, and just like echo it has the -n option to override this behavior (and it will also automatically not do this with binary data and in watch mode). If you wl-copy hello, then it, unlike echo, copies "hello" sans the '\n' to the clipboard, so that you get the expected result when you paste into your text editor.

But if you're giving a file as an input to wl-copy (think wl-copy < war-and-peace.txt), it won't, by default, modify it, and will copy the exact bytes to the clipboard as is. Still, in many cases the file may actually be an output of a Unix command and you'd like it not to end with a newline. You can either ask that command not to add a newline — so, in your example, echo -n hello | wl-copy, or explicitly ask wl-copy to trim it (wl-copy -n).

To summarize, there is a difference in conventions, and wl-clipboard goes to great lengths to do the most intuitive thing most of the time. But there are some scenarios that still uncover the issue — thankfully, copying using command line and then pasting back using command line is a pretty rare thing to do (outside testing wl-clipboard behavior, of course).

And here's a short guide with different versions of your example:

louib commented 5 years ago

@bugaevc thanks for the explanation!