Compare commits

..
11 Commits
25 changed files with 452 additions and 217 deletions
+7
View File
@@ -0,0 +1,7 @@
# Ignore IDE directories
/.idea
# Ignore build directories
/build
/deb/temp
/deb/out
+27 -6
View File
@@ -1,24 +1,44 @@
# Installation paths # Installation paths
PREFIX ?= /usr/local PREFIX ?= /usr/local
BINDIR ?= $(PREFIX)/bin BINDIR ?= $(PREFIX)/bin
LIBEXECDIR ?= $(PREFIX)/libexec
SYSCONFDIR := $(PREFIX)/etc SYSCONFDIR := $(PREFIX)/etc
# Compilers and tools # Compilers and tools
GO ?= go GO ?= go
# Compiler flags
GOOS ?= $(shell $(GO) env | grep '^GOOS' | cut -d'=' -f2 | tr -d "'")
GOARCH ?= $(shell $(GO) env | grep '^GOARCH' | cut -d'=' -f2 | tr -d "'")
LDFLAGS ?= -w
# Build-time variables # Build-time variables
VERSION ?= $(shell git describe --tags --dirty) VERSION ?= $(shell git describe --tags --dirty)
build: build: build-stormfetch build-stormfetch-monitor-detection
mkdir -p build
cd src; $(GO) build -ldflags "-w -X 'main.StormfetchVersion=$(VERSION)' -X 'main.SystemConfigDir=$(SYSCONFDIR)'" -o ../build/stormfetch stormfetch
install: build/stormfetch config/ build-stormfetch:
# Create directoriy install -d build
cd src/stormfetch; GOOS=$(GOOS) GOARCH=$(GOARCH) $(GO) build -ldflags "$(LDFLAGS) -X 'main.StormfetchVersion=$(VERSION)' -X 'main.SystemConfigDir=$(SYSCONFDIR)' -X 'main.LibexecDir=$(LIBEXECDIR)'" -o ../../build/stormfetch
build-stormfetch-monitor-detection:
install -d build
cd src/stormfetch-monitor-detection; GOOS=$(GOOS) GOARCH=$(GOARCH) $(GO) build -ldflags "$(LDFLAGS)" -o ../../build/stormfetch-monitor-detection
install: install-stormfetch install-stormfetch-monitor-detection install-config
install-stormfetch: build/stormfetch
# Create directory
install -dm755 $(DESTDIR)$(BINDIR) install -dm755 $(DESTDIR)$(BINDIR)
# Install binary # Install binary
install -m755 build/stormfetch $(DESTDIR)$(BINDIR)/stormfetch install -m755 build/stormfetch $(DESTDIR)$(BINDIR)/stormfetch
install-stormfetch-monitor-detection: build/stormfetch-monitor-detection
# Create directory
install -dm755 $(DESTDIR)$(LIBEXECDIR)
# Install binary
install -m755 build/stormfetch-monitor-detection $(DESTDIR)$(LIBEXECDIR)/stormfetch-monitor-detection
install-config: install-config:
# Create directory # Create directory
install -dm755 $(DESTDIR)$(SYSCONFDIR) install -dm755 $(DESTDIR)$(SYSCONFDIR)
@@ -27,9 +47,10 @@ install-config:
uninstall: uninstall:
-rm -f $(DESTDIR)$(BINDIR)/stormfetch -rm -f $(DESTDIR)$(BINDIR)/stormfetch
-rm -f $(DESTDIR)$(LIBEXEDIR)/stormfetch-monitor-detection
-rm -rf $(DESTDIR)$(SYSCONFDIR)/stormfetch -rm -rf $(DESTDIR)$(SYSCONFDIR)/stormfetch
clean: clean:
rm -r build/ rm -r build/
.PHONY: build install install-config uninstall clean .PHONY: build build-stormfetch build-stormfetch-monitor-detection install install-config uninstall clean
+6 -2
View File
@@ -4,14 +4,18 @@
### Project Information ### Project Information
Stormfetch is a program that can read your system's information and display it in the terminal along with the ASCII art of the Linux distribution you are running. Stormfetch is a program that can read your system's information and display it in the terminal along with the ASCII art of the Linux distribution you are running.
Stormfetch is still in beta, so distro compatibility is limited. If you would like to contribute ASCII art or add other compatibility features feel free to create a pull request or notify me through GitLab Issues. At the moment ascii art for different distributions is limited. If you would like to contribute ascii art feel free to make a pull request.
### How it looks ### How it looks
![Stormfetch gif](media/stormfetch.gif) ![Stormfetch gif](media/stormfetch.gif)
### Installation Guide ### Installation Guide
#### Using a package manager #### Using a package manager
- Arch Linux: You may use your favorite AUR manager to install the `stormfetch` package | Distribution | Package name |
|:----------------------:|:------------------------------------------ |
| Arch Linux/Artix Linux | `stormfetch` from the AUR |
| Debian/Ubuntu | latest .deb file from the releases section |
| Tide Linux | `stormfetch` from the main repository |
#### Building from source #### Building from source
- Download `go` from your package manager or from the go website - Download `go` from your package manager or from the go website
- Download `make` from your package manager - Download `make` from your package manager
+5
View File
@@ -0,0 +1,5 @@
stormfetch (7.4.3-1) stretch; urgency=medium
* Initial packaging work with dpkg-buildpackage.
-- EnumDev <[email protected]> Fri, 17 Apr 2026 16:54:39 +0300
+27
View File
@@ -0,0 +1,27 @@
Source: stormfetch
Priority: optional
Maintainer: EnumDev <[email protected]>
Build-Depends:
debhelper-compat (= 13),
libgl-dev,
libx11-dev,
libxcursor-dev,
libxi-dev,
libxinerama-dev,
libxrandr-dev,
libxxf86vm-dev
Vcs-Git: https://github.com/EnumeratedDev/stormfetch.git
Vcs-Browser: https://github.com/EnumeratedDev/stormfetch
Package: stormfetch
Section: universe/utils
Architecture: any
Depends: bash
Suggests: stormfetch-monitor-detection
Description: A linux fetch program written in go
Package: stormfetch-monitor-detection
Section: universe/utils
Architecture: any
Depends: stormfetch,libgl1,libx11-6,libxcursor1,libxi6,libxinerama1,libxrandr2,libxxf86vm1
Description: Monitor detection utility for stormfetch
Vendored Executable
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/make -f
clean:
-rm -r debian/stormfetch
-rm -r debian/stormfetch-monitor-detection
build:
# Build program
make PREFIX=/usr SYSCONFDIR=/etc
binary:
# Create directories
mkdir -p debian/stormfetch
mkdir -p debian/stormfetch-monitor-detection
# Install program
make DESTDIR=debian/stormfetch PREFIX=/usr SYSCONFDIR=/etc install-stormfetch
make DESTDIR=debian/stormfetch PREFIX=/usr SYSCONFDIR=/etc install-config
# Install monitor detection program
make DESTDIR=debian/stormfetch-monitor-detection PREFIX=/usr SYSCONFDIR=/etc install-stormfetch-monitor-detection
# Finalize packages
dh_gencontrol
dh_builddeb
Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 12 MiB

