Compare commits

14 Commits
10 changed files with 301 additions and 144 deletions
+3 -2
View File
@@ -19,7 +19,8 @@ Stormfetch is still in beta, so distro compatibility is limited. If you would li
``` ```
make SYSCONFDIR=/etc make SYSCONFDIR=/etc
``` ```
- Run the following command to install stormfetch into your system. You may also append a DESTDIR variable at the end of this line if you wish to install in a different location - Run the following command to install stormfetch into your system. You may also append a DESTDIR variable at the end of this line if you wish to install in a different root directory
``` ```
make install PREFIX=/usr SYSCONFDIR=/etc make install
make install-config SYSCONFDIR=/etc
``` ```
+1 -1
View File
@@ -5,7 +5,7 @@ modules:
- name: kernel - name: kernel
- name: packages - name: packages
- name: shell - name: shell
- name: init - name: init_system
- name: motherboard - name: motherboard
- name: cpus - name: cpus
- name: gpus - name: gpus
+9 -5
View File
@@ -5,9 +5,13 @@ import (
"strings" "strings"
) )
func setupColorMap(asciiArtHeader string) map[int]string { func setupColorMap(asciiArtHeader string) []string {
colorMap := make(map[int]string) colorMap := make([]string, 10)
colorMap[0] = "\033[0m"
// Set default color map values
for i := range 10 {
colorMap[i] = "\033[0m"
}
// Return if header is empty // Return if header is empty
if asciiArtHeader == "" { if asciiArtHeader == "" {
@@ -16,8 +20,8 @@ func setupColorMap(asciiArtHeader string) map[int]string {
// Read colors from ascii art header // Read colors from ascii art header
ansiColors := strings.Split(strings.TrimPrefix(asciiArtHeader, "#/"), ";") ansiColors := strings.Split(strings.TrimPrefix(asciiArtHeader, "#/"), ";")
for i, ansiColor := range ansiColors { for i := 0; i < 9 && i < len(ansiColors); i++ {
colorMap[i+1] = fmt.Sprintf("\033[38;5;%sm", ansiColor) colorMap[i+1] = fmt.Sprintf("\033[38;5;%sm", ansiColors[i])
} }
return colorMap return colorMap
+5 -4
View File
@@ -10,7 +10,6 @@ import (
type StormfetchConfig struct { type StormfetchConfig struct {
Ascii string `yaml:"distro_ascii"` Ascii string `yaml:"distro_ascii"`
DistroName string `yaml:"distro_name"`
Modules []stormfetchModuleConfig `yaml:"modules"` Modules []stormfetchModuleConfig `yaml:"modules"`
AnsiiColors []int `yaml:"ansii_colors"` AnsiiColors []int `yaml:"ansii_colors"`
ForceConfigAnsii bool `yaml:"force_config_ansii"` ForceConfigAnsii bool `yaml:"force_config_ansii"`
@@ -22,20 +21,22 @@ var config = StormfetchConfig{
} }
func readConfig() { func readConfig() {
if ConfigPath == "" {
// Get home directory // Get home directory
userConfigDir, _ := os.UserConfigDir() userConfigDir, _ := os.UserConfigDir()
// Find valid config directory // Find valid config directory
if _, err := os.Stat(path.Join(userConfigDir, "stormfetch/config.yml")); err == nil { if _, err := os.Stat(path.Join(userConfigDir, "stormfetch/config.yml")); err == nil {
configPath = path.Join(userConfigDir, "stormfetch/config.yml") ConfigPath = path.Join(userConfigDir, "stormfetch/config.yml")
} else if _, err := os.Stat(path.Join(SystemConfigDir, "stormfetch/config.yml")); err == nil { } else if _, err := os.Stat(path.Join(SystemConfigDir, "stormfetch/config.yml")); err == nil {
configPath = path.Join(SystemConfigDir, "stormfetch/config.yml") ConfigPath = path.Join(SystemConfigDir, "stormfetch/config.yml")
} else { } else {
log.Fatalf("Config file not found: %s", err.Error()) log.Fatalf("Config file not found: %s", err.Error())
} }
}
// Parse config // Parse config
bytes, err := os.ReadFile(configPath) bytes, err := os.ReadFile(ConfigPath)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
+9 -6
View File
@@ -15,22 +15,22 @@ var SystemConfigDir = "/etc/"
// Flag variables // Flag variables
var ShowVersion = false var ShowVersion = false
var ConfigPath = ""
var Ascii = ""
var ShowModuleTimeTaken = false var ShowModuleTimeTaken = false
var configPath = ""
func main() { func main() {
readConfig()
parseFlags() parseFlags()
readConfig()
initializeModuleMap() initializeModuleMap()
run() run()
} }
func parseFlags() { func parseFlags() {
flag.BoolVar(&ShowVersion, "version", false, "Show Stormfetch version") flag.BoolVar(&ShowVersion, "version", false, "Show Stormfetch version")
flag.StringVar(&ConfigPath, "config", "", "Use the specified config file")
flag.BoolVar(&ShowModuleTimeTaken, "time-taken", false, "Show time taken to execute each module") flag.BoolVar(&ShowModuleTimeTaken, "time-taken", false, "Show time taken to execute each module")
flag.StringVar(&config.Ascii, "ascii", config.Ascii, "Set distro ascii") flag.StringVar(&Ascii, "ascii", "", "Set distro ascii")
flag.StringVar(&config.DistroName, "distro-name", config.DistroName, "Set distro name")
flag.Parse() flag.Parse()
} }
@@ -91,6 +91,9 @@ func run() {
text := module.Execute(module) text := module.Execute(module)
end := time.Now().UnixMilli() end := time.Now().UnixMilli()
// Insert default color at the start of the module's text
text = colorMap[0] + text
// Show time taken // Show time taken
if ShowModuleTimeTaken { if ShowModuleTimeTaken {
fmt.Printf("Module '%s' took %d milliseconds\n", module.Name, end-start) fmt.Printf("Module '%s' took %d milliseconds\n", module.Name, end-start)
@@ -104,7 +107,7 @@ func run() {
} }
// Continue if text length is 0 // Continue if text length is 0
if len(textNoColor) == 0 { if len(textNoColor)-len(colorMap[0]) == 0 {
continue continue
} }
+58 -6
View File
@@ -100,10 +100,12 @@ func initializeModuleMap() {
// Packages module // Packages module
packagesModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "packages", Format: "%3Packages: %4$PACKAGES"}, Execute: func(sm StormfetchModule) string { packagesModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "packages", Format: "%3Packages: %4$PACKAGES"}, Execute: func(sm StormfetchModule) string {
packages := GetInstalledPackages()
return os.Expand(sm.Format, func(s string) string { return os.Expand(sm.Format, func(s string) string {
switch s { switch s {
case "PACKAGES": case "PACKAGES":
return GetInstalledPackages() return packages
default: default:
return "" return ""
} }
@@ -113,10 +115,12 @@ func initializeModuleMap() {
// Shell module // Shell module
shellModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "shell", Format: "%3Shell: %4$SHELL"}, Execute: func(sm StormfetchModule) string { shellModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "shell", Format: "%3Shell: %4$SHELL"}, Execute: func(sm StormfetchModule) string {
shell := GetShell()
return os.Expand(sm.Format, func(s string) string { return os.Expand(sm.Format, func(s string) string {
switch s { switch s {
case "SHELL": case "SHELL":
return GetShell() return shell
default: default:
return "" return ""
} }
@@ -126,10 +130,16 @@ func initializeModuleMap() {
// Init system module // Init system module
initSystemModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "init_system", Format: "%3Init: %4$INIT"}, Execute: func(sm StormfetchModule) string { initSystemModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "init_system", Format: "%3Init: %4$INIT"}, Execute: func(sm StormfetchModule) string {
initSystem := GetInitSystem()
if initSystem == "" {
return ""
}
return os.Expand(sm.Format, func(s string) string { return os.Expand(sm.Format, func(s string) string {
switch s { switch s {
case "INIT": case "INIT":
return GetInitSystem() return initSystem
default: default:
return "" return ""
} }
@@ -139,10 +149,12 @@ func initializeModuleMap() {
// Libc module // Libc module
libcModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "libc", Format: "%3Libc: %4$LIBC"}, Execute: func(sm StormfetchModule) string { libcModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "libc", Format: "%3Libc: %4$LIBC"}, Execute: func(sm StormfetchModule) string {
libc := GetLibc()
return os.Expand(sm.Format, func(s string) string { return os.Expand(sm.Format, func(s string) string {
switch s { switch s {
case "LIBC": case "LIBC":
return GetLibc() return libc
default: default:
return "" return ""
} }
@@ -244,6 +256,10 @@ func initializeModuleMap() {
memoryModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "memory", Format: "%3Memory: %4$MEM_USED MiB / $MEM_TOTAL MiB"}, Execute: func(sm StormfetchModule) string { memoryModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "memory", Format: "%3Memory: %4$MEM_USED MiB / $MEM_TOTAL MiB"}, Execute: func(sm StormfetchModule) string {
memoryInfo := GetMemoryInfo() memoryInfo := GetMemoryInfo()
if memoryInfo == nil {
return ""
}
return os.Expand(sm.Format, func(s string) string { return os.Expand(sm.Format, func(s string) string {
switch s { switch s {
case "MEM_TOTAL": case "MEM_TOTAL":
@@ -330,10 +346,12 @@ func initializeModuleMap() {
// Local IP module // Local IP module
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()
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":
return GetLocalIP() return localIP
default: default:
return "" return ""
} }
@@ -349,6 +367,7 @@ func initializeModuleMap() {
} }
dewm := GetDEWM() dewm := GetDEWM()
displayProtocol := GetDisplayProtocol()
// Return empty string if can't detect DE/WM // Return empty string if can't detect DE/WM
if dewm.Name == "Unknown" { if dewm.Name == "Unknown" {
@@ -364,7 +383,7 @@ func initializeModuleMap() {
case "DEWM_VERSION": case "DEWM_VERSION":
return dewm.Version return dewm.Version
case "DISPLAY_PROTOCOL": case "DISPLAY_PROTOCOL":
return GetDisplayProtocol() return displayProtocol
default: default:
return "" return ""
} }
@@ -399,4 +418,37 @@ func initializeModuleMap() {
return builder.String() return builder.String()
}} }}
RegisterModule(monitorsModule) RegisterModule(monitorsModule)
// Custom module
customModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "custom"}, Execute: func(sm StormfetchModule) string {
shell, _ := sm.GetData("shell", "/bin/sh")
commandList, _ := sm.GetData("commands", make([]any, 0))
// Exeucte all commands
commandOutput := make(map[int]string)
for i, value := range commandList.([]any) {
command, ok := value.(string)
if !ok {
continue
}
commandOutput[i+1] = runCommand(command, shell.(string))
}
return os.Expand(sm.Format, func(s string) string {
if len(s) <= 4 || !strings.HasPrefix(s, "CMD_") {
return ""
}
commandIndexStr := strings.Split(s, "CMD_")[1]
commandIndex, err := strconv.Atoi(commandIndexStr)
if err != nil {
return ""
}
return commandOutput[commandIndex]
})
}}
RegisterModule(customModule)
} }
+139 -15
View File
@@ -2,25 +2,29 @@ package main
import ( import (
"fmt" "fmt"
"os"
"os/exec" "os/exec"
"path"
"strconv"
"strings" "strings"
) )
type PackageManager struct { type PackageManager struct {
Name string Name string
ExecutableName string ExecutableName string
PackageListCommand string GetPackages func(...any) int
FunctionInput []any
} }
var PackageManagers = []PackageManager{ var PackageManagers = []PackageManager{
{Name: "dpkg", ExecutableName: "dpkg", PackageListCommand: "dpkg-query -f '${Package}\\n' -W"}, {Name: "dpkg", ExecutableName: "dpkg", GetPackages: pmFileLines, FunctionInput: []any{"/var/lib/dpkg/status", "Status: install ok installed"}},
{Name: "pacman", ExecutableName: "pacman", PackageListCommand: "pacman -Q"}, {Name: "pacman", ExecutableName: "pacman", GetPackages: pmDirectoryElements, FunctionInput: []any{"/var/lib/pacman/local/", true}},
{Name: "rpm", ExecutableName: "rpm", PackageListCommand: "rpm -qa"}, {Name: "rpm", ExecutableName: "rpm", GetPackages: pmShellCommandLines, FunctionInput: []any{"rpm -qa"}},
{Name: "xbps", ExecutableName: "xbps-query", PackageListCommand: "xbps-query -l"}, {Name: "xbps", ExecutableName: "xbps-query", GetPackages: pmFileLines, FunctionInput: []any{"/var/db/xbps/pkgdb-0.38.plist", "<string>installed</string>"}},
{Name: "bpm", ExecutableName: "bpm", PackageListCommand: "ls /var/lib/bpm/installed/"}, {Name: "bpm", ExecutableName: "bpm", GetPackages: pmDirectoryElements, FunctionInput: []any{"/var/lib/bpm/installed/"}},
{Name: "portage", ExecutableName: "emerge", PackageListCommand: "find /var/db/pkg/*/ -mindepth 1 -maxdepth 1"}, {Name: "portage", ExecutableName: "emerge", GetPackages: pmPortage},
{Name: "flatpak", ExecutableName: "flatpak", PackageListCommand: "flatpak list"}, {Name: "flatpak", ExecutableName: "flatpak", GetPackages: pmFlatpak},
{Name: "snap", ExecutableName: "snap", PackageListCommand: "snap list | tail +2"}, {Name: "snap", ExecutableName: "snap", GetPackages: pmSnap},
} }
func (pm *PackageManager) CountPackages() int { func (pm *PackageManager) CountPackages() int {
@@ -29,12 +33,7 @@ func (pm *PackageManager) CountPackages() int {
return 0 return 0
} }
output, err := exec.Command("/bin/sh", "-c", pm.PackageListCommand).Output() return pm.GetPackages(pm.FunctionInput...)
if err != nil {
return 0
}
return strings.Count(string(output), "\n")
} }
func GetInstalledPackages() (ret string) { func GetInstalledPackages() (ret string) {
@@ -51,3 +50,128 @@ func GetInstalledPackages() (ret string) {
return ret return ret
} }
func pmDirectoryElements(args ...any) int {
directory := args[0].(string)
dirsOnly := false
if len(args) >= 2 {
dirsOnly = args[1].(bool)
}
total := 0
dirEntries, _ := os.ReadDir(directory)
for _, entry := range dirEntries {
if !entry.IsDir() && dirsOnly {
continue
}
total++
}
return total
}
func pmFileLines(args ...any) int {
filepath := args[0].(string)
mustContain := ""
if len(args) >= 2 {
mustContain = args[1].(string)
}
total := 0
content, err := os.ReadFile(filepath)
if err == nil {
for _, line := range strings.Split(strings.TrimSpace(string(content)), "\n") {
if mustContain != "" && !strings.Contains(line, mustContain) {
continue
}
total++
}
}
return total
}
func pmShellCommandLines(args ...any) int {
command := args[0].(string)
output := runCommand(command, "/bin/sh")
return len(strings.Split(output, "\n"))
}
func pmShellCommandOutput(args ...any) int {
command := args[0].(string)
output := runCommand(command, "/bin/sh")
packageCount, _ := strconv.Atoi(output)
return packageCount
}
func pmPortage(args ...any) int {
portageDir := "/var/db/pkg"
total := 0
dirEntries, _ := os.ReadDir(portageDir)
for _, repo := range dirEntries {
if !repo.IsDir() {
continue
}
packages, _ := os.ReadDir(path.Join(portageDir, repo.Name()))
total += len(packages)
}
return total
}
func pmFlatpak(args ...any) int {
arch := GetArch()
flatpakDir := "/var/lib/flatpak"
total := 0
// Count applications
apps, err := os.ReadDir(path.Join(flatpakDir, "app"))
if err == nil {
for _, app := range apps {
if strings.HasSuffix(app.Name(), ".Locale") || strings.HasSuffix(app.Name(), ".Debug") {
continue
}
dirEntries, _ := os.ReadDir(path.Join(flatpakDir, "app", app.Name(), arch))
total += len(dirEntries)
}
}
// Count runtimes
runtimes, err := os.ReadDir(path.Join(flatpakDir, "runtime"))
if err == nil {
for _, runtime := range runtimes {
if strings.HasSuffix(runtime.Name(), ".Locale") || strings.HasSuffix(runtime.Name(), ".Debug") {
continue
}
dirEntries, _ := os.ReadDir(path.Join(flatpakDir, "runtime", runtime.Name(), arch))
total += len(dirEntries)
}
}
return total
}
func pmSnap(args ...any) int {
total := pmDirectoryElements("/snap", true)
if total > 0 {
return total - 1
}
total = pmDirectoryElements("/var/lib/snapd/snap", true)
if total > 0 {
return total - 1
}
return 0
}
+39 -54
View File
@@ -22,10 +22,6 @@ func GetDistroInfo() DistroInfo {
LongName: "Unknown", LongName: "Unknown",
ShortName: "Unknown", ShortName: "Unknown",
} }
if strings.TrimSpace(config.DistroName) != "" {
info.LongName = strings.TrimSpace(config.DistroName)
info.ShortName = strings.TrimSpace(config.DistroName)
}
// Detect release file location // Detect release file location
var releaseFile string var releaseFile string
@@ -39,20 +35,23 @@ func GetDistroInfo() DistroInfo {
return info return info
} }
// Read release file
releaseMap, err := ReadKeyValueFile(releaseFile) releaseMap, err := ReadKeyValueFile(releaseFile)
if err != nil { if err != nil {
return info return info
} }
// Set struct fields
if id, ok := releaseMap["ID"]; ok { if id, ok := releaseMap["ID"]; ok {
info.ID = id info.ID = id
} }
if longName, ok := releaseMap["PRETTY_NAME"]; ok && info.LongName == "Unknown" { if longName, ok := releaseMap["PRETTY_NAME"]; ok {
info.LongName = longName info.LongName = longName
} }
if shortName, ok := releaseMap["NAME"]; ok && info.ShortName == "Unknown" { if shortName, ok := releaseMap["NAME"]; ok {
info.ShortName = shortName info.ShortName = shortName
} }
return info return info
} }
@@ -65,40 +64,36 @@ func GetDistroAsciiArt() string {
(| | ) (| | )
/'\_ _/'\ /'\_ _/'\
\___)=(___/` \___)=(___/`
var id string
if config.Ascii == "auto" { // Get ascii name to use
id = GetDistroInfo().ID var asciiName string
if Ascii != "" {
asciiName = Ascii
} else if config.Ascii == "auto" {
asciiName = GetDistroInfo().ID
} else { } else {
id = config.Ascii asciiName = config.Ascii
} }
// Check for ascii art in home directory
userConfDir, err := os.UserConfigDir() userConfDir, err := os.UserConfigDir()
if err != nil { if err == nil {
if _, err := os.Stat(path.Join(SystemConfigDir, "stormfetch/ascii/", id)); err == nil { if _, err := os.Stat(path.Join(userConfDir, "stormfetch/ascii/", asciiName)); err == nil {
bytes, err := os.ReadFile(path.Join(SystemConfigDir, "stormfetch/ascii/", id)) if bytes, err := os.ReadFile(path.Join(userConfDir, "stormfetch/ascii/", asciiName)); err == nil {
if err != nil { return strings.TrimRight(string(bytes), "\n")
}
}
}
// Check for ascii art in system config directory
if _, err := os.Stat(path.Join(SystemConfigDir, "stormfetch/ascii/", asciiName)); err == nil {
if bytes, err := os.ReadFile(path.Join(SystemConfigDir, "stormfetch/ascii/", asciiName)); err == nil {
return strings.TrimRight(string(bytes), "\n")
}
}
return defaultAscii return defaultAscii
} }
return string(bytes)
} else {
return defaultAscii
}
}
if _, err := os.Stat(path.Join(userConfDir, "stormfetch/ascii/", id)); err == nil {
bytes, err := os.ReadFile(path.Join(userConfDir, "stormfetch/ascii/", id))
if err != nil {
return defaultAscii
}
return string(bytes)
} else if _, err := os.Stat(path.Join(SystemConfigDir, "stormfetch/ascii/", id)); err == nil {
bytes, err := os.ReadFile(path.Join(SystemConfigDir, "stormfetch/ascii/", id))
if err != nil {
return defaultAscii
}
return strings.TrimRight(string(bytes), "\n\t ")
} else {
return defaultAscii
}
}
func GetArch() string { func GetArch() string {
uname := syscall.Utsname{} uname := syscall.Utsname{}
@@ -138,42 +133,32 @@ func GetKernel() (string, string) {
} }
func GetInitSystem() string { func GetInitSystem() string {
runCommand := func(command string) string {
cmd := exec.Command("/bin/sh", "-c", command)
workdir, err := os.Getwd()
if err != nil {
return ""
}
cmd.Dir = workdir
cmd.Env = os.Environ()
out, err := cmd.Output()
if err != nil {
return ""
}
return strings.TrimSpace(string(out))
}
process, err := ps.FindProcess(1) process, err := ps.FindProcess(1)
if err != nil { if err != nil {
return "" return ""
} }
// Return if init system can't be found
if process == nil {
return ""
}
// 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}'") return "OpenRC " + runCommand("openrc --version | awk '{print $3}'", "/bin/sh")
} }
// Default PID 1 process name checking // Default PID 1 process name checking
switch process.Executable() { switch process.Executable() {
case "systemd": case "systemd":
return "Systemd " + runCommand("systemctl --version | head -n1 | awk '{print $2}'") return "Systemd " + runCommand("systemctl --version | head -n1 | awk '{print $2}'", "/bin/sh")
case "runit": case "runit":
return "Runit" return "Runit"
case "dinit": case "dinit":
return "Dinit " + runCommand("dinit --version | head -n1 | awk '{print substr($3, 1, length($3)-1)}'") return "Dinit " + 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}'") return "Enit " + runCommand("enit --version | awk '{print $3}'", "/bin/sh")
default: default:
return process.Executable() return process.Executable()
} }
+16 -45
View File
@@ -3,7 +3,6 @@ package main
import ( import (
"log" "log"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"slices" "slices"
"strconv" "strconv"
@@ -19,20 +18,6 @@ type DEWM struct {
} }
func GetShell() string { func GetShell() string {
runCommand := func(command string) string {
cmd := exec.Command("/bin/sh", "-c", command)
workdir, err := os.Getwd()
if err != nil {
return ""
}
cmd.Dir = workdir
cmd.Env = os.Environ()
out, err := cmd.Output()
if err != nil {
return ""
}
return strings.TrimSpace(string(out))
}
file, err := os.ReadFile("/etc/passwd") file, err := os.ReadFile("/etc/passwd")
if err != nil { if err != nil {
return "" return ""
@@ -54,13 +39,13 @@ func GetShell() string {
case "dash": case "dash":
return "Dash" return "Dash"
case "bash": case "bash":
return "Bash " + runCommand("echo $BASH_VERSION") return "Bash " + runCommand("echo $BASH_VERSION", "/bin/sh")
case "zsh": case "zsh":
return "Zsh " + runCommand("$SHELL --version | awk '{print $2}'") return "Zsh " + runCommand("$SHELL --version | awk '{print $2}'", "/bin/sh")
case "fish": case "fish":
return "Fish " + runCommand("$SHELL --version | awk '{print $3}'") return "Fish " + runCommand("$SHELL --version | awk '{print $3}'", "/bin/sh")
case "nu": case "nu":
return "Nushell " + runCommand("$SHELL --version") return "Nushell " + runCommand("$SHELL --version", "/bin/sh")
default: default:
return "Unknown" return "Unknown"
} }
@@ -79,53 +64,39 @@ func GetDEWM() DEWM {
processExists := func(process string) bool { processExists := func(process string) bool {
return slices.Contains(executables, process) return slices.Contains(executables, process)
} }
runCommand := func(command string) string {
cmd := exec.Command("/bin/sh", "-c", command)
workdir, err := os.Getwd()
if err != nil {
return ""
}
cmd.Dir = workdir
cmd.Env = os.Environ()
out, err := cmd.Output()
if err != nil {
return ""
}
return strings.TrimSpace(string(out))
}
if processExists("plasmashell") { if processExists("plasmashell") {
dewm := DEWM{ dewm := DEWM{
Name: "KDE Plasma", Name: "KDE Plasma",
Type: "DE", Type: "DE",
Version: runCommand("plasmashell --version | awk '{print $2}'"), Version: runCommand("plasmashell --version | awk '{print $2}'", "/bin/sh"),
} }
return dewm return dewm
} else if processExists("gnome-session") { } else if processExists("gnome-session") {
dewm := DEWM{ dewm := DEWM{
Name: "Gnome", Name: "Gnome",
Type: "DE", Type: "DE",
Version: runCommand("gnome-shell --version | awk '{print $3}'"), Version: runCommand("gnome-shell --version | awk '{print $3}'", "/bin/sh"),
} }
return dewm return dewm
} else if processExists("xfce4-session") { } else if processExists("xfce4-session") {
dewm := DEWM{ dewm := DEWM{
Name: "XFCE", Name: "XFCE",
Type: "DE", Type: "DE",
Version: runCommand("xfce4-session --version | head -n1 | awk '{print $2}'"), Version: runCommand("xfce4-session --version | head -n1 | awk '{print $2}'", "/bin/sh"),
} }
return dewm return dewm
} else if processExists("cinnamon") { } else if processExists("cinnamon") {
dewm := DEWM{ dewm := DEWM{
Name: "Cinnamon", Name: "Cinnamon",
Type: "DE", Type: "DE",
Version: runCommand("cinnamon --version | awk '{print $3}'"), Version: runCommand("cinnamon --version | awk '{print $3}'", "/bin/sh"),
} }
return dewm return dewm
} else if processExists("mate-panel") { } else if processExists("mate-panel") {
dewm := DEWM{ dewm := DEWM{
Name: "MATE", Name: "MATE",
Type: "DE", Type: "DE",
Version: runCommand("mate-about --version | awk '{print $4}'"), Version: runCommand("mate-about --version | awk '{print $4}'", "/bin/sh"),
} }
return dewm return dewm
} else if processExists("lxsession") { } else if processExists("lxsession") {
@@ -139,23 +110,23 @@ func GetDEWM() DEWM {
dewm := DEWM{ dewm := DEWM{
Name: "LXQt", Name: "LXQt",
Type: "DE", Type: "DE",
Version: runCommand("lxqt-session --version | head -n1 | awk '{print $2}'"), Version: runCommand("lxqt-session --version | head -n1 | awk '{print $2}'", "/bin/sh"),
} }
return dewm return dewm
} else if processExists("i3") || processExists("i3-with-shmlog") { } else if processExists("i3") || processExists("i3-with-shmlog") {
dewm := DEWM{ dewm := DEWM{
Name: "i3", Name: "i3",
Type: "WM", Type: "WM",
Version: runCommand("i3 --version | awk '{print $3}'"), Version: runCommand("i3 --version | awk '{print $3}'", "/bin/sh"),
} }
return dewm return dewm
} else if processExists("sway") { } else if processExists("sway") {
dewm := DEWM{ dewm := DEWM{
Name: "Sway", Name: "Sway",
Type: "WM", Type: "WM",
Version: runCommand("sway --version | awk '{print $3}'"), Version: runCommand("sway --version | awk '{print $3}'", "/bin/sh"),
} }
if runCommand("sway --version | awk '{print $1}'") == "swayfx" { if runCommand("sway --version | awk '{print $1}'", "/bin/sh") == "swayfx" {
dewm.Name = "SwayFX" dewm.Name = "SwayFX"
} else { } else {
dewm.Name = "Sway" dewm.Name = "Sway"
@@ -165,21 +136,21 @@ func GetDEWM() DEWM {
dewm := DEWM{ dewm := DEWM{
Name: "Bspwm", Name: "Bspwm",
Type: "WM", Type: "WM",
Version: runCommand("bspwm -v"), Version: runCommand("bspwm -v", "/bin/sh"),
} }
return dewm return dewm
} else if processExists("Hyprland") { } else if processExists("Hyprland") {
dewm := DEWM{ dewm := DEWM{
Name: "Hyprland", Name: "Hyprland",
Type: "WM", Type: "WM",
Version: runCommand("hyprctl version | sed -n 3p | awk '{print $2}' | tr -d 'v,'"), Version: runCommand("hyprctl version | sed -n 3p | awk '{print $2}' | tr -d 'v,'", "/bin/sh"),
} }
return dewm return dewm
} else if processExists("icewm-session") { } else if processExists("icewm-session") {
dewm := DEWM{ dewm := DEWM{
Name: "IceWM", Name: "IceWM",
Type: "WM", Type: "WM",
Version: runCommand("icewm --version | awk '{print $2}'"), Version: runCommand("icewm --version | awk '{print $2}'", "/bin/sh"),
} }
return dewm return dewm
} }
+16
View File
@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"math" "math"
"os" "os"
"os/exec"
"regexp" "regexp"
"strings" "strings"
) )
@@ -56,3 +57,18 @@ func ReadKeyValueFile(filepath string) (map[string]string, error) {
} }
return ret, nil return ret, nil
} }
func runCommand(command string, shell string) string {
cmd := exec.Command(shell, "-c", command)
workdir, err := os.Getwd()
if err != nil {
return ""
}
cmd.Dir = workdir
cmd.Env = os.Environ()
out, err := cmd.Output()
if err != nil {
return ""
}
return strings.TrimSpace(string(out))
}