Skip to content

Commit

Permalink
feat: add adaptive colors (#482)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrexox committed May 18, 2023
1 parent 7679af6 commit 65ea468
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 38 deletions.
22 changes: 21 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

- [Top level options](#top-level-options)
- [`colors`](#colors)
- [`yellow`](#colors)
- [`green`](#colors)
- [`cyan`](#colors)
- [`gray`](#colors)
- [`red`](#colors)
- [`no_tty`](#no_tty)
- [`extends`](#extends)
- [`min_version`](#min_version)
Expand Down Expand Up @@ -58,16 +63,31 @@ These options are not related to git hooks, and they only control lefthook behav

**Default: `true`**

Whether enable or disable colorful output of Lefthook. This option can be overwritten with `--no-colors` option.
Whether enable or disable colorful output of Lefthook. This option can be overwritten with `--no-colors` option. You can also provide your own color codes.

**Example**

Disable colors.

```yml
# lefthook.yml

colors: false
```

Custom color codes. Can be hex or ANSI codes.

```yml
# lefthook.yml

colors:
cyan: 14
gray: 244
green: '#32CD32'
red: '#FF1493'
yellow: '#F0E68C'
```

### `no_tty`

**Default: `false`**
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.19
require (
github.com/MakeNowJust/heredoc v1.0.0
github.com/briandowns/spinner v1.23.0
github.com/charmbracelet/lipgloss v0.7.1
github.com/charmbracelet/lipgloss v0.6.0
github.com/creack/pty v1.1.18
github.com/gobwas/glob v0.2.3
github.com/google/go-cmp v0.5.9
Expand Down Expand Up @@ -41,5 +41,5 @@ require (
golang.org/x/term v0.5.0 // indirect
golang.org/x/text v0.5.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gopkg.in/yaml.v3 v3.0.1
)
10 changes: 8 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ
github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A=
github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E=
github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNWpFujkNawKNhE2c=
github.com/charmbracelet/lipgloss v0.6.0 h1:1StyZB9vBSOyuZxQUcUwGr17JmojPNm87inij9N3wJY=
github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
Expand Down Expand Up @@ -157,16 +157,21 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ=
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs=
github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs=
github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ=
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
Expand Down Expand Up @@ -343,6 +348,7 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
Expand Down
18 changes: 9 additions & 9 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import (
const dumpIndent = 2

type Config struct {
Colors bool `mapstructure:"colors"`
Extends []string `mapstructure:"extends" yaml:",omitempty"`
Remote Remote `mapstructure:"remote" yaml:",omitempty"`
MinVersion string `mapstructure:"min_version" yaml:"min_version,omitempty"`
SkipOutput []string `mapstructure:"skip_output" yaml:"skip_output,omitempty"`
SourceDir string `mapstructure:"source_dir" yaml:"source_dir,omitempty"`
SourceDirLocal string `mapstructure:"source_dir_local" yaml:"source_dir_local,omitempty"`
Rc string `mapstructure:"rc" yaml:",omitempty"`
NoTTY bool `mapstructure:"no_tty" yaml:"no_tty,omitempty"`
Colors interface{} `mapstructure:"colors" yaml:",omitempty"`
Extends []string `mapstructure:"extends" yaml:",omitempty"`
Remote Remote `mapstructure:"remote" yaml:",omitempty"`
MinVersion string `mapstructure:"min_version" yaml:"min_version,omitempty"`
SkipOutput []string `mapstructure:"skip_output" yaml:"skip_output,omitempty"`
SourceDir string `mapstructure:"source_dir" yaml:"source_dir,omitempty"`
SourceDirLocal string `mapstructure:"source_dir_local" yaml:"source_dir_local,omitempty"`
Rc string `mapstructure:"rc" yaml:",omitempty"`
NoTTY bool `mapstructure:"no_tty" yaml:"no_tty,omitempty"`

Hooks map[string]*Hook
}
Expand Down
3 changes: 1 addition & 2 deletions internal/config/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ const (
DefaultConfigName = "lefthook.yml"
DefaultSourceDir = ".lefthook"
DefaultSourceDirLocal = ".lefthook-local"
DefaultColorsEnabled = true
)

var hookKeyRegexp = regexp.MustCompile(`^(?P<hookName>[^.]+)\.(scripts|commands)`)
Expand Down Expand Up @@ -52,7 +51,6 @@ func Load(fs afero.Fs, repo *git.Repository) (*Config, error) {

var config Config

config.Colors = DefaultColorsEnabled
config.SourceDir = DefaultSourceDir
config.SourceDirLocal = DefaultSourceDirLocal

Expand All @@ -61,6 +59,7 @@ func Load(fs afero.Fs, repo *git.Repository) (*Config, error) {
return nil, err
}

log.SetColors(config.Colors)
return &config, nil
}

Expand Down
15 changes: 9 additions & 6 deletions internal/config/load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ post-commit:
result: &Config{
SourceDir: DefaultSourceDir,
SourceDirLocal: DefaultSourceDirLocal,
Colors: DefaultColorsEnabled,
Colors: nil,
Hooks: map[string]*Hook{
"pre-commit": {
Parallel: false,
Expand Down Expand Up @@ -160,7 +160,7 @@ lints:
result: &Config{
SourceDir: DefaultSourceDir,
SourceDirLocal: DefaultSourceDirLocal,
Colors: DefaultColorsEnabled,
Colors: nil,
Hooks: map[string]*Hook{
"tests": {
Parallel: false,
Expand All @@ -183,6 +183,9 @@ lints:
{
name: "with extra hooks only in local config",
global: `
colors:
yellow: '#FFE4B5'
red: 196
tests:
commands:
tests:
Expand All @@ -197,7 +200,7 @@ lints:
result: &Config{
SourceDir: DefaultSourceDir,
SourceDirLocal: DefaultSourceDirLocal,
Colors: DefaultColorsEnabled,
Colors: map[string]interface{}{"yellow": "#FFE4B5", "red": 196},
Hooks: map[string]*Hook{
"tests": {
Parallel: false,
Expand Down Expand Up @@ -236,7 +239,7 @@ pre-commit:
result: &Config{
SourceDir: DefaultSourceDir,
SourceDirLocal: DefaultSourceDirLocal,
Colors: DefaultColorsEnabled,
Colors: nil,
Remote: Remote{
GitURL: "git@github.com:evilmartians/lefthook",
},
Expand Down Expand Up @@ -291,7 +294,7 @@ pre-commit:
result: &Config{
SourceDir: DefaultSourceDir,
SourceDirLocal: DefaultSourceDirLocal,
Colors: DefaultColorsEnabled,
Colors: nil,
Remote: Remote{
GitURL: "git@github.com:evilmartians/lefthook",
Ref: "v1.0.0",
Expand Down Expand Up @@ -376,7 +379,7 @@ pre-push:
result: &Config{
SourceDir: DefaultSourceDir,
SourceDirLocal: DefaultSourceDirLocal,
Colors: DefaultColorsEnabled,
Colors: nil,
Remote: Remote{
GitURL: "https://github.com/evilmartians/lefthook",
Config: "examples/config.yml",
Expand Down
4 changes: 0 additions & 4 deletions internal/lefthook/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,6 @@ func (l *Lefthook) Run(hookName string, args RunArgs, gitArgs []string) error {
(&logSettings).ApplySetting(skipOption)
}

if cfg.Colors != config.DefaultColorsEnabled {
log.SetColors(cfg.Colors)
}

if !logSettings.SkipMeta() {
log.Info(log.Cyan("Lefthook v" + version.Version(false)))
}
Expand Down
80 changes: 68 additions & 12 deletions internal/log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"io"
"os"
"strconv"
"strings"
"sync"
"time"
Expand All @@ -12,15 +13,34 @@ import (
"github.com/charmbracelet/lipgloss"
)

const (
colorCyan = "#70C0BA"
colorYellow = "#fada5e"
colorRed = "#ff6347"
colorGreen = "#76ff7a"
colorGray = "#808080"
)
var (
colorRed lipgloss.TerminalColor = lipgloss.CompleteAdaptiveColor{
Dark: lipgloss.CompleteColor{TrueColor: "#ff6347", ANSI256: "196", ANSI: "9"},
Light: lipgloss.CompleteColor{TrueColor: "#d70000", ANSI256: "160", ANSI: "1"},
}

var std = New()
colorGreen lipgloss.TerminalColor = lipgloss.CompleteAdaptiveColor{
Dark: lipgloss.CompleteColor{TrueColor: "#76ff7a", ANSI256: "155", ANSI: "10"},
Light: lipgloss.CompleteColor{TrueColor: "#afd700", ANSI256: "148", ANSI: "2"},
}

colorYellow lipgloss.TerminalColor = lipgloss.CompleteAdaptiveColor{
Dark: lipgloss.CompleteColor{TrueColor: "#fada5e", ANSI256: "191", ANSI: "11"},
Light: lipgloss.CompleteColor{TrueColor: "#ffaf00", ANSI256: "214", ANSI: "3"},
}

colorCyan lipgloss.TerminalColor = lipgloss.CompleteAdaptiveColor{
Dark: lipgloss.CompleteColor{TrueColor: "#70C0BA", ANSI256: "37", ANSI: "14"},
Light: lipgloss.CompleteColor{TrueColor: "#00af87", ANSI256: "36", ANSI: "6"},
}

colorGray lipgloss.TerminalColor = lipgloss.CompleteAdaptiveColor{
Dark: lipgloss.CompleteColor{TrueColor: "#808080", ANSI256: "244", ANSI: "7"},
Light: lipgloss.CompleteColor{TrueColor: "#4e4e4e", ANSI256: "239", ANSI: "8"},
}

std = New()
)

type Level uint32

Expand Down Expand Up @@ -112,8 +132,44 @@ func SetLevel(level Level) {
std.SetLevel(level)
}

func SetColors(enable bool) {
std.colors = enable
func SetColors(colors interface{}) {
switch typedColors := colors.(type) {
case bool:
std.colors = typedColors
return
case map[string]interface{}:
std.colors = true
setColor(typedColors["red"], &colorRed)
setColor(typedColors["green"], &colorGreen)
setColor(typedColors["yellow"], &colorYellow)
setColor(typedColors["cyan"], &colorCyan)
setColor(typedColors["gray"], &colorGray)
return
default:
std.colors = true
}
}

func setColor(colorCode interface{}, adaptiveColor *lipgloss.TerminalColor) {
if colorCode == nil {
return
}

var code string
switch typedCode := colorCode.(type) {
case int:
code = strconv.Itoa(typedCode)
case string:
code = typedCode
default:
return
}

if len(code) == 0 {
return
}

*adaptiveColor = lipgloss.Color(code)
}

func Cyan(s string) string {
Expand All @@ -140,12 +196,12 @@ func Bold(s string) string {
return lipgloss.NewStyle().Bold(true).Render(s)
}

func color(colorCode string) lipgloss.Style {
func color(clr lipgloss.TerminalColor) lipgloss.Style {
if !std.colors {
return lipgloss.NewStyle()
}

return lipgloss.NewStyle().Foreground(lipgloss.Color(colorCode))
return lipgloss.NewStyle().Foreground(clr)
}

func SetOutput(out io.Writer) {
Expand Down

0 comments on commit 65ea468

Please sign in to comment.