mirror of
				https://github.com/containers/podman.git
				synced 2025-11-01 02:42:11 +08:00 
			
		
		
		
	 8e4a42aa42
			
		
	
	8e4a42aa42
	
	
	
		
			
			Add support for short-name aliasing. Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
		
			
				
	
	
		
			250 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // +build windows
 | |
| 
 | |
| package readline
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"io"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 	"sync"
 | |
| 	"unicode/utf8"
 | |
| 	"unsafe"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	_                = uint16(0)
 | |
| 	COLOR_FBLUE      = 0x0001
 | |
| 	COLOR_FGREEN     = 0x0002
 | |
| 	COLOR_FRED       = 0x0004
 | |
| 	COLOR_FINTENSITY = 0x0008
 | |
| 
 | |
| 	COLOR_BBLUE      = 0x0010
 | |
| 	COLOR_BGREEN     = 0x0020
 | |
| 	COLOR_BRED       = 0x0040
 | |
| 	COLOR_BINTENSITY = 0x0080
 | |
| 
 | |
| 	COMMON_LVB_UNDERSCORE = 0x8000
 | |
| 	COMMON_LVB_BOLD       = 0x0007
 | |
| )
 | |
| 
 | |
| var ColorTableFg = []word{
 | |
| 	0,                                       // 30: Black
 | |
| 	COLOR_FRED,                              // 31: Red
 | |
| 	COLOR_FGREEN,                            // 32: Green
 | |
| 	COLOR_FRED | COLOR_FGREEN,               // 33: Yellow
 | |
| 	COLOR_FBLUE,                             // 34: Blue
 | |
| 	COLOR_FRED | COLOR_FBLUE,                // 35: Magenta
 | |
| 	COLOR_FGREEN | COLOR_FBLUE,              // 36: Cyan
 | |
| 	COLOR_FRED | COLOR_FBLUE | COLOR_FGREEN, // 37: White
 | |
| }
 | |
| 
 | |
| var ColorTableBg = []word{
 | |
| 	0,                                       // 40: Black
 | |
| 	COLOR_BRED,                              // 41: Red
 | |
| 	COLOR_BGREEN,                            // 42: Green
 | |
| 	COLOR_BRED | COLOR_BGREEN,               // 43: Yellow
 | |
| 	COLOR_BBLUE,                             // 44: Blue
 | |
| 	COLOR_BRED | COLOR_BBLUE,                // 45: Magenta
 | |
| 	COLOR_BGREEN | COLOR_BBLUE,              // 46: Cyan
 | |
| 	COLOR_BRED | COLOR_BBLUE | COLOR_BGREEN, // 47: White
 | |
| }
 | |
| 
 | |
| type ANSIWriter struct {
 | |
| 	target io.Writer
 | |
| 	wg     sync.WaitGroup
 | |
| 	ctx    *ANSIWriterCtx
 | |
| 	sync.Mutex
 | |
| }
 | |
| 
 | |
| func NewANSIWriter(w io.Writer) *ANSIWriter {
 | |
| 	a := &ANSIWriter{
 | |
| 		target: w,
 | |
| 		ctx:    NewANSIWriterCtx(w),
 | |
| 	}
 | |
| 	return a
 | |
| }
 | |
| 
 | |
