diff --git a/vendor/github.com/kr/pty/License b/vendor/github.com/kr/pty/License new file mode 100644 index 0000000..6b7558b --- /dev/null +++ b/vendor/github.com/kr/pty/License @@ -0,0 +1,23 @@ +Copyright (c) 2011 Keith Rarick + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall +be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/kr/pty/README.md b/vendor/github.com/kr/pty/README.md new file mode 100644 index 0000000..7b7900c --- /dev/null +++ b/vendor/github.com/kr/pty/README.md @@ -0,0 +1,36 @@ +# pty + +Pty is a Go package for using unix pseudo-terminals. + +## Install + + go get github.com/kr/pty + +## Example + +```go +package main + +import ( + "github.com/kr/pty" + "io" + "os" + "os/exec" +) + +func main() { + c := exec.Command("grep", "--color=auto", "bar") + f, err := pty.Start(c) + if err != nil { + panic(err) + } + + go func() { + f.Write([]byte("foo\n")) + f.Write([]byte("bar\n")) + f.Write([]byte("baz\n")) + f.Write([]byte{4}) // EOT + }() + io.Copy(os.Stdout, f) +} +``` diff --git a/vendor/github.com/kr/pty/doc.go b/vendor/github.com/kr/pty/doc.go new file mode 100644 index 0000000..190cfbe --- /dev/null +++ b/vendor/github.com/kr/pty/doc.go @@ -0,0 +1,16 @@ +// Package pty provides functions for working with Unix terminals. +package pty + +import ( + "errors" + "os" +) + +// ErrUnsupported is returned if a function is not +// available on the current platform. +var ErrUnsupported = errors.New("unsupported") + +// Opens a pty and its corresponding tty. +func Open() (pty, tty *os.File, err error) { + return open() +} diff --git a/vendor/github.com/kr/pty/ioctl.go b/vendor/github.com/kr/pty/ioctl.go new file mode 100644 index 0000000..c57c19e --- /dev/null +++ b/vendor/github.com/kr/pty/ioctl.go @@ -0,0 +1,13 @@ +// +build !windows + +package pty + +import "syscall" + +func ioctl(fd, cmd, ptr uintptr) error { + _, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, ptr) + if e != 0 { + return e + } + return nil +} diff --git a/vendor/github.com/kr/pty/ioctl_bsd.go b/vendor/github.com/kr/pty/ioctl_bsd.go new file mode 100644 index 0000000..73b12c5 --- /dev/null +++ b/vendor/github.com/kr/pty/ioctl_bsd.go @@ -0,0 +1,39 @@ +// +build darwin dragonfly freebsd netbsd openbsd + +package pty + +// from +const ( + _IOC_VOID uintptr = 0x20000000 + _IOC_OUT uintptr = 0x40000000 + _IOC_IN uintptr = 0x80000000 + _IOC_IN_OUT uintptr = _IOC_OUT | _IOC_IN + _IOC_DIRMASK = _IOC_VOID | _IOC_OUT | _IOC_IN + + _IOC_PARAM_SHIFT = 13 + _IOC_PARAM_MASK = (1 << _IOC_PARAM_SHIFT) - 1 +) + +func _IOC_PARM_LEN(ioctl uintptr) uintptr { + return (ioctl >> 16) & _IOC_PARAM_MASK +} + +func _IOC(inout uintptr, group byte, ioctl_num uintptr, param_len uintptr) uintptr { + return inout | (param_len&_IOC_PARAM_MASK)<<16 | uintptr(group)<<8 | ioctl_num +} + +func _IO(group byte, ioctl_num uintptr) uintptr { + return _IOC(_IOC_VOID, group, ioctl_num, 0) +} + +func _IOR(group byte, ioctl_num uintptr, param_len uintptr) uintptr { + return _IOC(_IOC_OUT, group, ioctl_num, param_len) +} + +func _IOW(group byte, ioctl_num uintptr, param_len uintptr) uintptr { + return _IOC(_IOC_IN, group, ioctl_num, param_len) +} + +func _IOWR(group byte, ioctl_num uintptr, param_len uintptr) uintptr { + return _IOC(_IOC_IN_OUT, group, ioctl_num, param_len) +} diff --git a/vendor/github.com/kr/pty/mktypes.bash b/vendor/github.com/kr/pty/mktypes.bash new file mode 100644 index 0000000..0c07680 --- /dev/null +++ b/vendor/github.com/kr/pty/mktypes.bash @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +GOOSARCH="${GOOS}_${GOARCH}" +case "$GOOSARCH" in +_* | *_ | _) + echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2 + exit 1 + ;; +esac + +GODEFS="go tool cgo -godefs" + +$GODEFS types.go |gofmt > ztypes_$GOARCH.go + +case $GOOS in +freebsd|dragonfly) + $GODEFS types_$GOOS.go |gofmt > ztypes_$GOOSARCH.go + ;; +esac diff --git a/vendor/github.com/kr/pty/pty_darwin.go b/vendor/github.com/kr/pty/pty_darwin.go new file mode 100644 index 0000000..4f4d5ca --- /dev/null +++ b/vendor/github.com/kr/pty/pty_darwin.go @@ -0,0 +1,60 @@ +package pty + +import ( + "errors" + "os" + "syscall" + "unsafe" +) + +func open() (pty, tty *os.File, err error) { + p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + err = grantpt(p) + if err != nil { + return nil, nil, err + } + + err = unlockpt(p) + if err != nil { + return nil, nil, err + } + + t, err := os.OpenFile(sname, os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func ptsname(f *os.File) (string, error) { + n := make([]byte, _IOC_PARM_LEN(syscall.TIOCPTYGNAME)) + + err := ioctl(f.Fd(), syscall.TIOCPTYGNAME, uintptr(unsafe.Pointer(&n[0]))) + if err != nil { + return "", err + } + + for i, c := range n { + if c == 0 { + return string(n[:i]), nil + } + } + return "", errors.New("TIOCPTYGNAME string not NUL-terminated") +} + +func grantpt(f *os.File) error { + return ioctl(f.Fd(), syscall.TIOCPTYGRANT, 0) +} + +func unlockpt(f *os.File) error { + return ioctl(f.Fd(), syscall.TIOCPTYUNLK, 0) +} diff --git a/vendor/github.com/kr/pty/pty_dragonfly.go b/vendor/github.com/kr/pty/pty_dragonfly.go new file mode 100644 index 0000000..5431fb5 --- /dev/null +++ b/vendor/github.com/kr/pty/pty_dragonfly.go @@ -0,0 +1,76 @@ +package pty + +import ( + "errors" + "os" + "strings" + "syscall" + "unsafe" +) + +// same code as pty_darwin.go +func open() (pty, tty *os.File, err error) { + p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + err = grantpt(p) + if err != nil { + return nil, nil, err + } + + err = unlockpt(p) + if err != nil { + return nil, nil, err + } + + t, err := os.OpenFile(sname, os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func grantpt(f *os.File) error { + _, err := isptmaster(f.Fd()) + return err +} + +func unlockpt(f *os.File) error { + _, err := isptmaster(f.Fd()) + return err +} + +func isptmaster(fd uintptr) (bool, error) { + err := ioctl(fd, syscall.TIOCISPTMASTER, 0) + return err == nil, err +} + +var ( + emptyFiodgnameArg fiodgnameArg + ioctl_FIODNAME = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg)) +) + +func ptsname(f *os.File) (string, error) { + name := make([]byte, _C_SPECNAMELEN) + fa := fiodgnameArg{Name: (*byte)(unsafe.Pointer(&name[0])), Len: _C_SPECNAMELEN, Pad_cgo_0: [4]byte{0, 0, 0, 0}} + + err := ioctl(f.Fd(), ioctl_FIODNAME, uintptr(unsafe.Pointer(&fa))) + if err != nil { + return "", err + } + + for i, c := range name { + if c == 0 { + s := "/dev/" + string(name[:i]) + return strings.Replace(s, "ptm", "pts", -1), nil + } + } + return "", errors.New("TIOCPTYGNAME string not NUL-terminated") +} diff --git a/vendor/github.com/kr/pty/pty_freebsd.go b/vendor/github.com/kr/pty/pty_freebsd.go new file mode 100644 index 0000000..b341bab --- /dev/null +++ b/vendor/github.com/kr/pty/pty_freebsd.go @@ -0,0 +1,73 @@ +package pty + +import ( + "errors" + "os" + "syscall" + "unsafe" +) + +func posix_openpt(oflag int) (fd int, err error) { + r0, _, e1 := syscall.Syscall(syscall.SYS_POSIX_OPENPT, uintptr(oflag), 0, 0) + fd = int(r0) + if e1 != 0 { + err = e1 + } + return +} + +func open() (pty, tty *os.File, err error) { + fd, err := posix_openpt(syscall.O_RDWR | syscall.O_CLOEXEC) + if err != nil { + return nil, nil, err + } + + p := os.NewFile(uintptr(fd), "/dev/pts") + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + t, err := os.OpenFile("/dev/"+sname, os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func isptmaster(fd uintptr) (bool, error) { + err := ioctl(fd, syscall.TIOCPTMASTER, 0) + return err == nil, err +} + +var ( + emptyFiodgnameArg fiodgnameArg + ioctl_FIODGNAME = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg)) +) + +func ptsname(f *os.File) (string, error) { + master, err := isptmaster(f.Fd()) + if err != nil { + return "", err + } + if !master { + return "", syscall.EINVAL + } + + const n = _C_SPECNAMELEN + 1 + var ( + buf = make([]byte, n) + arg = fiodgnameArg{Len: n, Buf: (*byte)(unsafe.Pointer(&buf[0]))} + ) + err = ioctl(f.Fd(), ioctl_FIODGNAME, uintptr(unsafe.Pointer(&arg))) + if err != nil { + return "", err + } + + for i, c := range buf { + if c == 0 { + return string(buf[:i]), nil + } + } + return "", errors.New("FIODGNAME string not NUL-terminated") +} diff --git a/vendor/github.com/kr/pty/pty_linux.go b/vendor/github.com/kr/pty/pty_linux.go new file mode 100644 index 0000000..cb901a2 --- /dev/null +++ b/vendor/github.com/kr/pty/pty_linux.go @@ -0,0 +1,46 @@ +package pty + +import ( + "os" + "strconv" + "syscall" + "unsafe" +) + +func open() (pty, tty *os.File, err error) { + p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + err = unlockpt(p) + if err != nil { + return nil, nil, err + } + + t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func ptsname(f *os.File) (string, error) { + var n _C_uint + err := ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))) + if err != nil { + return "", err + } + return "/dev/pts/" + strconv.Itoa(int(n)), nil +} + +func unlockpt(f *os.File) error { + var u _C_int + // use TIOCSPTLCK with a zero valued arg to clear the slave pty lock + return ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) +} diff --git a/vendor/github.com/kr/pty/pty_unsupported.go b/vendor/github.com/kr/pty/pty_unsupported.go new file mode 100644 index 0000000..bd3d1e7 --- /dev/null +++ b/vendor/github.com/kr/pty/pty_unsupported.go @@ -0,0 +1,11 @@ +// +build !linux,!darwin,!freebsd,!dragonfly + +package pty + +import ( + "os" +) + +func open() (pty, tty *os.File, err error) { + return nil, nil, ErrUnsupported +} diff --git a/vendor/github.com/kr/pty/run.go b/vendor/github.com/kr/pty/run.go new file mode 100644 index 0000000..baecca8 --- /dev/null +++ b/vendor/github.com/kr/pty/run.go @@ -0,0 +1,34 @@ +// +build !windows + +package pty + +import ( + "os" + "os/exec" + "syscall" +) + +// Start assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, +// and c.Stderr, calls c.Start, and returns the File of the tty's +// corresponding pty. +func Start(c *exec.Cmd) (pty *os.File, err error) { + pty, tty, err := Open() + if err != nil { + return nil, err + } + defer tty.Close() + c.Stdout = tty + c.Stdin = tty + c.Stderr = tty + if c.SysProcAttr == nil { + c.SysProcAttr = &syscall.SysProcAttr{} + } + c.SysProcAttr.Setctty = true + c.SysProcAttr.Setsid = true + err = c.Start() + if err != nil { + pty.Close() + return nil, err + } + return pty, err +} diff --git a/vendor/github.com/kr/pty/util.go b/vendor/github.com/kr/pty/util.go new file mode 100644 index 0000000..a4fab9a --- /dev/null +++ b/vendor/github.com/kr/pty/util.go @@ -0,0 +1,37 @@ +// +build !windows + +package pty + +import ( + "os" + "syscall" + "unsafe" +) + +// Getsize returns the number of rows (lines) and cols (positions +// in each line) in terminal t. +func Getsize(t *os.File) (rows, cols int, err error) { + var ws winsize + err = windowrect(&ws, t.Fd()) + return int(ws.ws_row), int(ws.ws_col), err +} + +type winsize struct { + ws_row uint16 + ws_col uint16 + ws_xpixel uint16 + ws_ypixel uint16 +} + +func windowrect(ws *winsize, fd uintptr) error { + _, _, errno := syscall.Syscall( + syscall.SYS_IOCTL, + fd, + syscall.TIOCGWINSZ, + uintptr(unsafe.Pointer(ws)), + ) + if errno != 0 { + return syscall.Errno(errno) + } + return nil +} diff --git a/vendor/github.com/kr/pty/ztypes_386.go b/vendor/github.com/kr/pty/ztypes_386.go new file mode 100644 index 0000000..ff0b8fd --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_386.go @@ -0,0 +1,9 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_amd64.go b/vendor/github.com/kr/pty/ztypes_amd64.go new file mode 100644 index 0000000..ff0b8fd --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_amd64.go @@ -0,0 +1,9 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_arm.go b/vendor/github.com/kr/pty/ztypes_arm.go new file mode 100644 index 0000000..ff0b8fd --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_arm.go @@ -0,0 +1,9 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_arm64.go b/vendor/github.com/kr/pty/ztypes_arm64.go new file mode 100644 index 0000000..6c29a4b --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_arm64.go @@ -0,0 +1,11 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +// +build arm64 + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_dragonfly_amd64.go b/vendor/github.com/kr/pty/ztypes_dragonfly_amd64.go new file mode 100644 index 0000000..6b0ba03 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_dragonfly_amd64.go @@ -0,0 +1,14 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_dragonfly.go + +package pty + +const ( + _C_SPECNAMELEN = 0x3f +) + +type fiodgnameArg struct { + Name *byte + Len uint32 + Pad_cgo_0 [4]byte +} diff --git a/vendor/github.com/kr/pty/ztypes_freebsd_386.go b/vendor/github.com/kr/pty/ztypes_freebsd_386.go new file mode 100644 index 0000000..d997537 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_freebsd_386.go @@ -0,0 +1,13 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_freebsd.go + +package pty + +const ( + _C_SPECNAMELEN = 0x3f +) + +type fiodgnameArg struct { + Len int32 + Buf *byte +} diff --git a/vendor/github.com/kr/pty/ztypes_freebsd_amd64.go b/vendor/github.com/kr/pty/ztypes_freebsd_amd64.go new file mode 100644 index 0000000..5fa102f --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_freebsd_amd64.go @@ -0,0 +1,14 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_freebsd.go + +package pty + +const ( + _C_SPECNAMELEN = 0x3f +) + +type fiodgnameArg struct { + Len int32 + Pad_cgo_0 [4]byte + Buf *byte +} diff --git a/vendor/github.com/kr/pty/ztypes_freebsd_arm.go b/vendor/github.com/kr/pty/ztypes_freebsd_arm.go new file mode 100644 index 0000000..d997537 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_freebsd_arm.go @@ -0,0 +1,13 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_freebsd.go + +package pty + +const ( + _C_SPECNAMELEN = 0x3f +) + +type fiodgnameArg struct { + Len int32 + Buf *byte +} diff --git a/vendor/github.com/kr/pty/ztypes_mipsx.go b/vendor/github.com/kr/pty/ztypes_mipsx.go new file mode 100644 index 0000000..f0ce740 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_mipsx.go @@ -0,0 +1,12 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +// +build linux +// +build mips mipsle mips64 mips64le + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_ppc64.go b/vendor/github.com/kr/pty/ztypes_ppc64.go new file mode 100644 index 0000000..4e1af84 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_ppc64.go @@ -0,0 +1,11 @@ +// +build ppc64 + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_ppc64le.go b/vendor/github.com/kr/pty/ztypes_ppc64le.go new file mode 100644 index 0000000..e6780f4 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_ppc64le.go @@ -0,0 +1,11 @@ +// +build ppc64le + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_s390x.go b/vendor/github.com/kr/pty/ztypes_s390x.go new file mode 100644 index 0000000..a7452b6 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_s390x.go @@ -0,0 +1,11 @@ +// +build s390x + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/pmezard/go-difflib/LICENSE b/vendor/github.com/pmezard/go-difflib/LICENSE new file mode 100644 index 0000000..c67dad6 --- /dev/null +++ b/vendor/github.com/pmezard/go-difflib/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013, Patrick Mezard +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. + The names of its contributors may not 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 +HOLDER 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/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go new file mode 100644 index 0000000..003e99f --- /dev/null +++ b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go @@ -0,0 +1,772 @@ +// Package difflib is a partial port of Python difflib module. +// +// It provides tools to compare sequences of strings and generate textual diffs. +// +// The following class and functions have been ported: +// +// - SequenceMatcher +// +// - unified_diff +// +// - context_diff +// +// Getting unified diffs was the main goal of the port. Keep in mind this code +// is mostly suitable to output text differences in a human friendly way, there +// are no guarantees generated diffs are consumable by patch(1). +package difflib + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strings" +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func calculateRatio(matches, length int) float64 { + if length > 0 { + return 2.0 * float64(matches) / float64(length) + } + return 1.0 +} + +type Match struct { + A int + B int + Size int +} + +type OpCode struct { + Tag byte + I1 int + I2 int + J1 int + J2 int +} + +// SequenceMatcher compares sequence of strings. The basic +// algorithm predates, and is a little fancier than, an algorithm +// published in the late 1980's by Ratcliff and Obershelp under the +// hyperbolic name "gestalt pattern matching". The basic idea is to find +// the longest contiguous matching subsequence that contains no "junk" +// elements (R-O doesn't address junk). The same idea is then applied +// recursively to the pieces of the sequences to the left and to the right +// of the matching subsequence. This does not yield minimal edit +// sequences, but does tend to yield matches that "look right" to people. +// +// SequenceMatcher tries to compute a "human-friendly diff" between two +// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the +// longest *contiguous* & junk-free matching subsequence. That's what +// catches peoples' eyes. The Windows(tm) windiff has another interesting +// notion, pairing up elements that appear uniquely in each sequence. +// That, and the method here, appear to yield more intuitive difference +// reports than does diff. This method appears to be the least vulnerable +// to synching up on blocks of "junk lines", though (like blank lines in +// ordinary text files, or maybe "

