You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
4.4 KiB
Go
211 lines
4.4 KiB
Go
package clipboard
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"git.noahlan.cn/noahlan/ntool/ncli"
|
|
"git.noahlan.cn/noahlan/ntool/nfs"
|
|
"git.noahlan.cn/noahlan/ntool/nsys"
|
|
"github.com/gookit/color"
|
|
"io"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// Clipboard struct
|
|
type Clipboard struct {
|
|
// TODO add event on write, read
|
|
// buffer for write
|
|
buf *bytes.Buffer
|
|
|
|
// print exec command line on run
|
|
verbose bool
|
|
// available - bin file exist on the OS.
|
|
writeable, readable bool
|
|
|
|
readerBin string
|
|
readArgs []string
|
|
writerBin string
|
|
writeArgs []string
|
|
}
|
|
|
|
// New instance
|
|
func New() *Clipboard {
|
|
// special handle on with args
|
|
reader, readArgs := parseLine(GetReaderBin())
|
|
writer, writeArgs := parseLine(GetWriterBin())
|
|
|
|
return &Clipboard{
|
|
readerBin: reader,
|
|
readArgs: readArgs,
|
|
writerBin: writer,
|
|
writeArgs: writeArgs,
|
|
readable: nsys.HasExecutable(reader),
|
|
writeable: nsys.HasExecutable(writer),
|
|
}
|
|
}
|
|
|
|
// WithVerbose setting
|
|
func (c *Clipboard) WithVerbose(yn bool) *Clipboard {
|
|
c.verbose = yn
|
|
return c
|
|
}
|
|
|
|
// Clean the clipboard
|
|
func (c *Clipboard) Clean() error { return c.Reset() }
|
|
|
|
// Reset and clean the clipboard
|
|
func (c *Clipboard) Reset() error {
|
|
if c.buf != nil {
|
|
c.buf.Reset()
|
|
}
|
|
|
|
// echo empty string for clean clipboard.
|
|
// run: echo '' | pbcopy
|
|
return c.WriteFrom(strings.NewReader(""))
|
|
}
|
|
|
|
//
|
|
// ---------------------------------------- write ----------------------------------------
|
|
//
|
|
|
|
// Write bytes data to clipboard
|
|
func (c *Clipboard) Write(p []byte) (int, error) {
|
|
return c.WriteString(string(p))
|
|
}
|
|
|
|
// WriteString data to clipboard
|
|
func (c *Clipboard) WriteString(s string) (int, error) {
|
|
// if c.addSlashes {
|
|
// s = strutil.AddSlashes(s)
|
|
// }
|
|
return c.buffer().WriteString(s)
|
|
}
|
|
|
|
// Flush buffer contents to clipboard
|
|
func (c *Clipboard) Flush() error {
|
|
if c.buf == nil || c.buf.Len() == 0 {
|
|
return errors.New("clipboard: empty contents for write")
|
|
}
|
|
|
|
defer c.buf.Reset()
|
|
return c.WriteFrom(c.buf)
|
|
}
|
|
|
|
// WriteFromFile contents to clipboard
|
|
func (c *Clipboard) WriteFromFile(filepath string) error {
|
|
// eg:
|
|
// Mac: pbcopy < tempfile.txt
|
|
file, err := nfs.OpenReadFile(filepath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer file.Close()
|
|
return c.WriteFrom(file)
|
|
}
|
|
|
|
// WriteFrom reader data to clipboard
|
|
func (c *Clipboard) WriteFrom(r io.Reader) error {
|
|
if !c.writeable {
|
|
return fmt.Errorf("clipboard: write driver %q not found on OS", c.writerBin)
|
|
}
|
|
|
|
cmd := exec.Command(c.writerBin, c.writeArgs...)
|
|
cmd.Stdin = r
|
|
|
|
if c.verbose {
|
|
color.Yellow.Printf("clipboard> %s\n", ncli.BuildLine(c.writerBin, c.writeArgs))
|
|
}
|
|
return cmd.Run()
|
|
}
|
|
|
|
//
|
|
// ---------------------------------------- read ----------------------------------------
|
|
//
|
|
|
|
// Read contents from clipboard
|
|
func (c *Clipboard) Read() ([]byte, error) {
|
|
buf, err := c.ReadToBuffer()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
// ReadToBuffer contents from clipboard
|
|
func (c *Clipboard) ReadToBuffer() (*bytes.Buffer, error) {
|
|
var buf bytes.Buffer
|
|
if err := c.ReadTo(&buf); err != nil {
|
|
return nil, err
|
|
}
|
|
return &buf, nil
|
|
}
|
|
|
|
// ReadString contents as string from clipboard
|
|
func (c *Clipboard) ReadString() (string, error) {
|
|
bts, err := c.Read()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// fix: at Windows will always return end of the "\r\n"
|
|
if nsys.IsWindows() {
|
|
return string(bytes.TrimRight(bts, "\r\n")), nil
|
|
}
|
|
return string(bts), nil
|
|
}
|
|
|
|
// ReadToFile dump clipboard data to file
|
|
func (c *Clipboard) ReadToFile(filepath string) error {
|
|
file, err := nfs.QuickOpenFile(filepath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer file.Close()
|
|
return c.ReadTo(file)
|
|
}
|
|
|
|
// ReadTo read clipboard contents to writer
|
|
func (c *Clipboard) ReadTo(w io.Writer) error {
|
|
if !c.readable {
|
|
return fmt.Errorf("clipboard: read driver %q not found on OS", c.readerBin)
|
|
}
|
|
|
|
cmd := exec.Command(c.readerBin, c.readArgs...)
|
|
cmd.Stdout = w
|
|
|
|
if c.verbose {
|
|
color.Yellow.Printf("clipboard> %s\n", ncli.BuildLine(c.writerBin, c.writeArgs))
|
|
}
|
|
return cmd.Run()
|
|
}
|
|
|
|
//
|
|
// ---------------------------------------- help ----------------------------------------
|
|
//
|
|
|
|
// Available check
|
|
func (c *Clipboard) Available() bool {
|
|
return c.writeable && c.readable && available()
|
|
}
|
|
|
|
// Writeable check
|
|
func (c *Clipboard) Writeable() bool {
|
|
return c.writeable
|
|
}
|
|
|
|
// Readable check
|
|
func (c *Clipboard) Readable() bool {
|
|
return c.readable
|
|
}
|
|
|
|
func (c *Clipboard) buffer() *bytes.Buffer {
|
|
if c.buf == nil {
|
|
c.buf = new(bytes.Buffer)
|
|
}
|
|
return c.buf
|
|
}
|