github.com/puellanivis/breton@v0.2.16/lib/files/clipboard/clip.go (about) 1 // Package clipboard implements a scheme for "clipboard:" and "clip:". 2 package clipboard 3 4 import ( 5 "context" 6 "net/url" 7 "os" 8 "syscall" 9 "time" 10 11 "github.com/puellanivis/breton/lib/files" 12 "github.com/puellanivis/breton/lib/files/wrapper" 13 ) 14 15 type handler struct{} 16 17 func init() { 18 files.RegisterScheme(&handler{}, "clip", "clipboard") 19 } 20 21 type clipboard interface { 22 Stat() (os.FileInfo, error) 23 Read() ([]byte, error) 24 Write([]byte) error 25 } 26 27 var clipboards = make(map[string]clipboard) 28 29 func getClip(uri *url.URL) (clipboard, error) { 30 if uri.Host != "" || uri.User != nil { 31 return nil, os.ErrInvalid 32 } 33 34 path := uri.Path 35 if path == "" { 36 path = uri.Opaque 37 } 38 39 clip := clipboards[path] 40 if clip == nil { 41 return nil, os.ErrNotExist 42 } 43 44 return clip, nil 45 } 46 47 func (h *handler) Open(ctx context.Context, uri *url.URL) (files.Reader, error) { 48 clip, err := getClip(uri) 49 if err != nil { 50 return nil, files.PathError("open", uri.String(), err) 51 } 52 53 b, err := clip.Read() 54 if err != nil { 55 return nil, err 56 } 57 58 return wrapper.NewReaderFromBytes(b, uri, time.Now()), nil 59 } 60 61 func (h *handler) Create(ctx context.Context, uri *url.URL) (files.Writer, error) { 62 clip, err := getClip(uri) 63 if err != nil { 64 return nil, files.PathError("create", uri.String(), err) 65 } 66 67 return wrapper.NewWriter(ctx, uri, func(b []byte) error { 68 return clip.Write(b) 69 }), nil 70 } 71 72 func (h *handler) List(ctx context.Context, uri *url.URL) ([]os.FileInfo, error) { 73 if uri.Host != "" || uri.User != nil { 74 return nil, files.PathError("readdir", uri.String(), os.ErrInvalid) 75 } 76 77 path := uri.Path 78 if path == "" { 79 path = uri.Opaque 80 } 81 82 clip := clipboards[path] 83 if clip == nil { 84 return nil, files.PathError("readdir", uri.String(), os.ErrNotExist) 85 } 86 87 if path != "" { 88 return nil, files.PathError("readdir", uri.String(), syscall.ENOTDIR) 89 } 90 91 if len(clipboards) < 1 { 92 return nil, files.PathError("readdir", uri.String(), os.ErrNotExist) 93 } 94 95 var ret []os.FileInfo 96 97 for _, clip := range clipboards { 98 if fi, err := clip.Stat(); err == nil { 99 ret = append(ret, fi) 100 } 101 } 102 103 return ret, nil 104 }