vendor: update go-colorable, go-isatty, go-runewidth

This commit is contained in:
hackyminer 2018-09-20 16:30:30 +09:00
parent d9e324a331
commit 3d15a8663c
No known key found for this signature in database
GPG key ID: 46D453DDCA4B766F
12 changed files with 324 additions and 146 deletions

View file

@ -1,5 +1,10 @@
# go-colorable # go-colorable
[![Godoc Reference](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable)
[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable)
[![Coverage Status](https://coveralls.io/repos/github/mattn/go-colorable/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-colorable?branch=master)
[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable)
Colorable writer for windows. Colorable writer for windows.
For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.) For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.)

View file

@ -1,10 +1,13 @@
// +build !windows // +build !windows
// +build !appengine
package colorable package colorable
import ( import (
"io" "io"
"os" "os"
_ "github.com/mattn/go-isatty"
) )
// NewColorable return new instance of Writer which handle escape sequence. // NewColorable return new instance of Writer which handle escape sequence.

View file

@ -1,3 +1,6 @@
// +build windows
// +build !appengine
package colorable package colorable
import ( import (
@ -26,6 +29,15 @@ const (
backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity) backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
) )
const (
genericRead = 0x80000000
genericWrite = 0x40000000
)
const (
consoleTextmodeBuffer = 0x1
)
type wchar uint16 type wchar uint16
type short int16 type short int16
type dword uint32 type dword uint32
@ -65,14 +77,18 @@ var (
procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute") procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute")
procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo") procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo")
procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo") procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo")
procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW")
procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer")
) )
// Writer provide colorable Writer to the console
type Writer struct { type Writer struct {
out io.Writer out io.Writer
handle syscall.Handle handle syscall.Handle
lastbuf bytes.Buffer althandle syscall.Handle
oldattr word oldattr word
oldpos coord oldpos coord
rest bytes.Buffer
} }
// NewColorable return new instance of Writer which handle escape sequence from File. // NewColorable return new instance of Writer which handle escape sequence from File.
@ -86,9 +102,8 @@ func NewColorable(file *os.File) io.Writer {
handle := syscall.Handle(file.Fd()) handle := syscall.Handle(file.Fd())
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
return &Writer{out: file, handle: handle, oldattr: csbi.attributes, oldpos: coord{0, 0}} return &Writer{out: file, handle: handle, oldattr: csbi.attributes, oldpos: coord{0, 0}}
} else {
return file
} }
return file
} }
// NewColorableStdout return new instance of Writer which handle escape sequence for stdout. // NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
@ -360,20 +375,65 @@ var color256 = map[int]int{
255: 0xeeeeee, 255: 0xeeeeee,
} }
// `\033]0;TITLESTR\007`
func doTitleSequence(er *bytes.Reader) error {
var c byte
var err error
c, err = er.ReadByte()
if err != nil {
return err
}
if c != '0' && c != '2' {
return nil
}
c, err = er.ReadByte()
if err != nil {
return err
}
if c != ';' {
return nil
}
title := make([]byte, 0, 80)
for {
c, err = er.ReadByte()
if err != nil {
return err
}
if c == 0x07 || c == '\n' {
break
}
title = append(title, c)
}
if len(title) > 0 {
title8, err := syscall.UTF16PtrFromString(string(title))
if err == nil {
procSetConsoleTitle.Call(uintptr(unsafe.Pointer(title8)))
}
}
return nil
}
// Write write data on console // Write write data on console
func (w *Writer) Write(data []byte) (n int, err error) { func (w *Writer) Write(data []byte) (n int, err error) {
var csbi consoleScreenBufferInfo var csbi consoleScreenBufferInfo
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
er := bytes.NewReader(data) handle := w.handle
var er *bytes.Reader
if w.rest.Len() > 0 {
var rest bytes.Buffer
w.rest.WriteTo(&rest)
w.rest.Reset()
rest.Write(data)
er = bytes.NewReader(rest.Bytes())
} else {
er = bytes.NewReader(data)
}
var bw [1]byte var bw [1]byte
loop: loop:
for { for {
r1, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
if r1 == 0 {
break loop
}
c1, err := er.ReadByte() c1, err := er.ReadByte()
if err != nil { if err != nil {
break loop break loop
@ -385,100 +445,133 @@ loop:
} }
c2, err := er.ReadByte() c2, err := er.ReadByte()
if err != nil { if err != nil {
w.lastbuf.WriteByte(c1)
break loop break loop
} }
if c2 != 0x5b {
w.lastbuf.WriteByte(c1) switch c2 {
w.lastbuf.WriteByte(c2) case '>':
continue
case ']':
w.rest.WriteByte(c1)
w.rest.WriteByte(c2)
er.WriteTo(&w.rest)
if bytes.IndexByte(w.rest.Bytes(), 0x07) == -1 {
break loop
}
er = bytes.NewReader(w.rest.Bytes()[2:])
err := doTitleSequence(er)
if err != nil {
break loop
}
w.rest.Reset()
continue
// https://github.com/mattn/go-colorable/issues/27
case '7':
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
w.oldpos = csbi.cursorPosition
continue
case '8':
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
continue
case 0x5b:
// execute part after switch
default:
continue continue
} }
w.rest.WriteByte(c1)
w.rest.WriteByte(c2)
er.WriteTo(&w.rest)
var buf bytes.Buffer var buf bytes.Buffer
var m byte var m byte
for { for i, c := range w.rest.Bytes()[2:] {
c, err := er.ReadByte()
if err != nil {
w.lastbuf.WriteByte(c1)
w.lastbuf.WriteByte(c2)
w.lastbuf.Write(buf.Bytes())
break loop
}
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
m = c m = c
er = bytes.NewReader(w.rest.Bytes()[2+i+1:])
w.rest.Reset()
break break
} }
buf.Write([]byte(string(c))) buf.Write([]byte(string(c)))
} }
if m == 0 {
break loop
}
var csbi consoleScreenBufferInfo
switch m { switch m {
case 'A': case 'A':
n, err = strconv.Atoi(buf.String()) n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.y -= short(n) csbi.cursorPosition.y -= short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'B': case 'B':
n, err = strconv.Atoi(buf.String()) n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.y += short(n) csbi.cursorPosition.y += short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'C': case 'C':
n, err = strconv.Atoi(buf.String()) n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x -= short(n) csbi.cursorPosition.x += short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'D': case 'D':
n, err = strconv.Atoi(buf.String()) n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
if n, err = strconv.Atoi(buf.String()); err == nil { procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
var csbi consoleScreenBufferInfo csbi.cursorPosition.x -= short(n)
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) if csbi.cursorPosition.x < 0 {
csbi.cursorPosition.x += short(n) csbi.cursorPosition.x = 0
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
} }
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'E': case 'E':
n, err = strconv.Atoi(buf.String()) n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x = 0 csbi.cursorPosition.x = 0
csbi.cursorPosition.y += short(n) csbi.cursorPosition.y += short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'F': case 'F':
n, err = strconv.Atoi(buf.String()) n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x = 0 csbi.cursorPosition.x = 0
csbi.cursorPosition.y -= short(n) csbi.cursorPosition.y -= short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'G': case 'G':
n, err = strconv.Atoi(buf.String()) n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x = short(n - 1) csbi.cursorPosition.x = short(n - 1)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'H': case 'H', 'f':
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
if buf.Len() > 0 {
token := strings.Split(buf.String(), ";") token := strings.Split(buf.String(), ";")
if len(token) != 2 { switch len(token) {
case 1:
n1, err := strconv.Atoi(token[0])
if err != nil {
continue continue
} }
csbi.cursorPosition.y = short(n1 - 1)
case 2:
n1, err := strconv.Atoi(token[0]) n1, err := strconv.Atoi(token[0])
if err != nil { if err != nil {
continue continue
@ -489,51 +582,65 @@ loop:
} }
csbi.cursorPosition.x = short(n2 - 1) csbi.cursorPosition.x = short(n2 - 1)
csbi.cursorPosition.y = short(n1 - 1) csbi.cursorPosition.y = short(n1 - 1)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) }
} else {
csbi.cursorPosition.y = 0
}
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'J': case 'J':
n, err := strconv.Atoi(buf.String()) n := 0
if buf.Len() > 0 {
n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) }
var count, written dword
var cursor coord var cursor coord
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
switch n { switch n {
case 0: case 0:
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
case 1: case 1:
cursor = coord{x: csbi.window.left, y: csbi.window.top} cursor = coord{x: csbi.window.left, y: csbi.window.top}
count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.window.top-csbi.cursorPosition.y)*dword(csbi.size.x)
case 2: case 2:
cursor = coord{x: csbi.window.left, y: csbi.window.top} cursor = coord{x: csbi.window.left, y: csbi.window.top}
count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
} }
var count, written dword procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x) procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
case 'K': case 'K':
n, err := strconv.Atoi(buf.String()) n := 0
if buf.Len() > 0 {
n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) }
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
var cursor coord var cursor coord
var count, written dword
switch n { switch n {
case 0: case 0:
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
case 1:
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
case 2:
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
}
var count, written dword
count = dword(csbi.size.x - csbi.cursorPosition.x) count = dword(csbi.size.x - csbi.cursorPosition.x)
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) case 1:
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
count = dword(csbi.size.x - csbi.cursorPosition.x)
case 2:
cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
count = dword(csbi.size.x)
}
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
case 'm': case 'm':
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
attr := csbi.attributes attr := csbi.attributes
cs := buf.String() cs := buf.String()
if cs == "" { if cs == "" {
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.oldattr)) procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr))
continue continue
} }
token := strings.Split(cs, ";") token := strings.Split(cs, ";")
@ -547,7 +654,7 @@ loop:
attr |= foregroundIntensity attr |= foregroundIntensity
case n == 7: case n == 7:
attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4) attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
case 22 == n || n == 25 || n == 25: case n == 22 || n == 25:
attr |= foregroundIntensity attr |= foregroundIntensity
case n == 27: case n == 27:
attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4) attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
@ -572,6 +679,21 @@ loop:
attr |= n256foreAttr[n256] attr |= n256foreAttr[n256]
i += 2 i += 2
} }
} else if len(token) == 5 && token[i+1] == "2" {
var r, g, b int
r, _ = strconv.Atoi(token[i+2])
g, _ = strconv.Atoi(token[i+3])
b, _ = strconv.Atoi(token[i+4])
i += 4
if r > 127 {
attr |= foregroundRed
}
if g > 127 {
attr |= foregroundGreen
}
if b > 127 {
attr |= foregroundBlue
}
} else { } else {
attr = attr & (w.oldattr & backgroundMask) attr = attr & (w.oldattr & backgroundMask)
} }
@ -599,6 +721,21 @@ loop:
attr |= n256backAttr[n256] attr |= n256backAttr[n256]
i += 2 i += 2
} }
} else if len(token) == 5 && token[i+1] == "2" {
var r, g, b int
r, _ = strconv.Atoi(token[i+2])
g, _ = strconv.Atoi(token[i+3])
b, _ = strconv.Atoi(token[i+4])
i += 4
if r > 127 {
attr |= backgroundRed
}
if g > 127 {
attr |= backgroundGreen
}
if b > 127 {
attr |= backgroundBlue
}
} else { } else {
attr = attr & (w.oldattr & foregroundMask) attr = attr & (w.oldattr & foregroundMask)
} }
@ -630,33 +767,56 @@ loop:
attr |= backgroundBlue attr |= backgroundBlue
} }
} }
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr)) procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr))
} }
} }
case 'h': case 'h':
cs := buf.String()
if cs == "?25" {
var ci consoleCursorInfo var ci consoleCursorInfo
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) cs := buf.String()
if cs == "5>" {
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 0
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?25" {
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 1 ci.visible = 1
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?1049" {
if w.althandle == 0 {
h, _, _ := procCreateConsoleScreenBuffer.Call(uintptr(genericRead|genericWrite), 0, 0, uintptr(consoleTextmodeBuffer), 0, 0)
w.althandle = syscall.Handle(h)
if w.althandle != 0 {
handle = w.althandle
}
}
} }
case 'l': case 'l':
cs := buf.String()
if cs == "?25" {
var ci consoleCursorInfo var ci consoleCursorInfo
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) cs := buf.String()
if cs == "5>" {
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 1
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?25" {
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 0 ci.visible = 0
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?1049" {
if w.althandle != 0 {
syscall.CloseHandle(w.althandle)
w.althandle = 0
handle = w.handle
}
} }
case 's': case 's':
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
w.oldpos = csbi.cursorPosition w.oldpos = csbi.cursorPosition
case 'u': case 'u':
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&w.oldpos))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
} }
} }
return len(data) - w.lastbuf.Len(), nil
return len(data), nil
} }
type consoleColor struct { type consoleColor struct {
@ -700,22 +860,22 @@ func (c consoleColor) backgroundAttr() (attr word) {
} }
var color16 = []consoleColor{ var color16 = []consoleColor{
consoleColor{0x000000, false, false, false, false}, {0x000000, false, false, false, false},
consoleColor{0x000080, false, false, true, false}, {0x000080, false, false, true, false},
consoleColor{0x008000, false, true, false, false}, {0x008000, false, true, false, false},
consoleColor{0x008080, false, true, true, false}, {0x008080, false, true, true, false},
consoleColor{0x800000, true, false, false, false}, {0x800000, true, false, false, false},
consoleColor{0x800080, true, false, true, false}, {0x800080, true, false, true, false},
consoleColor{0x808000, true, true, false, false}, {0x808000, true, true, false, false},
consoleColor{0xc0c0c0, true, true, true, false}, {0xc0c0c0, true, true, true, false},
consoleColor{0x808080, false, false, false, true}, {0x808080, false, false, false, true},
consoleColor{0x0000ff, false, false, true, true}, {0x0000ff, false, false, true, true},
consoleColor{0x00ff00, false, true, false, true}, {0x00ff00, false, true, false, true},
consoleColor{0x00ffff, false, true, true, true}, {0x00ffff, false, true, true, true},
consoleColor{0xff0000, true, false, false, true}, {0xff0000, true, false, false, true},
consoleColor{0xff00ff, true, false, true, true}, {0xff00ff, true, false, true, true},
consoleColor{0xffff00, true, true, false, true}, {0xffff00, true, true, false, true},
consoleColor{0xffffff, true, true, true, true}, {0xffffff, true, true, true, true},
} }
type hsv struct { type hsv struct {

View file

@ -8,7 +8,6 @@ import (
// NonColorable hold writer but remove escape sequence. // NonColorable hold writer but remove escape sequence.
type NonColorable struct { type NonColorable struct {
out io.Writer out io.Writer
lastbuf bytes.Buffer
} }
// NewNonColorable return new instance of Writer which remove escape sequence from Writer. // NewNonColorable return new instance of Writer which remove escape sequence from Writer.
@ -33,12 +32,9 @@ loop:
} }
c2, err := er.ReadByte() c2, err := er.ReadByte()
if err != nil { if err != nil {
w.lastbuf.WriteByte(c1)
break loop break loop
} }
if c2 != 0x5b { if c2 != 0x5b {
w.lastbuf.WriteByte(c1)
w.lastbuf.WriteByte(c2)
continue continue
} }
@ -46,9 +42,6 @@ loop:
for { for {
c, err := er.ReadByte() c, err := er.ReadByte()
if err != nil { if err != nil {
w.lastbuf.WriteByte(c1)
w.lastbuf.WriteByte(c2)
w.lastbuf.Write(buf.Bytes())
break loop break loop
} }
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
@ -57,5 +50,6 @@ loop:
buf.Write([]byte(string(c))) buf.Write([]byte(string(c)))
} }
} }
return len(data) - w.lastbuf.Len(), nil
return len(data), nil
} }

