MASSIVE update, you know what else is massive?

This commit is contained in:
nekohepott 2026-06-17 04:16:26 +03:00
parent 203e966106
commit 697319178b
No known key found for this signature in database
8 changed files with 205 additions and 52 deletions

View File

@ -25,7 +25,7 @@ buildGoApplication {
postInstall = '' postInstall = ''
mkdir -p $out/share/gogofetch/logos 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 \ wrapProgram $out/bin/goGoFetch \
--prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.chafa ]} --prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.chafa ]}

7
go.mod
View File

@ -2,9 +2,4 @@ module goGoFetch
go 1.26 go 1.26
require github.com/mattn/go-sixel v0.0.8 require github.com/BurntSushi/toml v1.6.0
require (
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/soniakeys/quant v1.0.0 // indirect
)

6
go.sum
View File

@ -1,8 +1,2 @@
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= 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=

7
logos/arch.txt Normal file
View File

@ -0,0 +1,7 @@
/\
/ \
/ \
/ \
/ ,, \
/ | | \
/_-'' ''-_\

6
logos/debian.txt Normal file
View File

@ -0,0 +1,6 @@
_____
/ __ \
| / |
| \___-
-_
--_

8
logos/linux.txt Normal file
View File

@ -0,0 +1,8 @@
.--.
|o_o |
|:_/ |
// \ \
(| | )
/'\_ _/`\
\___)=(___/

7
logos/nixos.txt Normal file
View File

@ -0,0 +1,7 @@
\\ \\ //
==\\__\\/ //
// \\//
==// //==
//\\___//
// /\\ \\==
// \\ \\

214
main.go
View File

@ -13,6 +13,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/BurntSushi/toml"
) )
const ( const (
@ -22,6 +24,72 @@ const (
var dist string 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 { func getDist() string {
f, _ := os.Open("/etc/os-release") f, _ := os.Open("/etc/os-release")
defer func(f *os.File) { defer func(f *os.File) {
@ -102,23 +170,39 @@ func getCpu() string {
func getGpu() string { func getGpu() string {
out, err := exec.Command("sh", "-c", "lspci | grep -E 'VGA|3D'").Output() out, err := exec.Command("sh", "-c", "lspci | grep -E 'VGA|3D'").Output()
if err != nil { if err != nil || len(out) == 0 {
return "Unknown GPU" return "Unknown or no GPU"
} }
line := string(out)
parts := strings.Split(line, ": ") lines := strings.Split(strings.TrimSpace(string(out)), "\n")
if len(parts) > 1 { var gpus []string
return cleanGpuString(parts[1])
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" return "GPU not found"
} }
func cleanGpuString(raw string) string { func cleanGpuString(raw string) string {
re := regexp.MustCompile(`\(.*\)`) re := regexp.MustCompile(`\[.*?]|\(.*?\)`)
res := re.ReplaceAllString(raw, "") res := re.ReplaceAllString(raw, "")
res = strings.ReplaceAll(res, "Corporation", "") res = strings.ReplaceAll(res, "Corporation", "")
res = strings.ReplaceAll(res, "[", "") res = strings.ReplaceAll(res, "Controller", "")
res = strings.ReplaceAll(res, "]", "") res = strings.ReplaceAll(res, "VGA compatible", "")
res = strings.ReplaceAll(res, "3D", "")
return strings.Join(strings.Fields(res), " ") return strings.Join(strings.Fields(res), " ")
} }
@ -164,7 +248,7 @@ func getPkgs() string {
out, _ := exec.Command("sh", "-c", "pacman -Qq | wc -l").Output() out, _ := exec.Command("sh", "-c", "pacman -Qq | wc -l").Output()
pkgs = strings.TrimSpace(string(out)) + " (pacman)" pkgs = strings.TrimSpace(string(out)) + " (pacman)"
if haveNix { if haveNix {
pkgs = strings.TrimSpace(string(pkgs + ", " + addNix())) pkgs = strings.TrimSpace(pkgs + ", " + addNix())
} }
return pkgs return pkgs
} }
@ -172,7 +256,7 @@ func getPkgs() string {
out, _ := exec.Command("sh", "-c", "dpkg -l | grep ^ii | wc -l").Output() out, _ := exec.Command("sh", "-c", "dpkg -l | grep ^ii | wc -l").Output()
pkgs = strings.TrimSpace(string(out)) + " (apt)" pkgs = strings.TrimSpace(string(out)) + " (apt)"
if haveNix { if haveNix {
pkgs = strings.TrimSpace(string(pkgs + ", " + addNix())) pkgs = strings.TrimSpace(pkgs + ", " + addNix())
} }
return pkgs 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 cols := width / 8
sizeArg := fmt.Sprintf("--size=%dx%d", cols, cols/2) sizeArg := fmt.Sprintf("--size=%dx%d", cols, cols/2)
cmd := exec.Command("chafa", path, sizeArg, "--symbols=half") cmd := exec.Command("chafa", path, sizeArg, "--symbols=half")
@ -270,41 +375,72 @@ func getUptime() string {
} }
func main() { 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 { type Info struct {
Label string Label string
Value string Value string
} }
dist := getDist() var stats []Info
logo := getLogo(dist)
absoluteDefaultLogo := getAbsLogoPath(logo) for _, item := range conf.Layout {
switch strings.ToLower(item) {
stats := []Info{ case "dist":
{"dist", dist}, stats = append(stats, Info{"dist", dist})
{"host", getHostname()}, case "host":
{"cpu", getCpu()}, stats = append(stats, Info{"host", getHostname()})
{"krnl", getKernel()}, case "cpu":
{"ram", getRam()}, stats = append(stats, Info{"cpu", getCpu()})
{"gpu", getGpu()}, case "kernel", "krnl":
{"de/wm", getDE()}, stats = append(stats, Info{"krnl", getKernel()})
{"pkgs", getPkgs()}, case "ram":
{"shell", getShell()}, stats = append(stats, Info{"ram", getRam()})
{"term", getTerminal()}, case "gpu":
{"uptime", getUptime()}, 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") if _, err := os.Stat(*logoPath); err == nil {
width := flag.Int("w", 200, "Logo width in lines") if conf.Ascii {
flag.Parse() fmt.Print(printAsciiLogo(*logoPath))
if _, err := os.Stat(*logoPath); os.IsNotExist(err) { fmt.Println()
fmt.Printf("Image '%s' not found\n", *logoPath) } else {
return printLogoChafa(*logoPath, uint(*width))
}
} else {
fmt.Printf("Logo not found at: %s\n", *logoPath)
} }
printLogo(*logoPath, uint(*width)) for _, info := range stats {
fmt.Printf("~ %s%s%s: %s\n", Blue, info.Label, Reset, info.Value)
for _, s := range stats {
fmt.Printf("~ %s%s%s: %s\n", Blue, s.Label, Reset, s.Value)
} }
} }