" lines in HTML files). That may be +// because this is the only method of the 3 that has a *concept* of +// "junk" . +// +// Timing: Basic R-O is cubic time worst case and quadratic time expected +// case. SequenceMatcher is quadratic time for the worst case and has +// expected-case behavior dependent in a complicated way on how many +// elements the sequences have in common; best case time is linear. +type SequenceMatcher struct { + a []string + b []string + b2j map[string][]int + IsJunk func(string) bool + autoJunk bool + bJunk map[string]struct{} + matchingBlocks []Match + fullBCount map[string]int + bPopular map[string]struct{} + opCodes []OpCode +} + +func NewMatcher(a, b []string) *SequenceMatcher { + m := SequenceMatcher{autoJunk: true} + m.SetSeqs(a, b) + return &m +} + +func NewMatcherWithJunk(a, b []string, autoJunk bool, + isJunk func(string) bool) *SequenceMatcher { + + m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} + m.SetSeqs(a, b) + return &m +} + +// Set two sequences to be compared. +func (m *SequenceMatcher) SetSeqs(a, b []string) { + m.SetSeq1(a) + m.SetSeq2(b) +} + +// Set the first sequence to be compared. The second sequence to be compared is +// not changed. +// +// SequenceMatcher computes and caches detailed information about the second +// sequence, so if you want to compare one sequence S against many sequences, +// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other +// sequences. +// +// See also SetSeqs() and SetSeq2(). +func (m *SequenceMatcher) SetSeq1(a []string) { + if &a == &m.a { + return + } + m.a = a + m.matchingBlocks = nil + m.opCodes = nil +} + +// Set the second sequence to be compared. The first sequence to be compared is +// not changed. +func (m *SequenceMatcher) SetSeq2(b []string) { + if &b == &m.b { + return + } + m.b = b + m.matchingBlocks = nil + m.opCodes = nil + m.fullBCount = nil + m.chainB() +} + +func (m *SequenceMatcher) chainB() { + // Populate line -> index mapping + b2j := map[string][]int{} + for i, s := range m.b { + indices := b2j[s] + indices = append(indices, i) + b2j[s] = indices + } + + // Purge junk elements + m.bJunk = map[string]struct{}{} + if m.IsJunk != nil { + junk := m.bJunk + for s, _ := range b2j { + if m.IsJunk(s) { + junk[s] = struct{}{} + } + } + for s, _ := range junk { + delete(b2j, s) + } + } + + // Purge remaining popular elements + popular := map[string]struct{}{} + n := len(m.b) + if m.autoJunk && n >= 200 { + ntest := n/100 + 1 + for s, indices := range b2j { + if len(indices) > ntest { + popular[s] = struct{}{} + } + } + for s, _ := range popular { + delete(b2j, s) + } + } + m.bPopular = popular + m.b2j = b2j +} + +func (m *SequenceMatcher) isBJunk(s string) bool { + _, ok := m.bJunk[s] + return ok +} + +// Find longest matching block in a[alo:ahi] and b[blo:bhi]. +// +// If IsJunk is not defined: +// +// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where +// alo <= i <= i+k <= ahi +// blo <= j <= j+k <= bhi +// and for all (i',j',k') meeting those conditions, +// k >= k' +// i <= i' +// and if i == i', j <= j' +// +// In other words, of all maximal matching blocks, return one that +// starts earliest in a, and of all those maximal matching blocks that +// start earliest in a, return the one that starts earliest in b. +// +// If IsJunk is defined, first the longest matching block is +// determined as above, but with the additional restriction that no +// junk element appears in the block. Then that block is extended as +// far as possible by matching (only) junk elements on both sides. So +// the resulting block never matches on junk except as identical junk +// happens to be adjacent to an "interesting" match. +// +// If no blocks match, return (alo, blo, 0). +func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { + // CAUTION: stripping common prefix or suffix would be incorrect. + // E.g., + // ab + // acab + // Longest matching block is "ab", but if common prefix is + // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so + // strip, so ends up claiming that ab is changed to acab by + // inserting "ca" in the middle. That's minimal but unintuitive: + // "it's obvious" that someone inserted "ac" at the front. + // Windiff ends up at the same place as diff, but by pairing up + // the unique 'b's and then matching the first two 'a's. + besti, bestj, bestsize := alo, blo, 0 + + // find longest junk-free match + // during an iteration of the loop, j2len[j] = length of longest + // junk-free match ending with a[i-1] and b[j] + j2len := map[int]int{} + for i := alo; i != ahi; i++ { + // look at all instances of a[i] in b; note that because + // b2j has no junk keys, the loop is skipped if a[i] is junk + newj2len := map[int]int{} + for _, j := range m.b2j[m.a[i]] { + // a[i] matches b[j] + if j < blo { + continue + } + if j >= bhi { + break + } + k := j2len[j-1] + 1 + newj2len[j] = k + if k > bestsize { + besti, bestj, bestsize = i-k+1, j-k+1, k + } + } + j2len = newj2len + } + + // Extend the best by non-junk elements on each end. In particular, + // "popular" non-junk elements aren't in b2j, which greatly speeds + // the inner loop above, but also means "the best" match so far + // doesn't contain any junk *or* popular non-junk elements. + for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + !m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + // Now that we have a wholly interesting match (albeit possibly + // empty!), we may as well suck up the matching junk on each + // side of it too. Can't think of a good reason not to, and it + // saves post-processing the (possibly considerable) expense of + // figuring out what to do with it. In the case of an empty + // interesting match, this is clearly the right thing to do, + // because no other kind of match is possible in the regions. + for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + return Match{A: besti, B: bestj, Size: bestsize} +} + +// Return list of triples describing matching subsequences. +// +// Each triple is of the form (i, j, n), and means that +// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in +// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are +// adjacent triples in the list, and the second is not the last triple in the +// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe +// adjacent equal blocks. +// +// The last triple is a dummy, (len(a), len(b), 0), and is the only +// triple with n==0. +func (m *SequenceMatcher) GetMatchingBlocks() []Match { + if m.matchingBlocks != nil { + return m.matchingBlocks + } + + var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match + matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { + match := m.findLongestMatch(alo, ahi, blo, bhi) + i, j, k := match.A, match.B, match.Size + if match.Size > 0 { + if alo < i && blo < j { + matched = matchBlocks(alo, i, blo, j, matched) + } + matched = append(matched, match) + if i+k < ahi && j+k < bhi { + matched = matchBlocks(i+k, ahi, j+k, bhi, matched) + } + } + return matched + } + matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) + + // It's possible that we have adjacent equal blocks in the + // matching_blocks list now. + nonAdjacent := []Match{} + i1, j1, k1 := 0, 0, 0 + for _, b := range matched { + // Is this block adjacent to i1, j1, k1? + i2, j2, k2 := b.A, b.B, b.Size + if i1+k1 == i2 && j1+k1 == j2 { + // Yes, so collapse them -- this just increases the length of + // the first block by the length of the second, and the first + // block so lengthened remains the block to compare against. + k1 += k2 + } else { + // Not adjacent. Remember the first block (k1==0 means it's + // the dummy we started with), and make the second block the + // new block to compare against. + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + i1, j1, k1 = i2, j2, k2 + } + } + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + + nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) + m.matchingBlocks = nonAdjacent + return m.matchingBlocks +} + +// Return list of 5-tuples describing how to turn a into b. +// +// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple +// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the +// tuple preceding it, and likewise for j1 == the previous j2. +// +// The tags are characters, with these meanings: +// +// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] +// +// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. +// +// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. +// +// 'e' (equal): a[i1:i2] == b[j1:j2] +func (m *SequenceMatcher) GetOpCodes() []OpCode { + if m.opCodes != nil { + return m.opCodes + } + i, j := 0, 0 + matching := m.GetMatchingBlocks() + opCodes := make([]OpCode, 0, len(matching)) + for _, m := range matching { + // invariant: we've pumped out correct diffs to change + // a[:i] into b[:j], and the next matching block is + // a[ai:ai+size] == b[bj:bj+size]. So we need to pump + // out a diff to change a[i:ai] into b[j:bj], pump out + // the matching block, and move (i,j) beyond the match + ai, bj, size := m.A, m.B, m.Size + tag := byte(0) + if i < ai && j < bj { + tag = 'r' + } else if i < ai { + tag = 'd' + } else if j < bj { + tag = 'i' + } + if tag > 0 { + opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) + } + i, j = ai+size, bj+size + // the list of matching blocks is terminated by a + // sentinel with size 0 + if size > 0 { + opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) + } + } + m.opCodes = opCodes + return m.opCodes +} + +// Isolate change clusters by eliminating ranges with no changes. +// +// Return a generator of groups with up to n lines of context. +// Each group is in the same format as returned by GetOpCodes(). +func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { + if n < 0 { + n = 3 + } + codes := m.GetOpCodes() + if len(codes) == 0 { + codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} + } + // Fixup leading and trailing groups if they show no changes. + if codes[0].Tag == 'e' { + c := codes[0] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} + } + if codes[len(codes)-1].Tag == 'e' { + c := codes[len(codes)-1] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} + } + nn := n + n + groups := [][]OpCode{} + group := []OpCode{} + for _, c := range codes { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + // End the current group and start a new one whenever + // there is a large range with no changes. + if c.Tag == 'e' && i2-i1 > nn { + group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), + j1, min(j2, j1+n)}) + groups = append(groups, group) + group = []OpCode{} + i1, j1 = max(i1, i2-n), max(j1, j2-n) + } + group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) + } + if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { + groups = append(groups, group) + } + return groups +} + +// Return a measure of the sequences' similarity (float in [0,1]). +// +// Where T is the total number of elements in both sequences, and +// M is the number of matches, this is 2.0*M / T. +// Note that this is 1 if the sequences are identical, and 0 if +// they have nothing in common. +// +// .Ratio() is expensive to compute if you haven't already computed +// .GetMatchingBlocks() or .GetOpCodes(), in which case you may +// want to try .QuickRatio() or .RealQuickRation() first to get an +// upper bound. +func (m *SequenceMatcher) Ratio() float64 { + matches := 0 + for _, m := range m.GetMatchingBlocks() { + matches += m.Size + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() relatively quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute. +func (m *SequenceMatcher) QuickRatio() float64 { + // viewing a and b as multisets, set matches to the cardinality + // of their intersection; this counts the number of matches + // without regard to order, so is clearly an upper bound + if m.fullBCount == nil { + m.fullBCount = map[string]int{} + for _, s := range m.b { + m.fullBCount[s] = m.fullBCount[s] + 1 + } + } + + // avail[x] is the number of times x appears in 'b' less the + // number of times we've seen it in 'a' so far ... kinda + avail := map[string]int{} + matches := 0 + for _, s := range m.a { + n, ok := avail[s] + if !ok { + n = m.fullBCount[s] + } + avail[s] = n - 1 + if n > 0 { + matches += 1 + } + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() very quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute than either .Ratio() or .QuickRatio(). +func (m *SequenceMatcher) RealQuickRatio() float64 { + la, lb := len(m.a), len(m.b) + return calculateRatio(min(la, lb), la+lb) +} + +// Convert range to the "ed" format +func formatRangeUnified(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 1 { + return fmt.Sprintf("%d", beginning) + } + if length == 0 { + beginning -= 1 // empty ranges begin at line just before the range + } + return fmt.Sprintf("%d,%d", beginning, length) +} + +// Unified diff parameters +type UnifiedDiff struct { + A []string // First sequence lines + FromFile string // First file name + FromDate string // First file time + B []string // Second sequence lines + ToFile string // Second file name + ToDate string // Second file time + Eol string // Headers end of line, defaults to LF + Context int // Number of context lines +} + +// Compare two sequences of lines; generate the delta as a unified diff. +// +// Unified diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by 'n' which +// defaults to three. +// +// By default, the diff control lines (those with ---, +++, or @@) are +// created with a trailing newline. This is helpful so that inputs +// created from file.readlines() result in diffs that are suitable for +// file.writelines() since both the inputs and outputs have trailing +// newlines. +// +// For inputs that do not have trailing newlines, set the lineterm +// argument to "" so that the output will be uniformly newline free. +// +// The unidiff format normally has a header for filenames and modification +// times. Any or all of these may be specified using strings for +// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. +// The modification times are normally expressed in the ISO 8601 format. +func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + wf := func(format string, args ...interface{}) error { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + return err + } + ws := func(s string) error { + _, err := buf.WriteString(s) + return err + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + if diff.FromFile != "" || diff.ToFile != "" { + err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) + if err != nil { + return err + } + err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) + if err != nil { + return err + } + } + } + first, last := g[0], g[len(g)-1] + range1 := formatRangeUnified(first.I1, last.I2) + range2 := formatRangeUnified(first.J1, last.J2) + if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { + return err + } + for _, c := range g { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + if c.Tag == 'e' { + for _, line := range diff.A[i1:i2] { + if err := ws(" " + line); err != nil { + return err + } + } + continue + } + if c.Tag == 'r' || c.Tag == 'd' { + for _, line := range diff.A[i1:i2] { + if err := ws("-" + line); err != nil { + return err + } + } + } + if c.Tag == 'r' || c.Tag == 'i' { + for _, line := range diff.B[j1:j2] { + if err := ws("+" + line); err != nil { + return err + } + } + } + } + } + return nil +} + +// Like WriteUnifiedDiff but returns the diff a string. +func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteUnifiedDiff(w, diff) + return string(w.Bytes()), err +} + +// Convert range to the "ed" format. +func formatRangeContext(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 0 { + beginning -= 1 // empty ranges begin at line just before the range + } + if length <= 1 { + return fmt.Sprintf("%d", beginning) + } + return fmt.Sprintf("%d,%d", beginning, beginning+length-1) +} + +type ContextDiff UnifiedDiff + +// Compare two sequences of lines; generate the delta as a context diff. +// +// Context diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by diff.Context +// which defaults to three. +// +// By default, the diff control lines (those with *** or ---) are +// created with a trailing newline. +// +// For inputs that do not have trailing newlines, set the diff.Eol +// argument to "" so that the output will be uniformly newline free. +// +// The context diff format normally has a header for filenames and +// modification times. Any or all of these may be specified using +// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate. +// The modification times are normally expressed in the ISO 8601 format. +// If not specified, the strings default to blanks. +func WriteContextDiff(writer io.Writer, diff ContextDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + var diffErr error + wf := func(format string, args ...interface{}) { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + if diffErr == nil && err != nil { + diffErr = err + } + } + ws := func(s string) { + _, err := buf.WriteString(s) + if diffErr == nil && err != nil { + diffErr = err + } + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + prefix := map[byte]string{ + 'i': "+ ", + 'd': "- ", + 'r': "! ", + 'e': " ", + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + if diff.FromFile != "" || diff.ToFile != "" { + wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) + wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol) + } + } + + first, last := g[0], g[len(g)-1] + ws("***************" + diff.Eol) + + range1 := formatRangeContext(first.I1, last.I2) + wf("*** %s ****%s", range1, diff.Eol) + for _, c := range g { + if c.Tag == 'r' || c.Tag == 'd' { + for _, cc := range g { + if cc.Tag == 'i' { + continue + } + for _, line := range diff.A[cc.I1:cc.I2] { + ws(prefix[cc.Tag] + line) + } + } + break + } + } + + range2 := formatRangeContext(first.J1, last.J2) + wf("--- %s ----%s", range2, diff.Eol) + for _, c := range g { + if c.Tag == 'r' || c.Tag == 'i' { + for _, cc := range g { + if cc.Tag == 'd' { + continue + } + for _, line := range diff.B[cc.J1:cc.J2] { + ws(prefix[cc.Tag] + line) + } + } + break + } + } + } + return diffErr +} + +// Like WriteContextDiff but returns the diff a string. +func GetContextDiffString(diff ContextDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteContextDiff(w, diff) + return string(w.Bytes()), err +} + +// Split a string on "\n" while preserving them. The output can be used +// as input for UnifiedDiff and ContextDiff structures. +func SplitLines(s string) []string { + lines := strings.SplitAfter(s, "\n") + lines[len(lines)-1] += "\n" + return lines +} diff --git a/vendor/github.com/visualfc/gotools/LICENSE b/vendor/github.com/visualfc/gotools/LICENSE index 624d856..ca2493d 100644 --- a/vendor/github.com/visualfc/gotools/LICENSE +++ b/vendor/github.com/visualfc/gotools/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015, visualfc +Copyright (c) 2011-2017, visualfc All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/vendor/github.com/visualfc/gotools/README.md b/vendor/github.com/visualfc/gotools/README.md index a8ab9f3..7ad5359 100644 --- a/vendor/github.com/visualfc/gotools/README.md +++ b/vendor/github.com/visualfc/gotools/README.md @@ -1,2 +1,28 @@ -# gotools -liteide golang tools +LiteIDE Golang Tools +========= + +### LiteIDE + +_LiteIDE is a simple, open source, cross-platform Go IDE._ + +### GoTools +_GoTools is a golang tools support for LiteIDE._ + +### Website +* LiteIDE Source code + +* Gotools Source code + +* Binary downloads + +* Google group + +* How to Install + +* FAQ + +* Changes + + +### Donate +* diff --git a/vendor/github.com/visualfc/gotools/command/command.go b/vendor/github.com/visualfc/gotools/command/command.go index a20a3fb..2f6676b 100644 --- a/vendor/github.com/visualfc/gotools/command/command.go +++ b/vendor/github.com/visualfc/gotools/command/command.go @@ -191,7 +191,10 @@ func Main() { cmd.Stdin = Stdin cmd.Stdout = Stdout cmd.Stderr = Stderr - cmd.Run(cmd, args) + err := cmd.Run(cmd, args) + if err != nil { + SetExitStatus(2) + } Exit() return } diff --git a/vendor/github.com/visualfc/gotools/doc.go b/vendor/github.com/visualfc/gotools/doc.go index 2a2e1c4..e992f7d 100644 --- a/vendor/github.com/visualfc/gotools/doc.go +++ b/vendor/github.com/visualfc/gotools/doc.go @@ -1,4 +1,4 @@ -// Copyright 2011-2015 visualfc . All rights reserved. +// Copyright 2011-2017 visualfc . All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/vendor/github.com/visualfc/gotools/finddecl/finddecl.go b/vendor/github.com/visualfc/gotools/finddecl/finddecl.go new file mode 100644 index 0000000..b9f3f9c --- /dev/null +++ b/vendor/github.com/visualfc/gotools/finddecl/finddecl.go @@ -0,0 +1,135 @@ +// Copyright 2011-2015 visualfc . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package finddecl + +import ( + "errors" + "fmt" + "go/ast" + "go/parser" + "go/token" + "os" + "path/filepath" + "strconv" + + "github.com/visualfc/gotools/command" +) + +var Command = &command.Command{ + Run: runFindDecl, + UsageLine: "finddecl", + Short: "golang finddecl util", + Long: `golang finddecl util.`, +} +var ( + filePath string + fileLine int +) + +func init() { + Command.Flag.StringVar(&filePath, "file", "", "file path") + Command.Flag.IntVar(&fileLine, "line", -1, "file line") +} + +func runFindDecl(cmd *command.Command, args []string) error { + if len(filePath) == 0 || fileLine == -1 { + cmd.Usage() + return os.ErrInvalid + } + if !filepath.IsAbs(filePath) { + dir, err := os.Getwd() + if err != nil { + return err + } + filePath = filepath.Join(dir, filePath) + } + + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, filePath, nil, 0) + if err != nil { + return err + } + decl := findDecl(fset, f, fileLine) + if decl == nil { + fmt.Println("-") + return errors.New("error find decl") + } + printDecl(fset, decl, fileLine) + return nil +} + +type Info struct { + Type string + Name string + BeginLine int + EndLine int +} + +func printDecl(fset *token.FileSet, decl ast.Decl, line int) { + var tag string + var name string + + tag = "-" + name = "-" + switch d := decl.(type) { + case *ast.GenDecl: + switch d.Tok { + case token.IMPORT: + tag = "import" + if len(d.Specs) > 0 { + if ts := d.Specs[0].(*ast.ImportSpec); ts != nil { + name, _ = strconv.Unquote(ts.Path.Value) + } + } + case token.TYPE: + tag = "type" + if len(d.Specs) > 0 { + if ts := d.Specs[0].(*ast.TypeSpec); ts != nil { + name = ts.Name.Name + switch ts.Type.(type) { + case *ast.StructType: + tag = "struct" + case *ast.InterfaceType: + tag = "interface" + default: + tag = "type" + } + } + } + case token.VAR, token.CONST: + tag = d.Tok.String() + var testName string + for _, ds := range d.Specs { + if ts := ds.(*ast.ValueSpec); ts != nil { + name = ts.Names[0].Name + for _, n := range ts.Names { + if line >= fset.Position(n.Pos()).Line && line <= fset.Position(n.End()).Line { + testName = n.Name + break + } + } + } + } + if testName != "" { + name = testName + } + default: + tag = d.Tok.String() + } + case *ast.FuncDecl: + tag = "func" + name = d.Name.Name + } + fmt.Println(tag, name, fset.Position(decl.Pos()).Line, fset.Position(decl.End()).Line) +} + +func findDecl(fset *token.FileSet, file *ast.File, line int) ast.Decl { + for _, decl := range file.Decls { + if line >= fset.Position(decl.Pos()).Line && line <= fset.Position(decl.End()).Line { + return decl + } + } + return nil +} diff --git a/vendor/github.com/visualfc/gotools/godiff/godiff.go b/vendor/github.com/visualfc/gotools/godiff/godiff.go new file mode 100644 index 0000000..f4169aa --- /dev/null +++ b/vendor/github.com/visualfc/gotools/godiff/godiff.go @@ -0,0 +1,64 @@ +// Copyright 2011-2015 visualfc . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package godiff + +import ( + "io/ioutil" + "os" + "os/exec" + + "github.com/pmezard/go-difflib/difflib" +) + +func UnifiedDiffLines(a []string, b []string) (string, error) { + diff := difflib.UnifiedDiff{ + A: a, + B: b, + FromFile: "Original", + ToFile: "Current", + Context: 3, + Eol: "\n", + } + return difflib.GetUnifiedDiffString(diff) +} + +func UnifiedDiffString(a string, b string) (string, error) { + diff := difflib.UnifiedDiff{ + A: difflib.SplitLines(a), + B: difflib.SplitLines(b), + FromFile: "Original", + ToFile: "Current", + Context: 3, + Eol: "\n", + } + return difflib.GetUnifiedDiffString(diff) +} + +func UnifiedDiffBytesByCmd(b1, b2 []byte) (data []byte, err error) { + f1, err := ioutil.TempFile("", "godiff") + if err != nil { + return + } + defer os.Remove(f1.Name()) + defer f1.Close() + + f2, err := ioutil.TempFile("", "godiff") + if err != nil { + return + } + defer os.Remove(f2.Name()) + defer f2.Close() + + f1.Write(b1) + f2.Write(b2) + + data, err = exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput() + if len(data) > 0 { + // diff exits with a non-zero status when the files don't match. + // Ignore that failure as long as we get output. + err = nil + } + return +} diff --git a/vendor/github.com/visualfc/gotools/gofmt/gofmt.go b/vendor/github.com/visualfc/gotools/gofmt/gofmt.go new file mode 100644 index 0000000..af10755 --- /dev/null +++ b/vendor/github.com/visualfc/gotools/gofmt/gofmt.go @@ -0,0 +1,198 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gofmt + +import ( + "bytes" + "fmt" + "go/scanner" + "go/token" + "io" + "io/ioutil" + "os" + "path/filepath" + "runtime" + "strings" + "sync" + + "github.com/visualfc/gotools/command" + "github.com/visualfc/gotools/godiff" + "golang.org/x/tools/imports" +) + +var Command = &command.Command{ + Run: runGofmt, + UsageLine: "gofmt [flags] [path ...]", + Short: "gofmt formats Go source.", + Long: `gofmt formats Go source`, +} + +var ( + gofmtList bool + gofmtWrite bool + gofmtDiff bool + gofmtAllErrors bool + gofmtFixImports bool + gofmtSortImports bool + gofmtUseGodiffLib bool + + // layout control + gofmtComments bool + gofmtTabWidth int + gofmtTabIndent bool +) + +//func init +func init() { + Command.Flag.BoolVar(&gofmtList, "l", false, "list files whose formatting differs from goimport's") + Command.Flag.BoolVar(&gofmtWrite, "w", false, "write result to (source) file instead of stdout") + Command.Flag.BoolVar(&gofmtDiff, "d", false, "display diffs instead of rewriting files") + Command.Flag.BoolVar(&gofmtAllErrors, "e", false, "report all errors (not just the first 10 on different lines)") + Command.Flag.BoolVar(&gofmtFixImports, "fiximports", false, "updates Go import lines, adding missing ones and removing unreferenced ones") + Command.Flag.BoolVar(&gofmtSortImports, "sortimports", false, "sort Go import lines use goimports style") + Command.Flag.BoolVar(&gofmtUseGodiffLib, "godiff", true, "diff use godiff library") + + // layout control + Command.Flag.BoolVar(&gofmtComments, "comments", true, "print comments") + Command.Flag.IntVar(&gofmtTabWidth, "tabwidth", 8, "tab width") + Command.Flag.BoolVar(&gofmtTabIndent, "tabs", true, "indent with tabs") +} + +var ( + fileSet = token.NewFileSet() // per process FileSet + exitCode = 0 + + initModesOnce sync.Once // guards calling initModes + //parserMode parser.Mode + //printerMode printer.Mode + options *imports.Options +) + +func report(err error) { + scanner.PrintError(os.Stderr, err) + exitCode = 2 +} + +func runGofmt(cmd *command.Command, args []string) error { + runtime.GOMAXPROCS(runtime.NumCPU()) + + if gofmtTabWidth < 0 { + fmt.Fprintf(os.Stderr, "negative tabwidth %d\n", gofmtTabWidth) + exitCode = 2 + os.Exit(exitCode) + return os.ErrInvalid + } + + if gofmtFixImports { + gofmtSortImports = true + } + + options = &imports.Options{ + FormatOnly: !gofmtFixImports, + TabWidth: gofmtTabWidth, + TabIndent: gofmtTabIndent, + Comments: gofmtComments, + AllErrors: gofmtAllErrors, + Fragment: true, + } + + if len(args) == 0 { + if err := processFile("", os.Stdin, os.Stdout, true); err != nil { + report(err) + } + } else { + for _, path := range args { + switch dir, err := os.Stat(path); { + case err != nil: + report(err) + case dir.IsDir(): + walkDir(path) + default: + if err := processFile(path, nil, os.Stdout, false); err != nil { + report(err) + } + } + } + } + os.Exit(exitCode) + return nil +} + +func isGoFile(f os.FileInfo) bool { + // ignore non-Go files + name := f.Name() + return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") +} + +func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error { + if in == nil { + f, err := os.Open(filename) + if err != nil { + return err + } + defer f.Close() + in = f + } + + src, err := ioutil.ReadAll(in) + if err != nil { + return err + } + + res, err := imports.Process(filename, src, options) + if err != nil { + return err + } + + if !bytes.Equal(src, res) { + // formatting has changed + if gofmtList { + fmt.Fprintln(out, filename) + } + if gofmtWrite { + err = ioutil.WriteFile(filename, res, 0) + if err != nil { + return err + } + } + if gofmtDiff { + if gofmtUseGodiffLib { + data, err := godiff.UnifiedDiffString(string(src), string(res)) + if err != nil { + return fmt.Errorf("computing diff: %s", err) + } + fmt.Printf("diff %s gofmt/%s\n", filename, filename) + out.Write([]byte(data)) + } else { + data, err := godiff.UnifiedDiffBytesByCmd(src, res) + if err != nil { + return fmt.Errorf("computing diff: %s", err) + } + fmt.Printf("diff %s gofmt/%s\n", filename, filename) + out.Write(data) + } + } + } + + if !gofmtList && !gofmtWrite && !gofmtDiff { + _, err = out.Write(res) + } + + return err +} + +func visitFile(path string, f os.FileInfo, err error) error { + if err == nil && isGoFile(f) { + err = processFile(path, nil, os.Stdout, false) + } + if err != nil { + report(err) + } + return nil +} + +func walkDir(path string) { + filepath.Walk(path, visitFile) +} diff --git a/vendor/github.com/visualfc/gotools/gotest/gotest.go b/vendor/github.com/visualfc/gotools/gotest/gotest.go new file mode 100644 index 0000000..5098686 --- /dev/null +++ b/vendor/github.com/visualfc/gotools/gotest/gotest.go @@ -0,0 +1,99 @@ +// Copyright 2011-2015 visualfc . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gotest + +import ( + "fmt" + "go/build" + "os" + "os/exec" + "strings" + + "github.com/visualfc/gotools/command" +) + +var Command = &command.Command{ + Run: runGotest, + UsageLine: "gotest -f filename [build/test flags]", + Short: "go test go filename", + Long: `go test go filename`, + CustomFlags: true, +} + +var testFileName string +var testFileArgs string + +//func init() { +// Command.Flag.StringVar(&testFileName, "f", "", "test go filename") +//} + +func runGotest(cmd *command.Command, args []string) error { + index := -1 + for n, arg := range args { + if arg == "-f" { + index = n + break + } + } + if index >= 0 && index < len(args) { + testFileName = args[index+1] + var r []string + r = append(r, args[0:index]...) + r = append(r, args[index+2:]...) + args = r + } + + if testFileName == "" { + cmd.Usage() + return os.ErrInvalid + } + if !strings.HasSuffix(testFileName, "_test.go") { + fmt.Println("The test filename must xxx_test.go") + return os.ErrInvalid + } + + pkg, err := build.ImportDir(".", 0) + if err != nil { + fmt.Println("import dir error", err) + return err + } + + var testFiles []string + + for _, file := range pkg.XTestGoFiles { + if file == testFileName { + testFiles = append(testFiles, file) + break + } + } + for _, file := range pkg.TestGoFiles { + if file == testFileName { + testFiles = append(testFiles, pkg.GoFiles...) + testFiles = append(testFiles, file) + break + } + } + + gobin, err := exec.LookPath("go") + if err != nil { + fmt.Println("error look go", err) + return err + } + + var testArgs []string + testArgs = append(testArgs, "test") + if len(args) > 0 { + testArgs = append(testArgs, args...) + } + testArgs = append(testArgs, testFiles...) + + command := exec.Command(gobin, testArgs...) + command.Dir = pkg.Dir + command.Stdin = os.Stdin + command.Stdout = os.Stdout + command.Stderr = os.Stderr + + return command.Run() +} diff --git a/vendor/github.com/visualfc/gotools/main.go b/vendor/github.com/visualfc/gotools/main.go index bc14399..eb0d28c 100644 --- a/vendor/github.com/visualfc/gotools/main.go +++ b/vendor/github.com/visualfc/gotools/main.go @@ -1,4 +1,4 @@ -// Copyright 2011-2015 visualfc . All rights reserved. +// Copyright 2011-2017 visualfc . All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -8,14 +8,17 @@ import ( "github.com/visualfc/gotools/astview" "github.com/visualfc/gotools/command" "github.com/visualfc/gotools/docview" + "github.com/visualfc/gotools/finddecl" "github.com/visualfc/gotools/finddoc" "github.com/visualfc/gotools/goapi" - "github.com/visualfc/gotools/goimports" + "github.com/visualfc/gotools/gofmt" "github.com/visualfc/gotools/gopresent" + "github.com/visualfc/gotools/gotest" "github.com/visualfc/gotools/jsonfmt" "github.com/visualfc/gotools/oracle" "github.com/visualfc/gotools/pkgs" "github.com/visualfc/gotools/runcmd" + "github.com/visualfc/gotools/terminal" "github.com/visualfc/gotools/types" ) @@ -26,16 +29,19 @@ func init() { command.Register(runcmd.Command) command.Register(docview.Command) command.Register(astview.Command) - command.Register(goimports.Command) command.Register(gopresent.Command) command.Register(goapi.Command) command.Register(pkgs.Command) command.Register(oracle.Command) + command.Register(gofmt.Command) + command.Register(gotest.Command) + command.Register(finddecl.Command) + command.Register(terminal.Command) } func main() { command.AppName = "gotools" - command.AppVersion = "1.0" + command.AppVersion = "1.9" command.AppInfo = "Go tools for liteide." command.Main() } diff --git a/vendor/github.com/visualfc/gotools/terminal/command.go b/vendor/github.com/visualfc/gotools/terminal/command.go new file mode 100644 index 0000000..32e8253 --- /dev/null +++ b/vendor/github.com/visualfc/gotools/terminal/command.go @@ -0,0 +1,33 @@ +// +build !windows + +package terminal + +import ( + "io" + "os" + "os/exec" + + "github.com/kr/pty" +) + +func GetShell() (cmd string, args []string) { + return "/bin/sh", []string{"-l", "-i"} +} + +func Execute(c *exec.Cmd) error { + f, err := pty.Start(c) + if err != nil { + return nil + } + go func() { + for { + io.Copy(f, os.Stdin) + } + }() + go func() { + for { + io.Copy(os.Stdout, f) + } + }() + return c.Wait() +} diff --git a/vendor/github.com/visualfc/gotools/terminal/command_windows.go b/vendor/github.com/visualfc/gotools/terminal/command_windows.go new file mode 100644 index 0000000..18bc5f6 --- /dev/null +++ b/vendor/github.com/visualfc/gotools/terminal/command_windows.go @@ -0,0 +1,34 @@ +// +build windows + +package terminal + +import ( + "os" + "os/exec" +) + +func checkFiles(names ...string) string { + for _, name := range names { + _, err := os.Stat(name) + if err == nil { + return name + } + } + return "" +} + +func GetShell() (cmd string, args []string) { + windir := os.Getenv("windir") + if windir == "" { + windir = "c:\\windows" + } + cmd = checkFiles(windir+"\\Sysnative\\cmd.exe", windir+"\\System32\\cmd.exe") + return +} + +func Execute(c *exec.Cmd) error { + c.Stdin = os.Stdin + c.Stdout = os.Stdout + c.Stderr = os.Stderr + return c.Run() +} diff --git a/vendor/github.com/visualfc/gotools/terminal/terminal.go b/vendor/github.com/visualfc/gotools/terminal/terminal.go new file mode 100644 index 0000000..8138a49 --- /dev/null +++ b/vendor/github.com/visualfc/gotools/terminal/terminal.go @@ -0,0 +1,39 @@ +// Copyright 2011-2017 visualfc . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package terminal + +import ( + "os" + "os/exec" + + "github.com/visualfc/gotools/command" +) + +var Command = &command.Command{ + Run: runTerminal, + UsageLine: "terminal [program_name arguments...]", + Short: "terminal [program]", + Long: `terminal program and arguments`, + CustomFlags: true, +} + +func runTerminal(cmd *command.Command, args []string) (err error) { + var c *exec.Cmd + if len(args) >= 1 { + var carg []string + if len(args) >= 2 { + carg = append(carg, args[1:]...) + } + c = exec.Command(args[0], carg...) + } else { + shellCmd, shellArgs := GetShell() + c = exec.Command(shellCmd, shellArgs...) + } + if c == nil { + return os.ErrInvalid + } + err = Execute(c) + + return +} diff --git a/vendor/golang.org/x/tools/imports/mkindex.go b/vendor/golang.org/x/tools/imports/mkindex.go deleted file mode 100644 index 755e239..0000000 --- a/vendor/golang.org/x/tools/imports/mkindex.go +++ /dev/null @@ -1,173 +0,0 @@ -// +build ignore - -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Command mkindex creates the file "pkgindex.go" containing an index of the Go -// standard library. The file is intended to be built as part of the imports -// package, so that the package may be used in environments where a GOROOT is -// not available (such as App Engine). -package main - -import ( - "bytes" - "fmt" - "go/ast" - "go/build" - "go/format" - "go/parser" - "go/token" - "io/ioutil" - "log" - "os" - "path" - "path/filepath" - "strings" -) - -var ( - pkgIndex = make(map[string][]pkg) - exports = make(map[string]map[string]bool) -) - -func main() { - // Don't use GOPATH. - ctx := build.Default - ctx.GOPATH = "" - - // Populate pkgIndex global from GOROOT. - for _, path := range ctx.SrcDirs() { - f, err := os.Open(path) - if err != nil { - log.Print(err) - continue - } - children, err := f.Readdir(-1) - f.Close() - if err != nil { - log.Print(err) - continue - } - for _, child := range children { - if child.IsDir() { - loadPkg(path, child.Name()) - } - } - } - // Populate exports global. - for _, ps := range pkgIndex { - for _, p := range ps { - e := loadExports(p.dir) - if e != nil { - exports[p.dir] = e - } - } - } - - // Construct source file. - var buf bytes.Buffer - fmt.Fprint(&buf, pkgIndexHead) - fmt.Fprintf(&buf, "var pkgIndexMaster = %#v\n", pkgIndex) - fmt.Fprintf(&buf, "var exportsMaster = %#v\n", exports) - src := buf.Bytes() - - // Replace main.pkg type name with pkg. - src = bytes.Replace(src, []byte("main.pkg"), []byte("pkg"), -1) - // Replace actual GOROOT with "/go". - src = bytes.Replace(src, []byte(ctx.GOROOT), []byte("/go"), -1) - // Add some line wrapping. - src = bytes.Replace(src, []byte("}, "), []byte("},\n"), -1) - src = bytes.Replace(src, []byte("true, "), []byte("true,\n"), -1) - - var err error - src, err = format.Source(src) - if err != nil { - log.Fatal(err) - } - - // Write out source file. - err = ioutil.WriteFile("pkgindex.go", src, 0644) - if err != nil { - log.Fatal(err) - } -} - -const pkgIndexHead = `package imports - -func init() { - pkgIndexOnce.Do(func() { - pkgIndex.m = pkgIndexMaster - }) - loadExports = func(dir string) map[string]bool { - return exportsMaster[dir] - } -} -` - -type pkg struct { - importpath string // full pkg import path, e.g. "net/http" - dir string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt" -} - -var fset = token.NewFileSet() - -func loadPkg(root, importpath string) { - shortName := path.Base(importpath) - if shortName == "testdata" { - return - } - - dir := filepath.Join(root, importpath) - pkgIndex[shortName] = append(pkgIndex[shortName], pkg{ - importpath: importpath, - dir: dir, - }) - - pkgDir, err := os.Open(dir) - if err != nil { - return - } - children, err := pkgDir.Readdir(-1) - pkgDir.Close() - if err != nil { - return - } - for _, child := range children { - name := child.Name() - if name == "" { - continue - } - if c := name[0]; c == '.' || ('0' <= c && c <= '9') { - continue - } - if child.IsDir() { - loadPkg(root, filepath.Join(importpath, name)) - } - } -} - -func loadExports(dir string) map[string]bool { - exports := make(map[string]bool) - buildPkg, err := build.ImportDir(dir, 0) - if err != nil { - if strings.Contains(err.Error(), "no buildable Go source files in") { - return nil - } - log.Printf("could not import %q: %v", dir, err) - return nil - } - for _, file := range buildPkg.GoFiles { - f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0) - if err != nil { - log.Printf("could not parse %q: %v", file, err) - continue - } - for name := range f.Scope.Objects { - if ast.IsExported(name) { - exports[name] = true - } - } - } - return exports -} diff --git a/vendor/golang.org/x/tools/imports/mkstdlib.go b/vendor/golang.org/x/tools/imports/mkstdlib.go deleted file mode 100644 index c43d325..0000000 --- a/vendor/golang.org/x/tools/imports/mkstdlib.go +++ /dev/null @@ -1,90 +0,0 @@ -// +build ignore - -// mkstdlib generates the zstdlib.go file, containing the Go standard -// library API symbols. It's baked into the binary to avoid scanning -// GOPATH in the common case. -package main - -import ( - "bufio" - "bytes" - "fmt" - "go/format" - "io" - "log" - "os" - "path" - "path/filepath" - "regexp" - "sort" - "strings" -) - -func mustOpen(name string) io.Reader { - f, err := os.Open(name) - if err != nil { - log.Fatal(err) - } - return f -} - -func api(base string) string { - return filepath.Join(os.Getenv("GOROOT"), "api", base) -} - -var sym = regexp.MustCompile(`^pkg (\S+).*?, (?:var|func|type|const) ([A-Z]\w*)`) - -func main() { - var buf bytes.Buffer - outf := func(format string, args ...interface{}) { - fmt.Fprintf(&buf, format, args...) - } - outf("// AUTO-GENERATED BY mkstdlib.go\n\n") - outf("package imports\n") - outf("var stdlib = map[string]string{\n") - f := io.MultiReader( - mustOpen(api("go1.txt")), - mustOpen(api("go1.1.txt")), - mustOpen(api("go1.2.txt")), - ) - sc := bufio.NewScanner(f) - fullImport := map[string]string{} // "zip.NewReader" => "archive/zip" - ambiguous := map[string]bool{} - var keys []string - for sc.Scan() { - l := sc.Text() - has := func(v string) bool { return strings.Contains(l, v) } - if has("struct, ") || has("interface, ") || has(", method (") { - continue - } - if m := sym.FindStringSubmatch(l); m != nil { - full := m[1] - key := path.Base(full) + "." + m[2] - if exist, ok := fullImport[key]; ok { - if exist != full { - ambiguous[key] = true - } - } else { - fullImport[key] = full - keys = append(keys, key) - } - } - } - if err := sc.Err(); err != nil { - log.Fatal(err) - } - sort.Strings(keys) - for _, key := range keys { - if ambiguous[key] { - outf("\t// %q is ambiguous\n", key) - } else { - outf("\t%q: %q,\n", key, fullImport[key]) - } - } - outf("}\n") - fmtbuf, err := format.Source(buf.Bytes()) - if err != nil { - log.Fatal(err) - } - os.Stdout.Write(fmtbuf) -} diff --git a/vendor/vendor.json b/vendor/vendor.json index 07d1218..0be34c5 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -5,8 +5,8 @@ { "checksumSHA1": "ZesPb1w0u5/uv/fdVc+G6wOee30=", "path": "github.com/b3log/wide", - "revision": "bfd836c6fc8fbc007ce437db1406455493cd532f", - "revisionTime": "2018-03-13T04:57:02Z" + "revision": "0a51a03f35a3fa9edbfa790698aa615f4dd49783", + "revisionTime": "2018-03-13T05:05:45Z" }, { "checksumSHA1": "83iEp3SqOoIkZUYyR7BOVP4vaGE=", @@ -44,6 +44,13 @@ "revision": "a3ec486e6a7a41858210b0fc5d7b5df593b3c4a3", "revisionTime": "2015-05-30T03:03:52Z" }, + { + "checksumSHA1": "8jdAN2n9kJasxFmikoyDZAbv8ig=", + "origin": "github.com/visualfc/gotools/vendor/github.com/kr/pty", + "path": "github.com/kr/pty", + "revision": "a74583d2ad8773983f273657291df981033308a4", + "revisionTime": "2018-02-17T01:27:43Z" + }, { "checksumSHA1": "gKm38IQHqLfYHwS7B6JDTJzXYYI=", "path": "github.com/nsf/gocode", @@ -51,10 +58,17 @@ "revisionTime": "2018-01-07T08:36:41Z" }, { - "checksumSHA1": "4fp/TH5nX7seO5p4qJfIj/BokbI=", + "checksumSHA1": "R3yk3OJzuq4MVfVGX5AhkkYv1ko=", + "origin": "github.com/visualfc/gotools/vendor/github.com/pmezard/go-difflib/difflib", + "path": "github.com/pmezard/go-difflib/difflib", + "revision": "a74583d2ad8773983f273657291df981033308a4", + "revisionTime": "2018-02-17T01:27:43Z" + }, + { + "checksumSHA1": "+1Mo4q3vpSB8ibclS1t/AWeDQ50=", "path": "github.com/visualfc/gotools", - "revision": "b8348693492ca3791bccfa028f3c19634c11c5b5", - "revisionTime": "2015-04-09T14:25:36Z" + "revision": "a74583d2ad8773983f273657291df981033308a4", + "revisionTime": "2018-02-17T01:27:43Z" }, { "checksumSHA1": "QBwzyczN2ftqO2Vxag5TS79q32E=", @@ -63,10 +77,10 @@ "revisionTime": "2015-04-09T14:25:36Z" }, { - "checksumSHA1": "wqPqP7RGlukrSMzGKVk1tvyWh1o=", + "checksumSHA1": "02f7N5GTTddWpIDhsRthRKZs4nI=", "path": "github.com/visualfc/gotools/command", - "revision": "b8348693492ca3791bccfa028f3c19634c11c5b5", - "revisionTime": "2015-04-09T14:25:36Z" + "revision": "a74583d2ad8773983f273657291df981033308a4", + "revisionTime": "2018-02-17T01:27:43Z" }, { "checksumSHA1": "sA2FN414rFhNEgac/a0IyUR8dMA=", @@ -74,6 +88,12 @@ "revision": "b8348693492ca3791bccfa028f3c19634c11c5b5", "revisionTime": "2015-04-09T14:25:36Z" }, + { + "checksumSHA1": "5sCU5oJIkeXHHhzNyzusSH+de/8=", + "path": "github.com/visualfc/gotools/finddecl", + "revision": "a74583d2ad8773983f273657291df981033308a4", + "revisionTime": "2018-02-17T01:27:43Z" + }, { "checksumSHA1": "LvxdwB9kJ77cFS4qiRAh9ts2nz4=", "path": "github.com/visualfc/gotools/finddoc", @@ -86,6 +106,18 @@ "revision": "b8348693492ca3791bccfa028f3c19634c11c5b5", "revisionTime": "2015-04-09T14:25:36Z" }, + { + "checksumSHA1": "o0usAkdrTaqufvGTZu++Cc/DVMM=", + "path": "github.com/visualfc/gotools/godiff", + "revision": "a74583d2ad8773983f273657291df981033308a4", + "revisionTime": "2018-02-17T01:27:43Z" + }, + { + "checksumSHA1": "Wnc0wf1qEhXNdqLPMlIA3vCPpPY=", + "path": "github.com/visualfc/gotools/gofmt", + "revision": "a74583d2ad8773983f273657291df981033308a4", + "revisionTime": "2018-02-17T01:27:43Z" + }, { "checksumSHA1": "RLl3M7ywfbgNYR2HfBywCruQz9c=", "path": "github.com/visualfc/gotools/goimports", @@ -98,6 +130,12 @@ "revision": "b8348693492ca3791bccfa028f3c19634c11c5b5", "revisionTime": "2015-04-09T14:25:36Z" }, + { + "checksumSHA1": "f8zd5auG22z/GqXqW9giRDYEw6A=", + "path": "github.com/visualfc/gotools/gotest", + "revision": "a74583d2ad8773983f273657291df981033308a4", + "revisionTime": "2018-02-17T01:27:43Z" + }, { "checksumSHA1": "kyKBo2ux+HflucDj/qzoko5YoMA=", "path": "github.com/visualfc/gotools/jsonfmt", @@ -128,6 +166,12 @@ "revision": "b8348693492ca3791bccfa028f3c19634c11c5b5", "revisionTime": "2015-04-09T14:25:36Z" }, + { + "checksumSHA1": "6CSw3Gtu+hJ6QTfhJ+985cualxs=", + "path": "github.com/visualfc/gotools/terminal", + "revision": "a74583d2ad8773983f273657291df981033308a4", + "revisionTime": "2018-02-17T01:27:43Z" + }, { "checksumSHA1": "qlJsyinWZ07PaOyTYyxXOmhDN/I=", "path": "github.com/visualfc/gotools/types", @@ -220,7 +264,7 @@ "revision": "" }, { - "checksumSHA1": "p3oUXqh8ecOL76mLRB5h/Qlz9lE=", + "checksumSHA1": "TzQP7S5QaE3ipab7SNo/PcFb2bI=", "path": "golang.org/x/tools/imports", "revision": "" },