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}