mirror of
https://github.com/EnumeratedDev/stormfetch.git
synced 2026-09-16 07:56:12 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b0ad32b6b
|
||
|
|
b52145614f
|
||
|
|
705a40047b
|
||
|
|
341138116b
|
||
|
|
051301aacd
|
||
|
|
3131d94429
|
||
|
|
c7bfaf7a31
|
||
|
|
9ce8e5ef0b
|
||
|
|
92ea038c77
|
||
|
|
9680c024b9
|
||
|
|
13cd6f1d45
|
||
|
|
e400e338a0
|
||
|
|
d1b095ba73
|
||
|
|
663e69638b
|
||
|
|
4e296b5104
|
||
|
|
eef69eed9a
|
||
|
|
489e6e2143
|
||
|
|
ba43a98926
|
@@ -1,32 +1,35 @@
|
|||||||
SHELL := /bin/bash
|
# Installation paths
|
||||||
|
PREFIX ?= /usr/local
|
||||||
ifeq ($(PREFIX),)
|
BINDIR ?= $(PREFIX)/bin
|
||||||
PREFIX := /usr/local
|
|
||||||
endif
|
|
||||||
ifeq ($(BINDIR),)
|
|
||||||
BINDIR := $(PREFIX)/bin
|
|
||||||
endif
|
|
||||||
ifeq ($(SYSCONFDIR),)
|
|
||||||
SYSCONFDIR := $(PREFIX)/etc
|
SYSCONFDIR := $(PREFIX)/etc
|
||||||
endif
|
|
||||||
ifeq ($(GO),)
|
# Compilers and tools
|
||||||
GO := $(shell type -a -P go | head -n 1)
|
GO ?= go
|
||||||
endif
|
|
||||||
|
# Build-time variables
|
||||||
|
VERSION ?= $(shell git describe --tags --dirty)
|
||||||
|
|
||||||
build:
|
build:
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd src; $(GO) build -ldflags "-w -X 'main.systemConfigDir=$(SYSCONFDIR)'" -o ../build/stormfetch stormfetch
|
cd src; $(GO) build -ldflags "-w -X 'main.StormfetchVersion=$(VERSION)' -X 'main.SystemConfigDir=$(SYSCONFDIR)'" -o ../build/stormfetch stormfetch
|
||||||
|
|
||||||
install: build/stormfetch config/
|
install: build/stormfetch config/
|
||||||
mkdir -p $(DESTDIR)$(BINDIR)
|
# Create directoriy
|
||||||
mkdir -p $(DESTDIR)$(SYSCONFDIR)/stormfetch/
|
install -dm755 $(DESTDIR)$(BINDIR)
|
||||||
cp build/stormfetch $(DESTDIR)$(BINDIR)/stormfetch
|
# Install binary
|
||||||
cp -r config/. $(DESTDIR)$(SYSCONFDIR)/stormfetch/
|
install -m755 build/stormfetch $(DESTDIR)$(BINDIR)/stormfetch
|
||||||
|
|
||||||
run: build/stormfetch
|
install-config:
|
||||||
build/stormfetch
|
# Create directory
|
||||||
|
install -dm755 $(DESTDIR)$(SYSCONFDIR)
|
||||||
|
# Install files
|
||||||
|
cp -r config $(DESTDIR)$(SYSCONFDIR)/stormfetch/
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
-rm -f $(DESTDIR)$(BINDIR)/stormfetch
|
||||||
|
-rm -rf $(DESTDIR)$(SYSCONFDIR)/stormfetch
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -r build/
|
rm -r build/
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build install install-config uninstall clean
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
# Stormfetch
|
# Stormfetch
|
||||||
## A simple linux fetch program written in go and bash
|
## A simple linux fetch program written in go
|
||||||
|
|
||||||
### 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.
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
#/4;27;4;11
|
#/4;27;4;11
|
||||||
${C1} -`
|
%1 -`
|
||||||
.o+`
|
.o+`
|
||||||
`ooo/
|
`ooo/
|
||||||
`+oooo:
|
`+oooo:
|
||||||
@@ -8,9 +8,9 @@ ${C1} -`
|
|||||||
`/:-:++oooo+:
|
`/:-:++oooo+:
|
||||||
`/++++/+++++++:
|
`/++++/+++++++:
|
||||||
`/++++++++++++++:
|
`/++++++++++++++:
|
||||||
`/+++o${C2}oooooooo${C1}oooo/`
|
`/+++o%2oooooooo%1oooo/`
|
||||||
${C2} ${C1}./${C2}ooosssso++osssssso${C1}+`
|
%2 %1./%2ooosssso++osssssso%1+`
|
||||||
${C2} .oossssso-````/ossssss+`
|
%2 .oossssso-````/ossssss+`
|
||||||
-osssssso. :ssssssso.
|
-osssssso. :ssssssso.
|
||||||
:osssssss/ osssso+++.
|
:osssssss/ osssso+++.
|
||||||
/ossssssss/ +ssssooo/-
|
/ossssssss/ +ssssooo/-
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
#/45;27;45;7
|
#/45;27;45;7
|
||||||
${C1} 'o'
|
%1 'o'
|
||||||
'ooo'
|
'ooo'
|
||||||
'ooxoo'
|
'ooxoo'
|
||||||
'ooxxxoo'
|
'ooxxxoo'
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#/7;8;8;7
|
#/7;8;8;7
|
||||||
${C1} \\\\\\\\\\\\
|
%1 \\\\\\\\\\\\
|
||||||
\\\ \\\
|
\\\ \\\
|
||||||
\\\ \\\
|
\\\ \\\
|
||||||
\\\ \\\\\\\\\\\\\\\\\
|
\\\ \\\\\\\\\\\\\\\\\
|
||||||
\\\ \\\
|
\\\ \\\
|
||||||
\\\ \\\
|
\\\ \\\
|
||||||
\\\ ${C2}______ \\\
|
\\\ %2______ \\\
|
||||||
\\\ ///
|
\\\ ///
|
||||||
\\\ ///
|
\\\ ///
|
||||||
\\\ ///
|
\\\ ///
|
||||||
|
|||||||
+22
-22
@@ -1,23 +1,23 @@
|
|||||||
#/43;45;45;15
|
#/43;45;45;15
|
||||||
${C3}.${C1}-------------------------:
|
%3.%1-------------------------:
|
||||||
.${C2}+=${C1}========================.
|
.%2+=%1========================.
|
||||||
:${C2}++${C1}===${C2}++===${C1}===============- :${C2}++${C1}-
|
:%2++%1===%2++===%1===============- :%2++%1-
|
||||||
:${C2}*++${C1}====${C2}+++++==${C1}===========- .==:
|
:%2*++%1====%2+++++==%1===========- .==:
|
||||||
-${C2}*+++${C1}=====${C2}+***++=${C1}=========:
|
-%2*+++%1=====%2+***++=%1=========:
|
||||||
=${C2}*++++=${C1}=======------------:
|
=%2*++++=%1=======------------:
|
||||||
=${C2}*+++++=${C1}====- ${C3}...${C1}
|
=%2*+++++=%1====- %3...%1
|
||||||
.${C2}+*+++++${C1}=-===: .${C2}=+++=${C1}:
|
.%2+*+++++%1=-===: .%2=+++=%1:
|
||||||
:${C2}++++${C1}=====-==: -***${C2}**${C1}+
|
:%2++++%1=====-==: -***%2**%1+
|
||||||
:${C2}++=${C1}=======-=. .=+**+${C3}.${C1}
|
:%2++=%1=======-=. .=+**+%3.%1
|
||||||
.${C2}+${C1}==========-. ${C3}.${C1}
|
.%2+%1==========-. %3.%1
|
||||||
:${C2}+++++++${C1}====- ${C3}.${C1}--==-${C3}.${C1}
|
:%2+++++++%1====- %3.%1--==-%3.%1
|
||||||
:${C2}++${C1}==========. ${C3}:${C2}+++++++${C1}${C3}:
|
:%2++%1==========. %3:%2+++++++%1%3:
|
||||||
${C1}.-===========. =*****+*+
|
%1.-===========. =*****+*+
|
||||||
${C1}.-===========: .+*****+:
|
%1.-===========: .+*****+:
|
||||||
${C1}-=======${C2}++++${C1}:::::::::::::::::::::::::-: ${C3}.${C1}---:
|
%1-=======%2++++%1:::::::::::::::::::::::::-: %3.%1---:
|
||||||
:======${C2}++++${C1}====${C2}+++******************=.
|
:======%2++++%1====%2+++******************=.
|
||||||
${C1}:=====${C2}+++${C1}==========${C2}++++++++++++++*-
|
%1:=====%2+++%1==========%2++++++++++++++*-
|
||||||
${C1}.====${C2}++${C1}==============${C2}++++++++++*-
|
%1.====%2++%1==============%2++++++++++*-
|
||||||
${C1}.===${C2}+${C1}==================${C2}+++++++:
|
%1.===%2+%1==================%2+++++++:
|
||||||
${C1}.-=======================${C2}+++:
|
%1.-=======================%2+++:
|
||||||
${C3}..........................
|
%3..........................
|
||||||
|
|||||||
+7
-7
@@ -1,16 +1,16 @@
|
|||||||
#/1;7;9;15
|
#/1;7;9;15
|
||||||
${C2} _,met&&&&&gg.
|
%2 _,met&&&&&gg.
|
||||||
,g&&&&&&&&&&&&&&&P.
|
,g&&&&&&&&&&&&&&&P.
|
||||||
,g&&P" """Y&&.".
|
,g&&P" """Y&&.".
|
||||||
,&&P' `&&&.
|
,&&P' `&&&.
|
||||||
',&&P ,ggs. `&&b:
|
',&&P ,ggs. `&&b:
|
||||||
`d&&' ,&P"' ${C1}.${C2} &&&
|
`d&&' ,&P"' %1.%2 &&&
|
||||||
&&P d&' ${C1},${C2} &&P
|
&&P d&' %1,%2 &&P
|
||||||
&&: &&. ${C1}-${C2} ,d&&'
|
&&: &&. %1-%2 ,d&&'
|
||||||
&&; Y&b._ _,d&P'
|
&&; Y&b._ _,d&P'
|
||||||
Y&&. ${C1}`.${C2}`"Y&&&&P"'
|
Y&&. %1`.%2`"Y&&&&P"'
|
||||||
${C2} `&&b ${C1}"-.__
|
%2 `&&b %1"-.__
|
||||||
${C2} `Y&&
|
%2 `Y&&
|
||||||
`Y&&.
|
`Y&&.
|
||||||
`&&b.
|
`&&b.
|
||||||
`Y&&b.
|
`Y&&b.
|
||||||
|
|||||||
+13
-13
@@ -1,20 +1,20 @@
|
|||||||
#/12;7;4;15
|
#/12;7;4;15
|
||||||
${C1} .',;::::;,'.
|
%1 .',;::::;,'.
|
||||||
.';:cccccccccccc:;,.
|
.';:cccccccccccc:;,.
|
||||||
.;cccccccccccccccccccccc;.
|
.;cccccccccccccccccccccc;.
|
||||||
.:cccccccccccccccccccccccccc:.
|
.:cccccccccccccccccccccccccc:.
|
||||||
.;ccccccccccccc;${C2}.:dddl:.${C1};ccccccc;.
|
.;ccccccccccccc;%2.:dddl:.%1;ccccccc;.
|
||||||
.:ccccccccccccc;${C2}OWMKOOXMWd${C1};ccccccc:.
|
.:ccccccccccccc;%2OWMKOOXMWd%1;ccccccc:.
|
||||||
.:ccccccccccccc;${C2}KMMc${C1};cc;${C2}xMMc${C1};ccccccc:.
|
.:ccccccccccccc;%2KMMc%1;cc;%2xMMc%1;ccccccc:.
|
||||||
,cccccccccccccc;${C2}MMM.${C1};cc;${C2};WW:${C1};cccccccc,
|
,cccccccccccccc;%2MMM.%1;cc;%2;WW:%1;cccccccc,
|
||||||
:cccccccccccccc;${C2}MMM.${C1};cccccccccccccccc:
|
:cccccccccccccc;%2MMM.%1;cccccccccccccccc:
|
||||||
:ccccccc;${C2}oxOOOo${C1};${C2}MMM0OOk.${C1};cccccccccccc:
|
:ccccccc;%2oxOOOo%1;%2MMM0OOk.%1;cccccccccccc:
|
||||||
cccccc;${C2}0MMKxdd:${C1};${C2}MMMkddc.${C1};cccccccccccc;
|
cccccc;%20MMKxdd:%1;%2MMMkddc.%1;cccccccccccc;
|
||||||
ccccc;${C2}XM0'${C1};cccc;${C2}MMM.${C1};cccccccccccccccc'
|
ccccc;%2XM0'%1;cccc;%2MMM.%1;cccccccccccccccc'
|
||||||
ccccc;${C2}MMo${C1};ccccc;${C2}MMW.${C1};ccccccccccccccc;
|
ccccc;%2MMo%1;ccccc;%2MMW.%1;ccccccccccccccc;
|
||||||
ccccc;${C2}0MNc.${C1}ccc${C2}.xMMd${C1};ccccccccccccccc;
|
ccccc;%20MNc.%1ccc%2.xMMd%1;ccccccccccccccc;
|
||||||
cccccc;${C2}dNMWXXXWM0:${C1};cccccccccccccc:,
|
cccccc;%2dNMWXXXWM0:%1;cccccccccccccc:,
|
||||||
cccccccc;${C2}.:odl:.${C1};cccccccccccccc:,.
|
cccccccc;%2.:odl:.%1;cccccccccccccc:,.
|
||||||
:cccccccccccccccccccccccccccc:'.
|
:cccccccccccccccccccccccccccc:'.
|
||||||
.:cccccccccccccccccccccc:;,..
|
.:cccccccccccccccccccccc:;,..
|
||||||
'::cccccccccccccc::;,.
|
'::cccccccccccccc::;,.
|
||||||
|
|||||||
+17
-17
@@ -1,19 +1,19 @@
|
|||||||
#/5;7;13;69
|
#/5;7;13;69
|
||||||
${C1} -/oyddmdhs+:.
|
%1 -/oyddmdhs+:.
|
||||||
-o${C2}dNMMMMMMMMNNmhy+${C1}-`
|
-o%2dNMMMMMMMMNNmhy+%1-`
|
||||||
-y${C2}NMMMMMMMMMMMNNNmmdhy${C1}+-
|
-y%2NMMMMMMMMMMMNNNmmdhy%1+-
|
||||||
`o${C2}mMMMMMMMMMMMMNmdmmmmddhhy${C1}/`
|
`o%2mMMMMMMMMMMMMNmdmmmmddhhy%1/`
|
||||||
om${C2}MMMMMMMMMMMN${C1}hhyyyo${C2}hmdddhhhd${C1}o`
|
om%2MMMMMMMMMMMN%1hhyyyo%2hmdddhhhd%1o`
|
||||||
.y${C2}dMMMMMMMMMMd${C1}hs++so/s${C2}mdddhhhhdm${C1}+`
|
.y%2dMMMMMMMMMMd%1hs++so/s%2mdddhhhhdm%1+`
|
||||||
oy${C2}hdmNMMMMMMMN${C1}dyooy${C2}dmddddhhhhyhN${C1}d.
|
oy%2hdmNMMMMMMMN%1dyooy%2dmddddhhhhyhN%1d.
|
||||||
:o${C2}yhhdNNMMMMMMMNNNmmdddhhhhhyym${C1}Mh
|
:o%2yhhdNNMMMMMMMNNNmmdddhhhhhyym%1Mh
|
||||||
.:${C2}+sydNMMMMMNNNmmmdddhhhhhhmM${C1}my
|
.:%2+sydNMMMMMNNNmmmdddhhhhhhmM%1my
|
||||||
/m${C2}MMMMMMNNNmmmdddhhhhhmMNh${C1}s:
|
/m%2MMMMMMNNNmmmdddhhhhhmMNh%1s:
|
||||||
`o${C2}NMMMMMMMNNNmmmddddhhdmMNhs${C1}+`
|
`o%2NMMMMMMMNNNmmmddddhhdmMNhs%1+`
|
||||||
`s${C2}NMMMMMMMMNNNmmmdddddmNMmhs${C1}/.
|
`s%2NMMMMMMMMNNNmmmdddddmNMmhs%1/.
|
||||||
/N${C2}MMMMMMMMNNNNmmmdddmNMNdso${C1}:`
|
/N%2MMMMMMMMNNNNmmmdddmNMNdso%1:`
|
||||||
+M${C2}MMMMMMNNNNNmmmmdmNMNdso${C1}/-
|
+M%2MMMMMMNNNNNmmmmdmNMNdso%1/-
|
||||||
yM${C2}MNNNNNNNmmmmmNNMmhs+/${C1}-`
|
yM%2MNNNNNNNmmmmmNNMmhs+/%1-`
|
||||||
/h${C2}MMNNNNNNNNMNdhs++/${C1}-`
|
/h%2MMNNNNNNNNMNdhs++/%1-`
|
||||||
`/${C2}ohdmmddhys+++/:${C1}.`
|
`/%2ohdmmddhys+++/:%1.`
|
||||||
`-//////:--.
|
`-//////:--.
|
||||||
|
|||||||
+19
-19
@@ -1,20 +1,20 @@
|
|||||||
#/34;15;46;252
|
#/34;15;46;252
|
||||||
${C2} ...-:::::-...
|
%2 ...-:::::-...
|
||||||
${C2} .-MMMMMMMMMMMMMMM-.
|
%2 .-MMMMMMMMMMMMMMM-.
|
||||||
.-MMMM${C1}`..-:::::::-..`${C2}MMMM-.
|
.-MMMM%1`..-:::::::-..`%2MMMM-.
|
||||||
.:MMMM${C1}.:MMMMMMMMMMMMMMM:.${C2}MMMM:.
|
.:MMMM%1.:MMMMMMMMMMMMMMM:.%2MMMM:.
|
||||||
-MMM${C1}-M---MMMMMMMMMMMMMMMMMMM.${C2}MMM-
|
-MMM%1-M---MMMMMMMMMMMMMMMMMMM.%2MMM-
|
||||||
`:MMM${C1}:MM` :MMMM:....::-...-MMMM:${C2}MMM:`
|
`:MMM%1:MM` :MMMM:....::-...-MMMM:%2MMM:`
|
||||||
:MMM${C1}:MMM` :MM:` `` `` `:MMM:${C2}MMM:
|
:MMM%1:MMM` :MM:` `` `` `:MMM:%2MMM:
|
||||||
.MMM${C1}.MMMM` :MM. -MM. .MM- `MMMM.${C2}MMM.
|
.MMM%1.MMMM` :MM. -MM. .MM- `MMMM.%2MMM.
|
||||||
:MMM${C1}:MMMM` :MM. -MM- .MM: `MMMM-${C2}MMM:
|
:MMM%1:MMMM` :MM. -MM- .MM: `MMMM-%2MMM:
|
||||||
:MMM${C1}:MMMM` :MM. -MM- .MM: `MMMM:${C2}MMM:
|
:MMM%1:MMMM` :MM. -MM- .MM: `MMMM:%2MMM:
|
||||||
:MMM${C1}:MMMM` :MM. -MM- .MM: `MMMM-${C2}MMM:
|
:MMM%1:MMMM` :MM. -MM- .MM: `MMMM-%2MMM:
|
||||||
.MMM${C1}.MMMM` :MM:--:MM:--:MM: `MMMM.${C2}MMM.
|
.MMM%1.MMMM` :MM:--:MM:--:MM: `MMMM.%2MMM.
|
||||||
:MMM${C1}:MMM- `-MMMMMMMMMMMM-` -MMM-${C2}MMM:
|
:MMM%1:MMM- `-MMMMMMMMMMMM-` -MMM-%2MMM:
|
||||||
:MMM${C1}:MMM:` `:MMM:${C2}MMM:
|
:MMM%1:MMM:` `:MMM:%2MMM:
|
||||||
.MMM${C1}.MMMM:--------------:MMMM.${C2}MMM.
|
.MMM%1.MMMM:--------------:MMMM.%2MMM.
|
||||||
'-MMMM${C1}.-MMMMMMMMMMMMMMM-.${C2}MMMM-'
|
'-MMMM%1.-MMMMMMMMMMMMMMM-.%2MMMM-'
|
||||||
'.-MMMM${C1}``--:::::--``${C2}MMMM-.'
|
'.-MMMM%1``--:::::--``%2MMMM-.'
|
||||||
${C2} '-MMMMMMMMMMMMM-'
|
%2 '-MMMMMMMMMMMMM-'
|
||||||
${C2} ``-:::::-``
|
%2 ``-:::::-``
|
||||||
|
|||||||
+12
-12
@@ -1,18 +1,18 @@
|
|||||||
#/2;7;10;15
|
#/2;7;10;15
|
||||||
${C2} .;ldkO0000Okdl;.
|
%2 .;ldkO0000Okdl;.
|
||||||
.;d00xl:^''''''^:ok00d;.
|
.;d00xl:^''''''^:ok00d;.
|
||||||
.d00l' 'o00d.
|
.d00l' 'o00d.
|
||||||
.d0Kd'${C1} Okxol:;,. ${C2}:O0d.
|
.d0Kd'%1 Okxol:;,. %2:O0d.
|
||||||
.OK${C1}KKK0kOKKKKKKKKKKOxo:, ${C2}lKO.
|
.OK%1KKK0kOKKKKKKKKKKOxo:, %2lKO.
|
||||||
,0K${C1}KKKKKKKKKKKKKKK0P^${C2},,,${C1}^dx:${C2} ;00,
|
,0K%1KKKKKKKKKKKKKKK0P^%2,,,%1^dx:%2 ;00,
|
||||||
.OK${C1}KKKKKKKKKKKKKKKk'${C2}.oOPPb.${C1}'0k.${C2} cKO.
|
.OK%1KKKKKKKKKKKKKKKk'%2.oOPPb.%1'0k.%2 cKO.
|
||||||
:KK${C1}KKKKKKKKKKKKKKK: ${C2}kKx..dd ${C1}lKd${C2} 'OK:
|
:KK%1KKKKKKKKKKKKKKK: %2kKx..dd %1lKd%2 'OK:
|
||||||
dKK${C1}KKKKKKKKKOx0KKKd ${C2}^0KKKO' ${C1}kKKc${C2} dKd
|
dKK%1KKKKKKKKKOx0KKKd %2^0KKKO' %1kKKc%2 dKd
|
||||||
dKK${C1}KKKKKKKKKK;.;oOKx,..${C2}^${C1}..;kKKK0.${C2} dKd
|
dKK%1KKKKKKKKKK;.;oOKx,..%2^%1..;kKKK0.%2 dKd
|
||||||
:KK${C1}KKKKKKKKKK0o;...^cdxxOK0O/^^' ${C2}.0K:
|
:KK%1KKKKKKKKKK0o;...^cdxxOK0O/^^' %2.0K:
|
||||||
kKK${C1}KKKKKKKKKKKKK0x;,,......,;od ${C2}lKk
|
kKK%1KKKKKKKKKKKKK0x;,,......,;od %2lKk
|
||||||
'0K${C1}KKKKKKKKKKKKKKKKKKKK00KKOo^ ${C2}c00'
|
'0K%1KKKKKKKKKKKKKKKKKKKK00KKOo^ %2c00'
|
||||||
'kK${C1}KKOxddxkOO00000Okxoc;'' ${C2}.dKk'
|
'kK%1KKOxddxkOO00000Okxoc;'' %2.dKk'
|
||||||
l0Ko. .c00l'
|
l0Ko. .c00l'
|
||||||
'l0Kk:. .;xK0l'
|
'l0Kk:. .;xK0l'
|
||||||
'lkK0xl:;,,,,;:ldO0kl'
|
'lkK0xl:;,,,,;:ldO0kl'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#/2;7;10;15
|
#/2;7;10;15
|
||||||
${C1} ......
|
%1 ......
|
||||||
.,cdxxxoc,. .:kKMMMNWMMMNk:.
|
.,cdxxxoc,. .:kKMMMNWMMMNk:.
|
||||||
cKMMN0OOOKWMMXo. ; ;0MWk:. .:OMMk.
|
cKMMN0OOOKWMMXo. ; ;0MWk:. .:OMMk.
|
||||||
;WMK;. .lKMMNM, :NMK, .OMW;
|
;WMK;. .lKMMNM, :NMK, .OMW;
|
||||||
|
|||||||
+16
-16
@@ -1,21 +1,21 @@
|
|||||||
#/33;7;11;15
|
#/33;7;11;15
|
||||||
${C1} /////////////
|
%1 /////////////
|
||||||
/////////////////////
|
/////////////////////
|
||||||
///////${C2}*767${C1}////////////////
|
///////%2*767%1////////////////
|
||||||
//////${C2}7676767676*${C1}//////////////
|
//////%27676767676*%1//////////////
|
||||||
/////${C2}76767${C1}//${C2}7676767${C1}//////////////
|
/////%276767%1//%27676767%1//////////////
|
||||||
/////${C2}767676${C1}///${C2}*76767${C1}///////////////
|
/////%2767676%1///%2*76767%1///////////////
|
||||||
///////${C2}767676${C1}///${C2}76767${C1}.///${C2}7676*${C1}///////
|
///////%2767676%1///%276767%1.///%27676*%1///////
|
||||||
/////////${C2}767676${C1}//${C2}76767${C1}///${C2}767676${C1}////////
|
/////////%2767676%1//%276767%1///%2767676%1////////
|
||||||
//////////${C2}76767676767${C1}////${C2}76767${C1}/////////
|
//////////%276767676767%1////%276767%1/////////
|
||||||
///////////${C2}76767676${C1}//////${C2}7676${C1}//////////
|
///////////%276767676%1//////%27676%1//////////
|
||||||
////////////,${C2}7676${C1},///////${C2}767${C1}///////////
|
////////////,%27676%1,///////%2767%1///////////
|
||||||
/////////////*${C2}7676${C1}///////${C2}76${C1}////////////
|
/////////////*%27676%1///////%276%1////////////
|
||||||
///////////////${C2}7676${C1}////////////////////
|
///////////////%27676%1////////////////////
|
||||||
///////////////${C2}7676${C1}///${C2}767${C1}////////////
|
///////////////%27676%1///%2767%1////////////
|
||||||
//////////////////////${C2}'${C1}////////////
|
//////////////////////%2'%1////////////
|
||||||
//////${C2}.7676767676767676767,${C1}//////
|
//////%2.7676767676767676767,%1//////
|
||||||
/////${C2}767676767676767676767${C1}/////
|
/////%2767676767676767676767%1/////
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
/////////////////////
|
/////////////////////
|
||||||
/////////////
|
/////////////
|
||||||
|
|||||||
+14
-14
@@ -1,15 +1,15 @@
|
|||||||
#/27;39;5;12
|
#/27;39;5;12
|
||||||
${C1}@@@@ ${C1}@@@${C2}*
|
%1@@@@ %1@@@%2*
|
||||||
${C1}@@${C2}~~~~${C1}@@ ${C1}@@${C2}~~~
|
%1@@%2~~~~%1@@ %1@@%2~~~
|
||||||
${C1}@@${C2}~~ ${C2}~~${C1}@ ${C1}@@${C2}~~
|
%1@@%2~~ %2~~%1@ %1@@%2~~
|
||||||
${C1}@@${C2}~~ ${C2}~${C1}@ ${C1}@@@${C2}~~
|
%1@@%2~~ %2~%1@ %1@@@%2~~
|
||||||
${C2}*${C1}@@${C2}~~ ${C1}@@@@ ${C2}~${C1}@@@@${C2}~~~ ${C1}@@@${C2}*
|
%2*%1@@%2~~ %1@@@@ %2~%1@@@@%2~~~ %1@@@%2*
|
||||||
${C2}~~ ${C1}@@${C2}~~~~${C1}@@ ${C2}~~~~ ${C1}@@${C2}~~~
|
%2~~ %1@@%2~~~~%1@@ %2~~~~ %1@@%2~~~
|
||||||
${C1}@@${C2}~~ ${C2}~~${C1}@ ${C1}@@${C2}~~
|
%1@@%2~~ %2~~%1@ %1@@%2~~
|
||||||
${C1}@@${C2}~~ ${C2}~${C1}@ ${C1}@@@${C2}~~
|
%1@@%2~~ %2~%1@ %1@@@%2~~
|
||||||
${C2}*${C1}@@${C2}~~ ${C1}@@@@ ${C2}~${C1}@@@@${C2}~~~ ${C1}@@@${C2}*
|
%2*%1@@%2~~ %1@@@@ %2~%1@@@@%2~~~ %1@@@%2*
|
||||||
${C2}~~ ${C1}@@${C2}~~~~${C1}@@ ${C2}~~~~ ${C1}@@${C2}~~~
|
%2~~ %1@@%2~~~~%1@@ %2~~~~ %1@@%2~~~
|
||||||
${C1}@@${C2}~~ ${C2}~~${C1}@ ${C1}@@${C2}~~
|
%1@@%2~~ %2~~%1@ %1@@%2~~
|
||||||
${C1}@@${C2}~~ ${C2}~${C1}@ ${C1}@@@${C2}~~
|
%1@@%2~~ %2~%1@ %1@@@%2~~
|
||||||
${C2}*${C1}@@${C2}~~ ${C2}~${C1}@@@@${C2}~~~
|
%2*%1@@%2~~ %2~%1@@@@%2~~~
|
||||||
${C2}~~ ${C2}~~~~
|
%2~~ %2~~~~
|
||||||
|
|||||||
+16
-16
@@ -1,21 +1,21 @@
|
|||||||
#/1;7;3;15
|
#/1;7;3;15
|
||||||
${C1} .-/+oossssoo+\-.
|
%1 .-/+oossssoo+\-.
|
||||||
':+ssssssssssssssssss+:'
|
':+ssssssssssssssssss+:'
|
||||||
-+ssssssssssssssssssyyssss+-
|
-+ssssssssssssssssssyyssss+-
|
||||||
.ossssssssssssssssss${C2}dMMMNy${C1}sssso.
|
.ossssssssssssssssss%2dMMMNy%1sssso.
|
||||||
/sssssssssss${C2}hdmmNNmmyNMMMMh${C1}ssssss\
|
/sssssssssss%2hdmmNNmmyNMMMMh%1ssssss\
|
||||||
+sssssssss${C2}hm${C1}yd${C2}MMMMMMMNddddy${C1}ssssssss+
|
+sssssssss%2hm%1yd%2MMMMMMMNddddy%1ssssssss+
|
||||||
/ssssssss${C2}hNMMM${C1}yh${C2}hyyyyhmNMMMNh${C1}ssssssss\
|
/ssssssss%2hNMMM%1yh%2hyyyyhmNMMMNh%1ssssssss\
|
||||||
.ssssssss${C2}dMMMNh${C1}ssssssssss${C2}hNMMMd${C1}ssssssss.
|
.ssssssss%2dMMMNh%1ssssssssss%2hNMMMd%1ssssssss.
|
||||||
+ssss${C2}hhhyNMMNy${C1}ssssssssssss${C2}yNMMMy${C1}sssssss+
|
+ssss%2hhhyNMMNy%1ssssssssssss%2yNMMMy%1sssssss+
|
||||||
oss${C2}yNMMMNyMMh${C1}ssssssssssssss${C2}hmmmh${C1}ssssssso
|
oss%2yNMMMNyMMh%1ssssssssssssss%2hmmmh%1ssssssso
|
||||||
oss${C2}yNMMMNyMMh${C1}sssssssssssssshmmmh${C1}ssssssso
|
oss%2yNMMMNyMMh%1sssssssssssssshmmmh%1ssssssso
|
||||||
+ssss${C2}hhhyNMMNy${C1}ssssssssssss${C2}yNMMMy${C1}sssssss+
|
+ssss%2hhhyNMMNy%1ssssssssssss%2yNMMMy%1sssssss+
|
||||||
.ssssssss${C2}dMMMNh${C1}ssssssssss${C2}hNMMMd${C1}ssssssss.
|
.ssssssss%2dMMMNh%1ssssssssss%2hNMMMd%1ssssssss.
|
||||||
\ssssssss${C2}hNMMM${C1}yh${C2}hyyyyhdNMMMNh${C1}ssssssss/
|
\ssssssss%2hNMMM%1yh%2hyyyyhdNMMMNh%1ssssssss/
|
||||||
+sssssssss${C2}dm${C1}yd${C2}MMMMMMMMddddy${C1}ssssssss+
|
+sssssssss%2dm%1yd%2MMMMMMMMddddy%1ssssssss+
|
||||||
\sssssssssss${C2}hdmNNNNmyNMMMMh${C1}ssssss/
|
\sssssssssss%2hdmNNNNmyNMMMMh%1ssssss/
|
||||||
.ossssssssssssssssss${C2}dMMMNy${C1}sssso.
|
.ossssssssssssssssss%2dMMMNy%1sssso.
|
||||||
-+sssssssssssssssss${C2}yyy${C1}ssss+-
|
-+sssssssssssssssss%2yyy%1ssss+-
|
||||||
':+ssssssssssssssssss+:'
|
':+ssssssssssssssssss+:'
|
||||||
.-\+oossssoo+/-.
|
.-\+oossssoo+/-.
|
||||||
|
|||||||
+18
-18
@@ -1,19 +1,19 @@
|
|||||||
#/2;36;72;15
|
#/2;36;72;15
|
||||||
${C2}:::::----:::::
|
%2:::::----:::::
|
||||||
${C2}::----------------::=
|
%2::----------------::=
|
||||||
${C2}:-------------------::
|
%2:-------------------::
|
||||||
${C1} : ${C2}:::. ..:-------:
|
%1 : %2:::. ..:-------:
|
||||||
${C1} =*=. ${C2}.:-----:
|
%1 =*=. %2.:-----:
|
||||||
${C1} =****- ${C2}:-----:
|
%1 =****- %2:-----:
|
||||||
${C1}=*****- ${C2}:::::: :-----:
|
%1=*****- %2:::::: :-----:
|
||||||
${C1}=****+ ${C2}:--------: :----:
|
%1=****+ %2:--------: :----:
|
||||||
${C1}+****- ${C2}.----------. :----:
|
%1+****- %2.----------. :----:
|
||||||
${C1}+****- ${C2}.----------. :-----
|
%1+****- %2.----------. :-----
|
||||||
${C1}=****+ ${C2}:--------: :----:
|
%1=****+ %2:--------: :----:
|
||||||
${C1}=*****- ${C2}:::::: :-----:
|
%1=*****- %2:::::: :-----:
|
||||||
${C1} =*****- ${C2}:----:
|
%1 =*****- %2:----:
|
||||||
${C1} =*****+: ${C2}:-:
|
%1 =*****+: %2:-:
|
||||||
${C1} =*******=:: ::=-. ${C2}.
|
%1 =*******=:: ::=-. %2.
|
||||||
${C1} ==*******************-
|
%1 ==*******************-
|
||||||
${C1} ===****************=-
|
%1 ===****************=-
|
||||||
${C1} ===+=****++===
|
%1 ===+=****++===
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
distro_ascii: auto
|
|
||||||
fetch_script: auto
|
|
||||||
show_fs_type: true
|
|
||||||
hidden_partitions: []
|
|
||||||
# Hiding squashfs prevents snaps from showing up
|
|
||||||
hidden_filesystems: ["squashfs"]
|
|
||||||
hidden_gpus: []
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
distro_ascii: auto
|
||||||
|
modules:
|
||||||
|
- name: distribution
|
||||||
|
- name: hostname
|
||||||
|
- name: kernel
|
||||||
|
- name: packages
|
||||||
|
- name: shell
|
||||||
|
- name: init
|
||||||
|
- name: motherboard
|
||||||
|
- name: cpus
|
||||||
|
- name: gpus
|
||||||
|
- name: memory
|
||||||
|
- name: partitions
|
||||||
|
- name: local_ip
|
||||||
|
- name: de_wm
|
||||||
|
- name: monitors
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
echo -e "${C3}Distribution: ${C4}${DISTRO_LONG_NAME} ($(uname -m))"
|
|
||||||
echo -e "${C3}Hostname: ${C4}$(cat /etc/hostname)"
|
|
||||||
echo -e "${C3}Kernel: ${C4}$(uname -s) $(uname -r)"
|
|
||||||
echo -e "${C3}Packages: ${C4}${PACKAGES}"
|
|
||||||
echo -e "${C3}Shell: ${C4}${USER_SHELL}"
|
|
||||||
echo -e "${C3}Init: ${C4}${INIT_SYSTEM}"
|
|
||||||
echo -e "${C3}Libc: ${C4}${LIBC}"
|
|
||||||
[ -n "$MOTHERBOARD" ] && echo -e "${C3}Motherboard: ${C4}${MOTHERBOARD}"
|
|
||||||
[ -n "$CPU_MODEL" ] && echo -e "${C3}CPU: ${C4}${CPU_MODEL} (${CPU_THREADS} threads)"
|
|
||||||
for i in $(seq "${CONNECTED_GPUS}"); do
|
|
||||||
gpu="GPU$i"
|
|
||||||
echo -e "${C3}GPU: ${C4}${!gpu}"
|
|
||||||
done
|
|
||||||
[ -n "$MEM_TOTAL" ] && [ -n "$MEM_USED" ] && echo -e "${C3}Memory: ${C4}${MEM_USED} MiB / ${MEM_TOTAL} MiB"
|
|
||||||
for i in $(seq "${MOUNTED_PARTITIONS}"); do
|
|
||||||
mountpoint="PARTITION${i}_MOUNTPOINT"
|
|
||||||
label="PARTITION${i}_LABEL"
|
|
||||||
type="PARTITION${i}_TYPE"
|
|
||||||
total="PARTITION${i}_TOTAL_SIZE"
|
|
||||||
used="PARTITION${i}_USED_SIZE"
|
|
||||||
if [ -z "${!type}" ]; then
|
|
||||||
if [ -z "${!label}" ]; then
|
|
||||||
echo -e "${C3}Partition ${!mountpoint}: ${C4}${!used}/${!total}"
|
|
||||||
else
|
|
||||||
echo -e "${C3}Partition ${!label}: ${C4}${!used}/${!total}"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if [ -z "${!label}" ]; then
|
|
||||||
echo -e "${C3}Partition ${!mountpoint} (${!type}): ${C4}${!used}/${!total}"
|
|
||||||
else
|
|
||||||
echo -e "${C3}Partition ${!label} (${!type}): ${C4}${!used}/${!total}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
[ -n "$LOCAL_IPV4" ] && echo -e "${C3}Local IPv4 Address: ${C4}${LOCAL_IPV4}"
|
|
||||||
if [ -n "$DISPLAY_PROTOCOL" ]; then
|
|
||||||
echo -e "${C3}Display Protocol: ${C4}${DISPLAY_PROTOCOL}"
|
|
||||||
for i in $(seq "${CONNECTED_MONITORS}"); do
|
|
||||||
monitor="MONITOR$i"
|
|
||||||
echo -e "${C3}Screen $i: ${C4}${!monitor}"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
[ -n "$DE_WM" ] && echo -e "${C3}DE/WM: ${C4}${DE_WM}"
|
|
||||||
|
|
||||||
# Exiting with error code 0 in case the condition above returns 1
|
|
||||||
exit 0
|
|
||||||
+15
-10
@@ -2,21 +2,26 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupColorMap(asciiArt string) map[string]string {
|
func setupColorMap(asciiArtHeader string) []string {
|
||||||
colorMap := make(map[string]string)
|
colorMap := make([]string, 10)
|
||||||
|
|
||||||
// Read colors from ascii art
|
// Set default color map values
|
||||||
if strings.HasPrefix(asciiArt, "#/") {
|
for i := range 10 {
|
||||||
firstLine := strings.Split(asciiArt, "\n")[0]
|
colorMap[i] = "\033[0m"
|
||||||
ansiColors := strings.Split(strings.TrimPrefix(firstLine, "#/"), ";")
|
|
||||||
|
|
||||||
for i, ansiColor := range ansiColors {
|
|
||||||
colorMap["C"+strconv.Itoa(i+1)] = fmt.Sprintf("\033[38;5;%sm", ansiColor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return if header is empty
|
||||||
|
if asciiArtHeader == "" {
|
||||||
|
return colorMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read colors from ascii art header
|
||||||
|
ansiColors := strings.Split(strings.TrimPrefix(asciiArtHeader, "#/"), ";")
|
||||||
|
for i := 0; i < 9 && i < len(ansiColors); i++ {
|
||||||
|
colorMap[i+1] = fmt.Sprintf("\033[38;5;%sm", ansiColors[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
return colorMap
|
return colorMap
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StormfetchConfig struct {
|
||||||
|
Ascii string `yaml:"distro_ascii"`
|
||||||
|
Modules []stormfetchModuleConfig `yaml:"modules"`
|
||||||
|
AnsiiColors []int `yaml:"ansii_colors"`
|
||||||
|
ForceConfigAnsii bool `yaml:"force_config_ansii"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = StormfetchConfig{
|
||||||
|
Ascii: "auto",
|
||||||
|
Modules: make([]stormfetchModuleConfig, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
} else if _, err := os.Stat(path.Join(SystemConfigDir, "stormfetch/config.yml")); err == nil {
|
||||||
|
ConfigPath = path.Join(SystemConfigDir, "stormfetch/config.yml")
|
||||||
|
} else {
|
||||||
|
log.Fatalf("Config file not found: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse config
|
||||||
|
bytes, err := os.ReadFile(ConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(bytes, &config)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
+47
-23
@@ -1,35 +1,53 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/go-gl/glfw/v3.3/glfw"
|
|
||||||
"github.com/jackmordaunt/ghw"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-gl/glfw/v3.3/glfw"
|
||||||
|
"github.com/jackmordaunt/ghw"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetCPUModel() string {
|
type CPU struct {
|
||||||
cpu, err := ghw.CPU()
|
Vendor string
|
||||||
if err != nil {
|
Model string
|
||||||
return ""
|
Cores int
|
||||||
}
|
Threads int
|
||||||
if len(cpu.Processors) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return cpu.Processors[0].Model
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCPUThreads() int {
|
type Monitor struct {
|
||||||
cpu, err := ghw.CPU()
|
Width int
|
||||||
if err != nil {
|
Height int
|
||||||
return 0
|
RefreshRate int
|
||||||
}
|
|
||||||
return int(cpu.TotalThreads)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetGPUModels() (ret []string) {
|
func GetCPUs(hiddenCPUs []int) []CPU {
|
||||||
|
ret := make([]CPU, 0)
|
||||||
|
|
||||||
|
cpus, err := ghw.CPU()
|
||||||
|
if err != nil {
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, cpu := range cpus.Processors {
|
||||||
|
if slices.Contains(hiddenCPUs, i+1) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, CPU{
|
||||||
|
Vendor: cpu.Vendor,
|
||||||
|
Model: cpu.Model,
|
||||||
|
Cores: int(cpu.NumCores),
|
||||||
|
Threads: int(cpu.NumThreads),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetGPUModels(hiddenGPUS []int) (ret []string) {
|
||||||
cmd := exec.Command("sh", "-c", "lspci -v -m | grep 'VGA' -A6 | grep '^Device:'")
|
cmd := exec.Command("sh", "-c", "lspci -v -m | grep 'VGA' -A6 | grep '^Device:'")
|
||||||
bytes, err := cmd.Output()
|
bytes, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -37,7 +55,7 @@ func GetGPUModels() (ret []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, gpu := range strings.Split(string(bytes), "\n") {
|
for i, gpu := range strings.Split(string(bytes), "\n") {
|
||||||
if slices.Contains(config.HiddenGPUS, i+1) {
|
if slices.Contains(hiddenGPUS, i+1) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if gpu == "" {
|
if gpu == "" {
|
||||||
@@ -58,16 +76,22 @@ func GetMotherboardModel() string {
|
|||||||
return strings.TrimSpace(string(bytes))
|
return strings.TrimSpace(string(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMonitorResolution() []string {
|
func GetMonitors() []Monitor {
|
||||||
var monitors []string
|
var monitors []Monitor
|
||||||
if GetDisplayProtocol() != "" {
|
if GetDisplayProtocol() != "" {
|
||||||
err := glfw.Init()
|
err := glfw.Init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, monitor := range glfw.GetMonitors() {
|
for _, monitor := range glfw.GetMonitors() {
|
||||||
mode := monitor.GetVideoMode()
|
mode := monitor.GetVideoMode()
|
||||||
monitors = append(monitors, fmt.Sprintf("%dx%d %dHz", mode.Width, mode.Height, mode.RefreshRate))
|
|
||||||
|
monitors = append(monitors, Monitor{
|
||||||
|
Width: mode.Width,
|
||||||
|
Height: mode.Height,
|
||||||
|
RefreshRate: mode.RefreshRate,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
defer glfw.Terminate()
|
defer glfw.Terminate()
|
||||||
}
|
}
|
||||||
|
|||||||
+120
-221
@@ -3,258 +3,157 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode"
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var systemConfigDir = "/etc/"
|
// Build-time variables
|
||||||
|
var StormfetchVersion = "dev"
|
||||||
|
var SystemConfigDir = "/etc/"
|
||||||
|
|
||||||
var configPath = ""
|
// Flag variables
|
||||||
var fetchScriptPath = ""
|
var ShowVersion = false
|
||||||
|
var ConfigPath = ""
|
||||||
var TimeTaken = false
|
var Ascii = ""
|
||||||
|
var ShowModuleTimeTaken = false
|
||||||
var config = StormfetchConfig{
|
|
||||||
Ascii: "auto",
|
|
||||||
FetchScript: "auto",
|
|
||||||
ShowFSType: false,
|
|
||||||
HiddenPartitions: make([]string, 0),
|
|
||||||
HiddenGPUS: make([]int, 0),
|
|
||||||
}
|
|
||||||
|
|
||||||
type StormfetchConfig struct {
|
|
||||||
Ascii string `yaml:"distro_ascii"`
|
|
||||||
DistroName string `yaml:"distro_name"`
|
|
||||||
FetchScript string `yaml:"fetch_script"`
|
|
||||||
AnsiiColors []int `yaml:"ansii_colors"`
|
|
||||||
ForceConfigAnsii bool `yaml:"force_config_ansii"`
|
|
||||||
ShowFSType bool `yaml:"show_fs_type"`
|
|
||||||
HiddenPartitions []string `yaml:"hidden_partitions"`
|
|
||||||
HiddenFilesystems []string `yaml:"hidden_filesystems"`
|
|
||||||
HiddenGPUS []int `yaml:"hidden_gpus"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
parseFlags()
|
||||||
readConfig()
|
readConfig()
|
||||||
readFlags()
|
initializeModuleMap()
|
||||||
runStormfetch()
|
run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func readConfig() {
|
func parseFlags() {
|
||||||
// Get home directory
|
flag.BoolVar(&ShowVersion, "version", false, "Show Stormfetch version")
|
||||||
userConfigDir, _ := os.UserConfigDir()
|
flag.StringVar(&ConfigPath, "config", "", "Use the specified config file")
|
||||||
// Find valid config directory
|
flag.BoolVar(&ShowModuleTimeTaken, "time-taken", false, "Show time taken to execute each module")
|
||||||
if _, err := os.Stat(path.Join(userConfigDir, "stormfetch/config.yaml")); err == nil {
|
flag.StringVar(&Ascii, "ascii", "", "Set distro ascii")
|
||||||
configPath = path.Join(userConfigDir, "stormfetch/config.yaml")
|
|
||||||
} else if _, err := os.Stat(path.Join(systemConfigDir, "stormfetch/config.yaml")); err == nil {
|
|
||||||
configPath = path.Join(systemConfigDir, "stormfetch/config.yaml")
|
|
||||||
} else {
|
|
||||||
log.Fatalf("Config file not found: %s", err.Error())
|
|
||||||
}
|
|
||||||
// Parse config
|
|
||||||
bytes, err := os.ReadFile(configPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
err = yaml.Unmarshal(bytes, &config)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if config.FetchScript == "" {
|
|
||||||
log.Fatalf("Fetch script path is empty")
|
|
||||||
} else if config.FetchScript != "auto" {
|
|
||||||
stat, err := os.Stat(config.FetchScript)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Fetch script file not found: %s", err.Error())
|
|
||||||
} else if stat.IsDir() {
|
|
||||||
log.Fatalf("Fetch script path points to a directory")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if _, err := os.Stat(path.Join(userConfigDir, "stormfetch/fetch_script.sh")); err == nil {
|
|
||||||
fetchScriptPath = path.Join(userConfigDir, "stormfetch/fetch_script.sh")
|
|
||||||
} else if _, err := os.Stat(path.Join(systemConfigDir, "stormfetch/fetch_script.sh")); err == nil {
|
|
||||||
fetchScriptPath = path.Join(systemConfigDir, "stormfetch/fetch_script.sh")
|
|
||||||
} else {
|
|
||||||
log.Fatalf("Fetch script file not found: %s", err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readFlags() {
|
|
||||||
flag.StringVar(&config.Ascii, "ascii", config.Ascii, "Set distro ascii")
|
|
||||||
flag.StringVar(&config.DistroName, "distro-name", config.DistroName, "Set distro name")
|
|
||||||
flag.BoolVar(&TimeTaken, "time-taken", false, "Show time taken for fetched information")
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetupFetchEnv(showTimeTaken bool) []string {
|
func run() {
|
||||||
var env = make(map[string]string)
|
if ShowVersion {
|
||||||
setVariable := func(key string, setter func() string) {
|
fmt.Printf("Stormfetch version %s\n", StormfetchVersion)
|
||||||
start := time.Now().UnixMilli()
|
return
|
||||||
env[key] = setter()
|
|
||||||
end := time.Now().UnixMilli()
|
|
||||||
if showTimeTaken {
|
|
||||||
fmt.Printf("Setting '%s' took %d milliseconds\n", key, end-start)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setVariable("PACKAGES", func() string { return GetInstalledPackages() })
|
|
||||||
setVariable("DISTRO_LONG_NAME", func() string { return GetDistroInfo().LongName })
|
|
||||||
setVariable("DISTRO_SHORT_NAME", func() string { return GetDistroInfo().ShortName })
|
|
||||||
setVariable("CPU_MODEL", func() string { return GetCPUModel() })
|
|
||||||
setVariable("MOTHERBOARD", func() string { return GetMotherboardModel() })
|
|
||||||
setVariable("CPU_THREADS", func() string { return strconv.Itoa(GetCPUThreads()) })
|
|
||||||
start := time.Now().UnixMilli()
|
|
||||||
memory := GetMemoryInfo()
|
|
||||||
end := time.Now().UnixMilli()
|
|
||||||
if showTimeTaken {
|
|
||||||
fmt.Printf("Setting '%s' took %d milliseconds\n", "MEM_*", end-start)
|
|
||||||
}
|
|
||||||
if memory != nil {
|
|
||||||
env["MEM_TOTAL"] = strconv.Itoa(memory.MemTotal)
|
|
||||||
env["MEM_USED"] = strconv.Itoa(memory.MemTotal - memory.MemAvailable)
|
|
||||||
env["MEM_FREE"] = strconv.Itoa(memory.MemAvailable)
|
|
||||||
}
|
|
||||||
start = time.Now().UnixMilli()
|
|
||||||
partitions := GetMountedPartitions(config.HiddenPartitions, config.HiddenFilesystems)
|
|
||||||
end = time.Now().UnixMilli()
|
|
||||||
if showTimeTaken {
|
|
||||||
fmt.Printf("Setting '%s' took %d milliseconds\n", "PARTITION_*", end-start)
|
|
||||||
}
|
|
||||||
if len(partitions) != 0 {
|
|
||||||
env["MOUNTED_PARTITIONS"] = strconv.Itoa(len(partitions))
|
|
||||||
for i, part := range partitions {
|
|
||||||
env["PARTITION"+strconv.Itoa(i+1)+"_DEVICE"] = part.Device
|
|
||||||
env["PARTITION"+strconv.Itoa(i+1)+"_MOUNTPOINT"] = part.MountPoint
|
|
||||||
if part.Label != "" {
|
|
||||||
env["PARTITION"+strconv.Itoa(i+1)+"_LABEL"] = part.Label
|
|
||||||
}
|
|
||||||
if part.FileystemType != "" && config.ShowFSType {
|
|
||||||
env["PARTITION"+strconv.Itoa(i+1)+"_TYPE"] = part.FileystemType
|
|
||||||
}
|
|
||||||
env["PARTITION"+strconv.Itoa(i+1)+"_TOTAL_SIZE"] = FormatBytes(part.TotalSize)
|
|
||||||
env["PARTITION"+strconv.Itoa(i+1)+"_USED_SIZE"] = FormatBytes(part.UsedSize)
|
|
||||||
env["PARTITION"+strconv.Itoa(i+1)+"_FREE_SIZE"] = FormatBytes(part.FreeSize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setVariable("DE_WM", func() string { return GetDEWM() })
|
|
||||||
setVariable("USER_SHELL", func() string { return GetShell() })
|
|
||||||
setVariable("DISPLAY_PROTOCOL", func() string { return GetDisplayProtocol() })
|
|
||||||
setVariable("LIBC", func() string { return GetLibc() })
|
|
||||||
setVariable("INIT_SYSTEM", func() string { return GetInitSystem() })
|
|
||||||
setVariable("LOCAL_IPV4", func() string { return GetLocalIP() })
|
|
||||||
start = time.Now().UnixMilli()
|
|
||||||
monitors := GetMonitorResolution()
|
|
||||||
end = time.Now().UnixMilli()
|
|
||||||
if showTimeTaken {
|
|
||||||
fmt.Printf("Setting '%s' took %d milliseconds\n", "MONITOR_*", end-start)
|
|
||||||
}
|
|
||||||
if len(monitors) != 0 {
|
|
||||||
env["CONNECTED_MONITORS"] = strconv.Itoa(len(monitors))
|
|
||||||
for i, monitor := range monitors {
|
|
||||||
env["MONITOR"+strconv.Itoa(i+1)] = monitor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
start = time.Now().UnixMilli()
|
|
||||||
gpus := GetGPUModels()
|
|
||||||
end = time.Now().UnixMilli()
|
|
||||||
if showTimeTaken {
|
|
||||||
fmt.Printf("Setting '%s' took %d milliseconds\n", "GPU_*", end-start)
|
|
||||||
}
|
|
||||||
if len(gpus) != 0 {
|
|
||||||
env["CONNECTED_GPUS"] = strconv.Itoa(len(gpus))
|
|
||||||
for i, gpu := range gpus {
|
|
||||||
if gpu == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
env["GPU"+strconv.Itoa(i+1)] = gpu
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var ret = make([]string, len(env))
|
// Fetch ascii art and remove header
|
||||||
i := 0
|
|
||||||
for key, value := range env {
|
|
||||||
ret[i] = fmt.Sprintf("%s=%s", key, value)
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func runStormfetch() {
|
|
||||||
// Fetch ascii art
|
|
||||||
asciiArt := GetDistroAsciiArt()
|
asciiArt := GetDistroAsciiArt()
|
||||||
|
asciiArtHeader := ""
|
||||||
// Setup color map
|
if strings.HasPrefix(asciiArt, "#/") {
|
||||||
colorMap := setupColorMap(asciiArt)
|
asciiArtHeader = strings.SplitN(asciiArt, "\n", 2)[0]
|
||||||
if len(colorMap) > 0 {
|
|
||||||
asciiArt = os.Expand(asciiArt, func(s string) string {
|
|
||||||
return colorMap[s]
|
|
||||||
})
|
|
||||||
|
|
||||||
asciiArt = strings.SplitN(asciiArt, "\n", 2)[1]
|
asciiArt = strings.SplitN(asciiArt, "\n", 2)[1]
|
||||||
}
|
}
|
||||||
|
asciiArtNoColor := asciiArt
|
||||||
|
|
||||||
asciiSplit := strings.Split(asciiArt, "\n")
|
// Rewrite last color code to the start of the next line
|
||||||
asciiNoColor := StripAnsii(asciiArt)
|
lastColor := "0"
|
||||||
|
for i := 1; i < len(asciiArt); i++ {
|
||||||
|
rune := rune(asciiArt[i])
|
||||||
|
|
||||||
// Execute fetch script
|
if unicode.IsDigit(rune) && asciiArt[i-1] == '%' {
|
||||||
cmd := exec.Command("/bin/bash", fetchScriptPath)
|
lastColor = string(rune)
|
||||||
cmd.Dir = path.Dir(fetchScriptPath)
|
}
|
||||||
cmd.Env = os.Environ()
|
|
||||||
cmd.Env = append(cmd.Env, SetupFetchEnv(TimeTaken)...)
|
if rune == '\n' {
|
||||||
cmd.Env = append(cmd.Env, "C0=\033[0m")
|
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 {
|
for key, value := range colorMap {
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", key, value))
|
asciiArt = strings.ReplaceAll(asciiArt, "%"+strconv.Itoa(key), value)
|
||||||
|
asciiArtNoColor = strings.ReplaceAll(asciiArtNoColor, "%"+strconv.Itoa(key), "")
|
||||||
}
|
}
|
||||||
out, err := cmd.Output()
|
|
||||||
if err != nil {
|
// Execute modules in order
|
||||||
log.Fatalf("Error: Could not run fetch script: %s", err)
|
modulesText := make([]string, 0)
|
||||||
|
for _, moduleConfig := range config.Modules {
|
||||||
|
module, ok := Modules[moduleConfig.Name]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
// Print Distro Information
|
|
||||||
|
// Set module config options
|
||||||
|
if moduleConfig.Format != "" {
|
||||||
|
module.Format = moduleConfig.Format
|
||||||
|
}
|
||||||
|
if moduleConfig.Data != nil {
|
||||||
|
module.Data = moduleConfig.Data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute module
|
||||||
|
start := time.Now().UnixMilli()
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace colors in returned string
|
||||||
|
textNoColor := text
|
||||||
|
for key, value := range colorMap {
|
||||||
|
text = strings.ReplaceAll(text, "%"+strconv.Itoa(key), value)
|
||||||
|
textNoColor = strings.ReplaceAll(textNoColor, "%"+strconv.Itoa(key), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue if text length is 0
|
||||||
|
if len(textNoColor) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add text to slice
|
||||||
|
for _, line := range strings.Split(strings.TrimSpace(text), "\n") {
|
||||||
|
modulesText = append(modulesText, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get longest line in ascii art
|
||||||
maxWidth := 0
|
maxWidth := 0
|
||||||
for _, line := range strings.Split(asciiNoColor, "\n") {
|
for _, line := range strings.Split(asciiArtNoColor, "\n") {
|
||||||
if len(line) > maxWidth {
|
if len(line) > maxWidth {
|
||||||
maxWidth = len(line)
|
maxWidth = len(line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final := ""
|
|
||||||
y := len(asciiSplit)
|
// Split ascii art into each line
|
||||||
if len(asciiSplit) < len(strings.Split(string(out), "\n")) {
|
asciiArtSplit := strings.Split(asciiArt, "\n")
|
||||||
y = len(strings.Split(string(out), "\n"))
|
asciiArtNoColorSplit := strings.Split(asciiArtNoColor, "\n")
|
||||||
|
|
||||||
|
// Get amount of lines to print
|
||||||
|
lineCount := max(len(asciiArtSplit), len(modulesText))
|
||||||
|
|
||||||
|
// Combine ascii art and module text
|
||||||
|
final := strings.Builder{}
|
||||||
|
for i := range lineCount {
|
||||||
|
// Write ascii art
|
||||||
|
currentLineLength := 0
|
||||||
|
if i < len(asciiArtSplit) {
|
||||||
|
final.WriteString(asciiArtSplit[i])
|
||||||
|
currentLineLength += len(asciiArtNoColorSplit[i])
|
||||||
}
|
}
|
||||||
for lineIndex := 0; lineIndex < y; lineIndex++ {
|
|
||||||
line := ""
|
// Write blank space between ascii art and module text
|
||||||
for i := 0; i < maxWidth+5; i++ {
|
for i := currentLineLength; i < maxWidth+3; i++ {
|
||||||
line = line + " "
|
final.WriteString(" ")
|
||||||
}
|
}
|
||||||
lastAsciiColor := ""
|
|
||||||
if lineIndex < len(asciiSplit) {
|
// Write module text
|
||||||
line = asciiSplit[lineIndex]
|
if i < len(modulesText) {
|
||||||
lineVisibleLength := len(strings.Split(asciiNoColor, "\n")[lineIndex])
|
final.WriteString(modulesText[i])
|
||||||
if lineIndex != 0 {
|
|
||||||
r := regexp.MustCompile("\033[38;5;[0-9]+m")
|
|
||||||
matches := r.FindAllString(asciiSplit[lineIndex-1], -1)
|
|
||||||
if len(matches) != 0 {
|
|
||||||
lastAsciiColor = r.FindAllString(asciiSplit[lineIndex-1], -1)[len(matches)-1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final.WriteString("\n")
|
||||||
}
|
}
|
||||||
for i := lineVisibleLength; i < maxWidth+5; i++ {
|
|
||||||
line = line + " "
|
fmt.Println(strings.TrimRight(final.String(), "\n") + "\033[0m")
|
||||||
}
|
|
||||||
asciiSplit[lineIndex] = lastAsciiColor + line
|
|
||||||
}
|
|
||||||
str := string(out)
|
|
||||||
if lineIndex < len(strings.Split(str, "\n")) {
|
|
||||||
line = line + colorMap["C0"] + strings.Split(str, "\n")[lineIndex]
|
|
||||||
}
|
|
||||||
final += lastAsciiColor + line + "\n"
|
|
||||||
}
|
|
||||||
final = strings.TrimRight(final, "\n\t ")
|
|
||||||
fmt.Println(final + "\033[0m")
|
|
||||||
}
|
}
|
||||||
|
|||||||
+435
@@ -0,0 +1,435 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Used to declare modules in config files
|
||||||
|
type stormfetchModuleConfig struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
Format string `yaml:"format"`
|
||||||
|
Data map[string]any `yaml:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StormfetchModule struct {
|
||||||
|
Execute func(StormfetchModule) string
|
||||||
|
stormfetchModuleConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
var Modules map[string]StormfetchModule = make(map[string]StormfetchModule)
|
||||||
|
|
||||||
|
func (sm StormfetchModule) GetData(key string, defaultValue any) (any, bool) {
|
||||||
|
if sm.Data == nil {
|
||||||
|
return defaultValue, false
|
||||||
|
}
|
||||||
|
|
||||||
|
data, ok := sm.Data[key]
|
||||||
|
if !ok {
|
||||||
|
return defaultValue, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if reflect.ValueOf(data).Kind() != reflect.ValueOf(defaultValue).Kind() {
|
||||||
|
return defaultValue, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterModule(module StormfetchModule) bool {
|
||||||
|
if _, ok := Modules[module.Name]; ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
Modules[module.Name] = module
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func initializeModuleMap() {
|
||||||
|
// Distribution Module
|
||||||
|
distributionModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "distribution", Format: "%3Distribution: %4$DISTRO_SHORT ($ARCH)"}, Execute: func(sm StormfetchModule) string {
|
||||||
|
distroInfo := GetDistroInfo()
|
||||||
|
return os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "DISTRO_ID":
|
||||||
|
return distroInfo.ID
|
||||||
|
case "DISTRO_SHORT":
|
||||||
|
return distroInfo.ShortName
|
||||||
|
case "DISTRO_LONG":
|
||||||
|
return distroInfo.LongName
|
||||||
|
case "ARCH":
|
||||||
|
return GetArch()
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
RegisterModule(distributionModule)
|
||||||
|
|
||||||
|
// Hostname module
|
||||||
|
hostnameModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "hostname", Format: "%3Hostname: %4$HOSTNAME"}, Execute: func(sm StormfetchModule) string {
|
||||||
|
hostname, _ := os.Hostname()
|
||||||
|
return os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "HOSTNAME":
|
||||||
|
return hostname
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
RegisterModule(hostnameModule)
|
||||||
|
|
||||||
|
// Kernel module
|
||||||
|
kernelModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "kernel", Format: "%3Kernel: %4$KERNEL_NAME $KERNEL_RELEASE"}, Execute: func(sm StormfetchModule) string {
|
||||||
|
kernelName, kernelRelease := GetKernel()
|
||||||
|
return os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "KERNEL_NAME":
|
||||||
|
return kernelName
|
||||||
|
case "KERNEL_RELEASE":
|
||||||
|
return kernelRelease
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
RegisterModule(kernelModule)
|
||||||
|
|
||||||
|
// Packages module
|
||||||
|
packagesModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "packages", Format: "%3Packages: %4$PACKAGES"}, Execute: func(sm StormfetchModule) string {
|
||||||
|
return os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "PACKAGES":
|
||||||
|
return GetInstalledPackages()
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
RegisterModule(packagesModule)
|
||||||
|
|
||||||
|
// Shell module
|
||||||
|
shellModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "shell", Format: "%3Shell: %4$SHELL"}, Execute: func(sm StormfetchModule) string {
|
||||||
|
return os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "SHELL":
|
||||||
|
return GetShell()
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
RegisterModule(shellModule)
|
||||||
|
|
||||||
|
// Init system module
|
||||||
|
initSystemModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "init_system", Format: "%3Init: %4$INIT"}, Execute: func(sm StormfetchModule) string {
|
||||||
|
return os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "INIT":
|
||||||
|
return GetInitSystem()
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
RegisterModule(initSystemModule)
|
||||||
|
|
||||||
|
// Libc module
|
||||||
|
libcModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "libc", Format: "%3Libc: %4$LIBC"}, Execute: func(sm StormfetchModule) string {
|
||||||
|
return os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "LIBC":
|
||||||
|
return GetLibc()
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
RegisterModule(libcModule)
|
||||||
|
|
||||||
|
// Motherboard module
|
||||||
|
MotherboardModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "motherboard", Format: "%3Motherboard: %4$MOTHERBOARD"}, Execute: func(sm StormfetchModule) string {
|
||||||
|
motherboard := GetMotherboardModel()
|
||||||
|
|
||||||
|
// Return empty string if can't detect motherboard model
|
||||||
|
if motherboard == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "MOTHERBOARD":
|
||||||
|
return motherboard
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
RegisterModule(MotherboardModule)
|
||||||
|
|
||||||
|
// Motherboard module
|
||||||
|
cpusModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "cpus", Format: "%3CPU: %4$CPU_MODEL ($CPU_THREADS threads)"}, Execute: func(sm StormfetchModule) string {
|
||||||
|
hiddenCPUsInterface, _ := sm.GetData("hidden_cpus", make([]any, 0))
|
||||||
|
|
||||||
|
// Convert interface slices to string slices
|
||||||
|
hiddenCPUs := make([]int, 0)
|
||||||
|
for _, value := range hiddenCPUsInterface.([]any) {
|
||||||
|
hiddenCPUs = append(hiddenCPUs, value.(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
builder := strings.Builder{}
|
||||||
|
cpus := GetCPUs(hiddenCPUs)
|
||||||
|
|
||||||
|
for i, cpu := range cpus {
|
||||||
|
expanded := os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "CPU_NUM":
|
||||||
|
return strconv.Itoa(i + 1)
|
||||||
|
case "CPU_VENDOR":
|
||||||
|
return cpu.Vendor
|
||||||
|
case "CPU_MODEL":
|
||||||
|
return cpu.Model
|
||||||
|
case "CPU_CORES":
|
||||||
|
return strconv.Itoa(cpu.Cores)
|
||||||
|
case "CPU_THREADS":
|
||||||
|
return strconv.Itoa(cpu.Threads)
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
builder.WriteString(expanded + "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.String()
|
||||||
|
}}
|
||||||
|
RegisterModule(cpusModule)
|
||||||
|
|
||||||
|
// GPUs module
|
||||||
|
gpusModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "gpus", Format: "%3GPU: %4$GPU_MODEL"}, Execute: func(sm StormfetchModule) string {
|
||||||
|
hiddenGPUsInterface, _ := sm.GetData("hidden_gpus", make([]any, 0))
|
||||||
|
|
||||||
|
// Convert interface slices to string slices
|
||||||
|
hiddenGPUs := make([]int, 0)
|
||||||
|
for _, value := range hiddenGPUsInterface.([]any) {
|
||||||
|
hiddenGPUs = append(hiddenGPUs, value.(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
builder := strings.Builder{}
|
||||||
|
gpus := GetGPUModels(hiddenGPUs)
|
||||||
|
|
||||||
|
for i, gpu := range gpus {
|
||||||
|
expanded := os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "GPU_NUM":
|
||||||
|
return strconv.Itoa(i + 1)
|
||||||
|
case "GPU_MODEL":
|
||||||
|
return gpu
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
builder.WriteString(expanded + "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.String()
|
||||||
|
}}
|
||||||
|
RegisterModule(gpusModule)
|
||||||
|
|
||||||
|
// Memory module
|
||||||
|
memoryModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "memory", Format: "%3Memory: %4$MEM_USED MiB / $MEM_TOTAL MiB"}, Execute: func(sm StormfetchModule) string {
|
||||||
|
memoryInfo := GetMemoryInfo()
|
||||||
|
|
||||||
|
return os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "MEM_TOTAL":
|
||||||
|
return strconv.Itoa(memoryInfo.MemTotal)
|
||||||
|
case "MEM_AVAILABLE":
|
||||||
|
return strconv.Itoa(memoryInfo.MemAvailable)
|
||||||
|
case "MEM_FREE":
|
||||||
|
return strconv.Itoa(memoryInfo.MemFree)
|
||||||
|
case "MEM_USED":
|
||||||
|
return strconv.Itoa(memoryInfo.MemTotal - memoryInfo.MemAvailable)
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
RegisterModule(memoryModule)
|
||||||
|
|
||||||
|
// Partitions module
|
||||||
|
partitionsModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "partitions", Format: "%3Partition ${PART_AUTONAME} (${PART_FS}): %4${PART_USED} / ${PART_TOTAL}"}, Execute: func(sm StormfetchModule) string {
|
||||||
|
hiddenPartitionsInterface, _ := sm.GetData("hidden_partitions", make([]any, 0))
|
||||||
|
hiddenFilesystemsInterface, _ := sm.GetData("hidden_filesystems", make([]any, 0))
|
||||||
|
alternativeNamesInterface, _ := sm.GetData("alternative_names", make(map[string]any, 0))
|
||||||
|
|
||||||
|
// Convert interface slices to string slices
|
||||||
|
hiddenPartitions := make([]string, 0)
|
||||||
|
for _, value := range hiddenPartitionsInterface.([]any) {
|
||||||
|
hiddenPartitions = append(hiddenPartitions, value.(string))
|
||||||
|
}
|
||||||
|
hiddenFilesystems := make([]string, 0)
|
||||||
|
for _, value := range hiddenFilesystemsInterface.([]any) {
|
||||||
|
hiddenFilesystems = append(hiddenFilesystems, value.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert interface map to map[string]string
|
||||||
|
alternativeNames := make(map[string]string)
|
||||||
|
for key, value := range alternativeNamesInterface.(map[string]any) {
|
||||||
|
alternativeNames[key] = value.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
builder := strings.Builder{}
|
||||||
|
partitions := GetMountedPartitions(hiddenPartitions, hiddenFilesystems)
|
||||||
|
|
||||||
|
for i, partition := range partitions {
|
||||||
|
partitionAutoname := ""
|
||||||
|
if altName, ok := alternativeNames[partition.Device]; ok {
|
||||||
|
partitionAutoname = altName
|
||||||
|
} else if partition.Label != "" {
|
||||||
|
partitionAutoname = partition.Label
|
||||||
|
} else {
|
||||||
|
partitionAutoname = partition.MountPoint
|
||||||
|
}
|
||||||
|
|
||||||
|
expanded := os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "PART_NUM":
|
||||||
|
return strconv.Itoa(i + 1)
|
||||||
|
case "PART_FS":
|
||||||
|
return partition.FileystemType
|
||||||
|
case "PART_DEVICE":
|
||||||
|
return partition.Device
|
||||||
|
case "PART_AUTONAME":
|
||||||
|
return partitionAutoname
|
||||||
|
case "PART_LABEL":
|
||||||
|
return partition.Label
|
||||||
|
case "PART_MOUNTPOINT":
|
||||||
|
return partition.MountPoint
|
||||||
|
case "PART_FREE":
|
||||||
|
return FormatBytes(partition.FreeSize)
|
||||||
|
case "PART_USED":
|
||||||
|
return FormatBytes(partition.UsedSize)
|
||||||
|
case "PART_TOTAL":
|
||||||
|
return FormatBytes(partition.TotalSize)
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
builder.WriteString(expanded + "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.String()
|
||||||
|
}}
|
||||||
|
RegisterModule(partitionsModule)
|
||||||
|
|
||||||
|
// Local IP module
|
||||||
|
localIpModule := StormfetchModule{stormfetchModuleConfig: stormfetchModuleConfig{Name: "local_ip", Format: "%3Local IP: %4$LOCAL_IP"}, Execute: func(sm StormfetchModule) string {
|
||||||
|
return os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "LOCAL_IP":
|
||||||
|
return GetLocalIP()
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
RegisterModule(localIpModule)
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
// Return empty string if currently in TTY
|
||||||
|
if os.Getenv("XDG_SESSION_TYPE") == "" || os.Getenv("XDG_SESSION_TYPE") == "tty" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
dewm := GetDEWM()
|
||||||
|
|
||||||
|
// Return empty string if can't detect DE/WM
|
||||||
|
if dewm.Name == "Unknown" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "DEWM_NAME":
|
||||||
|
return dewm.Name
|
||||||
|
case "DEWM_TYPE":
|
||||||
|
return dewm.Type
|
||||||
|
case "DEWM_VERSION":
|
||||||
|
return dewm.Version
|
||||||
|
case "DISPLAY_PROTOCOL":
|
||||||
|
return GetDisplayProtocol()
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
RegisterModule(dewmModule)
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
builder := strings.Builder{}
|
||||||
|
monitors := GetMonitors()
|
||||||
|
|
||||||
|
for i, monitor := range monitors {
|
||||||
|
expanded := os.Expand(sm.Format, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "MONITOR_NUM":
|
||||||
|
return strconv.Itoa(i + 1)
|
||||||
|
case "MONITOR_WIDTH":
|
||||||
|
return strconv.Itoa(monitor.Width)
|
||||||
|
case "MONITOR_HEIGHT":
|
||||||
|
return strconv.Itoa(monitor.Height)
|
||||||
|
case "MONITOR_REFRESH_RATE":
|
||||||
|
return strconv.Itoa(monitor.RefreshRate)
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
builder.WriteString(expanded + "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
+13
-8
@@ -72,14 +72,19 @@ func GetMountedPartitions(hiddenPartitions, hiddenFilesystems []string) []partit
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device, err := filepath.EvalSymlinks(fields[0])
|
||||||
|
if err != nil {
|
||||||
|
device = fields[0]
|
||||||
|
}
|
||||||
|
|
||||||
p := partition{
|
p := partition{
|
||||||
fields[0],
|
Device: device,
|
||||||
fields[1],
|
MountPoint: fields[1],
|
||||||
"",
|
Label: "",
|
||||||
fields[2],
|
FileystemType: fields[2],
|
||||||
0,
|
TotalSize: 0,
|
||||||
0,
|
UsedSize: 0,
|
||||||
0,
|
FreeSize: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip already added partitions
|
// Skip already added partitions
|
||||||
@@ -95,7 +100,7 @@ func GetMountedPartitions(hiddenPartitions, hiddenFilesystems []string) []partit
|
|||||||
|
|
||||||
// Set partition label if available
|
// Set partition label if available
|
||||||
if value, ok := labels[p.Device]; ok {
|
if value, ok := labels[p.Device]; ok {
|
||||||
p.Label = value
|
p.Label = strings.ReplaceAll(value, "\\x20", " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get partition total, used and free space
|
// Get partition total, used and free space
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ var PackageManagers = []PackageManager{
|
|||||||
{Name: "pacman", ExecutableName: "pacman", PackageListCommand: "pacman -Q"},
|
{Name: "pacman", ExecutableName: "pacman", PackageListCommand: "pacman -Q"},
|
||||||
{Name: "rpm", ExecutableName: "rpm", PackageListCommand: "rpm -qa"},
|
{Name: "rpm", ExecutableName: "rpm", PackageListCommand: "rpm -qa"},
|
||||||
{Name: "xbps", ExecutableName: "xbps-query", PackageListCommand: "xbps-query -l"},
|
{Name: "xbps", ExecutableName: "xbps-query", PackageListCommand: "xbps-query -l"},
|
||||||
{Name: "bpm", ExecutableName: "bpm", PackageListCommand: "bpm list -n"},
|
{Name: "bpm", ExecutableName: "bpm", PackageListCommand: "ls /var/lib/bpm/installed/"},
|
||||||
{Name: "portage", ExecutableName: "emerge", PackageListCommand: "find /var/db/pkg/*/ -mindepth 1 -maxdepth 1"},
|
{Name: "portage", ExecutableName: "emerge", PackageListCommand: "find /var/db/pkg/*/ -mindepth 1 -maxdepth 1"},
|
||||||
{Name: "flatpak", ExecutableName: "flatpak", PackageListCommand: "flatpak list"},
|
{Name: "flatpak", ExecutableName: "flatpak", PackageListCommand: "flatpak list"},
|
||||||
{Name: "snap", ExecutableName: "snap", PackageListCommand: "snap list | tail +2"},
|
{Name: "snap", ExecutableName: "snap", PackageListCommand: "snap list | tail +2"},
|
||||||
|
|||||||
+68
-50
@@ -5,6 +5,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/mitchellh/go-ps"
|
"github.com/mitchellh/go-ps"
|
||||||
)
|
)
|
||||||
@@ -21,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
|
||||||
@@ -38,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,57 +64,75 @@ 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 := 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
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetArch() string {
|
||||||
|
uname := syscall.Utsname{}
|
||||||
|
err := syscall.Uname(&uname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, err := os.Stat(path.Join(systemConfigDir, "stormfetch/ascii/", id)); err == nil {
|
return "unknown"
|
||||||
bytes, err := os.ReadFile(path.Join(systemConfigDir, "stormfetch/ascii/", id))
|
}
|
||||||
|
|
||||||
|
var byteString [65]byte
|
||||||
|
var indexLength int
|
||||||
|
for ; uname.Machine[indexLength] != 0; indexLength++ {
|
||||||
|
byteString[indexLength] = uint8(uname.Machine[indexLength])
|
||||||
|
}
|
||||||
|
return string(byteString[:indexLength])
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetKernel() (string, string) {
|
||||||
|
uname := syscall.Utsname{}
|
||||||
|
err := syscall.Uname(&uname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return defaultAscii
|
return "unknown", "unknown"
|
||||||
}
|
}
|
||||||
return string(bytes)
|
|
||||||
} else {
|
var kernelNameByteString [65]byte
|
||||||
return defaultAscii
|
var kernelNameLength int
|
||||||
|
for ; uname.Sysname[kernelNameLength] != 0; kernelNameLength++ {
|
||||||
|
kernelNameByteString[kernelNameLength] = uint8(uname.Sysname[kernelNameLength])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var kernelReleaseByteString [65]byte
|
||||||
|
var kernelReleaseLength int
|
||||||
|
for ; uname.Release[kernelReleaseLength] != 0; kernelReleaseLength++ {
|
||||||
|
kernelReleaseByteString[kernelReleaseLength] = uint8(uname.Release[kernelReleaseLength])
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(path.Join(userConfDir, "stormfetch/ascii/", id)); err == nil {
|
|
||||||
bytes, err := os.ReadFile(path.Join(userConfDir, "stormfetch/ascii/", id))
|
return string(kernelNameByteString[:kernelNameLength]), string(kernelReleaseByteString[:kernelReleaseLength])
|
||||||
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 GetInitSystem() string {
|
func GetInitSystem() string {
|
||||||
runCommand := func(command string) string {
|
|
||||||
cmd := exec.Command("/bin/bash", "-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 ""
|
||||||
@@ -123,19 +141,19 @@ 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}'")
|
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()
|
||||||
}
|
}
|
||||||
|
|||||||
+94
-49
@@ -1,31 +1,23 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/go-ps"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mitchellh/go-ps"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type DEWM struct {
|
||||||
|
Name string
|
||||||
|
Type string
|
||||||
|
Version string
|
||||||
|
}
|
||||||
|
|
||||||
func GetShell() string {
|
func GetShell() string {
|
||||||
runCommand := func(command string) string {
|
|
||||||
cmd := exec.Command("/bin/bash", "-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 ""
|
||||||
@@ -47,19 +39,19 @@ 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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDEWM() string {
|
func GetDEWM() DEWM {
|
||||||
processes, err := ps.Processes()
|
processes, err := ps.Processes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not get processes: %s", err)
|
log.Fatalf("Error: could not get processes: %s", err)
|
||||||
@@ -72,48 +64,101 @@ func GetDEWM() string {
|
|||||||
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/bash", "-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") {
|
||||||
return "KDE Plasma " + runCommand("plasmashell --version | awk '{print $2}'")
|
dewm := DEWM{
|
||||||
|
Name: "KDE Plasma",
|
||||||
|
Type: "DE",
|
||||||
|
Version: runCommand("plasmashell --version | awk '{print $2}'", "/bin/sh"),
|
||||||
|
}
|
||||||
|
return dewm
|
||||||
} else if processExists("gnome-session") {
|
} else if processExists("gnome-session") {
|
||||||
return "Gnome " + runCommand("gnome-shell --version | awk '{print $3}'")
|
dewm := DEWM{
|
||||||
|
Name: "Gnome",
|
||||||
|
Type: "DE",
|
||||||
|
Version: runCommand("gnome-shell --version | awk '{print $3}'", "/bin/sh"),
|
||||||
|
}
|
||||||
|
return dewm
|
||||||
} else if processExists("xfce4-session") {
|
} else if processExists("xfce4-session") {
|
||||||
return "XFCE " + runCommand("xfce4-session --version | head -n1 | awk '{print $2}'")
|
dewm := DEWM{
|
||||||
|
Name: "XFCE",
|
||||||
|
Type: "DE",
|
||||||
|
Version: runCommand("xfce4-session --version | head -n1 | awk '{print $2}'", "/bin/sh"),
|
||||||
|
}
|
||||||
|
return dewm
|
||||||
} else if processExists("cinnamon") {
|
} else if processExists("cinnamon") {
|
||||||
return "Cinnamon " + runCommand("cinnamon --version | awk '{print $3}'")
|
dewm := DEWM{
|
||||||
|
Name: "Cinnamon",
|
||||||
|
Type: "DE",
|
||||||
|
Version: runCommand("cinnamon --version | awk '{print $3}'", "/bin/sh"),
|
||||||
|
}
|
||||||
|
return dewm
|
||||||
} else if processExists("mate-panel") {
|
} else if processExists("mate-panel") {
|
||||||
return "MATE " + runCommand("mate-about --version | awk '{print $4}'")
|
dewm := DEWM{
|
||||||
|
Name: "MATE",
|
||||||
|
Type: "DE",
|
||||||
|
Version: runCommand("mate-about --version | awk '{print $4}'", "/bin/sh"),
|
||||||
|
}
|
||||||
|
return dewm
|
||||||
} else if processExists("lxsession") {
|
} else if processExists("lxsession") {
|
||||||
return "LXDE"
|
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") {
|
} else if processExists("i3") || processExists("i3-with-shmlog") {
|
||||||
return "i3 " + runCommand("i3 --version | awk '{print $3}'")
|
dewm := DEWM{
|
||||||
|
Name: "i3",
|
||||||
|
Type: "WM",
|
||||||
|
Version: runCommand("i3 --version | awk '{print $3}'", "/bin/sh"),
|
||||||
|
}
|
||||||
|
return dewm
|
||||||
} else if processExists("sway") {
|
} else if processExists("sway") {
|
||||||
if runCommand("sway --version | awk '{print $1}'") == "swayfx" {
|
dewm := DEWM{
|
||||||
return "SwayFX " + runCommand("sway --version | awk '{print $3}'")
|
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 {
|
} else {
|
||||||
return "Sway " + runCommand("sway --version | awk '{print $3}'")
|
dewm.Name = "Sway"
|
||||||
}
|
}
|
||||||
|
return dewm
|
||||||
} else if processExists("bspwm") {
|
} else if processExists("bspwm") {
|
||||||
return "Bspwm " + runCommand("bspwm -v")
|
dewm := DEWM{
|
||||||
|
Name: "Bspwm",
|
||||||
|
Type: "WM",
|
||||||
|
Version: runCommand("bspwm -v", "/bin/sh"),
|
||||||
|
}
|
||||||
|
return dewm
|
||||||
} else if processExists("Hyprland") {
|
} else if processExists("Hyprland") {
|
||||||
return "Hyprland " + runCommand("hyprctl version | sed -n 3p | awk '{print $2}' | tr -d 'v,'")
|
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") {
|
} else if processExists("icewm-session") {
|
||||||
return "IceWM " + runCommand("icewm --version | awk '{print $2}'")
|
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",
|
||||||
}
|
}
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDisplayProtocol() string {
|
func GetDisplayProtocol() string {
|
||||||
|
|||||||
@@ -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))
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user