diff --git a/CHANGELOG.md b/CHANGELOG.md index 95cb8e3..6a3ad8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +# 1.4.0 + +**New features** + +- optional desktop notifications on errors + +**Notable bug fixes** + +- the toolArgs option now understands complex patterns (spaces, quotes) + # 1.3.0 **Breaking changes** diff --git a/RELEASE_TODO.md b/RELEASE_TODO.md deleted file mode 100644 index 4d3eacc..0000000 --- a/RELEASE_TODO.md +++ /dev/null @@ -1,4 +0,0 @@ -- upgrade version number - - in main - - in man page -- update changelog diff --git a/docs/clipman.1 b/docs/clipman.1 index a7eb745..bdd8ef8 100644 --- a/docs/clipman.1 +++ b/docs/clipman.1 @@ -1,4 +1,4 @@ -.TH clipman 1 1.3.0 "" +.TH clipman 1 1.4.0 "" .SH "NAME" clipman .SH "SYNOPSIS" @@ -15,6 +15,9 @@ Show context-sensitive help (also try --help-long and --help-man). \fB--histpath="~/.local/share/clipman.json"\fR Path of history file .TP +\fB--notify\fR +Send desktop notifications on errors +.TP \fB-v, --version\fR Show application version. .SH "COMMANDS" diff --git a/main.go b/main.go index 10c63b0..cd3ce07 100644 --- a/main.go +++ b/main.go @@ -7,7 +7,6 @@ import ( "encoding/json" "fmt" "io/ioutil" - "log" "os" "os/exec" "strings" @@ -15,11 +14,12 @@ import ( "gopkg.in/alecthomas/kingpin.v2" ) -const version = "1.3.0" +const version = "1.4.0" var ( app = kingpin.New("clipman", "A clipboard manager for Wayland") histpath = app.Flag("histpath", "Path of history file").Default("~/.local/share/clipman.json").String() + alert = app.Flag("notify", "Send desktop notifications on errors").Bool() storer = app.Command("store", "Record clipboard events (run as argument to `wl-paste --watch`)") maxDemon = storer.Flag("max-items", "history size").Default("15").Int() @@ -47,7 +47,7 @@ func main() { histfile, history, err := getHistory(*histpath) if err != nil { - log.Fatal(err) + smartLog(err.Error(), "critical", *alert) } switch action { @@ -59,18 +59,18 @@ func main() { stdin = append(stdin, scanner.Text()) } if err := scanner.Err(); err != nil { - log.Fatal("Error getting input from stdin.") + smartLog("Couldn't get input from stdin.", "critical", *alert) } text := strings.Join(stdin, "\n") persist := !*noPersist if err := store(text, history, histfile, *maxDemon, persist); err != nil { - log.Fatal(err) + smartLog(err.Error(), "critical", *alert) } case "pick": selection, err := selector(history, *maxPicker, *pickTool, "pick", *pickToolArgs) if err != nil { - log.Fatal(err) + smartLog(err.Error(), "normal", *alert) } if selection != "" { @@ -79,7 +79,7 @@ func main() { } case "restore": if len(history) == 0 { - log.Println("Nothing to restore") + fmt.Println("Nothing to restore") return } @@ -88,7 +88,7 @@ func main() { // remove all history if *clearAll { if err := wipeAll(histfile); err != nil { - log.Fatal(err) + smartLog(err.Error(), "normal", *alert) } return } @@ -100,7 +100,7 @@ func main() { selection, err := selector(history, *maxClearer, *clearTool, "clear", *clearToolArgs) if err != nil { - log.Fatal(err) + smartLog(err.Error(), "normal", *alert) } if selection == "" { @@ -111,7 +111,7 @@ func main() { // there was only one possible item we could select, and we selected it, // so wipe everything if err := wipeAll(histfile); err != nil { - log.Fatal(err) + smartLog(err.Error(), "normal", *alert) } return } @@ -123,7 +123,7 @@ func main() { } if err := write(filter(history, selection), histfile); err != nil { - log.Fatal(err) + smartLog(err.Error(), "critical", *alert) } } } @@ -171,12 +171,12 @@ func getHistory(rawPath string) (string, []string, error) { func serveTxt(s string) { bin, err := exec.LookPath("wl-copy") if err != nil { - log.Printf("couldn't find wl-copy: %v\n", err) + smartLog(fmt.Sprintf("couldn't find wl-copy: %v\n", err), "low", *alert) } // 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)} if err := cmd.Run(); err != nil { - log.Printf("error running wl-copy: %s\n", err) + smartLog(fmt.Sprintf("error running wl-copy: %s\n", err), "low", *alert) } } diff --git a/notify.go b/notify.go new file mode 100644 index 0000000..42d552c --- /dev/null +++ b/notify.go @@ -0,0 +1,44 @@ +package main + +import ( + "fmt" + "log" + "os/exec" + "time" +) + +func smartLog(message, urgency string, alert bool) { + if alert { + if err := notify(message, urgency); err != nil { + log.Printf("failure sending notification: %s\n", err) + } + } + + switch urgency { + case "critical", "normal": + log.Fatal(message) + default: + log.Println(message) + } +} + +func notify(message string, urgency string) error { + var timeout time.Duration + switch urgency { + // cases accepted by notify-send: low, normal, critical + case "critical": + timeout = 5 * time.Second + case "low": + timeout = 2 * time.Second + default: + timeout = 3 * time.Second + } + + // notify-send only accepts milliseconds + millisec := fmt.Sprintf("%v", timeout.Seconds()*1000) + + args := []string{"-a", "Clipman", "-u", urgency, "-t", millisec, message} + + return exec.Command("notify-send", args...).Run() + +}