+5
View File
@@ -0,0 +1,5 @@
module stormfetch-monitor-detection
go 1.24.0
require github.com/go-gl/glfw/v3.3/glfw v0.0.0-20260406072232-3ac4aa2bb164
+2
View File
@@ -0,0 +1,2 @@
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20260406072232-3ac4aa2bb164 h1:ddtotcEXIT7dFhSeXIWjK8YMFYl5bB2NdYQwgv6Uqjk=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20260406072232-3ac4aa2bb164/go.mod h1:SyRD8YfuKk+ZXlDqYiqe1qMSqjNgtHzBTG810KUagMc=
+33
View File
@@ -0,0 +1,33 @@
package main
import (
"fmt"
"os"
"strconv"
"github.com/go-gl/glfw/v3.3/glfw"
)
func main() {
defer func() {
if r := recover(); r != nil {
os.Exit(1)
}
}()
err := glfw.Init()
if err != nil {
os.Exit(1)
}
for _, monitor := range glfw.GetMonitors() {
mode := monitor.GetVideoMode()
fmt.Print(monitor.GetName() + ",")
fmt.Print(strconv.Itoa(mode.Width) + ",")
fmt.Print(strconv.Itoa(mode.Height) + ",")
fmt.Print(strconv.Itoa(mode.RefreshRate))
fmt.Println()
}
defer glfw.Terminate()
}
-1
View File
@@ -3,7 +3,6 @@ module stormfetch
go 1.24.0 go 1.24.0
require ( require (
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728
github.com/jackmordaunt/ghw v1.0.5 github.com/jackmordaunt/ghw v1.0.5
github.com/mitchellh/go-ps v1.0.0 github.com/mitchellh/go-ps v1.0.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
-11
View File
@@ -1,13 +1,5 @@
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728 h1:RkGhqHxEVAvPM0/R+8g7XRwQnHatO0KAuVcwHo8q9W8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728/go.mod h1:SyRD8YfuKk+ZXlDqYiqe1qMSqjNgtHzBTG810KUagMc=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/jackmordaunt/ghw v1.0.4 h1:as+COFuPuXaNQC3WqzoHS/E2JYWZU7gN8ompNTUxNxs=
github.com/jackmordaunt/ghw v1.0.4/go.mod h1:4dReYvJ36CoAzIxlEx8du25Qi/YqKYvEGE9QJoRXiK8=
github.com/jackmordaunt/ghw v1.0.5 h1:3rTXwu0D9RkungV7/WlhC8HVuDlPaq0aKY8u0I51jLY= github.com/jackmordaunt/ghw v1.0.5 h1:3rTXwu0D9RkungV7/WlhC8HVuDlPaq0aKY8u0I51jLY=
github.com/jackmordaunt/ghw v1.0.5/go.mod h1:VpFlLXnJErgoRttR3WOxun4v5EE8/xfB4cK26G5q2U0= github.com/jackmordaunt/ghw v1.0.5/go.mod h1:VpFlLXnJErgoRttR3WOxun4v5EE8/xfB4cK26G5q2U0=
github.com/jackmordaunt/pcidb v1.0.1 h1:uLLZa6kD5P39r2cwMyJJkxmuHfH9Wq19gYQEbYcB0Z4= github.com/jackmordaunt/pcidb v1.0.1 h1:uLLZa6kD5P39r2cwMyJJkxmuHfH9Wq19gYQEbYcB0Z4=
@@ -21,10 +13,7 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+61 -10
View File
@@ -3,11 +3,12 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"os/exec"
"path"
"slices" "slices"
"strconv" "strconv"
"strings" "strings"
"github.com/go-gl/glfw/v3.3/glfw"
"github.com/jackmordaunt/ghw" "github.com/jackmordaunt/ghw"
) )
@@ -29,6 +30,7 @@ type GPU struct {
} }
type Monitor struct { type Monitor struct {
Name string
Width int Width int
Height int Height int
RefreshRate int RefreshRate int
@@ -92,8 +94,24 @@ func GetGPUModels(hiddenGPUs []int) []GPU {
continue continue
} }
// Check if device info is set
if gpu.DeviceInfo == nil {
ret = append(ret, GPU{
PCIAddress: gpu.Address,
Vendor: "Unknown",
Name: "GPU",
Product: "Unknown",
Subsystem: "Unknown",
Driver: "Unknown",
VramTotal: "Unknown",
VramUsed: "Unknown",
})
continue
}
// Set alternative names for vendors // Set alternative names for vendors
var vendor string var vendor string
switch gpu.DeviceInfo.Vendor.ID { switch gpu.DeviceInfo.Vendor.ID {
case "1002": case "1002":
vendor = "AMD" vendor = "AMD"
@@ -179,22 +197,55 @@ func GetMotherboardModel() string {
func GetMonitors() []Monitor { func GetMonitors() []Monitor {
var monitors []Monitor var monitors []Monitor
if GetDisplayProtocol() != "" { if GetDisplayProtocol() != "" {
err := glfw.Init() // Find stormfetch-monitor-detection program
if err != nil { execPath, _ := os.Executable()
panic(err) possiblePaths := []string{
path.Join(path.Dir(execPath), "stormfetch-monitor-detection"),
path.Join(LibexecDir, "stormfetch-monitor-detection"),
} }
for _, monitor := range glfw.GetMonitors() { monitorDetectionPath := ""
mode := monitor.GetVideoMode() for _, path := range possiblePaths {
if _, err := os.Stat(path); err == nil {
monitorDetectionPath = path
break
}
}
if monitorDetectionPath == "" {
return nil
}
// Get monitor detection program output
output, err := exec.Command(monitorDetectionPath).Output()
if err != nil {
return nil
}
// Parse output
for line := range strings.SplitSeq(strings.TrimSpace(string(output)), "\n") {
lineSplit := strings.Split(line, ",")
if len(lineSplit) != 4 {
continue
}
name := lineSplit[0]
width, err := strconv.Atoi(lineSplit[1])
height, err := strconv.Atoi(lineSplit[2])
refreshRate, err := strconv.Atoi(lineSplit[3])
if err != nil {
continue
}
monitors = append(monitors, Monitor{ monitors = append(monitors, Monitor{
Width: mode.Width, Name: name,
Height: mode.Height, Width: width,
RefreshRate: mode.RefreshRate, Height: height,
RefreshRate: refreshRate,
}) })
} }
defer glfw.Terminate()
} }
return monitors return monitors
} }
+1
View File
@@ -12,6 +12,7 @@ import (
// Build-time variables // Build-time variables
var StormfetchVersion = "dev" var StormfetchVersion = "dev"
var SystemConfigDir = "/etc/" var SystemConfigDir = "/etc/"
var LibexecDir = "/libexec/"
// Flag variables // Flag variables
var ShowVersion = false var ShowVersion = false
+10 -7
View File
@@ -358,6 +358,11 @@ func initializeModuleMap() {
localIpModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "local_ip", Format: "%3Local IP: %4$LOCAL_IP"}, Execute: func(sm StormfetchModule) string { localIpModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "local_ip", Format: "%3Local IP: %4$LOCAL_IP"}, Execute: func(sm StormfetchModule) string {
localIP := GetLocalIP() localIP := GetLocalIP()
// Return empty string if local IP is unavailable
if localIP == "Unknown" {
return ""
}
return os.Expand(sm.Format, func(s string) string { return os.Expand(sm.Format, func(s string) string {
switch s { switch s {
case "LOCAL_IP": case "LOCAL_IP":
@@ -370,7 +375,7 @@ func initializeModuleMap() {
RegisterModule(localIpModule) RegisterModule(localIpModule)
// DEWM module // DEWM module
dewmModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "de_wm", Format: "%3${DEWM_TYPE}: %4${DEWM_NAME} ${DEWM_VERSION} ($DISPLAY_PROTOCOL)"}, Execute: func(sm StormfetchModule) string { dewmModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "de_wm", Format: "%3${DEWM_TYPE}: %4${DEWM_NAME} ($DISPLAY_PROTOCOL)"}, Execute: func(sm StormfetchModule) string {
// Return empty string if currently in TTY // Return empty string if currently in TTY
if os.Getenv("XDG_SESSION_TYPE") == "" || os.Getenv("XDG_SESSION_TYPE") == "tty" { if os.Getenv("XDG_SESSION_TYPE") == "" || os.Getenv("XDG_SESSION_TYPE") == "tty" {
return "" return ""
@@ -390,8 +395,6 @@ func initializeModuleMap() {
return dewm.Name return dewm.Name
case "DEWM_TYPE": case "DEWM_TYPE":
return dewm.Type return dewm.Type
case "DEWM_VERSION":
return dewm.Version
case "DISPLAY_PROTOCOL": case "DISPLAY_PROTOCOL":
return displayProtocol return displayProtocol
default: default:
@@ -402,15 +405,15 @@ func initializeModuleMap() {
RegisterModule(dewmModule) RegisterModule(dewmModule)
// Monitors module // Monitors module
monitorsModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "monitors", Format: "%3Monitor: %4${MONITOR_WIDTH}x${MONITOR_HEIGHT} ${MONITOR_REFRESH_RATE}Hz"}, Execute: func(sm StormfetchModule) string { monitorsModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "monitors", Format: "%3Monitor ${MONITOR_NAME}: %4${MONITOR_WIDTH}x${MONITOR_HEIGHT} ${MONITOR_REFRESH_RATE}Hz"}, Execute: func(sm StormfetchModule) string {
builder := strings.Builder{} builder := strings.Builder{}
monitors := GetMonitors() monitors := GetMonitors()
for i, monitor := range monitors { for _, monitor := range monitors {
expanded := os.Expand(sm.Format, func(s string) string { expanded := os.Expand(sm.Format, func(s string) string {
switch s { switch s {
case "MONITOR_NUM": case "MONITOR_NAME":
return strconv.Itoa(i + 1) return monitor.Name
case "MONITOR_WIDTH": case "MONITOR_WIDTH":
return strconv.Itoa(monitor.Width) return strconv.Itoa(monitor.Width)
case "MONITOR_HEIGHT": case "MONITOR_HEIGHT":
+22 -8
View File
@@ -146,21 +146,35 @@ func GetInitSystem() string {
// Special cases // Special cases
// OpenRC check // OpenRC check
if _, err := os.Stat("/usr/sbin/openrc"); err == nil { if _, err := os.Stat("/usr/sbin/openrc"); err == nil {
return "OpenRC " + runCommand("openrc --version | awk '{print $3}'", "/bin/sh") openrcVersion := runCommand("openrc --version | awk '{print $3}'", "/bin/sh")
if openrcVersion != "" {
return "OpenRC " + openrcVersion
} else {
return "OpenRC"
}
} }
// Default PID 1 process name checking // Default PID 1 process name checking
switch process.Executable() { initName := process.Executable()
initVersion := ""
switch initName {
case "systemd": case "systemd":
return "Systemd " + runCommand("systemctl --version | head -n1 | awk '{print $2}'", "/bin/sh") initName = "Systemd"
initVersion = runCommand("systemctl --version | head -n1 | awk '{print $2}'", "/bin/sh")
case "runit": case "runit":
return "Runit" initName = "Runit"
case "dinit": case "dinit":
return "Dinit " + runCommand("dinit --version | head -n1 | awk '{print substr($3, 1, length($3)-1)}'", "/bin/sh") initName = "Dinit"
initVersion = runCommand("dinit --version | head -n1 | awk '{print substr($3, 1, length($3)-1)}'", "/bin/sh")
case "enit": case "enit":
return "Enit " + runCommand("enit --version | awk '{print $3}'", "/bin/sh") initName = "Enit"
default: initVersion = runCommand("enit --version | awk '{print $3}'", "/bin/sh")
return process.Executable() }
if initVersion != "" {
return initName + " " + initVersion
} else {
return initName
} }
} }
+224
View File
@@ -0,0 +1,224 @@
package main
import (
"log"
"os"
"path/filepath"
"slices"
"strconv"
"strings"
"github.com/mitchellh/go-ps"
)
type DEWM struct {
Name string
Type string
}
func GetShell() string {
file, err := os.ReadFile("/etc/passwd")
if err != nil {
return ""
}
str := string(file)
shell := ""
for _, line := range strings.Split(str, "\n") {
if strings.TrimSpace(line) == "" {
continue
}
userInfo := strings.Split(line, ":")
if userInfo[2] == strconv.Itoa(os.Getuid()) {
shell = userInfo[6]
}
}
shellName := "Unknown"
shellVersion := ""
switch filepath.Base(shell) {
case "bash":
shellName = "Bash"
shellVersion = runCommand("$SHELL --version | head -n1 | awk '{print $4}'", "/bin/sh")
case "zsh":
shellName = "Zsh"
shellVersion = runCommand("$SHELL --version | awk '{print $2}'", "/bin/sh")
case "fish":
shellName = "Fish"
shellVersion = runCommand("$SHELL --version | awk '{print $3}'", "/bin/sh")
case "nu":
shellName = "Nushell"
shellVersion = runCommand("$SHELL --version", "/bin/sh")
default:
return "Unknown"
}
if shellVersion != "" {
return shellName + " " + shellVersion
} else {
return shellName
}
}
func GetDEWM() DEWM {
processes, err := ps.Processes()
if err != nil {
log.Fatalf("Error: could not get processes: %s", err)
}
var executables []string
for _, process := range processes {
executables = append(executables, process.Executable())
}
processExists := func(process string) bool {
return slices.Contains(executables, process)
}
if processExists("plasmashell") {
dewm := DEWM{
Name: "KDE Plasma",
Type: "DE",
}
if version := runCommand("plasmashell --version | awk '{print $2}'", "/bin/sh"); version != "" {
dewm.Name += " " + version
}
return dewm
} else if processExists("gnome-session") {
dewm := DEWM{
Name: "Gnome",
Type: "DE",
}
if version := runCommand("gnome-shell --version | awk '{print $3}'", "/bin/sh"); version != "" {
dewm.Name += " " + version
}
return dewm
} else if processExists("xfce4-session") {
dewm := DEWM{
Name: "XFCE",
Type: "DE",
}
if version := runCommand("xfce4-session --version | head -n1 | awk '{print $2}'", "/bin/sh"); version != "" {
dewm.Name += " " + version
}
return dewm
} else if processExists("cinnamon") {
dewm := DEWM{
Name: "Cinnamon",
Type: "DE",
}
if version := runCommand("cinnamon --version | awk '{print $3}'", "/bin/sh"); version != "" {
dewm.Name += " " + version
}
return dewm
} else if processExists("mate-panel") {
dewm := DEWM{
Name: "MATE",
Type: "DE",
}
if version := runCommand("mate-about --version | awk '{print $4}'", "/bin/sh"); version != "" {
dewm.Name += " " + version
}
return dewm
} else if processExists("lxsession") {
dewm := DEWM{
Name: "LXDE",
Type: "DE",
}
return dewm
} else if processExists("lxqt-session") {
dewm := DEWM{
Name: "LXQt",
Type: "DE",
}
if version := runCommand("lxqt-session --version | head -n1 | awk '{print $2}'", "/bin/sh"); version != "" {
dewm.Name += " " + version
}
return dewm
} else if processExists("i3") || processExists("i3-with-shmlog") {
dewm := DEWM{
Name: "i3",
Type: "WM",
}
if version := runCommand("i3 --version | awk '{print $3}'", "/bin/sh"); version != "" {
dewm.Name += " " + version
}
return dewm
} else if processExists("sway") {
dewm := DEWM{
Name: "Sway",
Type: "WM",
}
if runCommand("sway --version | awk '{print $1}'", "/bin/sh") == "swayfx" {
dewm.Name = "SwayFX"
} else {
dewm.Name = "Sway"
}
if version := runCommand("sway --version | awk '{print $3}'", "/bin/sh"); version != "" {
dewm.Name += " " + version
}
return dewm
} else if processExists("bspwm") {
dewm := DEWM{
Name: "Bspwm",
Type: "WM",
}
if version := runCommand("bspwm -v", "/bin/sh"); version != "" {
dewm.Name += " " + version
}
return dewm
} else if processExists("Hyprland") {
dewm := DEWM{
Name: "Hyprland",
Type: "WM",
}
if version := runCommand("hyprctl version | sed -n 3p | awk '{print $2}' | tr -d 'v,'", "/bin/sh"); version != "" {
dewm.Name += " " + version
}
return dewm
} else if processExists("icewm-session") {
dewm := DEWM{
Name: "IceWM",
Type: "WM",
}
if version := runCommand("icewm --version | awk '{print $2}'", "/bin/sh"); version != "" {
dewm.Name += " " + version
}
return dewm
}
return DEWM{
Name: "Unknown",
Type: "Unknown",
}
}
func GetDisplayProtocol() string {
protocol := os.Getenv("XDG_SESSION_TYPE")
if protocol == "x11" {
return "X11"
} else if protocol == "wayland" {
return "Wayland"
}
return ""
}
-172
View File
@@ -1,172 +0,0 @@
package main
import (
"log"
"os"
"path/filepath"
"slices"
"strconv"
"strings"
"github.com/mitchellh/go-ps"
)
type DEWM struct {
Name string
Type string
Version string
}
func GetShell() string {
file, err := os.ReadFile("/etc/passwd")
if err != nil {
return ""
}
str := string(file)
shell := ""
for _, line := range strings.Split(str, "\n") {
if strings.TrimSpace(line) == "" {
continue
}
userInfo := strings.Split(line, ":")
if userInfo[2] == strconv.Itoa(os.Getuid()) {
shell = userInfo[6]
}
}
shellName := filepath.Base(shell)
switch shellName {
case "dash":
return "Dash"
case "bash":
return "Bash " + runCommand("echo $BASH_VERSION", "/bin/sh")
case "zsh":
return "Zsh " + runCommand("$SHELL --version | awk '{print $2}'", "/bin/sh")
case "fish":
return "Fish " + runCommand("$SHELL --version | awk '{print $3}'", "/bin/sh")
case "nu":
return "Nushell " + runCommand("$SHELL --version", "/bin/sh")
default:
return "Unknown"
}
}
func GetDEWM() DEWM {
processes, err := ps.Processes()
if err != nil {
log.Fatalf("Error: could not get processes: %s", err)
}
var executables []string
for _, process := range processes {
executables = append(executables, process.Executable())
}
processExists := func(process string) bool {
return slices.Contains(executables, process)
}
if processExists("plasmashell") {
dewm := DEWM{
Name: "KDE Plasma",
Type: "DE",
Version: runCommand("plasmashell --version | awk '{print $2}'", "/bin/sh"),
}
return dewm
} else if processExists("gnome-session") {
dewm := DEWM{
Name: "Gnome",
Type: "DE",
Version: runCommand("gnome-shell --version | awk '{print $3}'", "/bin/sh"),
}
return dewm
} else if processExists("xfce4-session") {
dewm := DEWM{
Name: "XFCE",
Type: "DE",
Version: runCommand("xfce4-session --version | head -n1 | awk '{print $2}'", "/bin/sh"),
}
return dewm
} else if processExists("cinnamon") {
dewm := DEWM{
Name: "Cinnamon",
Type: "DE",
Version: runCommand("cinnamon --version | awk '{print $3}'", "/bin/sh"),
}
return dewm
} else if processExists("mate-panel") {
dewm := DEWM{
Name: "MATE",
Type: "DE",
Version: runCommand("mate-about --version | awk '{print $4}'", "/bin/sh"),
}
return dewm
} else if processExists("lxsession") {
dewm := DEWM{
Name: "LXDE",
Type: "DE",
Version: "",
}
return dewm
} else if processExists("lxqt-session") {
dewm := DEWM{
Name: "LXQt",
Type: "DE",
Version: runCommand("lxqt-session --version | head -n1 | awk '{print $2}'", "/bin/sh"),
}
return dewm
} else if processExists("i3") || processExists("i3-with-shmlog") {
dewm := DEWM{
Name: "i3",
Type: "WM",
Version: runCommand("i3 --version | awk '{print $3}'", "/bin/sh"),
}
return dewm
} else if processExists("sway") {
dewm := DEWM{
Name: "Sway",
Type: "WM",
Version: runCommand("sway --version | awk '{print $3}'", "/bin/sh"),
}
if runCommand("sway --version | awk '{print $1}'", "/bin/sh") == "swayfx" {
dewm.Name = "SwayFX"
} else {
dewm.Name = "Sway"
}
return dewm
} else if processExists("bspwm") {
dewm := DEWM{
Name: "Bspwm",
Type: "WM",
Version: runCommand("bspwm -v", "/bin/sh"),
}
return dewm
} else if processExists("Hyprland") {
dewm := DEWM{
Name: "Hyprland",
Type: "WM",
Version: runCommand("hyprctl version | sed -n 3p | awk '{print $2}' | tr -d 'v,'", "/bin/sh"),
}
return dewm
} else if processExists("icewm-session") {
dewm := DEWM{
Name: "IceWM",
Type: "WM",
Version: runCommand("icewm --version | awk '{print $2}'", "/bin/sh"),
}
return dewm
}
return DEWM{
Name: "Unknown",
Type: "Unknown",
Version: "Unknown",
}
}
func GetDisplayProtocol() string {
protocol := os.Getenv("XDG_SESSION_TYPE")
if protocol == "x11" {
return "X11"
} else if protocol == "wayland" {
return "Wayland"
}
return ""
}