diff --git a/go.mod b/go.mod index c28f755fc5f..be48285376e 100644 --- a/go.mod +++ b/go.mod @@ -25,9 +25,11 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 github.com/hashicorp/go-envparse v0.1.0 + github.com/jedib0t/go-pretty/v6 v6.5.4 github.com/joho/godotenv v1.5.1 github.com/mattn/go-isatty v0.0.20 github.com/mholt/archiver/v4 v4.0.0-alpha.8 + github.com/mitchellh/go-wordwrap v1.0.1 github.com/pelletier/go-toml/v2 v2.1.1 github.com/pkg/errors v0.9.1 github.com/rogpeppe/go-internal v1.12.0 diff --git a/go.sum b/go.sum index 3c155e9355c..36b572df4b4 100644 --- a/go.sum +++ b/go.sum @@ -228,6 +228,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jedib0t/go-pretty/v6 v6.5.4 h1:gOGo0613MoqUcf0xCj+h/V3sHDaZasfv152G6/5l91s= +github.com/jedib0t/go-pretty/v6 v6.5.4/go.mod h1:5LQIxa52oJ/DlDSLv0HEkWOFMDGoWkJb9ss5KqPpJBg= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -277,6 +279,8 @@ github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQ github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mholt/archiver/v4 v4.0.0-alpha.8 h1:tRGQuDVPh66WCOelqe6LIGh0gwmfwxUrSSDunscGsRM= github.com/mholt/archiver/v4 v4.0.0-alpha.8/go.mod h1:5f7FUYGXdJWUjESffJaYR4R60VhnHxb2X3T1teMyv5A= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= 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.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= diff --git a/internal/boxcli/search.go b/internal/boxcli/search.go index dbe00c4e253..24a9c974835 100644 --- a/internal/boxcli/search.go +++ b/internal/boxcli/search.go @@ -5,12 +5,16 @@ package boxcli import ( "fmt" + "github.com/jedib0t/go-pretty/v6/text" + "github.com/spf13/cobra" "io" "math" + "net/url" + "slices" "strings" - "github.com/spf13/cobra" - + "github.com/jedib0t/go-pretty/v6/table" + "github.com/mitchellh/go-wordwrap" "go.jetpack.io/devbox/internal/boxcli/usererr" "go.jetpack.io/devbox/internal/searcher" "go.jetpack.io/devbox/internal/ux" @@ -86,24 +90,53 @@ func printSearchResults( pkgs = results.Packages[:int(math.Min(10, float64(len(results.Packages))))] } + rowConfigAutoMerge := table.RowConfig{AutoMerge: true} + + t := table.NewWriter() + t.AppendHeader(table.Row{"Package", "Versions", "Platforms"}, rowConfigAutoMerge) for _, pkg := range pkgs { - nonEmptyVersions := []string{} + systemKey := "" + var versions []string for i, v := range pkg.Versions { - if !showAll && i >= 10 { - resultsAreTrimmed = true - break - } if v.Version != "" { - nonEmptyVersions = append(nonEmptyVersions, v.Version) + if !showAll && i >= 10 { + resultsAreTrimmed = true + break + } + + var systems []string + for _, sys := range v.Systems { + systems = append(systems, sys.System) + } + slices.Sort(systems) + key := strings.Join(systems, " ") + if systemKey == "" || systemKey == key { + systemKey = key + versions = append(versions, v.Version) + } else { + wrappedVersions := wordwrap.WrapString(strings.Join(versions[:], " "), 35) + wrappedSystems := wordwrap.WrapString(systemKey, 15) + t.AppendRow(table.Row{pkg.Name, wrappedVersions, wrappedSystems}, rowConfigAutoMerge) + systemKey = "" + versions = []string{} + } } } - versionString := "" - if len(nonEmptyVersions) > 0 { - versionString = fmt.Sprintf(" (%s)", strings.Join(nonEmptyVersions, ", ")) + if len(versions) > 0 { + wrappedVersions := wordwrap.WrapString(strings.Join(versions[:], " "), 35) + wrappedSystems := wordwrap.WrapString(systemKey, 15) + t.AppendRow(table.Row{pkg.Name, wrappedVersions, wrappedSystems}, rowConfigAutoMerge) } - fmt.Fprintf(w, "* %s %s\n", pkg.Name, versionString) } + t.SetColumnConfigs([]table.ColumnConfig{ + {Number: 1, AutoMerge: true, VAlign: text.VAlignMiddle}, + {Number: 2, AutoMerge: true, Align: text.AlignJustify, AlignHeader: text.AlignCenter}, + {Number: 3, AutoMerge: true, Align: text.AlignJustify, AlignHeader: text.AlignCenter}, + }) + t.SetStyle(table.StyleLight) + t.Style().Options.SeparateRows = true + fmt.Println(t.Render()) if resultsAreTrimmed { fmt.Println() @@ -113,6 +146,7 @@ func printSearchResults( "show all.\n\n", ) } + ux.Finfo(w, "For more information go to: https://www.nixhub.io/search?q=%s\n\n", url.QueryEscape(query)) return nil }