summaryrefslogtreecommitdiff
path: root/vendor/github.com/ijc/Gotty/gotty.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/ijc/Gotty/gotty.go')
-rw-r--r--vendor/github.com/ijc/Gotty/gotty.go244
1 files changed, 0 insertions, 244 deletions
diff --git a/vendor/github.com/ijc/Gotty/gotty.go b/vendor/github.com/ijc/Gotty/gotty.go
deleted file mode 100644
index c329778a1..000000000
--- a/vendor/github.com/ijc/Gotty/gotty.go
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright 2012 Neal van Veen. All rights reserved.
-// Usage of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Gotty is a Go-package for reading and parsing the terminfo database
-package gotty
-
-// TODO add more concurrency to name lookup, look for more opportunities.
-
-import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
- "os"
- "path"
- "reflect"
- "strings"
- "sync"
-)
-
-// Open a terminfo file by the name given and construct a TermInfo object.
-// If something went wrong reading the terminfo database file, an error is
-// returned.
-func OpenTermInfo(termName string) (*TermInfo, error) {
- if len(termName) == 0 {
- return nil, errors.New("No termname given")
- }
- // Find the environment variables
- if termloc := os.Getenv("TERMINFO"); len(termloc) > 0 {
- return readTermInfo(path.Join(termloc, string(termName[0]), termName))
- } else {
- // Search like ncurses
- locations := []string{}
- if h := os.Getenv("HOME"); len(h) > 0 {
- locations = append(locations, path.Join(h, ".terminfo"))
- }
- locations = append(locations,
- "/etc/terminfo/",
- "/lib/terminfo/",
- "/usr/share/terminfo/")
- for _, str := range locations {
- term, err := readTermInfo(path.Join(str, string(termName[0]), termName))
- if err == nil {
- return term, nil
- }
- }
- return nil, errors.New("No terminfo file(-location) found")
- }
-}
-
-// Open a terminfo file from the environment variable containing the current
-// terminal name and construct a TermInfo object. If something went wrong
-// reading the terminfo database file, an error is returned.
-func OpenTermInfoEnv() (*TermInfo, error) {
- termenv := os.Getenv("TERM")
- return OpenTermInfo(termenv)
-}
-
-// Return an attribute by the name attr provided. If none can be found,
-// an error is returned.
-func (term *TermInfo) GetAttribute(attr string) (stacker, error) {
- // Channel to store the main value in.
- var value stacker
- // Add a blocking WaitGroup
- var block sync.WaitGroup
- // Keep track of variable being written.
- written := false
- // Function to put into goroutine.
- f := func(ats interface{}) {
- var ok bool
- var v stacker
- // Switch on type of map to use and assign value to it.
- switch reflect.TypeOf(ats).Elem().Kind() {
- case reflect.Bool:
- v, ok = ats.(map[string]bool)[attr]
- case reflect.Int16:
- v, ok = ats.(map[string]int16)[attr]
- case reflect.String:
- v, ok = ats.(map[string]string)[attr]
- }
- // If ok, a value is found, so we can write.
- if ok {
- value = v
- written = true
- }
- // Goroutine is done
- block.Done()
- }
- block.Add(3)
- // Go for all 3 attribute lists.
- go f(term.boolAttributes)
- go f(term.numAttributes)
- go f(term.strAttributes)
- // Wait until every goroutine is done.
- block.Wait()
- // If a value has been written, return it.
- if written {
- return value, nil
- }
- // Otherwise, error.
- return nil, fmt.Errorf("Erorr finding attribute")
-}
-
-// Return an attribute by the name attr provided. If none can be found,
-// an error is returned. A name is first converted to its termcap value.
-func (term *TermInfo) GetAttributeName(name string) (stacker, error) {
- tc := GetTermcapName(name)
- return term.GetAttribute(tc)
-}
-
-// A utility function that finds and returns the termcap equivalent of a
-// variable name.
-func GetTermcapName(name string) string {
- // Termcap name
- var tc string
- // Blocking group
- var wait sync.WaitGroup
- // Function to put into a goroutine
- f := func(attrs []string) {
- // Find the string corresponding to the name
- for i, s := range attrs {
- if s == name {
- tc = attrs[i+1]
- }
- }
- // Goroutine is finished
- wait.Done()
- }
- wait.Add(3)
- // Go for all 3 attribute lists
- go f(BoolAttr[:])
- go f(NumAttr[:])
- go f(StrAttr[:])
- // Wait until every goroutine is done
- wait.Wait()
- // Return the termcap name
- return tc
-}
-
-// This function takes a path to a terminfo file and reads it in binary
-// form to construct the actual TermInfo file.
-func readTermInfo(path string) (*TermInfo, error) {
- // Open the terminfo file
- file, err := os.Open(path)
- defer file.Close()
- if err != nil {
- return nil, err
- }
-
- // magic, nameSize, boolSize, nrSNum, nrOffsetsStr, strSize
- // Header is composed of the magic 0432 octal number, size of the name
- // section, size of the boolean section, the amount of number values,
- // the number of offsets of strings, and the size of the string section.
- var header [6]int16
- // Byte array is used to read in byte values
- var byteArray []byte
- // Short array is used to read in short values
- var shArray []int16
- // TermInfo object to store values
- var term TermInfo
-
- // Read in the header
- err = binary.Read(file, binary.LittleEndian, &header)
- if err != nil {
- return nil, err
- }
- // If magic number isn't there or isn't correct, we have the wrong filetype
- if header[0] != 0432 {
- return nil, errors.New(fmt.Sprintf("Wrong filetype"))
- }
-
- // Read in the names
- byteArray = make([]byte, header[1])
- err = binary.Read(file, binary.LittleEndian, &byteArray)
- if err != nil {
- return nil, err
- }
- term.Names = strings.Split(string(byteArray), "|")
-
- // Read in the booleans
- byteArray = make([]byte, header[2])
- err = binary.Read(file, binary.LittleEndian, &byteArray)
- if err != nil {
- return nil, err
- }
- term.boolAttributes = make(map[string]bool)
- for i, b := range byteArray {
- if b == 1 {
- term.boolAttributes[BoolAttr[i*2+1]] = true
- }
- }
- // If the number of bytes read is not even, a byte for alignment is added
- // We know the header is an even number of bytes so only need to check the
- // total of the names and booleans.
- if (header[1]+header[2])%2 != 0 {
- err = binary.Read(file, binary.LittleEndian, make([]byte, 1))
- if err != nil {
- return nil, err
- }
- }
-
- // Read in shorts
- shArray = make([]int16, header[3])
- err = binary.Read(file, binary.LittleEndian, &shArray)
- if err != nil {
- return nil, err
- }
- term.numAttributes = make(map[string]int16)
- for i, n := range shArray {
- if n != 0377 && n > -1 {
- term.numAttributes[NumAttr[i*2+1]] = n
- }
- }
-
- // Read the offsets into the short array
- shArray = make([]int16, header[4])
- err = binary.Read(file, binary.LittleEndian, &shArray)
- if err != nil {
- return nil, err
- }
- // Read the actual strings in the byte array
- byteArray = make([]byte, header[5])
- err = binary.Read(file, binary.LittleEndian, &byteArray)
- if err != nil {
- return nil, err
- }
- term.strAttributes = make(map[string]string)
- // We get an offset, and then iterate until the string is null-terminated
- for i, offset := range shArray {
- if offset > -1 {
- if int(offset) >= len(byteArray) {
- return nil, errors.New("array out of bounds reading string section")
- }
- r := bytes.IndexByte(byteArray[offset:], 0)
- if r == -1 {
- return nil, errors.New("missing nul byte reading string section")
- }
- r += int(offset)
- term.strAttributes[StrAttr[i*2+1]] = string(byteArray[offset:r])
- }
- }
- return &term, nil
-}