From 3615552b6d447305672668108757ba5cfc54d2f3 Mon Sep 17 00:00:00 2001 From: Ilya Turkin <63l06ri5@gmail.com> Date: Mon, 1 Feb 2021 17:08:39 +0300 Subject: [PATCH] add get clipboard files and image handling --- README.md | 3 +- main.go | 44 ++++++++- ns/pasteboard.go | 252 ++++++++++++++++++++++++++++++++++++----------- 3 files changed, 237 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index c39b7cb..e1a51d7 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ A tiny library to access the MacOS clipboard (a.k.a. NSPasteboard). ```go -go get git.wow.st/gmp/clip +go get git.wow.st/63l06ri5/clip ``` ## API: @@ -20,4 +20,3 @@ func Set(string) bool // Get retrieves the string currently on the pasteboard. func Get() string ``` - diff --git a/main.go b/main.go index ce4cf5c..6121ad9 100644 --- a/main.go +++ b/main.go @@ -1,11 +1,18 @@ package clip import ( - "git.wow.st/gmp/clip/ns" + "strings" + + "git.wow.st/63l06ri5/clip/ns" ) var pb *ns.NSPasteboard +const ( + uriPrefix = "file://" + uriPrefixLength = len(uriPrefix) +) + func Clear() { if pb == nil { pb = ns.NSPasteboardGeneralPasteboard() @@ -32,3 +39,38 @@ func Get() string { return ret.String() } } + +func PasteFileList(filePaths []string) { + if pb == nil { + pb = ns.NSPasteboardGeneralPasteboard() + } + pb.PasteFileList(filePaths) +} + +func GetFileList() []string { + if pb == nil { + pb = ns.NSPasteboardGeneralPasteboard() + } + ret := pb.GetFileList() + result := make([]string, 0) + if ret.Ptr() == nil { + return result + } else { + filesStr := ret.String() + arr := strings.Split(filesStr, pb.FilesDelimeter) + for _, item := range arr { + if strings.HasPrefix(item, uriPrefix) { + result = append(result, item[uriPrefixLength:]) + } + } + return result + } +} + +func GetImage(pathToStore string) bool { + if pb == nil { + pb = ns.NSPasteboardGeneralPasteboard() + } + + return pb.GetImage(pathToStore) +} diff --git a/ns/pasteboard.go b/ns/pasteboard.go index 7eca07a..6a18cb1 100644 --- a/ns/pasteboard.go +++ b/ns/pasteboard.go @@ -86,126 +86,260 @@ NSPasteboard_inst_GetString(void* o) { } +void +NSPasteboard_inst_PasteFileList(void* o, void* string) { + @autoreleasepool { + NSArray *values = [(NSString*)string componentsSeparatedByString:@"\n"]; + + NSMutableArray *urls = [NSMutableArray arrayWithCapacity:values.count + 1]; + for (NSString *value in values) { + id transformedValue = [NSURL fileURLWithPath:value isDirectory:NO]; + [urls addObject:transformedValue]; + } + + NSString* pathPerLine = [values componentsJoinedByString:@"\n"]; + + NSPasteboard* pasteboard = (NSPasteboard*)o; + [pasteboard clearContents]; + [pasteboard writeObjects:urls]; + //Now add the pathsPerLine as a string + [pasteboard setString:pathPerLine forType:NSPasteboardTypeString]; + + } +} + +void* _Nullable +NSPasteboard_inst_GetFileList(void* o) { + NSString* _Nullable ret; + @autoreleasepool { + NSArray *classes = [NSArray arrayWithObject:[NSURL class]]; + + NSDictionary *options = [NSDictionary dictionaryWithObject: + [NSNumber numberWithBool:YES] forKey:NSPasteboardURLReadingFileURLsOnlyKey]; + + NSArray *fileURLs = + [(NSPasteboard*)o readObjectsForClasses:classes options:options]; + + NSMutableArray *paths = [NSMutableArray arrayWithCapacity:fileURLs.count]; + for (NSURL *value in fileURLs) { + id transformedValue = value.absoluteString; + [paths addObject:transformedValue]; + } + + ret = [paths componentsJoinedByString:@"\n"]; + if (ret != nil && ret != o) { [ret retain]; } + } + return ret; + +} + +BOOL +NSPasteboard_inst_GetImage(void* o, void* filePath) { + BOOL ret; + @autoreleasepool { + + NSData *data = [(NSPasteboard*)o dataForType:NSPasteboardTypeTIFF]; + if (data != nil && data != o) { + // NSImage *img = [[NSImage alloc] initWithData:data]; + //NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"image.tiff"]; + [data writeToFile: (NSString*)filePath atomically: NO]; + ret = true; + } else + { + ret = false; + } + } + return ret; + +} + + */ import "C" import ( - "unsafe" "runtime" + "strings" + "unsafe" ) type Id struct { - ptr unsafe.Pointer + ptr unsafe.Pointer +} + +const FilesDelimeter = "\n" + +func (o *Id) Ptr() unsafe.Pointer { + if o == nil { + return nil + } + return o.ptr } -func (o *Id) Ptr() unsafe.Pointer { if o == nil { return nil }; return o.ptr } type NSObject interface { - Ptr() unsafe.Pointer + Ptr() unsafe.Pointer } -func (o *Id) Release() { - C.NSObject_inst_Release(o.Ptr()) - runtime.KeepAlive(o) +func (o *Id) Release() { + C.NSObject_inst_Release(o.Ptr()) + runtime.KeepAlive(o) } -func (o *NSPasteboard) Release() { - C.NSPasteboard_inst_Release(o.Ptr()) - runtime.KeepAlive(o) +func (o *NSPasteboard) Release() { + C.NSPasteboard_inst_Release(o.Ptr()) + runtime.KeepAlive(o) } -func (o *NSString) Release() { - C.NSString_inst_Release(o.Ptr()) - runtime.KeepAlive(o) +func (o *NSString) Release() { + C.NSString_inst_Release(o.Ptr()) + runtime.KeepAlive(o) } func (c *Char) Free() { - C.free(unsafe.Pointer(c)) + C.free(unsafe.Pointer(c)) } type BOOL C.uchar -type NSString struct { Id } -func (o *NSString) Ptr() unsafe.Pointer { if o == nil { return nil }; return o.ptr } +type NSString struct{ Id } + +func (o *NSString) Ptr() unsafe.Pointer { + if o == nil { + return nil + } + return o.ptr +} func (o *Id) NSString() *NSString { - return (*NSString)(unsafe.Pointer(o)) + return (*NSString)(unsafe.Pointer(o)) } func (o *NSString) UTF8String() *Char { - ret := (*Char)(unsafe.Pointer(C.NSString_inst_UTF8String(o.Ptr()))) - runtime.KeepAlive(o) - return ret + ret := (*Char)(unsafe.Pointer(C.NSString_inst_UTF8String(o.Ptr()))) + runtime.KeepAlive(o) + return ret } func (o *NSString) String() string { - utf8 := o.UTF8String() - ret := utf8.String() - utf8.Free() - runtime.KeepAlive(o) - return ret + utf8 := o.UTF8String() + ret := utf8.String() + utf8.Free() + runtime.KeepAlive(o) + return ret } -type NSPasteboard struct { Id } -func (o *NSPasteboard) Ptr() unsafe.Pointer { if o == nil { return nil }; return o.ptr } +type NSPasteboard struct{ Id } + +func (o *NSPasteboard) Ptr() unsafe.Pointer { + if o == nil { + return nil + } + return o.ptr +} func (o *Id) NSPasteboard() *NSPasteboard { - return (*NSPasteboard)(unsafe.Pointer(o)) + return (*NSPasteboard)(unsafe.Pointer(o)) } type Char C.char func CharWithGoString(s string) *Char { - return (*Char)(unsafe.Pointer(C.CString(s))) + return (*Char)(unsafe.Pointer(C.CString(s))) } func (c *Char) String() string { - return C.GoString((*C.char)(c)) + return C.GoString((*C.char)(c)) } func NSStringWithUTF8String(nullTerminatedCString *Char) *NSString { - ret := &NSString{} - ret.ptr = unsafe.Pointer(C.NSString_StringWithUTF8String(unsafe.Pointer(nullTerminatedCString))) - if ret.ptr == nil { return ret } - runtime.SetFinalizer(ret, func(o *NSString) { - o.Release() - }) - return ret + ret := &NSString{} + ret.ptr = unsafe.Pointer(C.NSString_StringWithUTF8String(unsafe.Pointer(nullTerminatedCString))) + if ret.ptr == nil { + return ret + } + runtime.SetFinalizer(ret, func(o *NSString) { + o.Release() + }) + return ret } func NSStringWithGoString(string string) *NSString { - string_chr := CharWithGoString(string) - defer string_chr.Free() - ret := NSStringWithUTF8String(string_chr) - return ret + string_chr := CharWithGoString(string) + defer string_chr.Free() + ret := NSStringWithUTF8String(string_chr) + return ret } func NSPasteboardGeneralPasteboard() *NSPasteboard { - ret := &NSPasteboard{} - ret.ptr = unsafe.Pointer(C.NSPasteboard_GeneralPasteboard()) - if ret.ptr == nil { return ret } - return ret + ret := &NSPasteboard{} + ret.ptr = unsafe.Pointer(C.NSPasteboard_GeneralPasteboard()) + if ret.ptr == nil { + return ret + } + return ret } func (o *NSPasteboard) ClearContents() { - C.NSPasteboard_inst_ClearContents(o.Ptr()) - runtime.KeepAlive(o) + C.NSPasteboard_inst_ClearContents(o.Ptr()) + runtime.KeepAlive(o) } func (o *NSPasteboard) SetString(s string) bool { string := NSStringWithGoString(s) - ret := (C.NSPasteboard_inst_SetString(o.Ptr(), string.Ptr())) != 0 - runtime.KeepAlive(o) + ret := (C.NSPasteboard_inst_SetString(o.Ptr(), string.Ptr())) != 0 + runtime.KeepAlive(o) runtime.KeepAlive(string) - return ret + return ret } func (o *NSPasteboard) GetString() *NSString { - ret := &NSString{} - ret.ptr = unsafe.Pointer(C.NSPasteboard_inst_GetString(o.Ptr())) - if ret.ptr == nil { runtime.KeepAlive(o); return ret } - if ret.ptr == o.ptr { runtime.KeepAlive(o); return (*NSString)(unsafe.Pointer(o)) } - runtime.SetFinalizer(ret, func(o *NSString) { - o.Release() - }) - runtime.KeepAlive(o) - return ret + ret := &NSString{} + ret.ptr = unsafe.Pointer(C.NSPasteboard_inst_GetString(o.Ptr())) + if ret.ptr == nil { + runtime.KeepAlive(o) + return ret + } + if ret.ptr == o.ptr { + runtime.KeepAlive(o) + return (*NSString)(unsafe.Pointer(o)) + } + runtime.SetFinalizer(ret, func(o *NSString) { + o.Release() + }) + runtime.KeepAlive(o) + return ret } +func (o *NSPasteboard) PasteFileList(values []string) { + inString := strings.Join(values, FilesDelimeter) + str := NSStringWithGoString(inString) + C.NSPasteboard_inst_PasteFileList(o.Ptr(), str.Ptr()) + runtime.KeepAlive(o) + runtime.KeepAlive(str) + return + +} + +func (o *NSPasteboard) GetFileList() *NSString { + ret := &NSString{} + ret.ptr = unsafe.Pointer(C.NSPasteboard_inst_GetFileList(o.Ptr())) + if ret.ptr == nil { + runtime.KeepAlive(o) + return ret + } + if ret.ptr == o.ptr { + runtime.KeepAlive(o) + return (*NSString)(unsafe.Pointer(o)) + } + runtime.SetFinalizer(ret, func(o *NSString) { + o.Release() + }) + runtime.KeepAlive(o) + return ret +} + +func (o *NSPasteboard) GetImage(filePath string) bool { + string := NSStringWithGoString(filePath) + ret := (C.NSPasteboard_inst_GetImage(o.Ptr(), string.Ptr())) != 0 + runtime.KeepAlive(o) + runtime.KeepAlive(string) + return ret +}