я навайбкодил этот крутой коммит!

This commit is contained in:
nekohepott 2026-06-17 04:16:26 +03:00
parent 43ef696c72
commit 4946fd1695
No known key found for this signature in database
5 changed files with 180 additions and 25 deletions

1
.gitignore vendored
View File

@ -12,3 +12,4 @@ result/
/.idea/go.imports.xml
/.idea/vcs.xml
/.idea/workspace.xml
/goGoFetch

View File

@ -22,11 +22,18 @@ to show custom image and set custom width:
```bash
gogofetch -l path -w 250
```
to place logo on the left (default) or right:
```bash
gogofetch -p left
gogofetch -p right
```
to show help message:
```bash
gogofetch -h
```
config file is created at `~/.config/gogofetch/config.toml`, all parameters are described in config file.
# NixOS
credits to melvi for flake

BIN
logos/arch.png (Stored with Git LFS)

Binary file not shown.

BIN
logos/debian.png (Stored with Git LFS)

Binary file not shown.

183
main.go
View File

@ -13,6 +13,7 @@ import (
"strconv"
"strings"
"time"
"unicode/utf8"
"github.com/BurntSushi/toml"
)
@ -24,10 +25,63 @@ const (
var dist string
var ansiEscapeRe = regexp.MustCompile(`\x1b\[[0-9;?]*[ -/]*[@-~]`)
type Config struct {
Ascii bool `toml:"ascii"`
Layout []string `toml:"layout"`
CustomLogo string `toml:"custom_logo"`
LogoPosition string `toml:"logo_position"`
}
func appendMissingConfigKeys(pathConf string, md toml.MetaData) error {
var missing []string
if !md.IsDefined("ascii") {
missing = append(missing, "# Set this to \"true\" if you like ascii more than images\nascii = false")
}
if !md.IsDefined("layout") {
missing = append(missing, `# 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",
]`)
}
if !md.IsDefined("custom_logo") {
missing = append(missing, "# Absolute path to a custom image or .txt file. Leave empty to use auto-detection.\ncustom_logo = \"\"")
}
if !md.IsDefined("logo_position") {
missing = append(missing, "# Position of the logo block relative to the stats block: \"left\" or \"right\".\nlogo_position = \"left\"")
}
if len(missing) == 0 {
return nil
}
f, err := os.OpenFile(pathConf, os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer func(f *os.File) {
_ = f.Close()
}(f)
block := "\n# Added automatically after update\n\n" + strings.Join(missing, "\n\n") + "\n"
_, err = f.WriteString(block)
return err
}
func getConfigPath() (string, error) {
@ -76,6 +130,9 @@ layout = [
# Absolute path to a custom image or .txt file. Leave empty to use auto-detection.
custom_logo = ""
# Position of the logo block relative to the stats block: "left" or "right".
logo_position = "left"
`)
err := os.WriteFile(pathConf, defaultConfig, 0644)
if err != nil {
@ -83,8 +140,18 @@ custom_logo = ""
}
}
if _, err := toml.DecodeFile(pathConf, &conf); err != nil {
md, err := toml.DecodeFile(pathConf, &conf)
if err != nil {
fmt.Printf("Error loading config at %s: %v\n", pathConf, err)
return conf, pathConf
}
if err := appendMissingConfigKeys(pathConf, md); err != nil {
fmt.Printf("Warning: Could not update config at %s: %v\n", pathConf, err)
} else {
if _, err := toml.DecodeFile(pathConf, &conf); err != nil {
fmt.Printf("Error reloading updated config at %s: %v\n", pathConf, err)
}
}
return conf, pathConf
@ -325,13 +392,88 @@ func printAsciiLogo(path string) string {
return string(content)
}
func printLogoChafa(path string, width uint) {
func renderLogoChafa(path string, width uint) []string {
cols := width / 8
if cols == 0 {
cols = 1
}
sizeArg := fmt.Sprintf("--size=%dx%d", cols, cols/2)
cmd := exec.Command("chafa", path, sizeArg, "--symbols=half")
cmd.Stdout = os.Stdout
if err := cmd.Run(); err != nil {
fmt.Println("Chafa error:", err)
cmd := exec.Command("chafa", path, "--format", "symbols", sizeArg, "--symbols=half")
out, err := cmd.Output()
if err != nil {
return []string{fmt.Sprintf("Chafa error: %v", err)}
}
return splitLines(string(out))
}
func normalizeLogoPosition(pos string) string {
value := strings.ToLower(strings.TrimSpace(pos))
if value == "left" || value == "right" {
return value
}
return "right"
}
func splitLines(content string) []string {
normalized := strings.ReplaceAll(content, "\r\n", "\n")
normalized = strings.TrimRight(normalized, "\n")
if normalized == "" {
return []string{}
}
return strings.Split(normalized, "\n")
}
func maxLineLen(lines []string) int {
maxLen := 0
for _, line := range lines {
lineLen := visibleWidth(line)
if lineLen > maxLen {
maxLen = lineLen
}
}
return maxLen
}
func visibleWidth(line string) int {
stripped := ansiEscapeRe.ReplaceAllString(line, "")
return utf8.RuneCountInString(stripped)
}
func padRightVisible(line string, targetWidth int) string {
pad := targetWidth - visibleWidth(line)
if pad <= 0 {
return line
}
return line + strings.Repeat(" ", pad)
}
func renderSideBySide(statsLines []string, logoLines []string, position string) {
const gap = " "
statsWidth := maxLineLen(statsLines)
logoWidth := maxLineLen(logoLines)
lineCount := len(statsLines)
if len(logoLines) > lineCount {
lineCount = len(logoLines)
}
for i := 0; i < lineCount; i++ {
stats := ""
logo := ""
if i < len(statsLines) {
stats = statsLines[i]
}
if i < len(logoLines) {
logo = logoLines[i]
}
if position == "left" {
fmt.Printf("%s%s%s\n", padRightVisible(logo, logoWidth), gap, stats)
continue
}
fmt.Printf("%s%s%s\n", padRightVisible(stats, statsWidth), gap, logo)
}
}
@ -414,9 +556,11 @@ func main() {
defaultLogo = getLogo(dist)
}
width := flag.Int("w", 200, "Logo width in lines")
width := flag.Int("w", 190, "Logo width in lines")
logoPath := flag.String("l", getAbsLogoPath(defaultLogo), "Path to the logo")
logoPos := flag.String("p", normalizeLogoPosition(conf.LogoPosition), "Logo position: left or right")
flag.Parse()
position := normalizeLogoPosition(*logoPos)
type Info struct {
Label string
@ -451,18 +595,21 @@ func main() {
}
}
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)
var statsLines []string
for _, info := range stats {
statsLines = append(statsLines, fmt.Sprintf("~ %s%s%s: %s", Blue, info.Label, Reset, info.Value))
}
for _, info := range stats {
fmt.Printf("~ %s%s%s: %s\n", Blue, info.Label, Reset, info.Value)
var logoLines []string
if _, err := os.Stat(*logoPath); err == nil {
if conf.Ascii {
logoLines = splitLines(printAsciiLogo(*logoPath))
} else {
logoLines = renderLogoChafa(*logoPath, uint(*width))
}
} else {
logoLines = []string{fmt.Sprintf("Logo not found at: %s", *logoPath)}
}
renderSideBySide(statsLines, logoLines, position)
}