2019-03-22 16:25:09 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2019-04-16 14:21:36 +02:00
|
|
|
"fmt"
|
2019-03-22 16:25:09 +01:00
|
|
|
"io/ioutil"
|
2019-04-18 16:15:35 +02:00
|
|
|
"log"
|
2019-03-22 16:25:09 +01:00
|
|
|
"os/exec"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
func write(history []string, histfile string) error {
|
|
|
|
histlog, err := json.Marshal(history)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = ioutil.WriteFile(histfile, histlog, 0644)
|
2019-05-22 11:36:39 +02:00
|
|
|
|
|
|
|
return err
|
2019-03-22 16:25:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func filter(history []string, text string) []string {
|
|
|
|
var (
|
|
|
|
found bool
|
|
|
|
idx int
|
|
|
|
)
|
|
|
|
|
|
|
|
for i, el := range history {
|
|
|
|
if el == text {
|
|
|
|
found = true
|
|
|
|
idx = i
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if found {
|
|
|
|
// we know that idx can't be the last element, because
|
|
|
|
// we never get to call this function if that's the case
|
|
|
|
history = append(history[:idx], history[idx+1:]...)
|
|
|
|
}
|
|
|
|
|
|
|
|
return history
|
|
|
|
}
|
|
|
|
|
2019-03-23 11:26:50 +01:00
|
|
|
func listen(history []string, histfile string, persist bool, max int) error {
|
2019-03-22 16:25:09 +01:00
|
|
|
for {
|
|
|
|
|
2019-04-18 16:15:35 +02:00
|
|
|
t, err := exec.Command("wl-paste", []string{"-n", "-t", "text"}...).CombinedOutput()
|
2019-04-16 14:21:36 +02:00
|
|
|
if err != nil {
|
2019-04-18 16:15:35 +02:00
|
|
|
// wl-paste exits 1 if there's no selection (e.g., when running it at OS startup)
|
2019-04-18 23:07:34 +02:00
|
|
|
if string(t) != "No selection\n" {
|
2019-04-18 16:15:35 +02:00
|
|
|
log.Printf("Error running wl-paste (demon.52): %s", t)
|
|
|
|
}
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
continue
|
2019-04-16 14:21:36 +02:00
|
|
|
}
|
|
|
|
|
2019-03-22 16:25:09 +01:00
|
|
|
text := string(t)
|
2019-04-18 16:15:35 +02:00
|
|
|
|
2019-04-16 14:21:36 +02:00
|
|
|
if text == "" {
|
2019-03-22 16:25:09 +01:00
|
|
|
// there's nothing to select, so we sleep.
|
2019-03-23 11:08:06 +01:00
|
|
|
time.Sleep(1 * time.Second)
|
2019-03-22 16:25:09 +01:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
l := len(history)
|
|
|
|
|
|
|
|
if l > 0 {
|
|
|
|
|
|
|
|
// wl-paste will always give back the last copied text
|
|
|
|
// (as long as the place we copied from is still running)
|
|
|
|
if history[l-1] == text {
|
2019-03-23 11:08:06 +01:00
|
|
|
time.Sleep(1 * time.Second)
|
2019-03-22 16:25:09 +01:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if l == max {
|
|
|
|
// we know that at any given time len(history) cannot be bigger than max,
|
|
|
|
// so it's enough to drop the first element
|
|
|
|
history = history[1:]
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove duplicates
|
|
|
|
history = filter(history, text)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
history = append(history, text)
|
|
|
|
|
|
|
|
// dump history to file so that other apps can query it
|
|
|
|
err = write(history, histfile)
|
|
|
|
if err != nil {
|
2019-06-11 21:53:30 +02:00
|
|
|
return fmt.Errorf("Error writing history (demon.83): %s", err)
|
2019-03-22 16:25:09 +01:00
|
|
|
}
|
|
|
|
|
2019-03-23 11:20:58 +01:00
|
|
|
if persist {
|
|
|
|
// make the copy buffer available to all applications,
|
|
|
|
// even when the source has disappeared
|
2019-04-16 14:30:07 +02:00
|
|
|
if err := exec.Command("wl-copy", []string{"--", text}...).Run(); err != nil {
|
2019-04-16 14:21:36 +02:00
|
|
|
return fmt.Errorf("error running wl-copy (demon.91): %s", err)
|
2019-03-23 11:20:58 +01:00
|
|
|
}
|
|
|
|
}
|
2019-03-22 16:25:09 +01:00
|
|
|
}
|
|
|
|
}
|