Add vendor
Specifically because I want to modify a dependency
This commit is contained in:
		
							
								
								
									
										9
									
								
								vendor/github.com/xo/terminfo/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/xo/terminfo/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
/.cache/
 | 
			
		||||
 | 
			
		||||
/cmd/infocmp/infocmp
 | 
			
		||||
/cmd/infocmp/.out/
 | 
			
		||||
 | 
			
		||||
/infocmp
 | 
			
		||||
/.out/
 | 
			
		||||
 | 
			
		||||
*.txt
 | 
			
		||||
							
								
								
									
										21
									
								
								vendor/github.com/xo/terminfo/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/xo/terminfo/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2016 Anmol Sethi
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
							
								
								
									
										139
									
								
								vendor/github.com/xo/terminfo/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								vendor/github.com/xo/terminfo/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,139 @@
 | 
			
		||||
# About terminfo [![GoDoc][1]][2]
 | 
			
		||||
 | 
			
		||||
Package `terminfo` provides a pure-Go implementation of reading information
 | 
			
		||||
from the terminfo database.
 | 
			
		||||
 | 
			
		||||
`terminfo` is meant as a replacement for `ncurses` in simple Go programs.
 | 
			
		||||
 | 
			
		||||
## Installing
 | 
			
		||||
 | 
			
		||||
Install in the usual Go way:
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
$ go get -u github.com/xo/terminfo
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Using
 | 
			
		||||
 | 
			
		||||
