load.go 1.5 KB

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