Compare commits
10 commits
b069dfe4f6
...
d5cf6d9f17
Author | SHA1 | Date | |
---|---|---|---|
|
d5cf6d9f17 | ||
|
8aac681b97 | ||
|
14bf2b7baa | ||
|
167e9ac93f | ||
|
77706941a3 | ||
|
c5de70df5f | ||
|
1eb93a5ff0 | ||
|
bb95b603d0 | ||
|
e1dea61d31 | ||
|
ef9e6bece2 |
5 changed files with 73 additions and 12 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,3 +1,16 @@
|
|||
# Next
|
||||
|
||||
**New features**
|
||||
|
||||
- `--unix` option to normalize all line endings to LF
|
||||
|
||||
# 1.5.2
|
||||
|
||||
**Notable bug fixes**
|
||||
|
||||
- wl-copy is now truly daemonized, allowing calling `alacritty -e sh -c clipman pick`
|
||||
- fzf couldn't recover the clipboard content in some cases
|
||||
|
||||
# 1.5.1
|
||||
|
||||
**Notable bug fixes**
|
||||
|
|
|
@ -24,10 +24,10 @@ These distros ship with clipman binaries in their repos:
|
|||
## Usage
|
||||
|
||||
Run the binary in your Sway session by adding `exec wl-paste -t text --watch clipman store` (or `exec wl-paste -t text --watch clipman store 1>> PATH/TO/LOGFILE 2>&1 &` to log errors) at the beginning of your config.
|
||||
For primary clipboard support, also add `exec wl-paste -p -t text --watch clipman store --histpath="~/.local/share/clipman-primary.json`.
|
||||
|
||||
For primary clipboard support, also add `exec wl-paste -p -t text --watch clipman store -P --histpath="~/.local/share/clipman-primary.json"` (note that both the `-p` in wl-paste and the `-P` in clipman are mandatory in this case).
|
||||
|
||||
To query the history and select items, run the binary as `clipman pick -t wofi`. You can assign it to a keybinding: `bindsym $mod+h exec clipman pick -t wofi`.
|
||||
For primary clipboard support, `clipman pick -t wofi --histpath="~/.local/share/clipman-primary.json`.
|
||||
You can pass additional arguments to the selector like this: `clipman pick --tool wofi -T'--prompt=my-prompt -i'` (both `--prompt` and `-i` are flags of wofi).
|
||||
You can use a custom selector like this: `clipman pick --print0 --tool=CUSTOM --tool-args="fzf --prompt 'pick > ' --bind 'tab:up' --cycle --read0"`.
|
||||
|
||||
|
@ -44,6 +44,10 @@ For more options: `clipman -h`.
|
|||
- All items stored in history are treated as plain text.
|
||||
- By default, we continue serving the last copied item even after its owner has exited. This means that, unless you run with the `--no-persist` option, you'll always immediately lose rich content: for example, if you copy formatted text inside Libre Office you'll lose all formatting on paste; or, if you copy a bookmark in Firefox, you won't be able to paste it in another bookmark folder.
|
||||
|
||||
### Vim's Visual Block mode breaks if persistence is enabled
|
||||
|
||||
Run `clipman store` with the `--no-persist` option if you are affected. Unfortunately, it seems that there is no way to make them play well together.
|
||||
|
||||
## Versions
|
||||
|
||||
This projects follows SemVer conventions.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.TH clipman 1 1.5.1 ""
|
||||
.TH clipman 1 1.5.2 ""
|
||||
.SH "NAME"
|
||||
clipman
|
||||
.SH "SYNOPSIS"
|
||||
|
@ -35,6 +35,9 @@ history size
|
|||
.TP
|
||||
\fB-P, --no-persist\fR
|
||||
Don't persist a copy buffer after a program exits
|
||||
.TP
|
||||
\fB--unix\fR
|
||||
Normalize line endings to LF
|
||||
.SS
|
||||
\fBpick --tool=TOOL [<flags>]\fR
|
||||
.PP
|
||||
|
@ -76,10 +79,10 @@ Separate items using NULL; recommended if your tool supports --read0 or similar
|
|||
Serve the last recorded item from history
|
||||
.SH "USAGE"
|
||||
Run the binary in your Sway session by adding `exec wl-paste -t text --watch clipman store` (or `exec wl-paste -t text --watch clipman store 1>> PATH/TO/LOGFILE 2>&1 &` to log errors) at the beginning of your config.
|
||||
For primary clipboard support, also add `exec wl-paste -p -t text --watch clipman store --histpath="~/.local/share/clipman-primary.json`.
|
||||
.PP
|
||||
For primary clipboard support, also add `exec wl-paste -p -t text --watch clipman store -P --histpath="~/.local/share/clipman-primary.json` (note that both the `-p` in wl-paste and the `-P` in clipman are mandatory in this case).
|
||||
.PP
|
||||
To query the history and select items, run the binary as `clipman pick -t wofi`. You can assign it to a keybinding: `bindsym $mod+h exec clipman pick -t wofi`.
|
||||
For primary clipboard support, `clipman pick -t wofi --histpath="~/.local/share/clipman-primary.json`.
|
||||
You can pass additional arguments to the selector like this: `clipman pick --tool wofi -T'--prompt=my-prompt -i'` (both `--prompt` and `-i` are flags of wofi).
|
||||
You can use a custom selector like this: `clipman pick --print0 --tool=CUSTOM --tool-args="fzf --prompt 'pick > ' --bind 'tab:up' --cycle --read0"`.
|
||||
.PP
|
||||
|
@ -87,6 +90,10 @@ To remove items from history, `clipman clear -t wofi` and `clipman clear --all`.
|
|||
.PP
|
||||
To serve the last history item at startup, add `exec clipman restore` to your Sway config.
|
||||
.SH "KNOWN ISSUES"
|
||||
All items stored in history are treated as plain text.
|
||||
\fBAll items stored in history are treated as plain text.\fR
|
||||
.PP
|
||||
By default, we continue serving the last copied item even after its owner has exited. This means that, unless you run with the `--no-persist` option, you'll always immediately lose rich content: for example, if you copy formatted text inside Libre Office you'll lose all formatting on paste; or, if you copy a bookmark in Firefox, you won't be able to paste it in another bookmark folder.
|
||||
.PP
|
||||
\fBVim's Visual Block mode breaks if persistence is enabled\fR
|
||||
.PP
|
||||
Run `clipman store` with the `--no-persist` option if you are affected. Unfortunately, it seems that there is no way to make them play well together.
|
||||
|
|
45
main.go
45
main.go
|
@ -11,11 +11,12 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
const version = "1.5.1"
|
||||
const version = "1.5.2"
|
||||
|
||||
var (
|
||||
app = kingpin.New("clipman", "A clipboard manager for Wayland")
|
||||
|
@ -25,6 +26,7 @@ var (
|
|||
storer = app.Command("store", "Record clipboard events (run as argument to `wl-paste --watch`)")
|
||||
maxDemon = storer.Flag("max-items", "history size").Default("15").Int()
|
||||
noPersist = storer.Flag("no-persist", "Don't persist a copy buffer after a program exits").Short('P').Default("false").Bool()
|
||||
unix = storer.Flag("unix", "Normalize line endings to LF").Bool()
|
||||
|
||||
picker = app.Command("pick", "Pick an item from clipboard history")
|
||||
maxPicker = picker.Flag("max-items", "scrollview length").Default("15").Int()
|
||||
|
@ -178,8 +180,14 @@ func serveTxt(s string) {
|
|||
smartLog(fmt.Sprintf("couldn't find wl-copy: %v\n", err), "low", *alert)
|
||||
}
|
||||
|
||||
// daemonize wl-copy into a truly independent process
|
||||
// necessary for running stuff like `alacritty -e sh -c clipman pick`
|
||||
attr := &syscall.SysProcAttr{
|
||||
Setpgid: true,
|
||||
}
|
||||
|
||||
// we mandate the mime type because we know we can only serve text; not doing this leads to weird bugs like #35
|
||||
cmd := exec.Cmd{Path: bin, Args: []string{bin, "-t", "TEXT"}, Stdin: strings.NewReader(s)}
|
||||
cmd := exec.Cmd{Path: bin, Args: []string{bin, "-t", "TEXT"}, Stdin: strings.NewReader(s), SysProcAttr: attr}
|
||||
if err := cmd.Run(); err != nil {
|
||||
smartLog(fmt.Sprintf("error running wl-copy: %s\n", err), "low", *alert)
|
||||
}
|
||||
|
@ -193,14 +201,43 @@ func scanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
|||
|
||||
if i := bytes.IndexByte(data, '\n'); i >= 0 {
|
||||
// We have a full newline-terminated line.
|
||||
return i + 1, data[0 : i+1], nil
|
||||
b := data[0 : i+1]
|
||||
if *unix {
|
||||
b = dropCR(b)
|
||||
}
|
||||
return i + 1, b, nil
|
||||
}
|
||||
|
||||
// If we're at EOF, we have a final, non-terminated line. Return it.
|
||||
if atEOF {
|
||||
return len(data), data, nil
|
||||
b := data
|
||||
if *unix {
|
||||
b = dropCR(b)
|
||||
}
|
||||
return len(data), b, nil
|
||||
}
|
||||
|
||||
// Request more data.
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
// dropCR drops a terminal \r from the data. Modified from Go's Stdlib
|
||||
func dropCR(data []byte) []byte {
|
||||
orig := data
|
||||
|
||||
var lf bool
|
||||
if len(data) > 0 && data[len(data)-1] == '\n' {
|
||||
lf = true
|
||||
data = data[0 : len(data)-1]
|
||||
}
|
||||
|
||||
if len(data) > 0 && data[len(data)-1] == '\r' {
|
||||
b := data[0 : len(data)-1]
|
||||
if lf {
|
||||
b = append(b, '\n')
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
return orig
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ func selector(data []string, max int, tool, prompt, toolArgs string, null bool)
|
|||
sep = "\000"
|
||||
}
|
||||
|
||||
cmd := exec.Cmd{Path: bin, Args: args, Stdin: strings.NewReader(strings.Join(processed, sep) + "\n")}
|
||||
cmd := exec.Cmd{Path: bin, Args: args, Stdin: strings.NewReader(strings.Join(processed, sep))}
|
||||
cmd.Stderr = os.Stderr // let stderr pass to console
|
||||
b, err := cmd.Output()
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in a new issue