comparison main.cpp @ 1:841975e638f2

add stuff
author Yasuri <yasuri@charliesmp.net>
date Sun, 04 Oct 2026 14:33:34 -0500
parents bb144f2c5a3b
children f7c837561bfa
comparison
equal deleted inserted replaced
0:bb144f2c5a3b 1:841975e638f2
1 // topfetch++ - live system monitor + fetch tool
2 // ISC licensed, see LICENSE.
3 // Logos adapted from pfetch (MIT), see THIRD-PARTY-NOTICES._
4 #include <algorithm>
5 #include <chrono>
6 #include <fstream>
7 #include <iomanip>
1 #include <iostream> 8 #include <iostream>
2 #include <fstream> 9 #include <map>
3 #include <sstream> 10 #include <sstream>
4 #include <iomanip> 11 #include <string>
5 int main() { 12 #include <thread>
6 std::string myText; 13 #include <vector>
7 std::ifstream Meminfo("/proc/meminfo"); 14
8 std::string uptimeText; 15 // ---------- simple readers ----------
9 std::ifstream Uptime("/proc/uptime"); 16
10 std::string distro; 17 std::string readHostname() {
11 std::ifstream OsRelease("/etc/os-release"); 18 std::ifstream f("/proc/sys/kernel/hostname");
19 if (!f.is_open()) return "(none)";
20 std::string s;
21 std::getline(f, s);
22 return s.empty() ? "(none)" : s;
23 }
24
25 std::string readVersion() {
26 std::ifstream f("/proc/version");
27 if (!f.is_open()) return "unknown";
28 std::string w1, w2, version;
29 f >> w1 >> w2 >> version; // "Linux version 6.x.y ..."
30 return version.empty() ? "unknown" : version;
31 }
32
33 long readUptime() {
34 std::ifstream f("/proc/uptime");
35 if (!f.is_open()) return -1;
36 double seconds = 0;
37 f >> seconds;
38 return static_cast<long>(seconds);
39 }
40
41 struct Mem {
42 long total = 0; // kB
43 long available = 0; // kB
44 };
45
46 Mem readMeminfo() {
47 Mem m;
48 std::ifstream f("/proc/meminfo");
49 if (!f.is_open()) return m;
50 std::string line;
51 while (std::getline(f, line)) {
52 std::istringstream ss(line);
53 std::string name;
54 long value = 0;
55 ss >> name >> value;
56 if (name == "MemTotal:") m.total = value;
57 else if (name == "MemAvailable:") m.available = value;
58 }
59 return m;
60 }
61
62 struct CpuTimes {
63 long busy = 0;
12 long total = 0; 64 long total = 0;
13 long available = 0; 65 };
14 while (std::getline (Meminfo, myText)) { 66
15 std::istringstream ss(myText); 67 CpuTimes readCpuTimes() {
16 std::string name; 68 CpuTimes t;
17 long value; 69 std::ifstream f("/proc/stat");
18 ss >> name >> value; 70 if (!f.is_open()) return t;
19 if (name == "MemTotal:") { 71
20 total = value; 72 std::string label;
73 f >> label; // "cpu"
74
75 long values[8] = {0}; // user nice system idle iowait irq softirq steal
76 for (int i = 0; i < 8; i++) f >> values[i];
77
78 long total = 0;
79 for (int i = 0; i < 8; i++) total += values[i];
80
81 long idle = values[3] + values[4];
82 t.total = total;
83 t.busy = total - idle;
84 return t;
85 }
86
87 // ---------- distro ----------
88
89 struct Distro {
90 std::string pretty = "Linux";
91 std::string id;
92 std::string idLike;
93 };
94
95 std::string unquote(const std::string& v) {
96 if (v.size() >= 2 && (v.front() == '"' || v.front() == '\'') &&
97 v.back() == v.front()) {
98 return v.substr(1, v.size() - 2);
99 }
100 return v;
101 }
102
103 Distro readDistro() {
104 Distro d;
105 std::ifstream f("/etc/os-release");
106 if (!f.is_open()) return d;
107
108 std::string line;
109 while (std::getline(f, line)) {
110 size_t pos = line.find('=');
111 if (pos == std::string::npos) continue;
112 std::string key = line.substr(0, pos);
113 std::string val = unquote(line.substr(pos + 1));
114 if (key == "PRETTY_NAME" && !val.empty()) d.pretty = val;
115 else if (key == "ID") d.id = val;
116 else if (key == "ID_LIKE") d.idLike = val;
117 }
118 return d;
119 }
120
121 // ---------- logos ----------
122
123 struct Logo {
124 std::vector<std::string> lines;
125 std::string color; // ANSI escape
126 };
127
128 // Logos adapted from pfetch (MIT)
129 // Copyright (c) 2016-2021 Dylan Araps
130 // Copyright (c) 2024-2025 Joey Reinhart
131 Logo pickLogo(const Distro& d, const std::string& override = "") {
132 static const std::map<std::string, Logo> logos = {
133 {"nixos", {{
134 R"art( \\ \\ //)art",
135 R"art( ==\\__\\/ //)art",
136 R"art( // \\//)art",
137 R"art(==// //==)art",
138 R"art( //\\___//)art",
139 R"art(// /\\ \\==)art",
140 R"art( // \\ \\)art",
141 }, "\033[34m"}},
142 {"arch", {{
143 R"art( /\)art",
144 R"art( / \)art",
145 R"art( /\ \)art",
146 R"art( / \)art",
147 R"art( / ,, \)art",
148 R"art( / | | -\)art",
149 R"art(/_-'' ''-_\)art",
150 }, "\033[36m"}},
151 {"gentoo", {{
152 R"art( _-----_)art",
153 R"art(( \)art",
154 R"art(\ 0 \)art",
155 R"art( \ ))art",
156 R"art( / _/)art",
157 R"art(( _-)art",
158 R"art(\____-)art",
159 }, "\033[35m"}},
160 };
161
162 static const Logo fallback = {{
163 R"art( .--.)art",
164 R"art( |o_o |)art",
165 R"art( |:_/ |)art",
166 R"art( // \ \)art",
167 R"art( (| | ))art",
168 R"art(/'\_ _/`\)art",
169 R"art(\___)=(___/)art",
170 }, "\033[33m"};
171
172 std::string id = override.empty() ? d.id : override;
173 auto it = logos.find(id);
174 if (it != logos.end()) return it->second;
175
176 // ID_LIKE fallback (Manjaro -> arch, etc.)
177 std::istringstream ss(d.idLike);
178 std::string word;
179 while (ss >> word) {
180 it = logos.find(word);
181 if (it != logos.end()) return it->second;
182 }
183 return fallback;
184 }
185
186 // ---------- main ----------
187
188 int main(int argc, char** argv) {
189 std::string override;
190 if (argc >= 3 && std::string(argv[1]) == "--logo") override = argv[2];
191
192 const Distro distro = readDistro();
193 const Logo logo = pickLogo(distro, override);
194 const std::string hostname = readHostname();
195 const std::string kernver = readVersion();
196
197 size_t logoWidth = 0;
198 for (const auto& line : logo.lines) logoWidth = std::max(logoWidth, line.size());
199
200 CpuTimes prev = readCpuTimes();
201 const double kbToGb = 1024.0 * 1024.0;
202
203 while (true) {
204 std::this_thread::sleep_for(std::chrono::seconds(1));
205
206 Mem m = readMeminfo();
207 long up = readUptime();
208 CpuTimes now = readCpuTimes();
209
210 long totalChange = now.total - prev.total;
211 double cpuPercent = 0.0;
212 if (totalChange > 0) cpuPercent = 100.0 * (now.busy - prev.busy) / totalChange;
213 prev = now;
214
215 std::ostringstream uptimeLine, memLine, cpuLine;
216 uptimeLine << "Uptime: ";
217 if (up < 0) {
218 uptimeLine << "Unknown";
219 } else {
220 uptimeLine << up / 86400 << "d " << (up % 86400) / 3600 << "h "
221 << (up % 3600) / 60 << "m";
21 } 222 }
22 if (name == "MemAvailable:") { 223
23 available = value; 224 memLine << std::fixed << std::setprecision(2) << "Memory: ";
225 if (m.total == 0) {
226 memLine << "Unknown";
227 } else {
228 memLine << (m.total - m.available) / kbToGb << " GB / "
229 << m.total / kbToGb << " GB";
24 } 230 }
25 } 231
26 std::string osLine; 232 cpuLine << std::fixed << std::setprecision(1)
27 while (std::getline(OsRelease, osLine)) { 233 << "CPU: " << cpuPercent << " %";
28 size_t pos = osLine.find('='); 234
29 if (pos == std::string::npos) continue; 235 std::vector<std::string> info = {
30 std::string key = osLine.substr(0, pos); 236 "OS: " + distro.pretty,
31 std::string val = osLine.substr(pos + 1); 237 "Hostname: " + hostname,
32 if (key == "PRETTY_NAME") { 238 "Kernel: " + kernver,
33 distro = val.substr(1, val.size() - 2); 239 uptimeLine.str(),
240 memLine.str(),
241 cpuLine.str(),
242 };
243
244 size_t rows = std::max(logo.lines.size(), info.size());
245
246 std::cout << "\033[H\033[2J";
247 for (size_t i = 0; i < rows; i++) {
248 std::string art = i < logo.lines.size() ? logo.lines[i] : "";
249 std::string text = i < info.size() ? info[i] : "";
250 std::cout << logo.color << std::left << std::setw(logoWidth) << art
251 << "\033[0m" << " " << text << '\n';
34 } 252 }
35 } 253 std::cout << std::flush;
36 long timeup = 0; 254 }
37 while (std::getline (Uptime, uptimeText)) { 255 }
38 std::istringstream ss2(uptimeText);
39 double uptime;
40 ss2 >> uptime;
41 timeup = uptime;
42 }
43 std::cout << std::fixed << std::setprecision(2);
44 std::cout << "Used: " << (total - available) / (1024.0 * 1024.0) << " GB" << "/" << total / (1024.0 * 1024.0) << "GB" << std::endl;
45 std::cout << "Uptime: " << "Hours: " << timeup / 3600 << " Minutes: " << (timeup % 3600) / 60 << std::endl;
46 std::cout << "OS: " << distro << std::endl;
47 Meminfo.close();
48 }