Compare commits
No commits in common. "d5cf6d9f17d1f4de0441351bc56714f29238454b" and "b069dfe4f6453c01286aa3412301df60c8fdbfc9" have entirely different histories.
d5cf6d9f17
...
b069dfe4f6
5 changed files with 12 additions and 73 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,16 +1,3 @@
|
||||||
# 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
|
# 1.5.1
|
||||||
|
|
||||||
**Notable bug fixes**
|
**Notable bug fixes**
|
||||||
|
|
|
@ -24,10 +24,10 @@ These distros ship with clipman binaries in their repos:
|
||||||
## Usage
|
## 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.
|
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`.
|
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 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"`.
|
You can use a custom selector like this: `clipman pick --print0 --tool=CUSTOM --tool-args="fzf --prompt 'pick > ' --bind 'tab:up' --cycle --read0"`.
|
||||||
|
|
||||||
|
@ -44,10 +44,6 @@ For more options: `clipman -h`.
|
||||||
- All items stored in history are treated as plain text.
|
- 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.
|
- 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
|
## Versions
|
||||||
|
|
||||||
This projects follows SemVer conventions.
|
This projects follows SemVer conventions.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.TH clipman 1 1.5.2 ""
|
.TH clipman 1 1.5.1 ""
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
clipman
|
clipman
|
||||||
.SH "SYNOPSIS"
|
.SH "SYNOPSIS"
|
||||||
|
@ -35,9 +35,6 @@ history size
|
||||||
.TP
|
.TP
|
||||||
\fB-P, --no-persist\fR
|
\fB-P, --no-persist\fR
|
||||||
Don't persist a copy buffer after a program exits
|
Don't persist a copy buffer after a program exits
|
||||||
.TP
|
|
||||||
\fB--unix\fR
|
|
||||||
Normalize line endings to LF
|
|
||||||
.SS
|
.SS
|
||||||
\fBpick --tool=TOOL [<flags>]\fR
|
\fBpick --tool=TOOL [<flags>]\fR
|
||||||
.PP
|
.PP
|
||||||
|
@ -79,10 +76,10 @@ Separate items using NULL; recommended if your tool supports --read0 or similar
|
||||||
Serve the last recorded item from history
|
Serve the last recorded item from history
|
||||||
.SH "USAGE"
|
.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.
|
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.
|
||||||
.PP
|
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).
|
|
||||||
.PP
|
.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`.
|
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 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"`.
|
You can use a custom selector like this: `clipman pick --print0 --tool=CUSTOM --tool-args="fzf --prompt 'pick > ' --bind 'tab:up' --cycle --read0"`.
|
||||||
.PP
|
.PP
|
||||||
|
@ -90,10 +87,6 @@ To remove items from history, `clipman clear -t wofi` and `clipman clear --all`.
|
||||||
.PP
|
.PP
|
||||||
To serve the last history item at startup, add `exec clipman restore` to your Sway config.
|
To serve the last history item at startup, add `exec clipman restore` to your Sway config.
|
||||||
.SH "KNOWN ISSUES"
|
.SH "KNOWN ISSUES"
|
||||||
\fBAll items stored in history are treated as plain text.\fR
|
All items stored in history are treated as plain text.
|
||||||
.PP
|
.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.
|
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,12 +11,11 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const version = "1.5.2"
|
const version = "1.5.1"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
app = kingpin.New("clipman", "A clipboard manager for Wayland")
|
app = kingpin.New("clipman", "A clipboard manager for Wayland")
|
||||||
|
@ -26,7 +25,6 @@ var (
|
||||||
storer = app.Command("store", "Record clipboard events (run as argument to `wl-paste --watch`)")
|
storer = app.Command("store", "Record clipboard events (run as argument to `wl-paste --watch`)")
|
||||||
maxDemon = storer.Flag("max-items", "history size").Default("15").Int()
|
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()
|
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")
|
picker = app.Command("pick", "Pick an item from clipboard history")
|
||||||
maxPicker = picker.Flag("max-items", "scrollview length").Default("15").Int()
|
maxPicker = picker.Flag("max-items", "scrollview length").Default("15").Int()
|
||||||
|
@ -180,14 +178,8 @@ func serveTxt(s string) {
|
||||||
smartLog(fmt.Sprintf("couldn't find wl-copy: %v\n", err), "low", *alert)
|
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
|
// 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), SysProcAttr: attr}
|
cmd := exec.Cmd{Path: bin, Args: []string{bin, "-t", "TEXT"}, Stdin: strings.NewReader(s)}
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
smartLog(fmt.Sprintf("error running wl-copy: %s\n", err), "low", *alert)
|
smartLog(fmt.Sprintf("error running wl-copy: %s\n", err), "low", *alert)
|
||||||
}
|
}
|
||||||
|
@ -201,43 +193,14 @@ func scanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||||
|
|
||||||
if i := bytes.IndexByte(data, '\n'); i >= 0 {
|
if i := bytes.IndexByte(data, '\n'); i >= 0 {
|
||||||
// We have a full newline-terminated line.
|
// We have a full newline-terminated line.
|
||||||
b := data[0 : i+1]
|
return i + 1, data[0 : i+1], nil
|
||||||
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 we're at EOF, we have a final, non-terminated line. Return it.
|
||||||
if atEOF {
|
if atEOF {
|
||||||
b := data
|
return len(data), data, nil
|
||||||
if *unix {
|
|
||||||
b = dropCR(b)
|
|
||||||
}
|
|
||||||
return len(data), b, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request more data.
|
// Request more data.
|
||||||
return 0, nil, nil
|
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"
|
sep = "\000"
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Cmd{Path: bin, Args: args, Stdin: strings.NewReader(strings.Join(processed, sep))}
|
cmd := exec.Cmd{Path: bin, Args: args, Stdin: strings.NewReader(strings.Join(processed, sep) + "\n")}
|
||||||
cmd.Stderr = os.Stderr // let stderr pass to console
|
cmd.Stderr = os.Stderr // let stderr pass to console
|
||||||
b, err := cmd.Output()
|
b, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue