From 697319178b4243557e37f682ddeff9822679fc44 Mon Sep 17 00:00:00 2001 From: nekohepott Date: Wed, 17 Jun 2026 04:16:26 +0300 Subject: [PATCH] MASSIVE update, you know what else is massive? --- default.nix | 2 +- go.mod | 7 +- go.sum | 6 -- logos/arch.txt | 7 ++ logos/debian.txt | 6 ++ logos/linux.txt | 8 ++ logos/nixos.txt | 7 ++ main.go | 214 ++++++++++++++++++++++++++++++++++++++--------- 8 files changed, 205 insertions(+), 52 deletions(-) create mode 100644 logos/arch.txt create mode 100644 logos/debian.txt create mode 100644 logos/linux.txt create mode 100644 logos/nixos.txt diff --git a/default.nix b/default.nix index 0ccf366..897f9c6 100644 --- a/default.nix +++ b/default.nix @@ -25,7 +25,7 @@ buildGoApplication { postInstall = '' mkdir -p $out/share/gogofetch/logos - cp -r assets/*.png $out/share/gogofetch/logos/ + cp -r logos/*.png $out/share/gogofetch/logos/ wrapProgram $out/bin/goGoFetch \ --prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.chafa ]} diff --git a/go.mod b/go.mod index 72deba9..9703dda 100644 --- a/go.mod +++ b/go.mod @@ -2,9 +2,4 @@ module goGoFetch go 1.26 -require github.com/mattn/go-sixel v0.0.8 - -require ( - github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect - github.com/soniakeys/quant v1.0.0 // indirect -) +require github.com/BurntSushi/toml v1.6.0 diff --git a/go.sum b/go.sum index 5cc24ad..f74b269 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,2 @@ github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/mattn/go-sixel v0.0.8 h1:H0bBGQVOJoSvzvtTgCInxvg1IZiNlTcIIIx8A6uvjpQ= -github.com/mattn/go-sixel v0.0.8/go.mod h1:wbDSbrwpykVI1qEHyjZYsDgaJTwpVg9wSwmmh2slnBw= -github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= -github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= -github.com/soniakeys/quant v1.0.0 h1:N1um9ktjbkZVcywBVAAYpZYSHxEfJGzshHCxx/DaI0Y= -github.com/soniakeys/quant v1.0.0/go.mod h1:HI1k023QuVbD4H8i9YdfZP2munIHU4QpjsImz6Y6zds= diff --git a/logos/arch.txt b/logos/arch.txt new file mode 100644 index 0000000..aeedf21 --- /dev/null +++ b/logos/arch.txt @@ -0,0 +1,7 @@ + /\ + / \ + / \ + / \ + / ,, \ + / | | \ +/_-'' ''-_\ \ No newline at end of file diff --git a/logos/debian.txt b/logos/debian.txt new file mode 100644 index 0000000..73083b3 --- /dev/null +++ b/logos/debian.txt @@ -0,0 +1,6 @@ + _____ + / __ \ +| / | +| \___- +-_ + --_ \ No newline at end of file diff --git a/logos/linux.txt b/logos/linux.txt new file mode 100644 index 0000000..abca686 --- /dev/null +++ b/logos/linux.txt @@ -0,0 +1,8 @@ + .--. + |o_o | + |:_/ | + // \ \ + (| | ) +/'\_ _/`\ +\___)=(___/ + diff --git a/logos/nixos.txt b/logos/nixos.txt new file mode 100644 index 0000000..d74dd64 --- /dev/null +++ b/logos/nixos.txt @@ -0,0 +1,7 @@ + \\ \\ // + ==\\__\\/ // + // \\// +==// //== + //\\___// +// /\\ \\== + // \\ \\ \ No newline at end of file diff --git a/main.go b/main.go index ac60f9a..26d0961 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,8 @@ import ( "strconv" "strings" "time" + + "github.com/BurntSushi/toml" ) const ( @@ -22,6 +24,72 @@ const ( var dist string +type Config struct { + Ascii bool `toml:"ascii"` + Layout []string `toml:"layout"` + CustomLogo string `toml:"custom_logo"` +} + +func getConfigPath() (string, error) { + configDir, err := os.UserConfigDir() + if err != nil { + return "", err + } + directoryName := "gogofetch" + fullPath := filepath.Join(configDir, directoryName, "config.toml") + + return fullPath, nil +} + +func initConfig() (Config, string) { + var conf Config + pathConf, err := getConfigPath() + if err != nil { + return conf, "" + } + + err = os.MkdirAll(filepath.Dir(pathConf), 0755) + if err != nil { + return Config{}, "" + } + + if _, err := os.Stat(pathConf); os.IsNotExist(err) { + defaultConfig := []byte(` +# Set this to "true" if you like ascii more than images +ascii = false + +# Stats layout: reorder or remove items to customize your fetch +# Available: "dist", "host", "cpu", "kernel", "ram", "gpu", "de/wm", "pkgs", "shell", "terminal", "uptime" +layout = [ + "dist", + "host", + "cpu", + "kernel", + "ram", + "gpu", + "de/wm", + "pkgs", + "shell", + "terminal", + "uptime", +] + +# Absolute path to a custom image or .txt file. Leave empty to use auto-detection. +custom_logo = "" +`) + err := os.WriteFile(pathConf, defaultConfig, 0644) + if err != nil { + return Config{}, "" + } + } + + if _, err := toml.DecodeFile(pathConf, &conf); err != nil { + fmt.Printf("Error loading config at %s: %v\n", pathConf, err) + } + + return conf, pathConf +} + func getDist() string { f, _ := os.Open("/etc/os-release") defer func(f *os.File) { @@ -102,23 +170,39 @@ func getCpu() string { func getGpu() string { out, err := exec.Command("sh", "-c", "lspci | grep -E 'VGA|3D'").Output() - if err != nil { - return "Unknown GPU" + if err != nil || len(out) == 0 { + return "Unknown or no GPU" } - line := string(out) - parts := strings.Split(line, ": ") - if len(parts) > 1 { - return cleanGpuString(parts[1]) + + lines := strings.Split(strings.TrimSpace(string(out)), "\n") + var gpus []string + + for _, line := range lines { + parts := strings.Split(line, ": ") + if len(parts) > 1 { + cleaned := cleanGpuString(parts[len(parts)-1]) + if cleaned != "" { + gpus = append(gpus, cleaned) + } + } } + + if len(gpus) > 0 { + return strings.Join(gpus, " / ") + } + return "GPU not found" } func cleanGpuString(raw string) string { - re := regexp.MustCompile(`\(.*\)`) + re := regexp.MustCompile(`\[.*?]|\(.*?\)`) res := re.ReplaceAllString(raw, "") + res = strings.ReplaceAll(res, "Corporation", "") - res = strings.ReplaceAll(res, "[", "") - res = strings.ReplaceAll(res, "]", "") + res = strings.ReplaceAll(res, "Controller", "") + res = strings.ReplaceAll(res, "VGA compatible", "") + res = strings.ReplaceAll(res, "3D", "") + return strings.Join(strings.Fields(res), " ") } @@ -164,7 +248,7 @@ func getPkgs() string { out, _ := exec.Command("sh", "-c", "pacman -Qq | wc -l").Output() pkgs = strings.TrimSpace(string(out)) + " (pacman)" if haveNix { - pkgs = strings.TrimSpace(string(pkgs + ", " + addNix())) + pkgs = strings.TrimSpace(pkgs + ", " + addNix()) } return pkgs } @@ -172,7 +256,7 @@ func getPkgs() string { out, _ := exec.Command("sh", "-c", "dpkg -l | grep ^ii | wc -l").Output() pkgs = strings.TrimSpace(string(out)) + " (apt)" if haveNix { - pkgs = strings.TrimSpace(string(pkgs + ", " + addNix())) + pkgs = strings.TrimSpace(pkgs + ", " + addNix()) } return pkgs } @@ -199,7 +283,28 @@ func getLogo(dist string) string { } } -func printLogo(path string, width uint) { +func getAscii(dist string) string { + switch { + case strings.HasPrefix(dist, "Arch"): + return "logos/arch.txt" + case strings.HasPrefix(dist, "NixOS"): + return "logos/nixos.txt" + case strings.HasPrefix(dist, "Debian"): + return "logos/debian.txt" + default: + return "logos/linux.txt" + } +} + +func printAsciiLogo(path string) string { + content, err := os.ReadFile(path) + if err != nil { + return fmt.Sprintf("Error: Could not read ASCII file at %s\n", path) + } + return string(content) +} + +func printLogoChafa(path string, width uint) { cols := width / 8 sizeArg := fmt.Sprintf("--size=%dx%d", cols, cols/2) cmd := exec.Command("chafa", path, sizeArg, "--symbols=half") @@ -270,41 +375,72 @@ func getUptime() string { } func main() { + conf, _ := initConfig() + + if len(conf.Layout) == 0 { + conf.Layout = []string{"dist", "host", "cpu", "ram", "shell", "uptime"} + } + + dist := getDist() + var defaultLogo string + + if conf.CustomLogo != "" { + defaultLogo = conf.CustomLogo + } else if conf.Ascii { + defaultLogo = getAscii(dist) + } else { + defaultLogo = getLogo(dist) + } + + width := flag.Int("w", 200, "Logo width in lines") + logoPath := flag.String("l", getAbsLogoPath(defaultLogo), "Path to the logo") + flag.Parse() + type Info struct { Label string Value string } - dist := getDist() - logo := getLogo(dist) + var stats []Info - absoluteDefaultLogo := getAbsLogoPath(logo) - - stats := []Info{ - {"dist", dist}, - {"host", getHostname()}, - {"cpu", getCpu()}, - {"krnl", getKernel()}, - {"ram", getRam()}, - {"gpu", getGpu()}, - {"de/wm", getDE()}, - {"pkgs", getPkgs()}, - {"shell", getShell()}, - {"term", getTerminal()}, - {"uptime", getUptime()}, + for _, item := range conf.Layout { + switch strings.ToLower(item) { + case "dist": + stats = append(stats, Info{"dist", dist}) + case "host": + stats = append(stats, Info{"host", getHostname()}) + case "cpu": + stats = append(stats, Info{"cpu", getCpu()}) + case "kernel", "krnl": + stats = append(stats, Info{"krnl", getKernel()}) + case "ram": + stats = append(stats, Info{"ram", getRam()}) + case "gpu": + stats = append(stats, Info{"gpu", getGpu()}) + case "de/wm", "de", "wm": + stats = append(stats, Info{"de/wm", getDE()}) + case "pkgs": + stats = append(stats, Info{"pkgs", getPkgs()}) + case "shell": + stats = append(stats, Info{"shell", getShell()}) + case "terminal", "term": + stats = append(stats, Info{"term", getTerminal()}) + case "uptime": + stats = append(stats, Info{"uptime", getUptime()}) + } } - logoPath := flag.String("l", absoluteDefaultLogo, "Absolute or relative path to the logo image") - width := flag.Int("w", 200, "Logo width in lines") - flag.Parse() - if _, err := os.Stat(*logoPath); os.IsNotExist(err) { - fmt.Printf("Image '%s' not found\n", *logoPath) - return + if _, err := os.Stat(*logoPath); err == nil { + if conf.Ascii { + fmt.Print(printAsciiLogo(*logoPath)) + fmt.Println() + } else { + printLogoChafa(*logoPath, uint(*width)) + } + } else { + fmt.Printf("Logo not found at: %s\n", *logoPath) } - printLogo(*logoPath, uint(*width)) - - for _, s := range stats { - fmt.Printf("~ %s%s%s: %s\n", Blue, s.Label, Reset, s.Value) + for _, info := range stats { + fmt.Printf("~ %s%s%s: %s\n", Blue, info.Label, Reset, info.Value) } - }