summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreltrac <hi@eltr.ac>2026-05-26 09:38:48 +0800
committereltrac <hi@eltr.ac>2026-05-26 09:38:48 +0800
commit4cec245383ab16656e1c5dcbbbe63350b57ab0ea (patch)
treead4453d4cbc904e060f9b93b77d199e7018b695d
parent6ab2a444250bb79aed3f65917ef28d32e90e69eb (diff)
refactor: separate fetch/display logic from main.go
-rw-r--r--actions.go108
-rw-r--r--main.go144
2 files changed, 130 insertions, 122 deletions
diff --git a/actions.go b/actions.go
new file mode 100644
index 0000000..81d0e63
--- /dev/null
+++ b/actions.go
@@ -0,0 +1,108 @@
+package main
+
+import (
+ "fmt"
+ "slices"
+ "sort"
+ "sync"
+
+ "github.com/fatih/color"
+)
+
+func fetchAndDisplay(pkgName string) *statistics {
+ fmt.Print("\033[s")
+ showLoadingPrompt(fmt.Sprintf("What the heck is \"%s\"", pkgName))
+
+ stat := initStat(pkgName)
+
+ fmlChan := make(chan *FormulaInfo)
+ caskChan := make(chan *CaskInfo)
+ rvsChan := make(chan []string)
+ fetchData(pkgName, fmlChan, caskChan, rvsChan)
+
+ var wg sync.WaitGroup
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ var fml *FormulaInfo
+ var cask *CaskInfo
+ var rvs []string
+ remaining := 3
+ for remaining > 0 {
+ select {
+ case v := <-fmlChan:
+ fml = v
+ remaining--
+ case v := <-caskChan:
+ cask = v
+ remaining--
+ case v := <-rvsChan:
+ rvs = v
+ remaining--
+ }
+ fmt.Print("\033[u\033[J")
+ stat = NewStatistics(fml, cask, pkgName, rvs)
+ stat.Print()
+ }
+ }()
+ wg.Wait()
+
+ return stat
+}
+
+func initStat(pkgName string) *statistics {
+ if NoCache {
+ return &statistics{PkgName: pkgName}
+ }
+ stat := NewStatisticsFromCache(pkgName)
+ if stat == nil {
+ return &statistics{PkgName: pkgName}
+ }
+ return stat
+}
+
+func runList() error {
+ depmap := GetBrewDeps()
+ list := GetBrewList()
+
+ keys := []string{}
+ for k := range depmap {
+ if !slices.Contains(list, k) {
+ delete(depmap, k)
+ } else {
+ keys = append(keys, k)
+ }
+ }
+
+ if ListAscend {
+ sort.Slice(keys, func(i, j int) bool {
+ return len(depmap[keys[i]]) > len(depmap[keys[j]])
+ })
+ } else if ListDescend {
+ sort.Slice(keys, func(i, j int) bool {
+ return len(depmap[keys[i]]) < len(depmap[keys[j]])
+ })
+ } else {
+ sort.Strings(keys)
+ }
+
+ for _, pkg := range keys {
+ deps := depmap[pkg]
+ count := len(deps)
+
+ color.New(color.FgBlue).Printf("%s", pkg)
+ if count > 1 {
+ fmt.Printf(" (%d dependencies)\n", count)
+ } else {
+ fmt.Printf(" (%d dependency)\n", count)
+ }
+
+ if ListNoDep {
+ continue
+ }
+ for _, dep := range deps {
+ fmt.Printf(" ► %s\n", dep)
+ }
+ }
+ return nil
+}
diff --git a/main.go b/main.go
index b30b665..d58fba3 100644
--- a/main.go
+++ b/main.go
@@ -5,22 +5,17 @@ import (
"fmt"
"log"
"os"
- "slices"
- "sort"
- "sync"
"github.com/fatih/color"
"github.com/urfave/cli/v3"
)
-// flags
var NoCache, DoClearCache bool
var ListAscend, ListDescend, ListNoDep bool
func main() {
EnsureBrewAvailable()
- // declare CLI app
cmd := &cli.Command{
Name: "wthis",
Usage: "Fetch information of a Homebrew formulae or cask, like how it got installed, reverse dependencies, etc.",
@@ -39,69 +34,23 @@ func main() {
fmt.Println("Cache cleared.")
os.Exit(0)
}
-
- // handle arguments
if cmd.Args().Len() == 0 {
printErrorAndExit("Please provide a formulae/cask name.")
}
- pkgName := cmd.Args().First()
-
- fmt.Print("\033[s")
- showLoadingPrompt(fmt.Sprintf("What the heck is \"%s\"", pkgName))
- // try reading from cache
- var stat *statistics
- if NoCache {
- stat = &statistics{PkgName: pkgName}
- } else {
- stat = NewStatisticsFromCache(pkgName)
- if stat == nil {
- stat = &statistics{PkgName: pkgName}
- }
- }
- fmlChan := make(chan *FormulaInfo)
- caskChan := make(chan *CaskInfo)
- rvsChan := make(chan []string)
- fetchData(pkgName, fmlChan, caskChan, rvsChan)
- var wg sync.WaitGroup
- wg.Add(1)
- go func(){
- defer wg.Done()
- var fml *FormulaInfo
- var cask *CaskInfo
- var rvs []string
- remaining := 3
- for remaining > 0 {
- select {
- case v := <-fmlChan:
- fml = v
- remaining--
- case v := <-caskChan:
- cask = v
- remaining--
- case v := <-rvsChan:
- rvs = v
- remaining--
- }
- fmt.Print("\033[u\033[J")
- stat = NewStatistics(fml, cask, pkgName, rvs)
- stat.Print()
- }
- }()
- wg.Wait()
+ pkgName := cmd.Args().First()
+ stat := fetchAndDisplay(pkgName)
- // cache
if !NoCache {
stat.Cache()
}
-
return nil
},
Commands: []*cli.Command{
{
- Name: "list",
+ Name: "list",
Aliases: []string{"l", "ls"},
- Usage: "Better brew list.",
+ Usage: "Better brew list.",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "ascending",
@@ -125,80 +74,32 @@ func main() {
Destination: &ListNoDep,
},
},
- Action: func(ctx context.Context, cmd *cli.Command) error {
- depmap := GetBrewDeps()
- list := GetBrewList()
-
- // filter and get essential items
- var keys = []string{}
- for k := range depmap {
- if !slices.Contains(list, k) {
- delete(depmap, k)
- } else {
- keys = append(keys, k)
- }
- }
-
- // sort based on dependency count
- if ListAscend {
- sort.Slice(keys, func(i, j int) bool {
- return len(depmap[keys[i]]) > len(depmap[keys[j]])
- })
- } else if ListDescend {
- sort.Slice(keys, func(i, j int) bool {
- return len(depmap[keys[i]]) < len(depmap[keys[j]])
- })
- } else {
- sort.Strings(keys)
- }
-
- //
- for _, pkg := range keys {
- deps := depmap[pkg]
- count := len(deps)
-
- color.New(color.FgBlue).Printf("%s", pkg)
- if count > 1 {
- fmt.Printf(" (%d dependencies)\n", count)
- } else {
- fmt.Printf(" (%d dependency)\n", count)
- }
-
- if ListNoDep { continue }
- for _, dep := range deps {
- fmt.Printf(" ► %s\n", dep)
- }
- }
- return nil
- },
- },
- {
- Name: "clean",
- Aliases: []string{"c", "cache"},
- Usage: "Delete all cache files.",
- Action: func(ctx context.Context, cmd *cli.Command) error {
- // TODO error handling here
- ClearCache()
+ Action: func(ctx context.Context, cmd *cli.Command) error {
+ return runList()
+ },
+ },
+ {
+ Name: "clean",
+ Aliases: []string{"c", "cache"},
+ Usage: "Delete all cache files.",
+ Action: func(ctx context.Context, cmd *cli.Command) error {
+ ClearCache()
fmt.Println("Cache cleared.")
return nil
- },
- },
+ },
+ },
},
}
- // run command and handle error
if err := cmd.Run(context.Background(), os.Args); err != nil {
log.Fatal(err)
}
}
-func fetchData(pkgName string,
- fmlChan chan *FormulaInfo,
- caskChan chan *CaskInfo,
- rvsChan chan []string) {
- // fetching formula/cask info and uses
- // async from brew CLI and HTTP API
- // use whoever comes first
+func fetchData(pkgName string,
+ fmlChan chan *FormulaInfo,
+ caskChan chan *CaskInfo,
+ rvsChan chan []string) {
go func() {
formula, cask := GetBrewInfo(pkgName)
fmlChan <- formula
@@ -207,11 +108,10 @@ func fetchData(pkgName string,
go func() {
fmlChan <- GetFormulaFromAPI(pkgName)
}()
- go func() {
+ go func() {
caskChan <- GetCaskFromAPI(pkgName)
}()
-
- // fetching brew uses
+
go func() {
rvsChan <- GetBrewUses(pkgName)
}()