Merge pull request #112 from foomo/feature/multi-checkers

feat: allow multiple checkers
This commit is contained in:
Kevin Franklin Kim 2025-04-07 16:05:28 +02:00 committed by GitHub
commit 1d6bfa9ea2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 146 additions and 53 deletions

View File

@ -19,7 +19,8 @@ outdated:
.PHONY: test .PHONY: test
## Run tests ## Run tests
test: test:
@go test -coverprofile=coverage.out -race -json ./... | gotestfmt @GO_TEST_TAGS=-skip go test -coverprofile=coverage.out -race ./...
#@GO_TEST_TAGS=-skip go test -coverprofile=coverage.out -race -json ./... | gotestfmt
.PHONY: test.demo .PHONY: test.demo
## Run tests ## Run tests

View File

@ -1,6 +1,6 @@
module {{ .module }}/posh module {{ .module }}/posh
go 1.23.0 go 1.24
replace ( replace (
github.com/c-bata/go-prompt v0.2.6 => github.com/franklinkim/go-prompt v0.2.7-0.20210427061716-a8f4995d7aa5 github.com/c-bata/go-prompt v0.2.6 => github.com/franklinkim/go-prompt v0.2.7-0.20210427061716-a8f4995d7aa5

View File

@ -110,12 +110,12 @@ func (p *Plugin) Prompt(ctx context.Context, cfg config.Prompt) error {
prompt.WithAliases(cfg.Aliases), prompt.WithAliases(cfg.Aliases),
prompt.WithCommands(p.commands), prompt.WithCommands(p.commands),
prompt.WithCheckers( prompt.WithCheckers(
func(ctx context.Context, l log.Logger) check.Info { func(ctx context.Context, l log.Logger) []check.Info {
return check.Info{ return []check.Info{check.Info{
Name: "example", Name: "example",
Note: "all good", Note: "all good",
Status: check.StatusSuccess, Status: check.StatusSuccess,
} }}
}, },
), ),
prompt.WithFileHistory( prompt.WithFileHistory(

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
ptermx "github.com/foomo/posh/pkg/pterm"
"github.com/pterm/pterm" "github.com/pterm/pterm"
) )
@ -167,7 +168,7 @@ func (l *PTerm) Must(err error) {
} }
func (l *PTerm) SlogHandler() slog.Handler { func (l *PTerm) SlogHandler() slog.Handler {
return pterm.NewSlogHandler(&pterm.DefaultLogger) return ptermx.NewSlogHandler()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -6,4 +6,4 @@ import (
"github.com/foomo/posh/pkg/log" "github.com/foomo/posh/pkg/log"
) )
type Checker func(ctx context.Context, l log.Logger) Info type Checker func(ctx context.Context, l log.Logger) []Info

View File

@ -2,6 +2,9 @@ package check
import ( import (
"context" "context"
"slices"
"strings"
"sync"
"time" "time"
"github.com/foomo/posh/pkg/log" "github.com/foomo/posh/pkg/log"
@ -10,29 +13,32 @@ import (
) )
func DefaultCheck(ctx context.Context, l log.Logger, checkers []Checker) error { func DefaultCheck(ctx context.Context, l log.Logger, checkers []Checker) error {
var mu sync.Mutex
var wg errgroup.Group var wg errgroup.Group
data := make(pterm.TableData, len(checkers)) var data pterm.TableData
wg.SetLimit(3) // wg.SetLimit(3)
for i, checker := range checkers { for _, checker := range checkers {
i := i
checker := checker
wg.Go(func() error { wg.Go(func() error {
cancelCtx, cancel := context.WithTimeout(ctx, 10*time.Second) cancelCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel() defer cancel()
info := checker(cancelCtx, l) infos := checker(cancelCtx, l)
var color pterm.Color mu.Lock()
switch info.Status { defer mu.Unlock()
case StatusFailure: for _, info := range infos {
color = pterm.FgRed var color pterm.Color
case StatusSuccess: switch info.Status {
color = pterm.FgGreen case StatusFailure:
default: color = pterm.FgRed
color = pterm.FgGray case StatusSuccess:
} color = pterm.FgGreen
data[i] = []string{ default:
info.Status.String(), color = pterm.FgGray
info.Name, }
color.Sprint(info.Note), data = append(data, []string{
info.Status.String(),
info.Name,
color.Sprint(info.Note),
})
} }
return nil return nil
}) })
@ -40,10 +46,10 @@ func DefaultCheck(ctx context.Context, l log.Logger, checkers []Checker) error {
if err := wg.Wait(); err != nil { if err := wg.Wait(); err != nil {
return err return err
} }
table := pterm.DefaultTable
if err := table.WithData(data).Render(); err != nil { slices.SortFunc(data, func(a, b []string) int {
return err return strings.Compare(a[1], b[1])
} })
pterm.Println()
return nil return pterm.DefaultTable.WithData(data).Render()
} }

View File

@ -27,7 +27,7 @@ type (
prefix string prefix string
prefixGit bool prefixGit bool
check check.Check check check.Check
checkers []check.Checker checkers check.Checkers
filter goprompt.Filter filter goprompt.Filter
readline *readline.Readline readline *readline.Readline
history history.History history history.History

20
pkg/pterm/ptermwriter.go Normal file
View File

@ -0,0 +1,20 @@
package pterm
import (
"github.com/pterm/pterm"
)
type Writer struct {
printer pterm.PrefixPrinter
}
func NewWriter(printer pterm.PrefixPrinter) *Writer {
return &Writer{
printer: printer,
}
}
func (p *Writer) Write(b []byte) (int, error) {
p.printer.Println(string(b))
return len(b), nil
}

85
pkg/pterm/sloghandler.go Normal file
View File

@ -0,0 +1,85 @@
package pterm
import (
"context"
"fmt"
"log/slog"
"github.com/pterm/pterm"
)
type SlogHandler struct {
attrs []slog.Attr
}
// NewSlogHandler returns a new logging handler that can be intrgrated with log/slog.
func NewSlogHandler() *SlogHandler {
return &SlogHandler{}
}
// Enabled returns true if the given level is enabled.
func (s *SlogHandler) Enabled(ctx context.Context, level slog.Level) bool {
switch level {
case slog.LevelDebug:
return pterm.PrintDebugMessages
default:
return true
}
}
// Handle handles the given record.
func (s *SlogHandler) Handle(ctx context.Context, record slog.Record) error {
level := record.Level
message := record.Message
// Convert slog Attrs to a map.
keyValsMap := make(map[string]any)
record.Attrs(func(attr slog.Attr) bool {
keyValsMap[attr.Key] = attr.Value
return true
})
for _, attr := range s.attrs {
keyValsMap[attr.Key] = attr.Value
}
args := pterm.DefaultLogger.ArgsFromMap(keyValsMap)
// Wrapping args inside another slice to match [][]LoggerArgument
argsWrapped := [][]pterm.LoggerArgument{args}
for _, arg := range argsWrapped {
for _, attr := range arg {
message += " " + attr.Key + ": " + fmt.Sprintf("%v", attr.Value)
}
}
switch level {
case slog.LevelDebug:
pterm.Debug.Println(message)
case slog.LevelInfo:
pterm.Info.Println(message)
case slog.LevelWarn:
pterm.Warning.Println(message)
case slog.LevelError:
pterm.Error.Println(message)
default:
pterm.Info.Println(message)
}
return nil
}
// WithAttrs returns a new handler with the given attributes.
func (s *SlogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
newS := *s
newS.attrs = attrs
return &newS
}
// WithGroup is not yet supported.
func (s *SlogHandler) WithGroup(name string) slog.Handler {
// Grouping is not yet supported by pterm.
return s
}

View File

@ -1,20 +0,0 @@
package shell
import (
"github.com/pterm/pterm"
)
type PTermWriter struct {
printer pterm.PrefixPrinter
}
func NewPTermWriter(printer pterm.PrefixPrinter) *PTermWriter {
return &PTermWriter{
printer: printer,
}
}
func (p *PTermWriter) Write(b []byte) (int, error) {
p.printer.Println(string(b))
return len(b), nil
}