Please see the [GoDoc API listing][2] for more information on using `terminfo`.
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
// _examples/simple/main.go
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/signal"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"syscall"
 | 
			
		||||
 | 
			
		||||
	"github.com/xo/terminfo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	//r := rand.New(nil)
 | 
			
		||||
 | 
			
		||||
	// load terminfo
 | 
			
		||||
	ti, err := terminfo.LoadFromEnv()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// cleanup
 | 
			
		||||
	defer func() {
 | 
			
		||||
		err := recover()
 | 
			
		||||
		termreset(ti)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	terminit(ti)
 | 
			
		||||
	termtitle(ti, "simple example!")
 | 
			
		||||
	termputs(ti, 3, 3, "Ctrl-C to exit")
 | 
			
		||||
	maxColors := termcolors(ti)
 | 
			
		||||
	if maxColors > 256 {
 | 
			
		||||
		maxColors = 256
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < maxColors; i++ {
 | 
			
		||||
		termputs(ti, 5+i/16, 5+i%16, ti.Colorf(i, 0, "█"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// wait for signal
 | 
			
		||||
	sigs := make(chan os.Signal, 1)
 | 
			
		||||
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
 | 
			
		||||
	<-sigs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// terminit initializes the special CA mode on the terminal, and makes the
 | 
			
		||||
// cursor invisible.
 | 
			
		||||
func terminit(ti *terminfo.Terminfo) {
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	// set the cursor invisible
 | 
			
		||||
	ti.Fprintf(buf, terminfo.CursorInvisible)
 | 
			
		||||
	// enter special mode
 | 
			
		||||
	ti.Fprintf(buf, terminfo.EnterCaMode)
 | 
			
		||||
	// clear the screen
 | 
			
		||||
	ti.Fprintf(buf, terminfo.ClearScreen)
 | 
			
		||||
	os.Stdout.Write(buf.Bytes())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// termreset is the inverse of terminit.
 | 
			
		||||
func termreset(ti *terminfo.Terminfo) {
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	ti.Fprintf(buf, terminfo.ExitCaMode)
 | 
			
		||||
	ti.Fprintf(buf, terminfo.CursorNormal)
 | 
			
		||||
	os.Stdout.Write(buf.Bytes())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// termputs puts a string at row, col, interpolating v.
 | 
			
		||||
func termputs(ti *terminfo.Terminfo, row, col int, s string, v ...interface{}) {
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	ti.Fprintf(buf, terminfo.CursorAddress, row, col)
 | 
			
		||||
	fmt.Fprintf(buf, s, v...)
 | 
			
		||||
	os.Stdout.Write(buf.Bytes())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// sl is the status line terminfo.
 | 
			
		||||
var sl *terminfo.Terminfo
 | 
			
		||||
 | 
			
		||||
// termtitle sets the window title.
 | 
			
		||||
func termtitle(ti *terminfo.Terminfo, s string) {
 | 
			
		||||
	var once sync.Once
 | 
			
		||||
	once.Do(func() {
 | 
			
		||||
		if ti.Has(terminfo.HasStatusLine) {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		// load the sl xterm if terminal is an xterm or has COLORTERM
 | 
			
		||||
		if strings.Contains(strings.ToLower(os.Getenv("TERM")), "xterm") || os.Getenv("COLORTERM") == "truecolor" {
 | 
			
		||||
			sl, _ = terminfo.Load("xterm+sl")
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
	if sl != nil {
 | 
			
		||||
		ti = sl
 | 
			
		||||
	}
 | 
			
		||||
	if !ti.Has(terminfo.HasStatusLine) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	ti.Fprintf(buf, terminfo.ToStatusLine)
 | 
			
		||||
	fmt.Fprint(buf, s)
 | 
			
		||||
	ti.Fprintf(buf, terminfo.FromStatusLine)
 | 
			
		||||
	os.Stdout.Write(buf.Bytes())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// termcolors returns the maximum colors available for the terminal.
 | 
			
		||||
func termcolors(ti *terminfo.Terminfo) int {
 | 
			
		||||
	if colors := ti.Num(terminfo.MaxColors); colors > 0 {
 | 
			
		||||
		return colors
 | 
			
		||||
	}
 | 
			
		||||
	return int(terminfo.ColorLevelBasic)
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
[1]: https://godoc.org/github.com/xo/terminfo?status.svg
 | 
			
		||||
[2]: https://godoc.org/github.com/xo/terminfo
 | 
			
		||||
							
								
								
									
										31
									
								
								vendor/github.com/xo/terminfo/caps.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								vendor/github.com/xo/terminfo/caps.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
package terminfo
 | 
			
		||||
 | 
			
		||||
// BoolCapName returns the bool capability name.
 | 
			
		||||
func BoolCapName(i int) string {
 | 
			
		||||
	return boolCapNames[2*i]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BoolCapNameShort returns the short bool capability name.
 | 
			
		||||
func BoolCapNameShort(i int) string {
 | 
			
		||||
	return boolCapNames[2*i+1]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NumCapName returns the num capability name.
 | 
			
		||||
func NumCapName(i int) string {
 | 
			
		||||
	return numCapNames[2*i]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NumCapNameShort returns the short num capability name.
 | 
			
		||||
func NumCapNameShort(i int) string {
 | 
			
		||||
	return numCapNames[2*i+1]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringCapName returns the string capability name.
 | 
			
		||||
func StringCapName(i int) string {
 | 
			
		||||
	return stringCapNames[2*i]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringCapNameShort returns the short string capability name.
 | 
			
		||||
func StringCapNameShort(i int) string {
 | 
			
		||||
	return stringCapNames[2*i+1]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1525
									
								
								vendor/github.com/xo/terminfo/capvals.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1525
									
								
								vendor/github.com/xo/terminfo/capvals.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										88
									
								
								vendor/github.com/xo/terminfo/color.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								vendor/github.com/xo/terminfo/color.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
			
		||||
package terminfo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ColorLevel is the color level supported by a terminal.
 | 
			
		||||
type ColorLevel uint
 | 
			
		||||
 | 
			
		||||
// ColorLevel values.
 | 
			
		||||
const (
 | 
			
		||||
	ColorLevelNone ColorLevel = iota
 | 
			
		||||
	ColorLevelBasic
 | 
			
		||||
	ColorLevelHundreds
 | 
			
		||||
	ColorLevelMillions
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// String satisfies the Stringer interface.
 | 
			
		||||
func (c ColorLevel) String() string {
 | 
			
		||||
	switch c {
 | 
			
		||||
	case ColorLevelBasic:
 | 
			
		||||
		return "basic"
 | 
			
		||||
	case ColorLevelHundreds:
 | 
			
		||||
		return "hundreds"
 | 
			
		||||
	case ColorLevelMillions:
 | 
			
		||||
		return "millions"
 | 
			
		||||
	}
 | 
			
		||||
	return "none"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ChromaFormatterName returns the github.com/alecthomas/chroma compatible
 | 
			
		||||
// formatter name for the color level.
 | 
			
		||||
func (c ColorLevel) ChromaFormatterName() string {
 | 
			
		||||
	switch c {
 | 
			
		||||
	case ColorLevelBasic:
 | 
			
		||||
		return "terminal"
 | 
			
		||||
	case ColorLevelHundreds:
 | 
			
		||||
		return "terminal256"
 | 
			
		||||
	case ColorLevelMillions:
 | 
			
		||||
		return "terminal16m"
 | 
			
		||||
	}
 | 
			
		||||
	return "noop"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ColorLevelFromEnv returns the color level COLORTERM, FORCE_COLOR,
 | 
			
		||||
// TERM_PROGRAM, or determined from the TERM environment variable.
 | 
			
		||||
func ColorLevelFromEnv() (ColorLevel, error) {
 | 
			
		||||
	// check for overriding environment variables
 | 
			
		||||
	colorTerm, termProg, forceColor := os.Getenv("COLORTERM"), os.Getenv("TERM_PROGRAM"), os.Getenv("FORCE_COLOR")
 | 
			
		||||
	switch {
 | 
			
		||||
	case strings.Contains(colorTerm, "truecolor") || strings.Contains(colorTerm, "24bit") || termProg == "Hyper":
 | 
			
		||||
		return ColorLevelMillions, nil
 | 
			
		||||
	case colorTerm != "" || forceColor != "":
 | 
			
		||||
		return ColorLevelBasic, nil
 | 
			
		||||
	case termProg == "Apple_Terminal":
 | 
			
		||||
		return ColorLevelHundreds, nil
 | 
			
		||||
	case termProg == "iTerm.app":
 | 
			
		||||
		ver := os.Getenv("TERM_PROGRAM_VERSION")
 | 
			
		||||
		if ver == "" {
 | 
			
		||||
			return ColorLevelHundreds, nil
 | 
			
		||||
		}
 | 
			
		||||
		i, err := strconv.Atoi(strings.Split(ver, ".")[0])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return ColorLevelNone, ErrInvalidTermProgramVersion
 | 
			
		||||
		}
 | 
			
		||||
		if i == 3 {
 | 
			
		||||
			return ColorLevelMillions, nil
 | 
			
		||||
		}
 | 
			
		||||
		return ColorLevelHundreds, nil
 | 
			
		||||
	}
 | 
			
		||||
	// otherwise determine from TERM's max_colors capability
 | 
			
		||||
	if term := os.Getenv("TERM"); term != "" {
 | 
			
		||||
		ti, err := Load(term)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return ColorLevelNone, err
 | 
			
		||||
		}
 | 
			
		||||
		v, ok := ti.Nums[MaxColors]
 | 
			
		||||
		switch {
 | 
			
		||||
		case !ok || v <= 16:
 | 
			
		||||
			return ColorLevelNone, nil
 | 
			
		||||
		case ok && v >= 256:
 | 
			
		||||
			return ColorLevelHundreds, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return ColorLevelBasic, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										245
									
								
								vendor/github.com/xo/terminfo/dec.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								vendor/github.com/xo/terminfo/dec.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,245 @@
 | 
			
		||||
package terminfo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sort"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// maxFileLength is the max file length.
 | 
			
		||||
	maxFileLength = 4096
 | 
			
		||||
	// magic is the file magic for terminfo files.
 | 
			
		||||
	magic = 0o432
 | 
			
		||||
	// magicExtended is the file magic for terminfo files with the extended
 | 
			
		||||
	// number format.
 | 
			
		||||
	magicExtended = 0o1036
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// header fields.
 | 
			
		||||
const (
 | 
			
		||||
	fieldMagic = iota
 | 
			
		||||
	fieldNameSize
 | 
			
		||||
	fieldBoolCount
 | 
			
		||||
	fieldNumCount
 | 
			
		||||
	fieldStringCount
 | 
			
		||||
	fieldTableSize
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// header extended fields.
 | 
			
		||||
const (
 | 
			
		||||
	fieldExtBoolCount = iota
 | 
			
		||||
	fieldExtNumCount
 | 
			
		||||
	fieldExtStringCount
 | 
			
		||||
	fieldExtOffsetCount
 | 
			
		||||
	fieldExtTableSize
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// hasInvalidCaps determines if the capabilities in h are invalid.
 | 
			
		||||
func hasInvalidCaps(h []int) bool {
 | 
			
		||||
	return h[fieldBoolCount] > CapCountBool ||
 | 
			
		||||
		h[fieldNumCount] > CapCountNum ||
 | 
			
		||||
		h[fieldStringCount] > CapCountString
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// capLength returns the total length of the capabilities in bytes.
 | 
			
		||||
func capLength(h []int) int {
 | 
			
		||||
	return h[fieldNameSize] +
 | 
			
		||||
		h[fieldBoolCount] +
 | 
			
		||||
		(h[fieldNameSize]+h[fieldBoolCount])%2 + // account for word align
 | 
			
		||||
		h[fieldNumCount]*2 +
 | 
			
		||||
		h[fieldStringCount]*2 +
 | 
			
		||||
		h[fieldTableSize]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// hasInvalidExtOffset determines if the extended offset field is valid.
 | 
			
		||||
func hasInvalidExtOffset(h []int) bool {
 | 
			
		||||
	return h[fieldExtBoolCount]+
 | 
			
		||||
		h[fieldExtNumCount]+
 | 
			
		||||
		h[fieldExtStringCount]*2 != h[fieldExtOffsetCount]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// extCapLength returns the total length of extended capabilities in bytes.
 | 
			
		||||
func extCapLength(h []int, numWidth int) int {
 | 
			
		||||
	return h[fieldExtBoolCount] +
 | 
			
		||||
		h[fieldExtBoolCount]%2 + // account for word align
 | 
			
		||||
		h[fieldExtNumCount]*(numWidth/8) +
 | 
			
		||||
		h[fieldExtOffsetCount]*2 +
 | 
			
		||||
		h[fieldExtTableSize]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// findNull finds the position of null in buf.
 | 
			
		||||
func findNull(buf []byte, i int) int {
 | 
			
		||||
	for ; i < len(buf); i++ {
 | 
			
		||||
		if buf[i] == 0 {
 | 
			
		||||
			return i
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return -1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readStrings decodes n strings from string data table buf using the indexes in idx.
 | 
			
		||||
func readStrings(idx []int, buf []byte, n int) (map[int][]byte, int, error) {
 | 
			
		||||
	var last int
 | 
			
		||||
	m := make(map[int][]byte)
 | 
			
		||||
	for i := 0; i < n; i++ {
 | 
			
		||||
		start := idx[i]
 | 
			
		||||
		if start < 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if end := findNull(buf, start); end != -1 {
 | 
			
		||||
			m[i], last = buf[start:end], end+1
 | 
			
		||||
		} else {
 | 
			
		||||
			return nil, 0, ErrInvalidStringTable
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return m, last, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decoder holds state info while decoding a terminfo file.
 | 
			
		||||
type decoder struct {
 | 
			
		||||
	buf []byte
 | 
			
		||||
	pos int
 | 
			
		||||
	n   int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readBytes reads the next n bytes of buf, incrementing pos by n.
 | 
			
		||||
func (d *decoder) readBytes(n int) ([]byte, error) {
 | 
			
		||||
	if d.n < d.pos+n {
 | 
			
		||||
		return nil, ErrUnexpectedFileEnd
 | 
			
		||||
	}
 | 
			
		||||
	n, d.pos = d.pos, d.pos+n
 | 
			
		||||
	return d.buf[n:d.pos], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readInts reads n number of ints with width w.
 | 
			
		||||
func (d *decoder) readInts(n, w int) ([]int, error) {
 | 
			
		||||
	w /= 8
 | 
			
		||||
	l := n * w
 | 
			
		||||
	buf, err := d.readBytes(l)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// align
 | 
			
		||||
	d.pos += d.pos % 2
 | 
			
		||||
	z := make([]int, n)
 | 
			
		||||
	for i, j := 0, 0; i < l; i, j = i+w, j+1 {
 | 
			
		||||
		switch w {
 | 
			
		||||
		case 1:
 | 
			
		||||
			z[i] = int(buf[i])
 | 
			
		||||
		case 2:
 | 
			
		||||
			z[j] = int(int16(buf[i+1])<<8 | int16(buf[i]))
 | 
			
		||||
		case 4:
 | 
			
		||||
			z[j] = int(buf[i+3])<<24 | int(buf[i+2])<<16 | int(buf[i+1])<<8 | int(buf[i])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return z, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readBools reads the next n bools.
 | 
			
		||||
func (d *decoder) readBools(n int) (map[int]bool, map[int]bool, error) {
 | 
			
		||||
	buf, err := d.readInts(n, 8)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// process
 | 
			
		||||
	bools, boolsM := make(map[int]bool), make(map[int]bool)
 | 
			
		||||
	for i, b := range buf {
 | 
			
		||||
		bools[i] = b == 1
 | 
			
		||||
		if int8(b) == -2 {
 | 
			
		||||
			boolsM[i] = true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return bools, boolsM, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readNums reads the next n nums.
 | 
			
		||||
func (d *decoder) readNums(n, w int) (map[int]int, map[int]bool, error) {
 | 
			
		||||
	buf, err := d.readInts(n, w)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// process
 | 
			
		||||
	nums, numsM := make(map[int]int), make(map[int]bool)
 | 
			
		||||
	for i := 0; i < n; i++ {
 | 
			
		||||
		nums[i] = buf[i]
 | 
			
		||||
		if buf[i] == -2 {
 | 
			
		||||
			numsM[i] = true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nums, numsM, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readStringTable reads the string data for n strings and the accompanying data
 | 
			
		||||
// table of length sz.
 | 
			
		||||
func (d *decoder) readStringTable(n, sz int) ([][]byte, []int, error) {
 | 
			
		||||
	buf, err := d.readInts(n, 16)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// read string data table
 | 
			
		||||
	data, err := d.readBytes(sz)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// align
 | 
			
		||||
	d.pos += d.pos % 2
 | 
			
		||||
	// process
 | 
			
		||||
	s := make([][]byte, n)
 | 
			
		||||
	var m []int
 | 
			
		||||
	for i := 0; i < n; i++ {
 | 
			
		||||
		start := buf[i]
 | 
			
		||||
		if start == -2 {
 | 
			
		||||
			m = append(m, i)
 | 
			
		||||
		} else if start >= 0 {
 | 
			
		||||
			if end := findNull(data, start); end != -1 {
 | 
			
		||||
				s[i] = data[start:end]
 | 
			
		||||
			} else {
 | 
			
		||||
				return nil, nil, ErrInvalidStringTable
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return s, m, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readStrings reads the next n strings and processes the string data table of
 | 
			
		||||
// length sz.
 | 
			
		||||
func (d *decoder) readStrings(n, sz int) (map[int][]byte, map[int]bool, error) {
 | 
			
		||||
	s, m, err := d.readStringTable(n, sz)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	strs := make(map[int][]byte)
 | 
			
		||||
	for k, v := range s {
 | 
			
		||||
		if k == AcsChars {
 | 
			
		||||
			v = canonicalizeAscChars(v)
 | 
			
		||||
		}
 | 
			
		||||
		strs[k] = v
 | 
			
		||||
	}
 | 
			
		||||
	strsM := make(map[int]bool, len(m))
 | 
			
		||||
	for _, k := range m {
 | 
			
		||||
		strsM[k] = true
 | 
			
		||||
	}
 | 
			
		||||
	return strs, strsM, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// canonicalizeAscChars reorders chars to be unique, in order.
 | 
			
		||||
//
 | 
			
		||||
// see repair_ascc in ncurses-6.3/progs/dump_entry.c
 | 
			
		||||
func canonicalizeAscChars(z []byte) []byte {
 | 
			
		||||
	var c []byte
 | 
			
		||||
	enc := make(map[byte]byte, len(z)/2)
 | 
			
		||||
	for i := 0; i < len(z); i += 2 {
 | 
			
		||||
		if _, ok := enc[z[i]]; !ok {
 | 
			
		||||
			a, b := z[i], z[i+1]
 | 
			
		||||
			// log.Printf(">>> a: %d %c, b: %d %c", a, a, b, b)
 | 
			
		||||
			c, enc[a] = append(c, b), b
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	sort.Slice(c, func(i, j int) bool {
 | 
			
		||||
		return c[i] < c[j]
 | 
			
		||||
	})
 | 
			
		||||
	r := make([]byte, 2*len(c))
 | 
			
		||||
	for i := 0; i < len(c); i++ {
 | 
			
		||||
		r[i*2], r[i*2+1] = c[i], enc[c[i]]
 | 
			
		||||
	}
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										64
									
								
								vendor/github.com/xo/terminfo/load.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								vendor/github.com/xo/terminfo/load.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
package terminfo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/user"
 | 
			
		||||
	"path"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// termCache is the terminfo cache.
 | 
			
		||||
var termCache = struct {
 | 
			
		||||
	db map[string]*Terminfo
 | 
			
		||||
	sync.RWMutex
 | 
			
		||||
}{
 | 
			
		||||
	db: make(map[string]*Terminfo),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Load follows the behavior described in terminfo(5) to find correct the
 | 
			
		||||
// terminfo file using the name, reads the file and then returns a Terminfo
 | 
			
		||||
// struct that describes the file.
 | 
			
		||||
func Load(name string) (*Terminfo, error) {
 | 
			
		||||
	if name == "" {
 | 
			
		||||
		return nil, ErrEmptyTermName
 | 
			
		||||
	}
 | 
			
		||||
	termCache.RLock()
 | 
			
		||||
	ti, ok := termCache.db[name]
 | 
			
		||||
	termCache.RUnlock()
 | 
			
		||||
	if ok {
 | 
			
		||||
		return ti, nil
 | 
			
		||||
	}
 | 
			
		||||
	var checkDirs []string
 | 
			
		||||
	// check $TERMINFO
 | 
			
		||||
	if dir := os.Getenv("TERMINFO"); dir != "" {
 | 
			
		||||
		checkDirs = append(checkDirs, dir)
 | 
			
		||||
	}
 | 
			
		||||
	// check $HOME/.terminfo
 | 
			
		||||
	u, err := user.Current()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	checkDirs = append(checkDirs, path.Join(u.HomeDir, ".terminfo"))
 | 
			
		||||
	// check $TERMINFO_DIRS
 | 
			
		||||
	if dirs := os.Getenv("TERMINFO_DIRS"); dirs != "" {
 | 
			
		||||
		checkDirs = append(checkDirs, strings.Split(dirs, ":")...)
 | 
			
		||||
	}
 | 
			
		||||
	// check fallback directories
 | 
			
		||||
	checkDirs = append(checkDirs, "/etc/terminfo", "/lib/terminfo", "/usr/share/terminfo")
 | 
			
		||||
	for _, dir := range checkDirs {
 | 
			
		||||
		ti, err = Open(dir, name)
 | 
			
		||||
		if err != nil && err != ErrFileNotFound && !os.IsNotExist(err) {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		} else if err == nil {
 | 
			
		||||
			return ti, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil, ErrDatabaseDirectoryNotFound
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadFromEnv loads the terminal info based on the name contained in
 | 
			
		||||
// environment variable TERM.
 | 
			
		||||
func LoadFromEnv() (*Terminfo, error) {
 | 
			
		||||
	return Load(os.Getenv("TERM"))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										405
									
								
								vendor/github.com/xo/terminfo/param.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										405
									
								
								vendor/github.com/xo/terminfo/param.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,405 @@
 | 
			
		||||
package terminfo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// parametizer represents the a scan state for a parameterized string.
 | 
			
		||||
type parametizer struct {
 | 
			
		||||
	// z is the string to parameterize
 | 
			
		||||
	z []byte
 | 
			
		||||
	// pos is the current position in s.
 | 
			
		||||
	pos int
 | 
			
		||||
	// nest is the current nest level.
 | 
			
		||||
	nest int
 | 
			
		||||
	// s is the variable stack.
 | 
			
		||||
	s stack
 | 
			
		||||
	// skipElse keeps the state of skipping else.
 | 
			
		||||
	skipElse bool
 | 
			
		||||
	// buf is the result buffer.
 | 
			
		||||
	buf *bytes.Buffer
 | 
			
		||||
	// params are the parameters to interpolate.
 | 
			
		||||
	params [9]interface{}
 | 
			
		||||
	// vars are dynamic variables.
 | 
			
		||||
	vars [26]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// staticVars are the static, global variables.
 | 
			
		||||
var staticVars = struct {
 | 
			
		||||
	vars [26]interface{}
 | 
			
		||||
	sync.Mutex
 | 
			
		||||
}{}
 | 
			
		||||
 | 
			
		||||
var parametizerPool = sync.Pool{
 | 
			
		||||
	New: func() interface{} {
 | 
			
		||||
		p := new(parametizer)
 | 
			
		||||
		p.buf = bytes.NewBuffer(make([]byte, 0, 45))
 | 
			
		||||
		return p
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newParametizer returns a new initialized parametizer from the pool.
 | 
			
		||||
func newParametizer(z []byte) *parametizer {
 | 
			
		||||
	p := parametizerPool.Get().(*parametizer)
 | 
			
		||||
	p.z = z
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// reset resets the parametizer.
 | 
			
		||||
func (p *parametizer) reset() {
 | 
			
		||||
	p.pos, p.nest = 0, 0
 | 
			
		||||
	p.s.reset()
 | 
			
		||||
	p.buf.Reset()
 | 
			
		||||
	p.params, p.vars = [9]interface{}{}, [26]interface{}{}
 | 
			
		||||
	parametizerPool.Put(p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateFn represents the state of the scanner as a function that returns the
 | 
			
		||||
// next state.
 | 
			
		||||
type stateFn func() stateFn
 | 
			
		||||
 | 
			
		||||
// exec executes the parameterizer, interpolating the supplied parameters.
 | 
			
		||||
func (p *parametizer) exec() string {
 | 
			
		||||
	for state := p.scanTextFn; state != nil; {
 | 
			
		||||
		state = state()
 | 
			
		||||
	}
 | 
			
		||||
	return p.buf.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// peek returns the next byte.
 | 
			
		||||
func (p *parametizer) peek() (byte, error) {
 | 
			
		||||
	if p.pos >= len(p.z) {
 | 
			
		||||
		return 0, io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	return p.z[p.pos], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// writeFrom writes the characters from ppos to pos to the buffer.
 | 
			
		||||
func (p *parametizer) writeFrom(ppos int) {
 | 
			
		||||
	if p.pos > ppos {
 | 
			
		||||
		// append remaining characters.
 | 
			
		||||
		p.buf.Write(p.z[ppos:p.pos])
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parametizer) scanTextFn() stateFn {
 | 
			
		||||
	ppos := p.pos
 | 
			
		||||
	for {
 | 
			
		||||
		ch, err := p.peek()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			p.writeFrom(ppos)
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		if ch == '%' {
 | 
			
		||||
			p.writeFrom(ppos)
 | 
			
		||||
			p.pos++
 | 
			
		||||
			return p.scanCodeFn
 | 
			
		||||
		}
 | 
			
		||||
		p.pos++
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parametizer) scanCodeFn() stateFn {
 | 
			
		||||
	ch, err := p.peek()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	switch ch {
 | 
			
		||||
	case '%':
 | 
			
		||||
		p.buf.WriteByte('%')
 | 
			
		||||
	case ':':
 | 
			
		||||
		// this character is used to avoid interpreting "%-" and "%+" as operators.
 | 
			
		||||
		// the next character is where the format really begins.
 | 
			
		||||
		p.pos++
 | 
			
		||||
		_, err = p.peek()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		return p.scanFormatFn
 | 
			
		||||
	case '#', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.':
 | 
			
		||||
		return p.scanFormatFn
 | 
			
		||||
	case 'o':
 | 
			
		||||
		p.buf.WriteString(strconv.FormatInt(int64(p.s.popInt()), 8))
 | 
			
		||||
	case 'd':
 | 
			
		||||
		p.buf.WriteString(strconv.Itoa(p.s.popInt()))
 | 
			
		||||
	case 'x':
 | 
			
		||||
		p.buf.WriteString(strconv.FormatInt(int64(p.s.popInt()), 16))
 | 
			
		||||
	case 'X':
 | 
			
		||||
		p.buf.WriteString(strings.ToUpper(strconv.FormatInt(int64(p.s.popInt()), 16)))
 | 
			
		||||
	case 's':
 | 
			
		||||
		p.buf.WriteString(p.s.popString())
 | 
			
		||||
	case 'c':
 | 
			
		||||
		p.buf.WriteByte(p.s.popByte())
 | 
			
		||||
	case 'p':
 | 
			
		||||
		p.pos++
 | 
			
		||||
		return p.pushParamFn
 | 
			
		||||
	case 'P':
 | 
			
		||||
		p.pos++
 | 
			
		||||
		return p.setDsVarFn
 | 
			
		||||
	case 'g':
 | 
			
		||||
		p.pos++
 | 
			
		||||
		return p.getDsVarFn
 | 
			
		||||
	case '\'':
 | 
			
		||||
		p.pos++
 | 
			
		||||
		ch, err = p.peek()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		p.s.push(ch)
 | 
			
		||||
		// skip the '\''
 | 
			
		||||
		p.pos++
 | 
			
		||||
	case '{':
 | 
			
		||||
		p.pos++
 | 
			
		||||
		return p.pushIntfn
 | 
			
		||||
	case 'l':
 | 
			
		||||
		p.s.push(len(p.s.popString()))
 | 
			
		||||
	case '+':
 | 
			
		||||
		bi, ai := p.s.popInt(), p.s.popInt()
 | 
			
		||||
		p.s.push(ai + bi)
 | 
			
		||||
	case '-':
 | 
			
		||||
		bi, ai := p.s.popInt(), p.s.popInt()
 | 
			
		||||
		p.s.push(ai - bi)
 | 
			
		||||
	case '*':
 | 
			
		||||
		bi, ai := p.s.popInt(), p.s.popInt()
 | 
			
		||||
		p.s.push(ai * bi)
 | 
			
		||||
	case '/':
 | 
			
		||||
		bi, ai := p.s.popInt(), p.s.popInt()
 | 
			
		||||
		if bi != 0 {
 | 
			
		||||
			p.s.push(ai / bi)
 | 
			
		||||
		} else {
 | 
			
		||||
			p.s.push(0)
 | 
			
		||||
		}
 | 
			
		||||
	case 'm':
 | 
			
		||||
		bi, ai := p.s.popInt(), p.s.popInt()
 | 
			
		||||
		if bi != 0 {
 | 
			
		||||
			p.s.push(ai % bi)
 | 
			
		||||
		} else {
 | 
			
		||||
			p.s.push(0)
 | 
			
		||||
		}
 | 
			
		||||
	case '&':
 | 
			
		||||
		bi, ai := p.s.popInt(), p.s.popInt()
 | 
			
		||||
		p.s.push(ai & bi)
 | 
			
		||||
	case '|':
 | 
			
		||||
		bi, ai := p.s.popInt(), p.s.popInt()
 | 
			
		||||
		p.s.push(ai | bi)
 | 
			
		||||
	case '^':
 | 
			
		||||
		bi, ai := p.s.popInt(), p.s.popInt()
 | 
			
		||||
		p.s.push(ai ^ bi)
 | 
			
		||||
	case '=':
 | 
			
		||||
		bi, ai := p.s.popInt(), p.s.popInt()
 | 
			
		||||
		p.s.push(ai == bi)
 | 
			
		||||
	case '>':
 | 
			
		||||
		bi, ai := p.s.popInt(), p.s.popInt()
 | 
			
		||||
		p.s.push(ai > bi)
 | 
			
		||||
	case '<':
 | 
			
		||||
		bi, ai := p.s.popInt(), p.s.popInt()
 | 
			
		||||
		p.s.push(ai < bi)
 | 
			
		||||
	case 'A':
 | 
			
		||||
		bi, ai := p.s.popBool(), p.s.popBool()
 | 
			
		||||
		p.s.push(ai && bi)
 | 
			
		||||
	case 'O':
 | 
			
		||||
		bi, ai := p.s.popBool(), p.s.popBool()
 | 
			
		||||
		p.s.push(ai || bi)
 | 
			
		||||
	case '!':
 | 
			
		||||
		p.s.push(!p.s.popBool())
 | 
			
		||||
	case '~':
 | 
			
		||||
		p.s.push(^p.s.popInt())
 | 
			
		||||
	case 'i':
 | 
			
		||||
		for i := range p.params[:2] {
 | 
			
		||||
			if n, ok := p.params[i].(int); ok {
 | 
			
		||||
				p.params[i] = n + 1
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	case '?', ';':
 | 
			
		||||
	case 't':
 | 
			
		||||
		return p.scanThenFn
 | 
			
		||||
	case 'e':
 | 
			
		||||
		p.skipElse = true
 | 
			
		||||
		return p.skipTextFn
 | 
			
		||||
	}
 | 
			
		||||
	p.pos++
 | 
			
		||||
	return p.scanTextFn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parametizer) scanFormatFn() stateFn {
 | 
			
		||||
	// the character was already read, so no need to check the error.
 | 
			
		||||
	ch, _ := p.peek()
 | 
			
		||||
	// 6 should be the maximum length of a format string, for example "%:-9.9d".
 | 
			
		||||
	f := []byte{'%', ch, 0, 0, 0, 0}
 | 
			
		||||
	var err error
 | 
			
		||||
	for {
 | 
			
		||||
		p.pos++
 | 
			
		||||
		ch, err = p.peek()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		f = append(f, ch)
 | 
			
		||||
		switch ch {
 | 
			
		||||
		case 'o', 'd', 'x', 'X':
 | 
			
		||||
			fmt.Fprintf(p.buf, string(f), p.s.popInt())
 | 
			
		||||
			break
 | 
			
		||||
		case 's':
 | 
			
		||||
			fmt.Fprintf(p.buf, string(f), p.s.popString())
 | 
			
		||||
			break
 | 
			
		||||
		case 'c':
 | 
			
		||||
			fmt.Fprintf(p.buf, string(f), p.s.popByte())
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	p.pos++
 | 
			
		||||
	return p.scanTextFn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parametizer) pushParamFn() stateFn {
 | 
			
		||||
	ch, err := p.peek()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if ai := int(ch - '1'); ai >= 0 && ai < len(p.params) {
 | 
			
		||||
		p.s.push(p.params[ai])
 | 
			
		||||
	} else {
 | 
			
		||||
		p.s.push(0)
 | 
			
		||||
	}
 | 
			
		||||
	// skip the '}'
 | 
			
		||||
	p.pos++
 | 
			
		||||
	return p.scanTextFn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parametizer) setDsVarFn() stateFn {
 | 
			
		||||
	ch, err := p.peek()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if ch >= 'A' && ch <= 'Z' {
 | 
			
		||||
		staticVars.Lock()
 | 
			
		||||
		staticVars.vars[int(ch-'A')] = p.s.pop()
 | 
			
		||||
		staticVars.Unlock()
 | 
			
		||||
	} else if ch >= 'a' && ch <= 'z' {
 | 
			
		||||
		p.vars[int(ch-'a')] = p.s.pop()
 | 
			
		||||
	}
 | 
			
		||||
	p.pos++
 | 
			
		||||
	return p.scanTextFn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parametizer) getDsVarFn() stateFn {
 | 
			
		||||
	ch, err := p.peek()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	var a byte
 | 
			
		||||
	if ch >= 'A' && ch <= 'Z' {
 | 
			
		||||
		a = 'A'
 | 
			
		||||
	} else if ch >= 'a' && ch <= 'z' {
 | 
			
		||||
		a = 'a'
 | 
			
		||||
	}
 | 
			
		||||
	staticVars.Lock()
 | 
			
		||||
	p.s.push(staticVars.vars[int(ch-a)])
 | 
			
		||||
	staticVars.Unlock()
 | 
			
		||||
	p.pos++
 | 
			
		||||
	return p.scanTextFn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parametizer) pushIntfn() stateFn {
 | 
			
		||||
	var ai int
 | 
			
		||||
	for {
 | 
			
		||||
		ch, err := p.peek()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		p.pos++
 | 
			
		||||
		if ch < '0' || ch > '9' {
 | 
			
		||||
			p.s.push(ai)
 | 
			
		||||
			return p.scanTextFn
 | 
			
		||||
		}
 | 
			
		||||
		ai = (ai * 10) + int(ch-'0')
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parametizer) scanThenFn() stateFn {
 | 
			
		||||
	p.pos++
 | 
			
		||||
	if p.s.popBool() {
 | 
			
		||||
		return p.scanTextFn
 | 
			
		||||
	}
 | 
			
		||||
	p.skipElse = false
 | 
			
		||||
	return p.skipTextFn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parametizer) skipTextFn() stateFn {
 | 
			
		||||
	for {
 | 
			
		||||
		ch, err := p.peek()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		p.pos++
 | 
			
		||||
		if ch == '%' {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if p.skipElse {
 | 
			
		||||
		return p.skipElseFn
 | 
			
		||||
	}
 | 
			
		||||
	return p.skipThenFn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parametizer) skipThenFn() stateFn {
 | 
			
		||||
	ch, err := p.peek()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	p.pos++
 | 
			
		||||
	switch ch {
 | 
			
		||||
	case ';':
 | 
			
		||||
		if p.nest == 0 {
 | 
			
		||||
			return p.scanTextFn
 | 
			
		||||
		}
 | 
			
		||||
		p.nest--
 | 
			
		||||
	case '?':
 | 
			
		||||
		p.nest++
 | 
			
		||||
	case 'e':
 | 
			
		||||
		if p.nest == 0 {
 | 
			
		||||
			return p.scanTextFn
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return p.skipTextFn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *parametizer) skipElseFn() stateFn {
 | 
			
		||||
	ch, err := p.peek()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	p.pos++
 | 
			
		||||
	switch ch {
 | 
			
		||||
	case ';':
 | 
			
		||||
		if p.nest == 0 {
 | 
			
		||||
			return p.scanTextFn
 | 
			
		||||
		}
 | 
			
		||||
		p.nest--
 | 
			
		||||
	case '?':
 | 
			
		||||
		p.nest++
 | 
			
		||||
	}
 | 
			
		||||
	return p.skipTextFn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Printf evaluates a parameterized terminfo value z, interpolating params.
 | 
			
		||||
func Printf(z []byte, params ...interface{}) string {
 | 
			
		||||
	p := newParametizer(z)
 | 
			
		||||
	defer p.reset()
 | 
			
		||||
	// make sure we always have 9 parameters -- makes it easier
 | 
			
		||||
	// later to skip checks and its faster
 | 
			
		||||
	for i := 0; i < len(p.params) && i < len(params); i++ {
 | 
			
		||||
		p.params[i] = params[i]
 | 
			
		||||
	}
 | 
			
		||||
	return p.exec()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Fprintf evaluates a parameterized terminfo value z, interpolating params and
 | 
			
		||||
// writing to w.
 | 
			
		||||
func Fprintf(w io.Writer, z []byte, params ...interface{}) {
 | 
			
		||||
	w.Write([]byte(Printf(z, params...)))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								vendor/github.com/xo/terminfo/stack.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/xo/terminfo/stack.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
package terminfo
 | 
			
		||||
 | 
			
		||||
type stack []interface{}
 | 
			
		||||
 | 
			
		||||
func (s *stack) push(v interface{}) {
 | 
			
		||||
	*s = append(*s, v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stack) pop() interface{} {
 | 
			
		||||
	if len(*s) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	v := (*s)[len(*s)-1]
 | 
			
		||||
	*s = (*s)[:len(*s)-1]
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stack) popInt() int {
 | 
			
		||||
	if i, ok := s.pop().(int); ok {
 | 
			
		||||
		return i
 | 
			
		||||
	}
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stack) popBool() bool {
 | 
			
		||||
	if b, ok := s.pop().(bool); ok {
 | 
			
		||||
		return b
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stack) popByte() byte {
 | 
			
		||||
	if b, ok := s.pop().(byte); ok {
 | 
			
		||||
		return b
 | 
			
		||||
	}
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stack) popString() string {
 | 
			
		||||
	if a, ok := s.pop().(string); ok {
 | 
			
		||||
		return a
 | 
			
		||||
	}
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stack) reset() {
 | 
			
		||||
	*s = (*s)[:0]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										479
									
								
								vendor/github.com/xo/terminfo/terminfo.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										479
									
								
								vendor/github.com/xo/terminfo/terminfo.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,479 @@
 | 
			
		||||
// Package terminfo implements reading terminfo files in pure go.
 | 
			
		||||
package terminfo
 | 
			
		||||
 | 
			
		||||
//go:generate go run gen.go
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"path"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Error is a terminfo error.
 | 
			
		||||
type Error string
 | 
			
		||||
 | 
			
		||||
// Error satisfies the error interface.
 | 
			
		||||
func (err Error) Error() string {
 | 
			
		||||
	return string(err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// ErrInvalidFileSize is the invalid file size error.
 | 
			
		||||
	ErrInvalidFileSize Error = "invalid file size"
 | 
			
		||||
	// ErrUnexpectedFileEnd is the unexpected file end error.
 | 
			
		||||
	ErrUnexpectedFileEnd Error = "unexpected file end"
 | 
			
		||||
	// ErrInvalidStringTable is the invalid string table error.
 | 
			
		||||
	ErrInvalidStringTable Error = "invalid string table"
 | 
			
		||||
	// ErrInvalidMagic is the invalid magic error.
 | 
			
		||||
	ErrInvalidMagic Error = "invalid magic"
 | 
			
		||||
	// ErrInvalidHeader is the invalid header error.
 | 
			
		||||
	ErrInvalidHeader Error = "invalid header"
 | 
			
		||||
	// ErrInvalidNames is the invalid names error.
 | 
			
		||||
	ErrInvalidNames Error = "invalid names"
 | 
			
		||||
	// ErrInvalidExtendedHeader is the invalid extended header error.
 | 
			
		||||
	ErrInvalidExtendedHeader Error = "invalid extended header"
 | 
			
		||||
	// ErrEmptyTermName is the empty term name error.
 | 
			
		||||
	ErrEmptyTermName Error = "empty term name"
 | 
			
		||||
	// ErrDatabaseDirectoryNotFound is the database directory not found error.
 | 
			
		||||
	ErrDatabaseDirectoryNotFound Error = "database directory not found"
 | 
			
		||||
	// ErrFileNotFound is the file not found error.
 | 
			
		||||
	ErrFileNotFound Error = "file not found"
 | 
			
		||||
	// ErrInvalidTermProgramVersion is the invalid TERM_PROGRAM_VERSION error.
 | 
			
		||||
	ErrInvalidTermProgramVersion Error = "invalid TERM_PROGRAM_VERSION"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Terminfo describes a terminal's capabilities.
 | 
			
		||||
type Terminfo struct {
 | 
			
		||||
	// File is the original source file.
 | 
			
		||||
	File string
 | 
			
		||||
	// Names are the provided cap names.
 | 
			
		||||
	Names []string
 | 
			
		||||
	// Bools are the bool capabilities.
 | 
			
		||||
	Bools map[int]bool
 | 
			
		||||
	// BoolsM are the missing bool capabilities.
 | 
			
		||||
	BoolsM map[int]bool
 | 
			
		||||
	// Nums are the num capabilities.
 | 
			
		||||
	Nums map[int]int
 | 
			
		||||
	// NumsM are the missing num capabilities.
 | 
			
		||||
	NumsM map[int]bool
 | 
			
		||||
	// Strings are the string capabilities.
 | 
			
		||||
	Strings map[int][]byte
 | 
			
		||||
	// StringsM are the missing string capabilities.
 | 
			
		||||
	StringsM map[int]bool
 | 
			
		||||
	// ExtBools are the extended bool capabilities.
 | 
			
		||||
	ExtBools map[int]bool
 | 
			
		||||
	// ExtBoolsNames is the map of extended bool capabilities to their index.
 | 
			
		||||
	ExtBoolNames map[int][]byte
 | 
			
		||||
	// ExtNums are the extended num capabilities.
 | 
			
		||||
	ExtNums map[int]int
 | 
			
		||||
	// ExtNumsNames is the map of extended num capabilities to their index.
 | 
			
		||||
	ExtNumNames map[int][]byte
 | 
			
		||||
	// ExtStrings are the extended string capabilities.
 | 
			
		||||
	ExtStrings map[int][]byte
 | 
			
		||||
	// ExtStringsNames is the map of extended string capabilities to their index.
 | 
			
		||||
	ExtStringNames map[int][]byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode decodes the terminfo data contained in buf.
 | 
			
		||||
func Decode(buf []byte) (*Terminfo, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	// check max file length
 | 
			
		||||
	if len(buf) >= maxFileLength {
 | 
			
		||||
		return nil, ErrInvalidFileSize
 | 
			
		||||
	}
 | 
			
		||||
	d := &decoder{
 | 
			
		||||
		buf: buf,
 | 
			
		||||
		n:   len(buf),
 | 
			
		||||
	}
 | 
			
		||||
	// read header
 | 
			
		||||
	h, err := d.readInts(6, 16)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	var numWidth int
 | 
			
		||||
	// check magic
 | 
			
		||||
	switch {
 | 
			
		||||
	case h[fieldMagic] == magic:
 | 
			
		||||
		numWidth = 16
 | 
			
		||||
	case h[fieldMagic] == magicExtended:
 | 
			
		||||
		numWidth = 32
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, ErrInvalidMagic
 | 
			
		||||
	}
 | 
			
		||||
	// check header
 | 
			
		||||
	if hasInvalidCaps(h) {
 | 
			
		||||
		return nil, ErrInvalidHeader
 | 
			
		||||
	}
 | 
			
		||||
	// check remaining length
 | 
			
		||||
	if d.n-d.pos < capLength(h) {
 | 
			
		||||
		return nil, ErrUnexpectedFileEnd
 | 
			
		||||
	}
 | 
			
		||||
	// read names
 | 
			
		||||
	names, err := d.readBytes(h[fieldNameSize])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// check name is terminated properly
 | 
			
		||||
	i := findNull(names, 0)
 | 
			
		||||
	if i == -1 {
 | 
			
		||||
		return nil, ErrInvalidNames
 | 
			
		||||
	}
 | 
			
		||||
	names = names[:i]
 | 
			
		||||
	// read bool caps
 | 
			
		||||
	bools, boolsM, err := d.readBools(h[fieldBoolCount])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// read num caps
 | 
			
		||||
	nums, numsM, err := d.readNums(h[fieldNumCount], numWidth)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// read string caps
 | 
			
		||||
	strs, strsM, err := d.readStrings(h[fieldStringCount], h[fieldTableSize])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	ti := &Terminfo{
 | 
			
		||||
		Names:    strings.Split(string(names), "|"),
 | 
			
		||||
		Bools:    bools,
 | 
			
		||||
		BoolsM:   boolsM,
 | 
			
		||||
		Nums:     nums,
 | 
			
		||||
		NumsM:    numsM,
 | 
			
		||||
		Strings:  strs,
 | 
			
		||||
		StringsM: strsM,
 | 
			
		||||
	}
 | 
			
		||||
	// at the end of file, so no extended caps
 | 
			
		||||
	if d.pos >= d.n {
 | 
			
		||||
		return ti, nil
 | 
			
		||||
	}
 | 
			
		||||
	// decode extended header
 | 
			
		||||
	eh, err := d.readInts(5, 16)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// check extended offset field
 | 
			
		||||
	if hasInvalidExtOffset(eh) {
 | 
			
		||||
		return nil, ErrInvalidExtendedHeader
 | 
			
		||||
	}
 | 
			
		||||
	// check extended cap lengths
 | 
			
		||||
	if d.n-d.pos != extCapLength(eh, numWidth) {
 | 
			
		||||
		return nil, ErrInvalidExtendedHeader
 | 
			
		||||
	}
 | 
			
		||||
	// read extended bool caps
 | 
			
		||||
	ti.ExtBools, _, err = d.readBools(eh[fieldExtBoolCount])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// read extended num caps
 | 
			
		||||
	ti.ExtNums, _, err = d.readNums(eh[fieldExtNumCount], numWidth)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// read extended string data table indexes
 | 
			
		||||
	extIndexes, err := d.readInts(eh[fieldExtOffsetCount], 16)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// read string data table
 | 
			
		||||
	extData, err := d.readBytes(eh[fieldExtTableSize])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// precautionary check that exactly at end of file
 | 
			
		||||
	if d.pos != d.n {
 | 
			
		||||
		return nil, ErrUnexpectedFileEnd
 | 
			
		||||
	}
 | 
			
		||||
	var last int
 | 
			
		||||
	// read extended string caps
 | 
			
		||||
	ti.ExtStrings, last, err = readStrings(extIndexes, extData, eh[fieldExtStringCount])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	extIndexes, extData = extIndexes[eh[fieldExtStringCount]:], extData[last:]
 | 
			
		||||
	// read extended bool names
 | 
			
		||||
	ti.ExtBoolNames, _, err = readStrings(extIndexes, extData, eh[fieldExtBoolCount])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	extIndexes = extIndexes[eh[fieldExtBoolCount]:]
 | 
			
		||||
	// read extended num names
 | 
			
		||||
	ti.ExtNumNames, _, err = readStrings(extIndexes, extData, eh[fieldExtNumCount])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	extIndexes = extIndexes[eh[fieldExtNumCount]:]
 | 
			
		||||
	// read extended string names
 | 
			
		||||
	ti.ExtStringNames, _, err = readStrings(extIndexes, extData, eh[fieldExtStringCount])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// extIndexes = extIndexes[eh[fieldExtStringCount]:]
 | 
			
		||||
	return ti, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Open reads the terminfo file name from the specified directory dir.
 | 
			
		||||
func Open(dir, name string) (*Terminfo, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	var buf []byte
 | 
			
		||||
	var filename string
 | 
			
		||||
	for _, f := range []string{
 | 
			
		||||
		path.Join(dir, name[0:1], name),
 | 
			
		||||
		path.Join(dir, strconv.FormatUint(uint64(name[0]), 16), name),
 | 
			
		||||
	} {
 | 
			
		||||
		buf, err = ioutil.ReadFile(f)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			filename = f
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if buf == nil {
 | 
			
		||||
		return nil, ErrFileNotFound
 | 
			
		||||
	}
 | 
			
		||||
	// decode
 | 
			
		||||
	ti, err := Decode(buf)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// save original file name
 | 
			
		||||
	ti.File = filename
 | 
			
		||||
	// add to cache
 | 
			
		||||
	termCache.Lock()
 | 
			
		||||
	for _, n := range ti.Names {
 | 
			
		||||
		termCache.db[n] = ti
 | 
			
		||||
	}
 | 
			
		||||
	termCache.Unlock()
 | 
			
		||||
	return ti, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// boolCaps returns all bool and extended capabilities using f to format the
 | 
			
		||||
// index key.
 | 
			
		||||
func (ti *Terminfo) boolCaps(f func(int) string, extended bool) map[string]bool {
 | 
			
		||||
	m := make(map[string]bool, len(ti.Bools)+len(ti.ExtBools))
 | 
			
		||||
	if !extended {
 | 
			
		||||
		for k, v := range ti.Bools {
 | 
			
		||||
			m[f(k)] = v
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		for k, v := range ti.ExtBools {
 | 
			
		||||
			m[string(ti.ExtBoolNames[k])] = v
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return m
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BoolCaps returns all bool capabilities.
 | 
			
		||||
func (ti *Terminfo) BoolCaps() map[string]bool {
 | 
			
		||||
	return ti.boolCaps(BoolCapName, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BoolCapsShort returns all bool capabilities, using the short name as the
 | 
			
		||||
// index.
 | 
			
		||||
func (ti *Terminfo) BoolCapsShort() map[string]bool {
 | 
			
		||||
	return ti.boolCaps(BoolCapNameShort, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtBoolCaps returns all extended bool capabilities.
 | 
			
		||||
func (ti *Terminfo) ExtBoolCaps() map[string]bool {
 | 
			
		||||
	return ti.boolCaps(BoolCapName, true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtBoolCapsShort returns all extended bool capabilities, using the short
 | 
			
		||||
// name as the index.
 | 
			
		||||
func (ti *Terminfo) ExtBoolCapsShort() map[string]bool {
 | 
			
		||||
	return ti.boolCaps(BoolCapNameShort, true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// numCaps returns all num and extended capabilities using f to format the
 | 
			
		||||
// index key.
 | 
			
		||||
func (ti *Terminfo) numCaps(f func(int) string, extended bool) map[string]int {
 | 
			
		||||
	m := make(map[string]int, len(ti.Nums)+len(ti.ExtNums))
 | 
			
		||||
	if !extended {
 | 
			
		||||
		for k, v := range ti.Nums {
 | 
			
		||||
			m[f(k)] = v
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		for k, v := range ti.ExtNums {
 | 
			
		||||
			m[string(ti.ExtNumNames[k])] = v
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return m
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NumCaps returns all num capabilities.
 | 
			
		||||
func (ti *Terminfo) NumCaps() map[string]int {
 | 
			
		||||
	return ti.numCaps(NumCapName, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NumCapsShort returns all num capabilities, using the short name as the
 | 
			
		||||
// index.
 | 
			
		||||
func (ti *Terminfo) NumCapsShort() map[string]int {
 | 
			
		||||
	return ti.numCaps(NumCapNameShort, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtNumCaps returns all extended num capabilities.
 | 
			
		||||
func (ti *Terminfo) ExtNumCaps() map[string]int {
 | 
			
		||||
	return ti.numCaps(NumCapName, true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtNumCapsShort returns all extended num capabilities, using the short
 | 
			
		||||
// name as the index.
 | 
			
		||||
func (ti *Terminfo) ExtNumCapsShort() map[string]int {
 | 
			
		||||
	return ti.numCaps(NumCapNameShort, true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stringCaps returns all string and extended capabilities using f to format the
 | 
			
		||||
// index key.
 | 
			
		||||
func (ti *Terminfo) stringCaps(f func(int) string, extended bool) map[string][]byte {
 | 
			
		||||
	m := make(map[string][]byte, len(ti.Strings)+len(ti.ExtStrings))
 | 
			
		||||
	if !extended {
 | 
			
		||||
		for k, v := range ti.Strings {
 | 
			
		||||
			m[f(k)] = v
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		for k, v := range ti.ExtStrings {
 | 
			
		||||
			m[string(ti.ExtStringNames[k])] = v
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return m
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringCaps returns all string capabilities.
 | 
			
		||||
func (ti *Terminfo) StringCaps() map[string][]byte {
 | 
			
		||||
	return ti.stringCaps(StringCapName, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringCapsShort returns all string capabilities, using the short name as the
 | 
			
		||||
// index.
 | 
			
		||||
func (ti *Terminfo) StringCapsShort() map[string][]byte {
 | 
			
		||||
	return ti.stringCaps(StringCapNameShort, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtStringCaps returns all extended string capabilities.
 | 
			
		||||
func (ti *Terminfo) ExtStringCaps() map[string][]byte {
 | 
			
		||||
	return ti.stringCaps(StringCapName, true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtStringCapsShort returns all extended string capabilities, using the short
 | 
			
		||||
// name as the index.
 | 
			
		||||
func (ti *Terminfo) ExtStringCapsShort() map[string][]byte {
 | 
			
		||||
	return ti.stringCaps(StringCapNameShort, true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Has determines if the bool cap i is present.
 | 
			
		||||
func (ti *Terminfo) Has(i int) bool {
 | 
			
		||||
	return ti.Bools[i]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Num returns the num cap i, or -1 if not present.
 | 
			
		||||
func (ti *Terminfo) Num(i int) int {
 | 
			
		||||
	n, ok := ti.Nums[i]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return -1
 | 
			
		||||
	}
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Printf formats the string cap i, interpolating parameters v.
 | 
			
		||||
func (ti *Terminfo) Printf(i int, v ...interface{}) string {
 | 
			
		||||
	return Printf(ti.Strings[i], v...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Fprintf prints the string cap i to writer w, interpolating parameters v.
 | 
			
		||||
func (ti *Terminfo) Fprintf(w io.Writer, i int, v ...interface{}) {
 | 
			
		||||
	Fprintf(w, ti.Strings[i], v...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Color takes a foreground and background color and returns string that sets
 | 
			
		||||
// them for this terminal.
 | 
			
		||||
func (ti *Terminfo) Colorf(fg, bg int, str string) string {
 | 
			
		||||
	maxColors := int(ti.Nums[MaxColors])
 | 
			
		||||
	// map bright colors to lower versions if the color table only holds 8.
 | 
			
		||||
	if maxColors == 8 {
 | 
			
		||||
		if fg > 7 && fg < 16 {
 | 
			
		||||
			fg -= 8
 | 
			
		||||
		}
 | 
			
		||||
		if bg > 7 && bg < 16 {
 | 
			
		||||
			bg -= 8
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	var s string
 | 
			
		||||
	if maxColors > fg && fg >= 0 {
 | 
			
		||||
		s += ti.Printf(SetAForeground, fg)
 | 
			
		||||
	}
 | 
			
		||||
	if maxColors > bg && bg >= 0 {
 | 
			
		||||
		s += ti.Printf(SetABackground, bg)
 | 
			
		||||
	}
 | 
			
		||||
	return s + str + ti.Printf(ExitAttributeMode)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Goto returns a string suitable for addressing the cursor at the given
 | 
			
		||||
// row and column. The origin 0, 0 is in the upper left corner of the screen.
 | 
			
		||||
func (ti *Terminfo) Goto(row, col int) string {
 | 
			
		||||
	return Printf(ti.Strings[CursorAddress], row, col)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Puts emits the string to the writer, but expands inline padding indications
 | 
			
		||||
// (of the form $<[delay]> where [delay] is msec) to a suitable number of
 | 
			
		||||
// padding characters (usually null bytes) based upon the supplied baud. At
 | 
			
		||||
// high baud rates, more padding characters will be inserted.
 | 
			
		||||
/*func (ti *Terminfo) Puts(w io.Writer, s string, lines, baud int) (int, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	for {
 | 
			
		||||
		start := strings.Index(s, "$<")
 | 
			
		||||
		if start == -1 {
 | 
			
		||||
			// most strings don't need padding, which is good news!
 | 
			
		||||
			return io.WriteString(w, s)
 | 
			
		||||
		}
 | 
			
		||||
		end := strings.Index(s, ">")
 | 
			
		||||
		if end == -1 {
 | 
			
		||||
			// unterminated... just emit bytes unadulterated.
 | 
			
		||||
			return io.WriteString(w, "$<"+s)
 | 
			
		||||
		}
 | 
			
		||||
		var c int
 | 
			
		||||
		c, err = io.WriteString(w, s[:start])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return n + c, err
 | 
			
		||||
		}
 | 
			
		||||
		n += c
 | 
			
		||||
		s = s[start+2:]
 | 
			
		||||
		val := s[:end]
 | 
			
		||||
		s = s[end+1:]
 | 
			
		||||
		var ms int
 | 
			
		||||
		var dot, mandatory, asterisk bool
 | 
			
		||||
		unit := 1000
 | 
			
		||||
		for _, ch := range val {
 | 
			
		||||
			switch {
 | 
			
		||||
			case ch >= '0' && ch <= '9':
 | 
			
		||||
				ms = (ms * 10) + int(ch-'0')
 | 
			
		||||
				if dot {
 | 
			
		||||
					unit *= 10
 | 
			
		||||
				}
 | 
			
		||||
			case ch == '.' && !dot:
 | 
			
		||||
				dot = true
 | 
			
		||||
			case ch == '*' && !asterisk:
 | 
			
		||||
				ms *= lines
 | 
			
		||||
				asterisk = true
 | 
			
		||||
			case ch == '/':
 | 
			
		||||
				mandatory = true
 | 
			
		||||
			default:
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		z, pad := ((baud/8)/unit)*ms, ti.Strings[PadChar]
 | 
			
		||||
		b := make([]byte, len(pad)*z)
 | 
			
		||||
		for bp := copy(b, pad); bp < len(b); bp *= 2 {
 | 
			
		||||
			copy(b[bp:], b[:bp])
 | 
			
		||||
		}
 | 
			
		||||
		if (!ti.Bools[XonXoff] && baud > int(ti.Nums[PaddingBaudRate])) || mandatory {
 | 
			
		||||
			c, err = w.Write(b)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return n + c, err
 | 
			
		||||
			}
 | 
			
		||||
			n += c
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return n, nil
 | 
			
		||||
}*/
 | 
			
		||||
		Reference in New Issue
	
	Block a user