mirror of
https://github.com/EnumeratedDev/stormfetch.git
synced 2026-09-24 03:36:11 +00:00
Compare commits
16
Commits
7.0
...
16b27c4002
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16b27c4002
|
||
|
|
2f71da0673
|
||
|
|
d4e324d79f
|
||
|
|
7f7c7d646d
|
||
|
|
cecce857e1
|
||
|
|
fabc1adbf7
|
||
|
|
3b7cb5e4e2
|
||
|
|
1b0ad32b6b
|
||
|
|
b52145614f
|
||
|
|
705a40047b
|
||
|
|
341138116b
|
||
|
|
051301aacd
|
||
|
|
3131d94429
|
||
|
|
c7bfaf7a31
|
||
|
|
9ce8e5ef0b
|
||
|
|
92ea038c77
|
@@ -19,7 +19,8 @@ Stormfetch is still in beta, so distro compatibility is limited. If you would li
|
||||
```
|
||||
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,23 +1,23 @@
|
||||
#/43;45;45;15
|
||||
${C3}.%1-------------------------:
|
||||
%3.%1-------------------------:
|
||||
.%2+=%1========================.
|
||||
:%2++%1===%2++===%1===============- :%2++%1-
|
||||
:%2*++%1====%2+++++==%1===========- .==:
|
||||
-%2*+++%1=====%2+***++=%1=========:
|
||||
=%2*++++=%1=======------------:
|
||||
=%2*+++++=%1====- ${C3}...%1
|
||||
=%2*+++++=%1====- %3...%1
|
||||
.%2+*+++++%1=-===: .%2=+++=%1:
|
||||
:%2++++%1=====-==: -***%2**%1+
|
||||
:%2++=%1=======-=. .=+**+${C3}.%1
|
||||
.%2+%1==========-. ${C3}.%1
|
||||
:%2+++++++%1====- ${C3}.%1--==-${C3}.%1
|
||||
:%2++%1==========. ${C3}:%2+++++++%1${C3}:
|
||||
:%2++=%1=======-=. .=+**+%3.%1
|
||||
.%2+%1==========-. %3.%1
|
||||
:%2+++++++%1====- %3.%1--==-%3.%1
|
||||
:%2++%1==========. %3:%2+++++++%1%3:
|
||||
%1.-===========. =*****+*+
|
||||
%1.-===========: .+*****+:
|
||||
%1-=======%2++++%1:::::::::::::::::::::::::-: ${C3}.%1---:
|
||||
%1-=======%2++++%1:::::::::::::::::::::::::-: %3.%1---:
|
||||
:======%2++++%1====%2+++******************=.
|
||||
%1:=====%2+++%1==========%2++++++++++++++*-
|
||||
%1.====%2++%1==============%2++++++++++*-
|
||||
%1.===%2+%1==================%2+++++++:
|
||||
%1.-=======================%2+++:
|
||||
${C3}..........................
|
||||
%3..........................
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ modules:
|
||||
- name: kernel
|
||||
- name: packages
|
||||
- name: shell
|
||||
- name: init
|
||||
- name: init_system
|
||||
- name: motherboard
|
||||
- name: cpus
|
||||
- name: gpus
|
||||
|
||||
+9
-5
@@ -5,9 +5,13 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func setupColorMap(asciiArtHeader string) map[int]string {
|
||||
colorMap := make(map[int]string)
|
||||
colorMap[0] = "\033[0m"
|
||||
func setupColorMap(asciiArtHeader string) []string {
|
||||
colorMap := make([]string, 10)
|
||||
|
||||
// Set default color map values
|
||||
for i := range 10 {
|
||||
colorMap[i] = "\033[0m"
|
||||
}
|
||||
|
||||
// Return if header is empty
|
||||
if asciiArtHeader == "" {
|
||||
@@ -16,8 +20,8 @@ func setupColorMap(asciiArtHeader string) map[int]string {
|
||||
|
||||
// Read colors from ascii art header
|
||||
ansiColors := strings.Split(strings.TrimPrefix(asciiArtHeader, "#/"), ";")
|
||||
for i, ansiColor := range ansiColors {
|
||||
colorMap[i+1] = fmt.Sprintf("\033[38;5;%sm", ansiColor)
|
||||
for i := 0; i < 9 && i < len(ansiColors); i++ {
|
||||
colorMap[i+1] = fmt.Sprintf("\033[38;5;%sm", ansiColors[i])
|
||||
}
|
||||
|
||||
return colorMap
|
||||
|
||||
+5
-4
@@ -10,7 +10,6 @@ import (
|
||||
|
||||
type StormfetchConfig struct {
|
||||
Ascii string `yaml:"distro_ascii"`
|
||||
DistroName string `yaml:"distro_name"`
|
||||
Modules []stormfetchModuleConfig `yaml:"modules"`
|
||||
AnsiiColors []int `yaml:"ansii_colors"`
|
||||
ForceConfigAnsii bool `yaml:"force_config_ansii"`
|
||||
@@ -22,20 +21,22 @@ var config = StormfetchConfig{
|
||||
}
|
||||
|
||||
func readConfig() {
|
||||
if ConfigPath == "" {
|
||||
// Get home directory
|
||||
userConfigDir, _ := os.UserConfigDir()
|
||||
|
||||
// Find valid config directory
|
||||
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 {
|
||||
configPath = path.Join(SystemConfigDir, "stormfetch/config.yml")
|
||||
ConfigPath = path.Join(SystemConfigDir, "stormfetch/config.yml")
|
||||
} else {
|
||||
log.Fatalf("Config file not found: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Parse config
|
||||
bytes, err := os.ReadFile(configPath)
|
||||
bytes, err := os.ReadFile(ConfigPath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
+25
-7
@@ -6,6 +6,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// Build-time variables
|
||||
@@ -14,22 +15,22 @@ var SystemConfigDir = "/etc/"
|
||||
|
||||
// Flag variables
|
||||
var ShowVersion = false
|
||||
var ConfigPath = ""
|
||||
var Ascii = ""
|
||||
var ShowModuleTimeTaken = false
|
||||
|
||||
var configPath = ""
|
||||
|
||||
func main() {
|
||||
readConfig()
|
||||
parseFlags()
|
||||
readConfig()
|
||||
initializeModuleMap()
|
||||
run()
|
||||
}
|
||||
|
||||
func parseFlags() {
|
||||
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.StringVar(&config.Ascii, "ascii", config.Ascii, "Set distro ascii")
|
||||
flag.StringVar(&config.DistroName, "distro-name", config.DistroName, "Set distro name")
|
||||
flag.StringVar(&Ascii, "ascii", "", "Set distro ascii")
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
@@ -48,6 +49,20 @@ func run() {
|
||||
}
|
||||
asciiArtNoColor := asciiArt
|
||||
|
||||
// Rewrite last color code to the start of the next line
|
||||
lastColor := "0"
|
||||
for i := 1; i < len(asciiArt); i++ {
|
||||
rune := rune(asciiArt[i])
|
||||
|
||||
if unicode.IsDigit(rune) && asciiArt[i-1] == '%' {
|
||||
lastColor = string(rune)
|
||||
}
|
||||
|
||||
if rune == '\n' {
|
||||
asciiArt = asciiArt[:i+1] + "%" + lastColor + asciiArt[i+1:]
|
||||
}
|
||||
}
|
||||
|
||||
// Setup color map and replace colors in ascii art
|
||||
colorMap := setupColorMap(asciiArtHeader)
|
||||
for key, value := range colorMap {
|
||||
@@ -76,6 +91,9 @@ func run() {
|
||||
text := module.Execute(module)
|
||||
end := time.Now().UnixMilli()
|
||||
|
||||
// Insert default color at the start of the module's text
|
||||
text = colorMap[0] + text
|
||||
|
||||
// Show time taken
|
||||
if ShowModuleTimeTaken {
|
||||
fmt.Printf("Module '%s' took %d milliseconds\n", module.Name, end-start)
|
||||
@@ -89,7 +107,7 @@ func run() {
|
||||
}
|
||||
|
||||
// Continue if text length is 0
|
||||
if len(textNoColor) == 0 {
|
||||
if len(textNoColor)-len(colorMap[0]) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -107,7 +125,7 @@ func run() {
|
||||
}
|
||||
}
|
||||
|
||||
// Split ascii art into each lien
|
||||
// Split ascii art into each line
|
||||
asciiArtSplit := strings.Split(asciiArt, "\n")
|
||||
asciiArtNoColorSplit := strings.Split(asciiArtNoColor, "\n")
|
||||
|
||||
|
||||
+58
-6
@@ -100,10 +100,12 @@ func initializeModuleMap() {
|
||||
|
||||
// Packages module
|
||||
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 {
|
||||
switch s {
|
||||
case "PACKAGES":
|
||||
return GetInstalledPackages()
|
||||
return packages
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
@@ -113,10 +115,12 @@ func initializeModuleMap() {
|
||||
|
||||
// Shell module
|
||||
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 {
|
||||
switch s {
|
||||
case "SHELL":
|
||||
return GetShell()
|
||||
return shell
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
@@ -126,10 +130,16 @@ func initializeModuleMap() {
|
||||
|
||||
// Init system module
|
||||
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 {
|
||||
switch s {
|
||||
case "INIT":
|
||||
return GetInitSystem()
|
||||
return initSystem
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
@@ -139,10 +149,12 @@ func initializeModuleMap() {
|
||||
|
||||
// Libc module
|
||||
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 {
|
||||
switch s {
|
||||
case "LIBC":
|
||||
return GetLibc()
|
||||
return libc
|
||||
default:
|
||||
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 {
|
||||
memoryInfo := GetMemoryInfo()
|
||||
|
||||
if memoryInfo == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return os.Expand(sm.Format, func(s string) string {
|
||||
switch s {
|
||||
case "MEM_TOTAL":
|
||||
@@ -330,10 +346,12 @@ func initializeModuleMap() {
|
||||
|
||||
// Local IP module
|
||||
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 {
|
||||
switch s {
|
||||
case "LOCAL_IP":
|
||||
return GetLocalIP()
|
||||
return localIP
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
@@ -349,6 +367,7 @@ func initializeModuleMap() {
|
||||
}
|
||||
|
||||
dewm := GetDEWM()
|
||||
displayProtocol := GetDisplayProtocol()
|
||||
|
||||
// Return empty string if can't detect DE/WM
|
||||
if dewm.Name == "Unknown" {
|
||||
@@ -364,7 +383,7 @@ func initializeModuleMap() {
|
||||
case "DEWM_VERSION":
|
||||
return dewm.Version
|
||||
case "DISPLAY_PROTOCOL":
|
||||
return GetDisplayProtocol()
|
||||
return displayProtocol
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
@@ -399,4 +418,37 @@ func initializeModuleMap() {
|
||||
return builder.String()
|
||||
}}
|
||||
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
@@ -2,25 +2,29 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type PackageManager struct {
|
||||
Name string
|
||||
ExecutableName string
|
||||
PackageListCommand string
|
||||
GetPackages func(...any) int
|
||||
FunctionInput []any
|
||||
}
|
||||
|
||||
var PackageManagers = []PackageManager{
|
||||
{Name: "dpkg", ExecutableName: "dpkg", PackageListCommand: "dpkg-query -f '${Package}\\n' -W"},
|
||||
{Name: "pacman", ExecutableName: "pacman", PackageListCommand: "pacman -Q"},
|
||||
{Name: "rpm", ExecutableName: "rpm", PackageListCommand: "rpm -qa"},
|
||||
{Name: "xbps", ExecutableName: "xbps-query", PackageListCommand: "xbps-query -l"},
|
||||
{Name: "bpm", ExecutableName: "bpm", PackageListCommand: "ls /var/lib/bpm/installed/"},
|
||||
{Name: "portage", ExecutableName: "emerge", PackageListCommand: "find /var/db/pkg/*/ -mindepth 1 -maxdepth 1"},
|
||||
{Name: "flatpak", ExecutableName: "flatpak", PackageListCommand: "flatpak list"},
|
||||
{Name: "snap", ExecutableName: "snap", PackageListCommand: "snap list | tail +2"},
|
||||
{Name: "dpkg", ExecutableName: "dpkg", GetPackages: pmFileLines, FunctionInput: []any{"/var/lib/dpkg/status", "Status: install ok installed"}},
|
||||
{Name: "pacman", ExecutableName: "pacman", GetPackages: pmDirectoryElements, FunctionInput: []any{"/var/lib/pacman/local/", true}},
|
||||
{Name: "rpm", ExecutableName: "rpm", GetPackages: pmShellCommandLines, FunctionInput: []any{"rpm -qa"}},
|
||||
{Name: "xbps", ExecutableName: "xbps-query", GetPackages: pmFileLines, FunctionInput: []any{"/var/db/xbps/pkgdb-0.38.plist", "<string>installed</string>"}},
|
||||
{Name: "bpm", ExecutableName: "bpm", GetPackages: pmDirectoryElements, FunctionInput: []any{"/var/lib/bpm/installed/"}},
|
||||
{Name: "portage", ExecutableName: "emerge", GetPackages: pmPortage},
|
||||
{Name: "flatpak", ExecutableName: "flatpak", GetPackages: pmFlatpak},
|
||||
{Name: "snap", ExecutableName: "snap", GetPackages: pmSnap},
|
||||
}
|
||||
|
||||
func (pm *PackageManager) CountPackages() int {
|
||||
@@ -29,12 +33,7 @@ func (pm *PackageManager) CountPackages() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
output, err := exec.Command("/bin/sh", "-c", pm.PackageListCommand).Output()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return strings.Count(string(output), "\n")
|
||||
return pm.GetPackages(pm.FunctionInput...)
|
||||
}
|
||||
|
||||
func GetInstalledPackages() (ret string) {
|
||||
@@ -51,3 +50,128 @@ func GetInstalledPackages() (ret string) {
|
||||
|
||||
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
@@ -22,10 +22,6 @@ func GetDistroInfo() DistroInfo {
|
||||
LongName: "Unknown",
|
||||
ShortName: "Unknown",
|
||||
}
|
||||
if strings.TrimSpace(config.DistroName) != "" {
|
||||
info.LongName = strings.TrimSpace(config.DistroName)
|
||||
info.ShortName = strings.TrimSpace(config.DistroName)
|
||||
}
|
||||
|
||||
// Detect release file location
|
||||
var releaseFile string
|
||||
@@ -39,20 +35,23 @@ func GetDistroInfo() DistroInfo {
|
||||
return info
|
||||
}
|
||||
|
||||
// Read release file
|
||||
releaseMap, err := ReadKeyValueFile(releaseFile)
|
||||
if err != nil {
|
||||
return info
|
||||
}
|
||||
|
||||
// Set struct fields
|
||||
if id, ok := releaseMap["ID"]; ok {
|
||||
info.ID = id
|
||||
}
|
||||
if longName, ok := releaseMap["PRETTY_NAME"]; ok && info.LongName == "Unknown" {
|
||||
if longName, ok := releaseMap["PRETTY_NAME"]; ok {
|
||||
info.LongName = longName
|
||||
}
|
||||
if shortName, ok := releaseMap["NAME"]; ok && info.ShortName == "Unknown" {
|
||||
if shortName, ok := releaseMap["NAME"]; ok {
|
||||
info.ShortName = shortName
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
@@ -65,40 +64,36 @@ func GetDistroAsciiArt() string {
|
||||
(| | )
|
||||
/'\_ _/'\
|
||||
\___)=(___/`
|
||||
var id string
|
||||
if config.Ascii == "auto" {
|
||||
id = GetDistroInfo().ID
|
||||
|
||||
// Get ascii name to use
|
||||
var asciiName string
|
||||
if Ascii != "" {
|
||||
asciiName = Ascii
|
||||
} else if config.Ascii == "auto" {
|
||||
asciiName = GetDistroInfo().ID
|
||||
} else {
|
||||
id = config.Ascii
|
||||
asciiName = config.Ascii
|
||||
}
|
||||
|
||||
// Check for ascii art in home directory
|
||||
userConfDir, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
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 {
|
||||
if err == nil {
|
||||
if _, err := os.Stat(path.Join(userConfDir, "stormfetch/ascii/", asciiName)); err == nil {
|
||||
if bytes, err := os.ReadFile(path.Join(userConfDir, "stormfetch/ascii/", asciiName)); 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 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 {
|
||||
uname := syscall.Utsname{}
|
||||
@@ -138,42 +133,32 @@ func GetKernel() (string, 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)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Return if init system can't be found
|
||||
if process == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Special cases
|
||||
// OpenRC check
|
||||
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
|
||||
switch process.Executable() {
|
||||
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":
|
||||
return "Runit"
|
||||
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":
|
||||
return "Enit " + runCommand("enit --version | awk '{print $3}'")
|
||||
return "Enit " + runCommand("enit --version | awk '{print $3}'", "/bin/sh")
|
||||
default:
|
||||
return process.Executable()
|
||||
}
|
||||
|
||||
+16
-45
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strconv"
|
||||
@@ -19,20 +18,6 @@ type DEWM struct {
|
||||
}
|
||||
|
||||
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")
|
||||
if err != nil {
|
||||
return ""
|
||||
@@ -54,13 +39,13 @@ func GetShell() string {
|
||||
case "dash":
|
||||
return "Dash"
|
||||
case "bash":
|
||||
return "Bash " + runCommand("echo $BASH_VERSION")
|
||||
return "Bash " + runCommand("echo $BASH_VERSION", "/bin/sh")
|
||||
case "zsh":
|
||||
return "Zsh " + runCommand("$SHELL --version | awk '{print $2}'")
|
||||
return "Zsh " + runCommand("$SHELL --version | awk '{print $2}'", "/bin/sh")
|
||||
case "fish":
|
||||
return "Fish " + runCommand("$SHELL --version | awk '{print $3}'")
|
||||
return "Fish " + runCommand("$SHELL --version | awk '{print $3}'", "/bin/sh")
|
||||
case "nu":
|
||||
return "Nushell " + runCommand("$SHELL --version")
|
||||
return "Nushell " + runCommand("$SHELL --version", "/bin/sh")
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
@@ -79,53 +64,39 @@ func GetDEWM() DEWM {
|
||||
processExists := func(process string) bool {
|
||||
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") {
|
||||
dewm := DEWM{
|
||||
Name: "KDE Plasma",
|
||||
Type: "DE",
|
||||
Version: runCommand("plasmashell --version | awk '{print $2}'"),
|
||||
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}'"),
|
||||
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}'"),
|
||||
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}'"),
|
||||
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}'"),
|
||||
Version: runCommand("mate-about --version | awk '{print $4}'", "/bin/sh"),
|
||||
}
|
||||
return dewm
|
||||
} else if processExists("lxsession") {
|
||||
@@ -139,23 +110,23 @@ func GetDEWM() DEWM {
|
||||
dewm := DEWM{
|
||||
Name: "LXQt",
|
||||
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
|
||||
} else if processExists("i3") || processExists("i3-with-shmlog") {
|
||||
dewm := DEWM{
|
||||
Name: "i3",
|
||||
Type: "WM",
|
||||
Version: runCommand("i3 --version | awk '{print $3}'"),
|
||||
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}'"),
|
||||
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"
|
||||
} else {
|
||||
dewm.Name = "Sway"
|
||||
@@ -165,21 +136,21 @@ func GetDEWM() DEWM {
|
||||
dewm := DEWM{
|
||||
Name: "Bspwm",
|
||||
Type: "WM",
|
||||
Version: runCommand("bspwm -v"),
|
||||
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,'"),
|
||||
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}'"),
|
||||
Version: runCommand("icewm --version | awk '{print $2}'", "/bin/sh"),
|
||||
}
|
||||
return dewm
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
@@ -56,3 +57,18 @@ func ReadKeyValueFile(filepath string) (map[string]string, error) {
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user