load.go

 1package terminfo
 2
 3import (
 4	"os"
 5	"os/user"
 6	"path"
 7	"strings"
 8	"sync"
 9)
10
11// termCache is the terminfo cache.
12var termCache = struct {
13	db map[string]*Terminfo
14	sync.RWMutex
15}{
16	db: make(map[string]*Terminfo),
17}
18
19// Load follows the behavior described in terminfo(5) to find correct the
20// terminfo file using the name, reads the file and then returns a Terminfo
21// struct that describes the file.
22func Load(name string) (*Terminfo, error) {
23	if name == "" {
24		return nil, ErrEmptyTermName
25	}
26	termCache.RLock()
27	ti, ok := termCache.db[name]
28	termCache.RUnlock()
29	if ok {
30		return ti, nil
31	}
32	var checkDirs []string
33	// check $TERMINFO
34	if dir := os.Getenv("TERMINFO"); dir != "" {
35		checkDirs = append(checkDirs, dir)
36	}
37	// check $HOME/.terminfo
38	u, err := user.Current()
39	if err != nil {
40		return nil, err
41	}
42	checkDirs = append(checkDirs, path.Join(u.HomeDir, ".terminfo"))
43	// check $TERMINFO_DIRS
44	if dirs := os.Getenv("TERMINFO_DIRS"); dirs != "" {
45		checkDirs = append(checkDirs, strings.Split(dirs, ":")...)
46	}
47	// check fallback directories
48	checkDirs = append(checkDirs, "/etc/terminfo", "/lib/terminfo", "/usr/share/terminfo")
49	for _, dir := range checkDirs {
50		ti, err = Open(dir, name)
51		if err != nil && err != ErrFileNotFound && !os.IsNotExist(err) {
52			return nil, err
53		} else if err == nil {
54			return ti, nil
55		}
56	}
57	return nil, ErrDatabaseDirectoryNotFound
58}
59
60// LoadFromEnv loads the terminal info based on the name contained in
61// environment variable TERM.
62func LoadFromEnv() (*Terminfo, error) {
63	return Load(os.Getenv("TERM"))
64}