| func (a *ANSIWriter) Close() error {
 | |
| 	a.wg.Wait()
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| type ANSIWriterCtx struct {
 | |
| 	isEsc     bool
 | |
| 	isEscSeq  bool
 | |
| 	arg       []string
 | |
| 	target    *bufio.Writer
 | |
| 	wantFlush bool
 | |
| }
 | |
| 
 | |
| func NewANSIWriterCtx(target io.Writer) *ANSIWriterCtx {
 | |
| 	return &ANSIWriterCtx{
 | |
| 		target: bufio.NewWriter(target),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (a *ANSIWriterCtx) Flush() {
 | |
| 	a.target.Flush()
 | |
| }
 | |
| 
 | |
| func (a *ANSIWriterCtx) process(r rune) bool {
 | |
| 	if a.wantFlush {
 | |
| 		if r == 0 || r == CharEsc {
 | |
| 			a.wantFlush = false
 | |
| 			a.target.Flush()
 | |
| 		}
 | |
| 	}
 | |
| 	if a.isEscSeq {
 | |
| 		a.isEscSeq = a.ioloopEscSeq(a.target, r, &a.arg)
 | |
| 		return true
 | |
| 	}
 | |
| 
 | |
| 	switch r {
 | |
| 	case CharEsc:
 | |
| 		a.isEsc = true
 | |
| 	case '[':
 | |
| 		if a.isEsc {
 | |
| 			a.arg = nil
 | |
| 			a.isEscSeq = true
 | |
| 			a.isEsc = false
 | |
| 			break
 | |
| 		}
 | |
| 		fallthrough
 | |
| 	default:
 | |
| 		a.target.WriteRune(r)
 | |
| 		a.wantFlush = true
 | |
| 	}
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func (a *ANSIWriterCtx) ioloopEscSeq(w *bufio.Writer, r rune, argptr *[]string) bool {
 | |
| 	arg := *argptr
 | |
| 	var err error
 | |
| 
 | |
| 	if r >= 'A' && r <= 'D' {
 | |
| 		count := short(GetInt(arg, 1))
 | |
| 		info, err := GetConsoleScreenBufferInfo()
 | |
| 		if err != nil {
 | |
| 			return false
 | |
| 		}
 | |
| 		switch r {
 | |
| 		case 'A': // up
 | |
| 			info.dwCursorPosition.y -= count
 | |
| 		case 'B': // down
 | |
| 			info.dwCursorPosition.y += count
 | |
| 		case 'C': // right
 | |
| 			info.dwCursorPosition.x += count
 | |
| 		case 'D': // left
 | |
| 			info.dwCursorPosition.x -= count
 | |
| 		}
 | |
| 		SetConsoleCursorPosition(&info.dwCursorPosition)
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	switch r {
 | |
| 	case 'J':
 | |
| 		killLines()
 | |
| 	case 'K':
 | |
| 		eraseLine()
 | |
| 	case 'm':
 | |
| 		color := word(0)
 | |
| 		for _, item := range arg {
 | |
| 			var c int
 | |
| 			c, err = strconv.Atoi(item)
 | |
| 			if err != nil {
 | |
| 				w.WriteString("[" + strings.Join(arg, ";") + "m")
 | |
| 				break
 | |
| 			}
 | |
| 			if c >= 30 && c < 40 {
 | |
| 				color ^= COLOR_FINTENSITY
 | |
| 				color |= ColorTableFg[c-30]
 | |
| 			} else if c >= 40 && c < 50 {
 | |
| 				color ^= COLOR_BINTENSITY
 | |
| 				color |= ColorTableBg[c-40]
 | |
| 			} else if c == 4 {
 | |
| 				color |= COMMON_LVB_UNDERSCORE | ColorTableFg[7]
 | |
| 			} else if c == 1 {
 | |
| 				color |= COMMON_LVB_BOLD | COLOR_FINTENSITY
 | |
| 			} else { // unknown code treat as reset
 | |
| 				color = ColorTableFg[7]
 | |
| 			}
 | |
| 		}
 | |
| 		if err != nil {
 | |
| 			break
 | |
| 		}
 | |
| 		kernel.SetConsoleTextAttribute(stdout, uintptr(color))
 | |
| 	case '\007': // set title
 | |
| 	case ';':
 | |
| 		if len(arg) == 0 || arg[len(arg)-1] != "" {
 | |
| 			arg = append(arg, "")
 | |
| 			*argptr = arg
 | |
| 		}
 | |
| 		return true
 | |
| 	default:
 | |
| 		if len(arg) == 0 {
 | |
| 			arg = append(arg, "")
 | |
| 		}
 | |
| 		arg[len(arg)-1] += string(r)
 | |
| 		*argptr = arg
 | |
| 		return true
 | |
| 	}
 | |
| 	*argptr = nil
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func (a *ANSIWriter) Write(b []byte) (int, error) {
 | |
| 	a.Lock()
 | |
| 	defer a.Unlock()
 | |
| 
 | |
| 	off := 0
 | |
| 	for len(b) > off {
 | |
| 		r, size := utf8.DecodeRune(b[off:])
 | |
| 		if size == 0 {
 | |
| 			return off, io.ErrShortWrite
 | |
| 		}
 | |
| 		off += size
 | |
| 		a.ctx.process(r)
 | |
| 	}
 | |
| 	a.ctx.Flush()
 | |
| 	return off, nil
 | |
| }
 | |
| 
 | |
| func killLines() error {
 | |
| 	sbi, err := GetConsoleScreenBufferInfo()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	size := (sbi.dwCursorPosition.y - sbi.dwSize.y) * sbi.dwSize.x
 | |
| 	size += sbi.dwCursorPosition.x
 | |
| 
 | |
| 	var written int
 | |
| 	kernel.FillConsoleOutputAttribute(stdout, uintptr(ColorTableFg[7]),
 | |
| 		uintptr(size),
 | |
| 		sbi.dwCursorPosition.ptr(),
 | |
| 		uintptr(unsafe.Pointer(&written)),
 | |
| 	)
 | |
| 	return kernel.FillConsoleOutputCharacterW(stdout, uintptr(' '),
 | |
| 		uintptr(size),
 | |
| 		sbi.dwCursorPosition.ptr(),
 | |
| 		uintptr(unsafe.Pointer(&written)),
 | |
| 	)
 | |
| }
 | |
| 
 | |
| func eraseLine() error {
 | |
| 	sbi, err := GetConsoleScreenBufferInfo()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	size := sbi.dwSize.x
 | |
| 	sbi.dwCursorPosition.x = 0
 | |
| 	var written int
 | |
| 	return kernel.FillConsoleOutputCharacterW(stdout, uintptr(' '),
 | |
| 		uintptr(size),
 | |
| 		sbi.dwCursorPosition.ptr(),
 | |
| 		uintptr(unsafe.Pointer(&written)),
 | |
| 	)
 | |
| }
 |