View file

@ -1,6 +1,9 @@
# go-isatty # go-isatty
[![Build Status](https://travis-ci.org/mattn/go-isatty.svg?branch=master)](https://travis-ci.org/mattn/go-isatty) [![Coverage Status](https://coveralls.io/repos/github/mattn/go-isatty/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-isatty?branch=master) [![Godoc Reference](https://godoc.org/github.com/mattn/go-isatty?status.svg)](http://godoc.org/github.com/mattn/go-isatty)
[![Build Status](https://travis-ci.org/mattn/go-isatty.svg?branch=master)](https://travis-ci.org/mattn/go-isatty)
[![Coverage Status](https://coveralls.io/repos/github/mattn/go-isatty/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-isatty?branch=master)
[![Go Report Card](https://goreportcard.com/badge/mattn/go-isatty)](https://goreportcard.com/report/mattn/go-isatty)
isatty for golang isatty for golang

View file

@ -1,9 +0,0 @@
// +build appengine
package isatty
// IsTerminal returns true if the file descriptor is terminal which
// is always false on on appengine classic which is a sandboxed PaaS.
func IsTerminal(fd uintptr) bool {
return false
}

View file

@ -16,3 +16,9 @@ func IsTerminal(fd uintptr) bool {
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
return err == 0 return err == 0
} }
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

View file

@ -1,5 +1,5 @@
// +build linux // +build linux
// +build !appengine // +build !appengine,!ppc64,!ppc64le
package isatty package isatty
@ -16,3 +16,9 @@ func IsTerminal(fd uintptr) bool {
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
return err == 0 return err == 0
} }
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

View file

@ -1,9 +0,0 @@
// +build !windows appengine
package isatty
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

View file

@ -14,3 +14,9 @@ func IsTerminal(fd uintptr) bool {
err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio) err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
return err == nil return err == nil
} }
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

View file

@ -1,13 +1,24 @@
package runewidth package runewidth
import "os"
var ( var (
// EastAsianWidth will be set true if the current locale is CJK // EastAsianWidth will be set true if the current locale is CJK
EastAsianWidth = IsEastAsian() EastAsianWidth bool
// DefaultCondition is a condition in current locale // DefaultCondition is a condition in current locale
DefaultCondition = &Condition{EastAsianWidth} DefaultCondition = &Condition{EastAsianWidth}
) )
func init() {
env := os.Getenv("RUNEWIDTH_EASTASIAN")
if env == "" {
EastAsianWidth = IsEastAsian()
} else {
EastAsianWidth = env == "1"
}
}
type interval struct { type interval struct {
first rune first rune
last rune last rune
@ -55,6 +66,7 @@ var private = table{
var nonprint = table{ var nonprint = table{
{0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD}, {0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD},
{0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F}, {0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F},
{0x2028, 0x2029},
{0x202A, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF}, {0x202A, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF},
{0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF},
} }

17
vendor/vendor.json vendored
View file

@ -268,22 +268,23 @@
"revisionTime": "2016-07-20T14:16:34Z" "revisionTime": "2016-07-20T14:16:34Z"
}, },
{ {
"checksumSHA1": "I4njd26dG5hxFT2nawuByM4pxzY=", "checksumSHA1": "SEnjvwVyfuU2xBaOfXfwPD5MZqk=",
"path": "github.com/mattn/go-colorable", "path": "github.com/mattn/go-colorable",
"revision": "5411d3eea5978e6cdc258b30de592b60df6aba96", "revision": "efa589957cd060542a26d2dd7832fd6a6c6c3ade",
"revisionTime": "2017-02-10T17:28:01Z" "revisionTime": "2018-03-10T13:32:14Z",
"version": "efa589957cd060542a26d2dd7832fd6a6c6c3ade"
}, },
{ {
"checksumSHA1": "EkT5JmFvz3zOPWappEFyYWUaeY0=", "checksumSHA1": "GiVgQkx5acnq+JZtYiuHPlhHoso=",
"path": "github.com/mattn/go-isatty", "path": "github.com/mattn/go-isatty",
"revision": "281032e84ae07510239465db46bf442aa44b953a", "revision": "3fb116b820352b7f0c281308a4d6250c22d94e27",
"revisionTime": "2017-02-09T17:56:15Z" "revisionTime": "2018-08-30T10:17:45Z"
}, },
{ {
"checksumSHA1": "MNkKJyk2TazKMJYbal5wFHybpyA=", "checksumSHA1": "MNkKJyk2TazKMJYbal5wFHybpyA=",
"path": "github.com/mattn/go-runewidth", "path": "github.com/mattn/go-runewidth",
"revision": "14207d285c6c197daabb5c9793d63e7af9ab2d50", "revision": "ce7b0b5c7b45a81508558cd1dba6bb1e4ddb51bb",
"revisionTime": "2017-02-01T02:35:40Z" "revisionTime": "2018-04-08T05:53:51Z"
}, },
{ {
"checksumSHA1": "L3leymg2RT8hFl5uL+5KP/LpBkg=", "checksumSHA1": "L3leymg2RT8hFl5uL+5KP/LpBkg=",