1package terminfo
2
3import (
4 "os"
5 "strconv"
6 "strings"
7)
8
9// ColorLevel is the color level supported by a terminal.
10type ColorLevel uint
11
12// ColorLevel values.
13const (
14 ColorLevelNone ColorLevel = iota
15 ColorLevelBasic
16 ColorLevelHundreds
17 ColorLevelMillions
18)
19
20// String satisfies the Stringer interface.
21func (c ColorLevel) String() string {
22 switch c {
23 case ColorLevelBasic:
24 return "basic"
25 case ColorLevelHundreds:
26 return "hundreds"
27 case ColorLevelMillions:
28 return "millions"
29 }
30 return "none"
31}
32
33// ChromaFormatterName returns the github.com/alecthomas/chroma compatible
34// formatter name for the color level.
35func (c ColorLevel) ChromaFormatterName() string {
36 switch c {
37 case ColorLevelBasic:
38 return "terminal"
39 case ColorLevelHundreds:
40 return "terminal256"
41 case ColorLevelMillions:
42 return "terminal16m"
43 }
44 return "noop"
45}
46
47// ColorLevelFromEnv returns the color level COLORTERM, FORCE_COLOR,
48// TERM_PROGRAM, or determined from the TERM environment variable.
49func ColorLevelFromEnv() (ColorLevel, error) {
50 // check for overriding environment variables
51 colorTerm, termProg, forceColor := os.Getenv("COLORTERM"), os.Getenv("TERM_PROGRAM"), os.Getenv("FORCE_COLOR")
52 switch {
53 case strings.Contains(colorTerm, "truecolor") || strings.Contains(colorTerm, "24bit") || termProg == "Hyper":
54 return ColorLevelMillions, nil
55 case colorTerm != "" || forceColor != "":
56 return ColorLevelBasic, nil
57 case termProg == "Apple_Terminal":
58 return ColorLevelHundreds, nil
59 case termProg == "iTerm.app":
60 ver := os.Getenv("TERM_PROGRAM_VERSION")
61 if ver == "" {
62 return ColorLevelHundreds, nil
63 }
64 i, err := strconv.Atoi(strings.Split(ver, ".")[0])
65 if err != nil {
66 return ColorLevelNone, ErrInvalidTermProgramVersion
67 }
68 if i == 3 {
69 return ColorLevelMillions, nil
70 }
71 return ColorLevelHundreds, nil
72 }
73 // otherwise determine from TERM's max_colors capability
74 if term := os.Getenv("TERM"); term != "" {
75 ti, err := Load(term)
76 if err != nil {
77 return ColorLevelNone, err
78 }
79 v, ok := ti.Nums[MaxColors]
80 switch {
81 case !ok || v <= 16:
82 return ColorLevelNone, nil
83 case ok && v >= 256:
84 return ColorLevelHundreds, nil
85 }
86 }
87 return ColorLevelBasic, nil
88}