master ohmu/fastfetch-openbsd / src / common / impl / temps.c
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}