ohmu
·
2026-10-15
1#include "fastfetch.h"
2#include "common/temps.h"
3#include "common/textModifier.h"
4#include "common/strutil.h"
5
6void ffTempsAppendNum(double celsius, FFstrbuf* buffer, FFColorRangeConfig config, const FFModuleArgs* module) {
7 if (celsius == -DBL_MAX) { // ignores invalid value
8 return;
9 }
10
11 const FFOptionsDisplay* options = &instance.config.display;
12 const char* colorGreen = options->tempColorGreen.chars;
13 const char* colorYellow = options->tempColorYellow.chars;
14 const char* colorRed = options->tempColorRed.chars;
15
16 uint8_t green = config.green, yellow = config.yellow;
17
18 if (!options->pipe) {
19 if (green <= yellow) {
20 if (celsius > yellow) {
21 ffStrbufAppendF(buffer, "\e[%sm", colorRed);
22 } else if (celsius > green) {
23 ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
24 } else {
25 ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
26 }
27 } else {
28 if (celsius < yellow) {
29 ffStrbufAppendF(buffer, "\e[%sm", colorRed);
30 } else if (celsius < green) {
31 ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
32 } else {
33 ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
34 }
35 }
36 }
37
38 switch (options->tempUnit) {
39 case FF_TEMPERATURE_UNIT_DEFAULT:
40 case FF_TEMPERATURE_UNIT_CELSIUS:
41 ffStrbufAppendF(buffer, "%.*f%s°C", options->tempNdigits, celsius, options->tempSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_ALWAYS ? " " : "");
42 break;
43 case FF_TEMPERATURE_UNIT_FAHRENHEIT:
44 ffStrbufAppendF(buffer, "%.*f%s°F", options->tempNdigits, celsius * 1.8 + 32, options->tempSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_ALWAYS ? " " : "");
45 break;
46 case FF_TEMPERATURE_UNIT_KELVIN:
47 ffStrbufAppendF(buffer, "%.*f%sK", options->tempNdigits, celsius + 273.15, options->tempSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_NEVER ? "" : " ");
48 break;
49 }
50
51 if (!options->pipe) {
52 ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
53 if (module->outputColor.length) {
54 ffStrbufAppendF(buffer, "\e[%sm", module->outputColor.chars);
55 } else if (instance.config.display.colorOutput.length) {
56 ffStrbufAppendF(buffer, "\e[%sm", instance.config.display.colorOutput.chars);
57 }
58 }
59}
60
61bool ffTempsParseCommandOptions(const char* key, const char* subkey, const char* value, bool* useTemp, FFColorRangeConfig* config) {
62 if (!ffStrStartsWithIgnCase(subkey, "temp")) {
63 return false;
64 }
65
66 if (subkey[strlen("temp")] == '\0') {
67 *useTemp = ffOptionParseBoolean(value);
68 return true;
69 }
70
71 if (subkey[strlen("temp")] != '-') {
72 return false;
73 }
74
75 subkey += strlen("temp-");
76
77 if (ffStrEqualsIgnCase(subkey, "green")) {
78 uint32_t num = ffOptionParseUInt32(key, value);
79 if (num > 100) {
80 fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key);
81 exit(480);
82 }
83 config->green = (uint8_t) num;
84 return true;
85 }
86
87 if (ffStrEqualsIgnCase(subkey, "yellow")) {
88 uint32_t num = ffOptionParseUInt32(key, value);
89 if (num > 100) {
90 fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key);
91 exit(480);
92 }
93 config->yellow = (uint8_t) num;
94 return true;
95 }
96
97 return false;
98}
99
100bool ffTempsParseJsonObject(yyjson_val* key, yyjson_val* value, bool* useTemp, FFColorRangeConfig* config) {
101 assert(key);
102
103 if (!unsafe_yyjson_equals_str(key, "temp")) {
104 return false;
105 }
106
107 if (yyjson_is_bool(value)) {
108 *useTemp = yyjson_get_bool(value);
109 return true;
110 }
111
112 if (yyjson_is_null(value)) {
113 *useTemp = false;
114 return true;
115 }
116
117 if (!yyjson_is_obj(value)) {
118 fprintf(stderr, "Error: usage: %s must be an object or a boolean\n", unsafe_yyjson_get_str(key));
119 exit(480);
120 }
121
122 *useTemp = true;
123
124 yyjson_val* greenVal = yyjson_obj_get(value, "green");
125 if (greenVal) {
126 if (!yyjson_is_int(greenVal)) {
127 fputs("Error: usage: temp.green must be an integer between 0 and 100\n", stderr);
128 exit(480);
129 }
130
131 int num = unsafe_yyjson_get_int(greenVal);
132 if (num < 0 || num > 100) {
133 fputs("Error: usage: temp.green must be between 0 and 100\n", stderr);
134 exit(480);
135 }
136 config->green = (uint8_t) num;
137 }
138
139 yyjson_val* yellowVal = yyjson_obj_get(value, "yellow");
140 if (yellowVal) {
141 if (!yyjson_is_int(yellowVal)) {
142 fputs("Error: usage: temp.yellow must be an integer between 0 and 100\n", stderr);
143 exit(480);
144 }
145
146 int num = unsafe_yyjson_get_int(yellowVal);
147 if (num < 0 || num > 100) {
148 fputs("Error: usage: temp.yellow must be between 0 and 100\n", stderr);
149 exit(480);
150 }
151 config->yellow = (uint8_t) num;
152 }
153
154 return true;
155}
156
157[[gnu::cold]]
158void ffTempsGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, bool temp, FFColorRangeConfig config) {
159 if (!temp) {
160 yyjson_mut_obj_add_bool(doc, module, "temp", false);
161 } else {
162 yyjson_mut_val* temp = yyjson_mut_obj_add_obj(doc, module, "temp");
163 yyjson_mut_obj_add_uint(doc, temp, "green", config.green);
164 yyjson_mut_obj_add_uint(doc, temp, "yellow", config.yellow);
165 }
166}