diff --git a/myast/myast.go b/myast/myast.go index 2c15b20..e6a0fd5 100644 --- a/myast/myast.go +++ b/myast/myast.go @@ -126,6 +126,8 @@ func (a *structAnalys) structFieldInfo(astPkg *ast.Package, sinfo *ast.StructTyp } case *ast.InterfaceType: info.Type = "Interface" + case *ast.ArrayType: + info.Type = "Array" } case *ast.StarExpr: switch x := exp.X.(type) { diff --git a/myclipboard/clipboard/LICENSE b/myclipboard/clipboard/LICENSE new file mode 100644 index 0000000..dee3257 --- /dev/null +++ b/myclipboard/clipboard/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 Ato Araki. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of @atotto. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/myclipboard/clipboard/README.md b/myclipboard/clipboard/README.md new file mode 100644 index 0000000..c451e55 --- /dev/null +++ b/myclipboard/clipboard/README.md @@ -0,0 +1,48 @@ +[![Build Status](https://travis-ci.com/atotto/clipboard.svg?branch=master)](https://travis-ci.com/atotto/clipboard) + +[![GoDoc](https://godoc.org/github.com/atotto/clipboard?status.svg)](http://godoc.org/github.com/atotto/clipboard) + +# Clipboard for Go + +Provide copying and pasting to the Clipboard for Go. + +Build: + + $ go get github.com/atotto/clipboard + +Platforms: + +* OSX +* Windows 7 (probably work on other Windows) +* Linux, Unix (requires 'xclip' or 'xsel' command to be installed) + + +Document: + +* http://godoc.org/github.com/atotto/clipboard + +Notes: + +* Text string only +* UTF-8 text encoding only (no conversion) + +TODO: + +* Clipboard watcher(?) + +## Commands: + +paste shell command: + + $ go get github.com/atotto/clipboard/cmd/gopaste + $ # example: + $ gopaste > document.txt + +copy shell command: + + $ go get github.com/atotto/clipboard/cmd/gocopy + $ # example: + $ cat document.txt | gocopy + + + diff --git a/myclipboard/clipboard/clipboard.go b/myclipboard/clipboard/clipboard.go new file mode 100644 index 0000000..d7907d3 --- /dev/null +++ b/myclipboard/clipboard/clipboard.go @@ -0,0 +1,20 @@ +// Copyright 2013 @atotto. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package clipboard read/write on clipboard +package clipboard + +// ReadAll read string from clipboard +func ReadAll() (string, error) { + return readAll() +} + +// WriteAll write string to clipboard +func WriteAll(text string) error { + return writeAll(text) +} + +// Unsupported might be set true during clipboard init, to help callers decide +// whether or not to offer clipboard options. +var Unsupported bool diff --git a/myclipboard/clipboard/clipboard_darwin.go b/myclipboard/clipboard/clipboard_darwin.go new file mode 100644 index 0000000..6f33078 --- /dev/null +++ b/myclipboard/clipboard/clipboard_darwin.go @@ -0,0 +1,52 @@ +// Copyright 2013 @atotto. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin + +package clipboard + +import ( + "os/exec" +) + +var ( + pasteCmdArgs = "pbpaste" + copyCmdArgs = "pbcopy" +) + +func getPasteCommand() *exec.Cmd { + return exec.Command(pasteCmdArgs) +} + +func getCopyCommand() *exec.Cmd { + return exec.Command(copyCmdArgs) +} + +func readAll() (string, error) { + pasteCmd := getPasteCommand() + out, err := pasteCmd.Output() + if err != nil { + return "", err + } + return string(out), nil +} + +func writeAll(text string) error { + copyCmd := getCopyCommand() + in, err := copyCmd.StdinPipe() + if err != nil { + return err + } + + if err := copyCmd.Start(); err != nil { + return err + } + if _, err := in.Write([]byte(text)); err != nil { + return err + } + if err := in.Close(); err != nil { + return err + } + return copyCmd.Wait() +} diff --git a/myclipboard/clipboard/clipboard_plan9.go b/myclipboard/clipboard/clipboard_plan9.go new file mode 100644 index 0000000..9d2fef4 --- /dev/null +++ b/myclipboard/clipboard/clipboard_plan9.go @@ -0,0 +1,42 @@ +// Copyright 2013 @atotto. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build plan9 + +package clipboard + +import ( + "os" + "io/ioutil" +) + +func readAll() (string, error) { + f, err := os.Open("/dev/snarf") + if err != nil { + return "", err + } + defer f.Close() + + str, err := ioutil.ReadAll(f) + if err != nil { + return "", err + } + + return string(str), nil +} + +func writeAll(text string) error { + f, err := os.OpenFile("/dev/snarf", os.O_WRONLY, 0666) + if err != nil { + return err + } + defer f.Close() + + _, err = f.Write([]byte(text)) + if err != nil { + return err + } + + return nil +} diff --git a/myclipboard/clipboard/clipboard_test.go b/myclipboard/clipboard/clipboard_test.go new file mode 100644 index 0000000..075e657 --- /dev/null +++ b/myclipboard/clipboard/clipboard_test.go @@ -0,0 +1,73 @@ +// Copyright 2013 @atotto. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package clipboard_test + +import ( + "testing" + + . "github.com/atotto/clipboard" +) + +func TestCopyAndPaste(t *testing.T) { + expected := "日本語" + + err := WriteAll(expected) + if err != nil { + t.Fatal(err) + } + + actual, err := ReadAll() + if err != nil { + t.Fatal(err) + } + + if actual != expected { + t.Errorf("want %s, got %s", expected, actual) + } +} + +func TestMultiCopyAndPaste(t *testing.T) { + expected1 := "French: éèêëàùœç" + expected2 := "Weird UTF-8: 💩☃" + + err := WriteAll(expected1) + if err != nil { + t.Fatal(err) + } + + actual1, err := ReadAll() + if err != nil { + t.Fatal(err) + } + if actual1 != expected1 { + t.Errorf("want %s, got %s", expected1, actual1) + } + + err = WriteAll(expected2) + if err != nil { + t.Fatal(err) + } + + actual2, err := ReadAll() + if err != nil { + t.Fatal(err) + } + if actual2 != expected2 { + t.Errorf("want %s, got %s", expected2, actual2) + } +} + +func BenchmarkReadAll(b *testing.B) { + for i := 0; i < b.N; i++ { + ReadAll() + } +} + +func BenchmarkWriteAll(b *testing.B) { + text := "いろはにほへと" + for i := 0; i < b.N; i++ { + WriteAll(text) + } +} diff --git a/myclipboard/clipboard/clipboard_unix.go b/myclipboard/clipboard/clipboard_unix.go new file mode 100644 index 0000000..d9f6a56 --- /dev/null +++ b/myclipboard/clipboard/clipboard_unix.go @@ -0,0 +1,149 @@ +// Copyright 2013 @atotto. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build freebsd linux netbsd openbsd solaris dragonfly + +package clipboard + +import ( + "errors" + "os" + "os/exec" +) + +const ( + xsel = "xsel" + xclip = "xclip" + powershellExe = "powershell.exe" + clipExe = "clip.exe" + wlcopy = "wl-copy" + wlpaste = "wl-paste" + termuxClipboardGet = "termux-clipboard-get" + termuxClipboardSet = "termux-clipboard-set" +) + +var ( + Primary bool + trimDos bool + + pasteCmdArgs []string + copyCmdArgs []string + + xselPasteArgs = []string{xsel, "--output", "--clipboard"} + xselCopyArgs = []string{xsel, "--input", "--clipboard"} + + xclipPasteArgs = []string{xclip, "-out", "-selection", "clipboard"} + xclipCopyArgs = []string{xclip, "-in", "-selection", "clipboard"} + + powershellExePasteArgs = []string{powershellExe, "Get-Clipboard"} + clipExeCopyArgs = []string{clipExe} + + wlpasteArgs = []string{wlpaste, "--no-newline"} + wlcopyArgs = []string{wlcopy} + + termuxPasteArgs = []string{termuxClipboardGet} + termuxCopyArgs = []string{termuxClipboardSet} + + missingCommands = errors.New("No clipboard utilities available. Please install xsel, xclip, wl-clipboard or Termux:API add-on for termux-clipboard-get/set.") +) + +func init() { + if os.Getenv("WAYLAND_DISPLAY") != "" { + pasteCmdArgs = wlpasteArgs + copyCmdArgs = wlcopyArgs + + if _, err := exec.LookPath(wlcopy); err == nil { + if _, err := exec.LookPath(wlpaste); err == nil { + return + } + } + } + + pasteCmdArgs = xclipPasteArgs + copyCmdArgs = xclipCopyArgs + + if _, err := exec.LookPath(xclip); err == nil { + return + } + + pasteCmdArgs = xselPasteArgs + copyCmdArgs = xselCopyArgs + + if _, err := exec.LookPath(xsel); err == nil { + return + } + + pasteCmdArgs = termuxPasteArgs + copyCmdArgs = termuxCopyArgs + + if _, err := exec.LookPath(termuxClipboardSet); err == nil { + if _, err := exec.LookPath(termuxClipboardGet); err == nil { + return + } + } + + pasteCmdArgs = powershellExePasteArgs + copyCmdArgs = clipExeCopyArgs + trimDos = true + + if _, err := exec.LookPath(clipExe); err == nil { + if _, err := exec.LookPath(powershellExe); err == nil { + return + } + } + + Unsupported = true +} + +func getPasteCommand() *exec.Cmd { + if Primary { + pasteCmdArgs = pasteCmdArgs[:1] + } + return exec.Command(pasteCmdArgs[0], pasteCmdArgs[1:]...) +} + +func getCopyCommand() *exec.Cmd { + if Primary { + copyCmdArgs = copyCmdArgs[:1] + } + return exec.Command(copyCmdArgs[0], copyCmdArgs[1:]...) +} + +func readAll() (string, error) { + if Unsupported { + return "", missingCommands + } + pasteCmd := getPasteCommand() + out, err := pasteCmd.Output() + if err != nil { + return "", err + } + result := string(out) + if trimDos && len(result) > 1 { + result = result[:len(result)-2] + } + return result, nil +} + +func writeAll(text string) error { + if Unsupported { + return missingCommands + } + copyCmd := getCopyCommand() + in, err := copyCmd.StdinPipe() + if err != nil { + return err + } + + if err := copyCmd.Start(); err != nil { + return err + } + if _, err := in.Write([]byte(text)); err != nil { + return err + } + if err := in.Close(); err != nil { + return err + } + return copyCmd.Wait() +} diff --git a/myclipboard/clipboard/clipboard_windows.go b/myclipboard/clipboard/clipboard_windows.go new file mode 100644 index 0000000..253bb93 --- /dev/null +++ b/myclipboard/clipboard/clipboard_windows.go @@ -0,0 +1,157 @@ +// Copyright 2013 @atotto. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows + +package clipboard + +import ( + "runtime" + "syscall" + "time" + "unsafe" +) + +const ( + cfUnicodetext = 13 + gmemMoveable = 0x0002 +) + +var ( + user32 = syscall.MustLoadDLL("user32") + isClipboardFormatAvailable = user32.MustFindProc("IsClipboardFormatAvailable") + openClipboard = user32.MustFindProc("OpenClipboard") + closeClipboard = user32.MustFindProc("CloseClipboard") + emptyClipboard = user32.MustFindProc("EmptyClipboard") + getClipboardData = user32.MustFindProc("GetClipboardData") + setClipboardData = user32.MustFindProc("SetClipboardData") + + kernel32 = syscall.NewLazyDLL("kernel32") + globalAlloc = kernel32.NewProc("GlobalAlloc") + globalFree = kernel32.NewProc("GlobalFree") + globalLock = kernel32.NewProc("GlobalLock") + globalUnlock = kernel32.NewProc("GlobalUnlock") + lstrcpy = kernel32.NewProc("lstrcpyW") +) + +// waitOpenClipboard opens the clipboard, waiting for up to a second to do so. +func waitOpenClipboard() error { + started := time.Now() + limit := started.Add(time.Second) + var r uintptr + var err error + for time.Now().Before(limit) { + r, _, err = openClipboard.Call(0) + if r != 0 { + return nil + } + time.Sleep(time.Millisecond) + } + return err +} + +func readAll() (string, error) { + // LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution). + // Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + if formatAvailable, _, err := isClipboardFormatAvailable.Call(cfUnicodetext); formatAvailable == 0 { + return "", err + } + err := waitOpenClipboard() + if err != nil { + return "", err + } + + h, _, err := getClipboardData.Call(cfUnicodetext) + if h == 0 { + _, _, _ = closeClipboard.Call() + return "", err + } + + l, _, err := globalLock.Call(h) + if l == 0 { + _, _, _ = closeClipboard.Call() + return "", err + } + + text := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(l))[:]) + + r, _, err := globalUnlock.Call(h) + if r == 0 { + _, _, _ = closeClipboard.Call() + return "", err + } + + closed, _, err := closeClipboard.Call() + if closed == 0 { + return "", err + } + return text, nil +} + +func writeAll(text string) error { + // LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution). + // Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := waitOpenClipboard() + if err != nil { + return err + } + + r, _, err := emptyClipboard.Call(0) + if r == 0 { + _, _, _ = closeClipboard.Call() + return err + } + + data := syscall.StringToUTF16(text) + + // "If the hMem parameter identifies a memory object, the object must have + // been allocated using the function with the GMEM_MOVEABLE flag." + h, _, err := globalAlloc.Call(gmemMoveable, uintptr(len(data)*int(unsafe.Sizeof(data[0])))) + if h == 0 { + _, _, _ = closeClipboard.Call() + return err + } + defer func() { + if h != 0 { + globalFree.Call(h) + } + }() + + l, _, err := globalLock.Call(h) + if l == 0 { + _, _, _ = closeClipboard.Call() + return err + } + + r, _, err = lstrcpy.Call(l, uintptr(unsafe.Pointer(&data[0]))) + if r == 0 { + _, _, _ = closeClipboard.Call() + return err + } + + r, _, err = globalUnlock.Call(h) + if r == 0 { + if err.(syscall.Errno) != 0 { + _, _, _ = closeClipboard.Call() + return err + } + } + + r, _, err = setClipboardData.Call(cfUnicodetext, h) + if r == 0 { + _, _, _ = closeClipboard.Call() + return err + } + h = 0 // suppress deferred cleanup + closed, _, err := closeClipboard.Call() + if closed == 0 { + return err + } + return nil +} diff --git a/myclipboard/clipboard/cmd/gocopy/gocopy.go b/myclipboard/clipboard/cmd/gocopy/gocopy.go new file mode 100644 index 0000000..5148f10 --- /dev/null +++ b/myclipboard/clipboard/cmd/gocopy/gocopy.go @@ -0,0 +1,38 @@ +package main + +import ( + "flag" + "io/ioutil" + "os" + "time" + + "github.com/atotto/clipboard" +) + +func main() { + timeout := flag.Duration("t", 0, "Erase clipboard after timeout. Durations are specified like \"20s\" or \"2h45m\". 0 (default) means never erase.") + flag.Parse() + + out, err := ioutil.ReadAll(os.Stdin) + if err != nil { + panic(err) + } + + if err := clipboard.WriteAll(string(out)); err != nil { + panic(err) + } + + if timeout != nil && *timeout > 0 { + <-time.After(*timeout) + text, err := clipboard.ReadAll() + if err != nil { + os.Exit(1) + } + if text == string(out) { + err = clipboard.WriteAll("") + } + } + if err != nil { + os.Exit(1) + } +} diff --git a/myclipboard/clipboard/cmd/gopaste/gopaste.go b/myclipboard/clipboard/cmd/gopaste/gopaste.go new file mode 100644 index 0000000..49f08ee --- /dev/null +++ b/myclipboard/clipboard/cmd/gopaste/gopaste.go @@ -0,0 +1,16 @@ +package main + +import ( + "fmt" + + "github.com/atotto/clipboard" +) + +func main() { + text, err := clipboard.ReadAll() + if err != nil { + panic(err) + } + + fmt.Print(text) +} diff --git a/myclipboard/clipboard/example_test.go b/myclipboard/clipboard/example_test.go new file mode 100644 index 0000000..0f970a0 --- /dev/null +++ b/myclipboard/clipboard/example_test.go @@ -0,0 +1,16 @@ +package clipboard_test + +import ( + "fmt" + + "github.com/atotto/clipboard" +) + +func Example() { + clipboard.WriteAll("日本語") + text, _ := clipboard.ReadAll() + fmt.Println(text) + + // Output: + // 日本語 +} diff --git a/myclipboard/myclipboard.go b/myclipboard/myclipboard.go index 5393672..d14d630 100644 --- a/myclipboard/myclipboard.go +++ b/myclipboard/myclipboard.go @@ -1,7 +1,7 @@ package myclipboard import ( - "github.com/atotto/clipboard" + "github.com/xxjwxc/public/myclipboard/clipboard" "github.com/xxjwxc/public/mylog" )