clipman/main.go

124 lines
3.2 KiB
Go
Raw Normal View History

2019-03-22 15:13:41 +01:00
package main
import (
"bufio"
2019-03-22 15:13:41 +01:00
"encoding/json"
2019-08-02 13:51:13 +02:00
"fmt"
2019-03-22 15:13:41 +01:00
"io/ioutil"
"log"
"os"
"os/exec"
2019-09-07 19:41:41 +02:00
"strings"
"gopkg.in/alecthomas/kingpin.v2"
2019-03-22 15:13:41 +01:00
)
var (
2019-09-17 09:46:30 +02:00
app = kingpin.New("clipman", "A clipboard manager for Wayland")
histpath = app.Flag("histpath", "Path of history file").Default("~/.local/share/clipman.json").String()
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()
picker = app.Command("pick", "Pick an item from clipboard history")
maxPicker = picker.Flag("max-items", "scrollview length").Default("15").Int()
2019-09-17 11:52:49 +02:00
pickTool = picker.Flag("tool", "Which selector to use: dmenu/rofi/-").Default("dmenu").String()
2019-09-17 09:46:30 +02:00
clearer = app.Command("clear", "Remove item(s) from history")
maxClearer = clearer.Flag("max-items", "scrollview length").Default("15").Int()
2019-09-17 11:52:49 +02:00
clearTool = clearer.Flag("tool", "Which selector to use: dmenu/rofi/-").Default("dmenu").String()
clearAll = clearer.Flag("all", "Remove all items").Short('a').Default("false").Bool()
)
2019-03-22 15:13:41 +01:00
func main() {
app.HelpFlag.Short('h')
switch kingpin.MustParse(app.Parse(os.Args[1:])) {
case "store":
2019-09-17 09:46:30 +02:00
histfile, history, err := getHistory(*histpath)
if err != nil {
log.Fatal(err)
}
// read copy from stdin
var stdin []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
stdin = append(stdin, scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal("Error getting input from stdin.")
}
text := strings.Join(stdin, "\n")
2019-09-17 09:46:30 +02:00
persist := !*noPersist
if err := store(text, history, histfile, *maxDemon, persist); err != nil {
log.Fatal(err)
}
case "pick":
2019-09-17 09:46:30 +02:00
_, history, err := getHistory(*histpath)
if err != nil {
log.Fatal(err)
}
selection, err := selector(history, *maxPicker, *pickTool)
if err != nil {
log.Fatal(err)
}
// serve selection to the OS
2019-09-17 11:03:37 +02:00
if err := exec.Command("wl-copy", []string{"--", selection}...).Run(); err != nil {
log.Fatal(err)
}
case "clear":
2019-09-17 09:46:30 +02:00
histfile, history, err := getHistory(*histpath)
if err != nil {
log.Fatal(err)
}
2019-09-17 09:46:30 +02:00
// remove all history
if *clearAll {
if err := os.Remove(histfile); err != nil {
log.Fatal(err)
}
os.Exit(0)
}
selection, err := selector(history, *maxClearer, *clearTool)
if err != nil {
log.Fatal(err)
}
if err := write(filter(history, selection), histfile); err != nil {
log.Fatal(err)
}
2019-03-22 15:13:41 +01:00
}
}
2019-03-22 15:13:41 +01:00
2019-09-17 09:46:30 +02:00
func getHistory(rawPath string) (string, []string, error) {
// set histfile; expand user home
histfile := rawPath
2019-09-07 19:41:41 +02:00
if strings.HasPrefix(histfile, "~") {
2019-08-24 21:08:38 +02:00
home, err := os.UserHomeDir()
if err != nil {
return "", nil, err
2019-08-24 21:08:38 +02:00
}
2019-09-07 19:41:41 +02:00
histfile = strings.Replace(histfile, "~", home, 1)
2019-03-22 15:13:41 +01:00
}
2019-09-17 09:46:30 +02:00
// read history if it exists
2019-03-25 19:13:19 +01:00
var history []string
b, err := ioutil.ReadFile(histfile)
2019-09-07 19:41:41 +02:00
if err != nil {
2019-09-16 12:51:33 +02:00
if !os.IsNotExist(err) {
2019-09-17 09:46:30 +02:00
return "", nil, fmt.Errorf("failure reading history file: %s", err)
2019-09-16 12:51:33 +02:00
}
} else {
if err := json.Unmarshal(b, &history); err != nil {
2019-09-17 09:46:30 +02:00
return "", nil, fmt.Errorf("failure parsing history: %s", err)
2019-09-16 12:51:33 +02:00
}
2019-03-22 15:13:41 +01:00
}
return histfile, history, nil
2019-03-22 15:13:41 +01:00
}