From 70b14215ec1d0dccce17109ea8b680dc0caec1e2 Mon Sep 17 00:00:00 2001 From: Heath Stewart Date: Fri, 11 Oct 2024 00:52:00 -0700 Subject: [PATCH] Print filtered gists similar to code search --- pkg/cmd/gist/list/list.go | 85 ++++++++++++++++++++++++++++++++++++- pkg/cmd/search/code/code.go | 16 +++---- pkg/iostreams/color.go | 30 +++++++++++++ 3 files changed, 120 insertions(+), 11 deletions(-) diff --git a/pkg/cmd/gist/list/list.go b/pkg/cmd/gist/list/list.go index ae138d6a2..c58ed06ea 100644 --- a/pkg/cmd/gist/list/list.go +++ b/pkg/cmd/gist/list/list.go @@ -136,8 +136,16 @@ func listRun(opts *ListOptions) error { fmt.Fprintf(opts.IO.ErrOut, "failed to start pager: %v\n", err) } - cs := opts.IO.ColorScheme() - tp := tableprinter.New(opts.IO, tableprinter.WithHeader("ID", "DESCRIPTION", "FILES", "VISIBILITY", "UPDATED")) + if opts.IO.ColorEnabled() && opts.Filter != nil { + return printHighlights(opts.IO, gists, opts.Filter) + } + + return printTable(opts.IO, gists) +} + +func printTable(io *iostreams.IOStreams, gists []shared.Gist) error { + cs := io.ColorScheme() + tp := tableprinter.New(io, tableprinter.WithHeader("ID", "DESCRIPTION", "FILES", "VISIBILITY", "UPDATED")) for _, gist := range gists { fileCount := len(gist.Files) @@ -172,3 +180,76 @@ func listRun(opts *ListOptions) error { return tp.Render() } + +func printHighlights(io *iostreams.IOStreams, gists []shared.Gist, filter *regexp.Regexp) error { + const tab string = " " + cs := io.ColorScheme() + + out := &strings.Builder{} + var filename, description string + var err error + text := func(s string) string { + return s + } + for _, gist := range gists { + for _, file := range gist.Files { + found := false + out.Reset() + + if filename, err = highlightMatch(file.Filename, filter, &found, cs.Green, cs.Highlight); err != nil { + return err + } + fmt.Fprintln(out, cs.Blue(gist.ID), filename) + + if gist.Description != "" { + if description, err = highlightMatch(gist.Description, filter, &found, cs.Bold, cs.Highlight); err != nil { + return err + } + fmt.Fprintln(out, tab, description) + } + + if file.Content != "" { + for _, line := range strings.Split(file.Content, "\n") { + if filter.MatchString(line) { + if line, err = highlightMatch(line, filter, &found, text, cs.Highlight); err != nil { + return err + } + fmt.Fprintln(out, tab, tab, line) + } + } + } + + if found { + fmt.Fprintln(io.Out, out.String()) + } + } + } + + return nil +} + +func highlightMatch(s string, filter *regexp.Regexp, found *bool, color, highlight func(string) string) (string, error) { + matches := filter.FindAllStringIndex(s, -1) + if matches == nil { + return color(s), nil + } + + out := strings.Builder{} + if _, err := out.WriteString(color(s[:matches[0][0]])); err != nil { + return "", err + } + + for _, match := range matches { + if _, err := out.WriteString(highlight(s[match[0]:match[1]])); err != nil { + return "", err + } + if _, err := out.WriteString(color(s[match[1]:])); err != nil { + return "", nil + } + } + + if found != nil { + *found = *found || true + } + return out.String(), nil +} diff --git a/pkg/cmd/search/code/code.go b/pkg/cmd/search/code/code.go index 0c318be74..63633cc53 100644 --- a/pkg/cmd/search/code/code.go +++ b/pkg/cmd/search/code/code.go @@ -143,7 +143,7 @@ func displayResults(io *iostreams.IOStreams, results search.CodeResult) error { } fmt.Fprintf(io.Out, "%s %s\n", cs.Blue(code.Repository.FullName), cs.GreenBold(code.Path)) for _, match := range code.TextMatches { - lines := formatMatch(match.Fragment, match.Matches, io.ColorEnabled()) + lines := formatMatch(match.Fragment, match.Matches, io) for _, line := range lines { fmt.Fprintf(io.Out, "\t%s\n", strings.TrimSpace(line)) } @@ -153,7 +153,7 @@ func displayResults(io *iostreams.IOStreams, results search.CodeResult) error { } for _, code := range results.Items { for _, match := range code.TextMatches { - lines := formatMatch(match.Fragment, match.Matches, io.ColorEnabled()) + lines := formatMatch(match.Fragment, match.Matches, io) for _, line := range lines { fmt.Fprintf(io.Out, "%s:%s: %s\n", cs.Blue(code.Repository.FullName), cs.GreenBold(code.Path), strings.TrimSpace(line)) } @@ -162,7 +162,9 @@ func displayResults(io *iostreams.IOStreams, results search.CodeResult) error { return nil } -func formatMatch(t string, matches []search.Match, colorize bool) []string { +func formatMatch(t string, matches []search.Match, io *iostreams.IOStreams) []string { + cs := io.ColorScheme() + startIndices := map[int]struct{}{} endIndices := map[int]struct{}{} for _, m := range matches { @@ -186,14 +188,10 @@ func formatMatch(t string, matches []search.Match, colorize bool) []string { continue } if _, ok := startIndices[i]; ok { - if colorize { - b.WriteString("\x1b[30;43m") // black text on yellow background - } + b.WriteString(cs.HighlightStart()) // black text on yellow background found = true } else if _, ok := endIndices[i]; ok { - if colorize { - b.WriteString("\x1b[m") // color reset - } + b.WriteString(cs.Reset()) // color reset } b.WriteRune(c) } diff --git a/pkg/iostreams/color.go b/pkg/iostreams/color.go index 804b9a275..c8d48168f 100644 --- a/pkg/iostreams/color.go +++ b/pkg/iostreams/color.go @@ -8,6 +8,10 @@ import ( "github.com/mgutz/ansi" ) +const ( + highlightStyle = "black:yellow" +) + var ( magenta = ansi.ColorFunc("magenta") cyan = ansi.ColorFunc("cyan") @@ -20,6 +24,8 @@ var ( bold = ansi.ColorFunc("default+b") cyanBold = ansi.ColorFunc("cyan+b") greenBold = ansi.ColorFunc("green+b") + highlightStart = ansi.ColorCode(highlightStyle) + highlight = ansi.ColorFunc(highlightStyle) gray256 = func(t string) string { return fmt.Sprintf("\x1b[%d;5;%dm%s\x1b[m", 38, 242, t) @@ -176,6 +182,30 @@ func (c *ColorScheme) FailureIconWithColor(colo func(string) string) string { return colo("X") } +func (c *ColorScheme) HighlightStart() string { + if !c.enabled { + return "" + } + + return highlightStart +} + +func (c *ColorScheme) Highlight(t string) string { + if !c.enabled { + return t + } + + return highlight(t) +} + +func (c *ColorScheme) Reset() string { + if !c.enabled { + return "" + } + + return ansi.Reset +} + func (c *ColorScheme) ColorFromString(s string) func(string) string { s = strings.ToLower(s) var fn func(string) string