2023-10-26 10:26:15 +08:00
#include "fastfetch.h"
2026-01-06 09:48:38 +08:00
#include "common/color.h"
#include "common/jsonconfig.h"
#include "common/percent.h"
2026-05-28 15:58:08 +08:00
#include "common/strutil.h"
2023-10-26 10:26:15 +08:00
#include "options/display.h"
#include <unistd.h>
2026-03-29 09:28:49 +08:00
const char * ffOptionsParseDisplayJsonConfig ( FFOptionsDisplay * options , yyjson_val * root ) {
2023-10-26 10:26:15 +08:00
yyjson_val * object = yyjson_obj_get ( root , "display" );
2026-03-29 09:28:49 +08:00
if ( ! object ) {
return NULL ;
}
if ( ! yyjson_is_obj ( object )) {
return "Property 'display' must be an object" ;
}
2023-10-26 10:26:15 +08:00
2025-08-05 13:37:53 +08:00
yyjson_val * key , * val ;
2023-10-26 10:26:15 +08:00
size_t idx , max ;
2026-03-29 09:28:49 +08:00
yyjson_obj_foreach ( object , idx , max , key , val ) {
if ( unsafe_yyjson_equals_str ( key , "stat" )) {
if ( yyjson_is_bool ( val )) {
if ( yyjson_get_bool ( val )) {
2024-08-12 16:16:47 +08:00
options -> stat = 0 ;
options -> showErrors = true ;
2026-03-29 09:28:49 +08:00
} else {
2024-08-12 16:16:47 +08:00
options -> stat = - 1 ;
2026-03-29 09:28:49 +08:00
}
} else if ( yyjson_is_uint ( val )) {
2024-08-12 16:16:47 +08:00
options -> stat = ( int ) yyjson_get_uint ( val );
2023-10-26 10:26:15 +08:00
options -> showErrors = true ;
2026-03-29 09:28:49 +08:00
} else {
2024-08-12 16:16:47 +08:00
return "display.stat must be a boolean or a positive integer" ;
2026-03-29 09:28:49 +08:00
}
} else if ( unsafe_yyjson_equals_str ( key , "pipe" )) {
2023-10-26 10:26:15 +08:00
options -> pipe = yyjson_get_bool ( val );
2026-03-29 09:28:49 +08:00
} else if ( unsafe_yyjson_equals_str ( key , "showErrors" )) {
2023-10-26 10:26:15 +08:00
options -> showErrors = yyjson_get_bool ( val );
2026-03-29 09:28:49 +08:00
} else if ( unsafe_yyjson_equals_str ( key , "disableLinewrap" )) {
2023-10-26 10:26:15 +08:00
options -> disableLinewrap = yyjson_get_bool ( val );
2026-03-29 09:28:49 +08:00
} else if ( unsafe_yyjson_equals_str ( key , "hideCursor" )) {
2023-10-26 10:26:15 +08:00
options -> hideCursor = yyjson_get_bool ( val );
2026-03-29 09:28:49 +08:00
} else if ( unsafe_yyjson_equals_str ( key , "separator" )) {
2025-08-02 17:41:19 +08:00
ffStrbufSetJsonVal ( & options -> keyValueSeparator , val );
2026-03-29 09:28:49 +08:00
} else if ( unsafe_yyjson_equals_str ( key , "color" )) {
if ( yyjson_is_str ( val )) {
2025-08-05 13:37:53 +08:00
ffOptionParseColor ( unsafe_yyjson_get_str ( val ), & options -> colorKeys );
2023-10-26 10:26:15 +08:00
ffStrbufSet ( & options -> colorTitle , & options -> colorKeys );
2026-03-29 09:28:49 +08:00
} else if ( yyjson_is_obj ( val )) {
2025-08-02 17:41:19 +08:00
yyjson_val * colorKeys = yyjson_obj_get ( val , "keys" );
2026-03-29 09:28:49 +08:00
if ( colorKeys ) {
2025-08-02 17:41:19 +08:00
ffOptionParseColor ( yyjson_get_str ( colorKeys ), & options -> colorKeys );
2026-03-29 09:28:49 +08:00
}
2025-08-02 17:41:19 +08:00
yyjson_val * colorTitle = yyjson_obj_get ( val , "title" );
2026-03-29 09:28:49 +08:00
if ( colorTitle ) {
2025-08-02 17:41:19 +08:00
ffOptionParseColor ( yyjson_get_str ( colorTitle ), & options -> colorTitle );
2026-03-29 09:28:49 +08:00
}
2025-08-02 17:41:19 +08:00
yyjson_val * colorOutput = yyjson_obj_get ( val , "output" );
2026-03-29 09:28:49 +08:00
if ( colorOutput ) {
2025-08-02 17:41:19 +08:00
ffOptionParseColor ( yyjson_get_str ( colorOutput ), & options -> colorOutput );
2026-03-29 09:28:49 +08:00
}
2025-08-02 17:41:19 +08:00
yyjson_val * colorSeparator = yyjson_obj_get ( val , "separator" );
2026-03-29 09:28:49 +08:00
if ( colorSeparator ) {
2025-08-02 17:41:19 +08:00
ffOptionParseColor ( yyjson_get_str ( colorSeparator ), & options -> colorSeparator );
2026-03-29 09:28:49 +08:00
}
} else {
2023-10-26 10:26:15 +08:00
return "display.color must be either a string or an object" ;
2026-03-29 09:28:49 +08:00
}
} else if ( unsafe_yyjson_equals_str ( key , "brightColor" )) {
2023-10-26 10:26:15 +08:00
options -> brightColor = yyjson_get_bool ( val );
2026-03-29 09:28:49 +08:00
} else if ( unsafe_yyjson_equals_str ( key , "duration" )) {
if ( ! yyjson_is_obj ( val )) {
2025-07-30 14:30:36 +08:00
return "display.duration must be an object" ;
2026-03-29 09:28:49 +08:00
}
2025-07-30 14:30:36 +08:00
yyjson_val * abbreviation = yyjson_obj_get ( val , "abbreviation" );
2026-03-29 09:28:49 +08:00
if ( abbreviation ) {
options -> durationAbbreviation = yyjson_get_bool ( abbreviation );
}
2025-07-30 14:30:36 +08:00
yyjson_val * spaceBeforeUnit = yyjson_obj_get ( val , "spaceBeforeUnit" );
2026-03-29 09:28:49 +08:00
if ( spaceBeforeUnit ) {
2025-07-30 14:30:36 +08:00
int value ;
const char * error = ffJsonConfigParseEnum ( spaceBeforeUnit , & value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "default" , FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always" , FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never" , FF_SPACE_BEFORE_UNIT_NEVER },
2026-03-29 09:28:49 +08:00
{},
});
if ( error ) {
return error ;
}
2025-07-30 14:30:36 +08:00
options -> durationSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) value ;
}
2026-03-29 09:28:49 +08:00
} else if ( unsafe_yyjson_equals_str ( key , "size" )) {
if ( ! yyjson_is_obj ( val )) {
2023-10-29 00:17:24 +08:00
return "display.size must be an object" ;
2026-03-29 09:28:49 +08:00
}
2023-10-29 00:17:24 +08:00
yyjson_val * maxPrefix = yyjson_obj_get ( val , "maxPrefix" );
2026-03-29 09:28:49 +08:00
if ( maxPrefix ) {
2023-10-29 00:17:24 +08:00
int value ;
2026-04-30 09:27:05 +08:00
const char * error = ffJsonConfigParseEnum (
maxPrefix ,
& value ,
( FFKeyValuePair []) {
{ "B" , 0 },
{ "kB" , 1 },
{ "MB" , 2 },
{ "GB" , 3 },
{ "TB" , 4 },
{ "PB" , 5 },
{ "EB" , 6 },
{ "ZB" , 7 },
{ "YB" , 8 },
{},
});
2026-03-29 09:28:49 +08:00
if ( error ) {
return error ;
}
2023-10-29 00:17:24 +08:00
options -> sizeMaxPrefix = ( uint8_t ) value ;
}
2024-07-22 10:51:27 +08:00
yyjson_val * binaryPrefix = yyjson_obj_get ( val , "binaryPrefix" );
2026-03-29 09:28:49 +08:00
if ( binaryPrefix ) {
2024-07-22 10:51:27 +08:00
int value ;
const char * error = ffJsonConfigParseEnum ( binaryPrefix , & value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "iec" , FF_SIZE_BINARY_PREFIX_TYPE_IEC },
{ "si" , FF_SIZE_BINARY_PREFIX_TYPE_SI },
{ "jedec" , FF_SIZE_BINARY_PREFIX_TYPE_JEDEC },
2026-03-29 09:28:49 +08:00
{},
});
if ( error ) {
return error ;
}
2024-07-22 10:59:23 +08:00
options -> sizeBinaryPrefix = ( FFSizeBinaryPrefixType ) value ;
2024-07-22 10:51:27 +08:00
}
2023-10-29 00:17:24 +08:00
yyjson_val * ndigits = yyjson_obj_get ( val , "ndigits" );
2026-03-29 09:28:49 +08:00
if ( ndigits ) {
if ( ! yyjson_is_uint ( ndigits )) {
2025-09-03 14:23:59 +08:00
return "display.size.ndigits must be an unsigned integer" ;
2026-03-29 09:28:49 +08:00
}
2025-09-03 14:23:59 +08:00
uint64_t val = yyjson_get_uint ( ndigits );
2026-03-29 09:28:49 +08:00
if ( val > 9 ) {
2025-09-03 14:23:59 +08:00
return "display.size.ndigits must be between 0 and 9" ;
2026-03-29 09:28:49 +08:00
}
2025-09-03 14:23:59 +08:00
options -> sizeNdigits = ( uint8_t ) val ;
}
2025-07-30 14:30:36 +08:00
yyjson_val * spaceBeforeUnit = yyjson_obj_get ( val , "spaceBeforeUnit" );
2026-03-29 09:28:49 +08:00
if ( spaceBeforeUnit ) {
2025-07-30 14:30:36 +08:00
int value ;
const char * error = ffJsonConfigParseEnum ( spaceBeforeUnit , & value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "default" , FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always" , FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never" , FF_SPACE_BEFORE_UNIT_NEVER },
2026-03-29 09:28:49 +08:00
{},
});
if ( error ) {
return error ;
}
2025-07-30 14:30:36 +08:00
options -> sizeSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) value ;
}
2026-03-29 09:28:49 +08:00
} else if ( unsafe_yyjson_equals_str ( key , "temp" )) {
if ( ! yyjson_is_obj ( val )) {
2024-02-27 13:11:39 +08:00
return "display.temp must be an object" ;
2026-03-29 09:28:49 +08:00
}
2024-02-26 10:46:13 +08:00
yyjson_val * unit = yyjson_obj_get ( val , "unit" );
2026-03-29 09:28:49 +08:00
if ( unit ) {
2024-02-26 10:46:13 +08:00
int value ;
const char * error = ffJsonConfigParseEnum ( unit , & value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "DEFAULT" , FF_TEMPERATURE_UNIT_DEFAULT },
{ "D" , FF_TEMPERATURE_UNIT_DEFAULT },
{ "CELSIUS" , FF_TEMPERATURE_UNIT_CELSIUS },
{ "C" , FF_TEMPERATURE_UNIT_CELSIUS },
{ "FAHRENHEIT" , FF_TEMPERATURE_UNIT_FAHRENHEIT },
{ "F" , FF_TEMPERATURE_UNIT_FAHRENHEIT },
{ "KELVIN" , FF_TEMPERATURE_UNIT_KELVIN },
{ "K" , FF_TEMPERATURE_UNIT_KELVIN },
2026-03-29 09:28:49 +08:00
{},
});
if ( error ) {
return error ;
}
2024-05-09 08:46:52 +08:00
options -> tempUnit = ( FFTemperatureUnit ) value ;
2024-02-26 10:46:13 +08:00
}
yyjson_val * ndigits = yyjson_obj_get ( val , "ndigits" );
2026-03-29 09:28:49 +08:00
if ( ndigits ) {
if ( ! yyjson_is_uint ( ndigits )) {
2025-09-03 14:23:59 +08:00
return "display.temperature.ndigits must be an unsigned integer" ;
2026-03-29 09:28:49 +08:00
}
2025-09-03 14:23:59 +08:00
uint64_t val = yyjson_get_uint ( ndigits );
2026-03-29 09:28:49 +08:00
if ( val > 9 ) {
2025-09-03 14:23:59 +08:00
return "display.temperature.ndigits must be between 0 and 9" ;
2026-03-29 09:28:49 +08:00
}
2025-09-03 14:23:59 +08:00
options -> tempNdigits = ( uint8_t ) val ;
}
2024-02-26 10:46:13 +08:00
yyjson_val * color = yyjson_obj_get ( val , "color" );
2026-03-29 09:28:49 +08:00
if ( color ) {
if ( ! yyjson_is_obj ( color )) {
2024-02-26 10:46:13 +08:00
return "display.temperature.color must be an object" ;
2026-03-29 09:28:49 +08:00
}
2024-02-26 10:46:13 +08:00
yyjson_val * green = yyjson_obj_get ( color , "green" );
2026-03-29 09:28:49 +08:00
if ( green ) {
ffOptionParseColor ( yyjson_get_str ( green ), & options -> tempColorGreen );
}
2024-02-26 10:46:13 +08:00
yyjson_val * yellow = yyjson_obj_get ( color , "yellow" );
2026-03-29 09:28:49 +08:00
if ( yellow ) {
ffOptionParseColor ( yyjson_get_str ( yellow ), & options -> tempColorYellow );
}
2024-02-26 10:46:13 +08:00
yyjson_val * red = yyjson_obj_get ( color , "red" );
2026-03-29 09:28:49 +08:00
if ( red ) {
ffOptionParseColor ( yyjson_get_str ( red ), & options -> tempColorRed );
}
2024-02-26 10:46:13 +08:00
}
2025-07-30 14:30:36 +08:00
yyjson_val * spaceBeforeUnit = yyjson_obj_get ( val , "spaceBeforeUnit" );
2026-03-29 09:28:49 +08:00
if ( spaceBeforeUnit ) {
2025-07-30 14:30:36 +08:00
int value ;
const char * error = ffJsonConfigParseEnum ( spaceBeforeUnit , & value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "default" , FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always" , FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never" , FF_SPACE_BEFORE_UNIT_NEVER },
2026-03-29 09:28:49 +08:00
{},
});
if ( error ) {
return error ;
}
2025-07-30 14:30:36 +08:00
options -> tempSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) value ;
}
2026-03-29 09:28:49 +08:00
} else if ( unsafe_yyjson_equals_str ( key , "percent" )) {
if ( ! yyjson_is_obj ( val )) {
2023-10-29 00:17:24 +08:00
return "display.percent must be an object" ;
2026-03-29 09:28:49 +08:00
}
2023-10-29 00:17:24 +08:00
yyjson_val * type = yyjson_obj_get ( val , "type" );
2026-03-29 09:28:49 +08:00
if ( type ) {
2024-11-14 14:21:55 +08:00
const char * error = ffPercentParseTypeJsonConfig ( type , & options -> percentType );
2026-03-29 09:28:49 +08:00
if ( error ) {
return error ;
}
2024-11-14 14:21:55 +08:00
}
2023-10-29 00:17:24 +08:00
yyjson_val * ndigits = yyjson_obj_get ( val , "ndigits" );
2026-03-29 09:28:49 +08:00
if ( ndigits ) {
if ( ! yyjson_is_uint ( ndigits )) {
2025-09-03 14:23:59 +08:00
return "display.percent.ndigits must be an unsigned integer" ;
2026-03-29 09:28:49 +08:00
}
2025-09-03 14:23:59 +08:00
uint64_t val = yyjson_get_uint ( ndigits );
2026-03-29 09:28:49 +08:00
if ( val > 9 ) {
2025-09-03 14:23:59 +08:00
return "display.percent.ndigits must be between 0 and 9" ;
2026-03-29 09:28:49 +08:00
}
2025-09-03 14:23:59 +08:00
options -> percentNdigits = ( uint8_t ) val ;
}
2024-01-20 19:59:13 +08:00
yyjson_val * color = yyjson_obj_get ( val , "color" );
2026-03-29 09:28:49 +08:00
if ( color ) {
if ( ! yyjson_is_obj ( color )) {
2024-01-20 19:59:13 +08:00
return "display.percent.color must be an object" ;
2026-03-29 09:28:49 +08:00
}
2024-01-20 19:59:13 +08:00
yyjson_val * green = yyjson_obj_get ( color , "green" );
2026-03-29 09:28:49 +08:00
if ( green ) {
ffOptionParseColor ( yyjson_get_str ( green ), & options -> percentColorGreen );
}
2024-01-20 19:59:13 +08:00
yyjson_val * yellow = yyjson_obj_get ( color , "yellow" );
2026-03-29 09:28:49 +08:00
if ( yellow ) {
ffOptionParseColor ( yyjson_get_str ( yellow ), & options -> percentColorYellow );
}
2024-01-20 19:59:13 +08:00
yyjson_val * red = yyjson_obj_get ( color , "red" );
2026-03-29 09:28:49 +08:00
if ( red ) {
ffOptionParseColor ( yyjson_get_str ( red ), & options -> percentColorRed );
}
2024-01-20 19:59:13 +08:00
}
2025-07-30 14:30:36 +08:00
yyjson_val * spaceBeforeUnit = yyjson_obj_get ( val , "spaceBeforeUnit" );
2026-03-29 09:28:49 +08:00
if ( spaceBeforeUnit ) {
2025-07-30 14:30:36 +08:00
int value ;
const char * error = ffJsonConfigParseEnum ( spaceBeforeUnit , & value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "default" , FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always" , FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never" , FF_SPACE_BEFORE_UNIT_NEVER },
2026-03-29 09:28:49 +08:00
{},
});
if ( error ) {
return error ;
}
2025-07-30 14:30:36 +08:00
options -> percentSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) value ;
}
2025-07-30 15:06:16 +08:00
yyjson_val * width = yyjson_obj_get ( val , "width" );
2026-03-29 09:28:49 +08:00
if ( width ) {
options -> percentWidth = ( uint8_t ) yyjson_get_uint ( width );
}
} else if ( unsafe_yyjson_equals_str ( key , "bar" )) {
if ( yyjson_is_obj ( val )) {
2025-08-01 15:12:30 +08:00
yyjson_val * char_ = yyjson_obj_get ( val , "char" );
2026-03-29 09:28:49 +08:00
if ( char_ ) {
if ( ! yyjson_is_obj ( char_ )) {
return "display.bar.char must be an object" ;
}
2024-06-06 16:36:57 +08:00
2025-08-02 17:41:19 +08:00
yyjson_val * charElapsed = yyjson_obj_get ( char_ , "elapsed" );
2026-03-29 09:28:49 +08:00
if ( charElapsed ) {
2025-08-02 17:41:19 +08:00
ffStrbufSetJsonVal ( & options -> barCharElapsed , charElapsed );
2026-03-29 09:28:49 +08:00
}
2023-10-26 10:26:15 +08:00
2025-08-02 17:41:19 +08:00
yyjson_val * charTotal = yyjson_obj_get ( char_ , "total" );
2026-03-29 09:28:49 +08:00
if ( charTotal ) {
2025-08-02 17:41:19 +08:00
ffStrbufSetJsonVal ( & options -> barCharTotal , charTotal );
2026-03-29 09:28:49 +08:00
}
} else {
2025-08-02 17:41:19 +08:00
yyjson_val * charElapsed = yyjson_obj_get ( val , "charElapsed" );
2026-03-29 09:28:49 +08:00
if ( charElapsed ) {
2025-08-01 15:12:30 +08:00
return "display.bar.charElapsed has been renamed to display.bar.char.elapsed." ;
2026-03-29 09:28:49 +08:00
}
2025-08-01 10:51:26 +08:00
2025-08-02 17:41:19 +08:00
yyjson_val * charTotal = yyjson_obj_get ( val , "charTotal" );
2026-03-29 09:28:49 +08:00
if ( charTotal ) {
2025-08-01 15:12:30 +08:00
return "display.bar.charTotal has been renamed to display.bar.char.total." ;
2026-03-29 09:28:49 +08:00
}
2025-08-01 15:12:30 +08:00
}
2025-08-01 10:51:26 +08:00
2025-08-01 15:12:30 +08:00
yyjson_val * border = yyjson_obj_get ( val , "border" );
2026-03-29 09:28:49 +08:00
if ( border ) {
if ( yyjson_is_null ( border )) {
2025-08-01 15:12:30 +08:00
ffStrbufClear ( & options -> barBorderLeft );
ffStrbufClear ( & options -> barBorderRight );
ffStrbufClear ( & options -> barBorderLeftElapsed );
ffStrbufClear ( & options -> barBorderRightElapsed );
2026-03-29 09:28:49 +08:00
} else {
if ( ! yyjson_is_obj ( border )) {
return "display.bar.border must be an object" ;
}
2025-08-01 15:12:30 +08:00
yyjson_val * borderLeft = yyjson_obj_get ( border , "left" );
2026-03-29 09:28:49 +08:00
if ( borderLeft ) {
2025-08-02 17:41:19 +08:00
ffStrbufSetJsonVal ( & options -> barBorderLeft , borderLeft );
2026-03-29 09:28:49 +08:00
}
2025-08-01 15:12:30 +08:00
yyjson_val * borderRight = yyjson_obj_get ( border , "right" );
2026-03-29 09:28:49 +08:00
if ( borderRight ) {
2025-08-02 17:41:19 +08:00
ffStrbufSetJsonVal ( & options -> barBorderRight , borderRight );
2026-03-29 09:28:49 +08:00
}
2025-08-01 15:12:30 +08:00
yyjson_val * borderLeftElapsed = yyjson_obj_get ( border , "leftElapsed" );
2026-03-29 09:28:49 +08:00
if ( borderLeftElapsed ) {
2025-08-02 17:41:19 +08:00
ffStrbufSetJsonVal ( & options -> barBorderLeftElapsed , borderLeftElapsed );
2026-03-29 09:28:49 +08:00
}
2025-08-01 15:12:30 +08:00
yyjson_val * borderRightElapsed = yyjson_obj_get ( border , "rightElapsed" );
2026-03-29 09:28:49 +08:00
if ( borderRightElapsed ) {
2025-08-02 17:41:19 +08:00
ffStrbufSetJsonVal ( & options -> barBorderRightElapsed , borderRightElapsed );
2026-03-29 09:28:49 +08:00
}
2025-08-01 15:12:30 +08:00
}
2026-03-29 09:28:49 +08:00
} else {
2025-08-01 15:12:30 +08:00
yyjson_val * borderLeft = yyjson_obj_get ( val , "borderLeft" );
2026-03-29 09:28:49 +08:00
if ( borderLeft ) {
2025-08-01 15:12:30 +08:00
return "display.bar.borderLeft has been renamed to display.bar.border.left." ;
2026-03-29 09:28:49 +08:00
}
2025-08-01 13:50:02 +08:00
2025-08-01 15:12:30 +08:00
yyjson_val * borderRight = yyjson_obj_get ( val , "borderRight" );
2026-03-29 09:28:49 +08:00
if ( borderRight ) {
2025-08-01 15:12:30 +08:00
return "display.bar.borderRight has been renamed to display.bar.border.right." ;
2026-03-29 09:28:49 +08:00
}
2025-08-01 15:12:30 +08:00
}
2025-08-01 13:50:02 +08:00
2025-08-01 15:12:30 +08:00
yyjson_val * color = yyjson_obj_get ( val , "color" );
2026-03-29 09:28:49 +08:00
if ( color ) {
if ( yyjson_is_null ( color )) {
2025-08-01 15:12:30 +08:00
ffStrbufClear ( & options -> barColorElapsed );
ffStrbufClear ( & options -> barColorTotal );
ffStrbufClear ( & options -> barColorBorder );
2026-03-29 09:28:49 +08:00
} else {
if ( ! yyjson_is_obj ( color )) {
return "display.bar.color must be an object" ;
}
2025-08-01 15:12:30 +08:00
yyjson_val * colorElapsed = yyjson_obj_get ( color , "elapsed" );
2026-03-29 09:28:49 +08:00
if ( colorElapsed ) {
2025-08-04 16:46:28 +08:00
const char * value = yyjson_get_str ( colorElapsed );
2026-03-29 09:28:49 +08:00
if ( ! value ) {
2025-08-04 16:46:28 +08:00
ffStrbufClear ( & options -> barColorElapsed );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( value , "auto" )) {
2025-08-04 16:46:28 +08:00
ffStrbufSetStatic ( & options -> barColorElapsed , "auto" );
2026-03-29 09:28:49 +08:00
} else {
2025-08-04 16:46:28 +08:00
ffOptionParseColor ( value , & options -> barColorElapsed );
2026-03-29 09:28:49 +08:00
}
2025-08-04 16:46:28 +08:00
}
2025-08-01 15:12:30 +08:00
yyjson_val * colorTotal = yyjson_obj_get ( color , "total" );
2026-03-29 09:28:49 +08:00
if ( colorTotal ) {
ffOptionParseColor ( yyjson_get_str ( colorTotal ), & options -> barColorTotal );
}
2025-08-01 15:12:30 +08:00
yyjson_val * colorBorder = yyjson_obj_get ( color , "border" );
2026-03-29 09:28:49 +08:00
if ( colorBorder ) {
ffOptionParseColor ( yyjson_get_str ( colorBorder ), & options -> barColorBorder );
}
2025-08-01 15:12:30 +08:00
}
}
2025-08-01 13:50:02 +08:00
2023-10-26 10:26:15 +08:00
yyjson_val * width = yyjson_obj_get ( val , "width" );
2026-03-29 09:28:49 +08:00
if ( width ) {
2023-10-26 10:26:15 +08:00
options -> barWidth = ( uint8_t ) yyjson_get_uint ( width );
2026-03-29 09:28:49 +08:00
}
} else {
2023-10-26 10:26:15 +08:00
return "display.bar must be an object" ;
2026-03-29 09:28:49 +08:00
}
} else if ( unsafe_yyjson_equals_str ( key , "fraction" )) {
if ( yyjson_is_obj ( val )) {
2025-07-16 10:30:45 +08:00
yyjson_val * ndigits = yyjson_obj_get ( val , "ndigits" );
2026-03-29 09:28:49 +08:00
if ( ndigits ) {
if ( yyjson_is_null ( ndigits )) {
2025-07-16 10:30:45 +08:00
options -> fractionNdigits = - 1 ;
2026-03-29 09:28:49 +08:00
} else {
if ( ! yyjson_is_int ( ndigits )) {
2025-09-02 14:44:15 +08:00
return "display.fraction.ndigits must be an integer" ;
2026-03-29 09:28:49 +08:00
}
2025-09-03 14:23:59 +08:00
int64_t val = yyjson_get_int ( ndigits );
2026-03-29 09:28:49 +08:00
if ( val < - 1 || val > 9 ) {
2025-09-03 14:23:59 +08:00
return "display.fraction.ndigits must be between -1 and 9" ;
2026-03-29 09:28:49 +08:00
}
2025-09-03 14:23:59 +08:00
options -> fractionNdigits = ( int8_t ) val ;
2025-09-02 14:44:15 +08:00
}
2025-07-16 10:30:45 +08:00
}
2025-09-02 14:12:58 +08:00
yyjson_val * trailingZeros = yyjson_obj_get ( val , "trailingZeros" );
2026-03-29 09:28:49 +08:00
if ( trailingZeros ) {
if ( yyjson_is_null ( trailingZeros )) {
2025-09-02 14:12:58 +08:00
options -> fractionTrailingZeros = FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT ;
2026-03-29 09:28:49 +08:00
} else {
2025-09-02 14:12:58 +08:00
int value ;
const char * error = ffJsonConfigParseEnum ( trailingZeros , & value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "default" , FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT },
{ "always" , FF_FRACTION_TRAILING_ZEROS_TYPE_ALWAYS },
{ "never" , FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER },
2026-03-29 09:28:49 +08:00
{},
});
if ( error ) {
return error ;
}
2025-09-02 14:12:58 +08:00
options -> fractionTrailingZeros = ( FFFractionTrailingZerosType ) value ;
}
}
2026-03-29 09:28:49 +08:00
} else {
2025-07-16 10:30:45 +08:00
return "display.fraction must be an object" ;
2026-03-29 09:28:49 +08:00
}
} else if ( unsafe_yyjson_equals_str ( key , "noBuffer" )) {
2023-10-26 10:26:15 +08:00
options -> noBuffer = yyjson_get_bool ( val );
2026-03-29 09:28:49 +08:00
} else if ( unsafe_yyjson_equals_str ( key , "key" )) {
if ( yyjson_is_obj ( val )) {
2024-07-24 15:12:25 +08:00
yyjson_val * width = yyjson_obj_get ( val , "width" );
2026-03-29 09:28:49 +08:00
if ( width ) {
2024-07-24 15:12:25 +08:00
options -> keyWidth = ( uint16_t ) yyjson_get_uint ( width );
2026-03-29 09:28:49 +08:00
}
2024-07-24 15:12:25 +08:00
yyjson_val * type = yyjson_obj_get ( val , "type" );
2026-03-29 09:28:49 +08:00
if ( type ) {
2024-07-24 15:12:25 +08:00
int value ;
2026-03-30 10:27:23 +08:00
const char * error = ffJsonConfigParseEnum ( type , & value , ( FFKeyValuePair []) { { "none" , FF_MODULE_KEY_TYPE_NONE }, { "string" , FF_MODULE_KEY_TYPE_STRING }, { "icon" , FF_MODULE_KEY_TYPE_ICON }, { "both" , FF_MODULE_KEY_TYPE_BOTH }, { "both-0" , FF_MODULE_KEY_TYPE_BOTH_0 }, { "both-1" , FF_MODULE_KEY_TYPE_BOTH_1 }, { "both-2" , FF_MODULE_KEY_TYPE_BOTH_2 }, { "both-3" , FF_MODULE_KEY_TYPE_BOTH_3 }, { "both-4" , FF_MODULE_KEY_TYPE_BOTH_4 }, {} });
2026-03-29 09:28:49 +08:00
if ( error ) {
return error ;
}
2024-07-24 15:12:25 +08:00
options -> keyType = ( uint8_t ) value ;
}
yyjson_val * paddingLeft = yyjson_obj_get ( val , "paddingLeft" );
2026-03-29 09:28:49 +08:00
if ( paddingLeft ) {
2024-07-24 15:12:25 +08:00
options -> keyPaddingLeft = ( uint16_t ) yyjson_get_uint ( paddingLeft );
2026-03-29 09:28:49 +08:00
}
} else {
2024-07-24 15:12:25 +08:00
return "display.key must be an object" ;
2026-03-29 09:28:49 +08:00
}
} else if ( unsafe_yyjson_equals_str ( key , "constants" )) {
if ( ! yyjson_is_arr ( val )) {
2024-07-15 11:00:15 +08:00
return "display.constants must be an array" ;
2026-03-29 09:28:49 +08:00
}
2024-07-15 11:00:15 +08:00
yyjson_val * item ;
size_t idx , max ;
2026-03-29 09:28:49 +08:00
yyjson_arr_foreach ( val , idx , max , item ) {
2026-04-14 10:41:18 +08:00
FFstrbuf * buffer = FF_LIST_ADD ( FFstrbuf , options -> constants );
ffStrbufInitJsonVal ( buffer , item );
2026-03-29 09:28:49 +08:00
}
} else if ( unsafe_yyjson_equals_str ( key , "freq" )) {
if ( ! yyjson_is_obj ( val )) {
2024-07-17 14:42:09 +08:00
return "display.freq must be an object" ;
2026-03-29 09:28:49 +08:00
}
2024-07-17 14:42:09 +08:00
yyjson_val * ndigits = yyjson_obj_get ( val , "ndigits" );
2026-03-29 09:28:49 +08:00
if ( ndigits ) {
if ( yyjson_is_null ( ndigits )) {
2025-09-03 14:23:59 +08:00
options -> freqNdigits = - 1 ;
2026-03-29 09:28:49 +08:00
} else {
if ( ! yyjson_is_int ( ndigits )) {
2025-09-03 14:23:59 +08:00
return "display.freq.ndigits must be an integer" ;
2026-03-29 09:28:49 +08:00
}
2025-09-03 14:23:59 +08:00
int64_t val = yyjson_get_int ( ndigits );
2026-03-29 09:28:49 +08:00
if ( val < - 1 || val > 9 ) {
2025-09-03 14:23:59 +08:00
return "display.freq.ndigits must be between -1 and 9" ;
2026-03-29 09:28:49 +08:00
}
2025-09-03 14:23:59 +08:00
options -> freqNdigits = ( int8_t ) val ;
}
}
2025-07-30 14:30:36 +08:00
yyjson_val * spaceBeforeUnit = yyjson_obj_get ( val , "spaceBeforeUnit" );
2026-03-29 09:28:49 +08:00
if ( spaceBeforeUnit ) {
2025-07-30 14:30:36 +08:00
int value ;
const char * error = ffJsonConfigParseEnum ( spaceBeforeUnit , & value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "default" , FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always" , FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never" , FF_SPACE_BEFORE_UNIT_NEVER },
2026-03-29 09:28:49 +08:00
{},
});
if ( error ) {
return error ;
}
2025-07-30 14:30:36 +08:00
options -> freqSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) value ;
}
2026-04-16 15:45:12 +08:00
} else if ( unsafe_yyjson_equals_str ( key , "common" )) {
if ( ! yyjson_is_obj ( val )) {
return "display.common must be an object" ;
}
yyjson_val * ndigits = yyjson_obj_get ( val , "ndigits" );
if ( ndigits ) {
if ( ! yyjson_is_uint ( ndigits )) {
return "display.common.ndigits must be an unsigned integer" ;
}
uint64_t val = yyjson_get_uint ( ndigits );
if ( val > 9 ) {
return "display.common.ndigits must be between 0 and 9" ;
}
options -> fractionNdigits = ( int8_t ) val ;
options -> freqNdigits = ( int8_t ) val ;
options -> percentNdigits = ( uint8_t ) val ;
options -> sizeNdigits = ( uint8_t ) val ;
options -> tempNdigits = ( uint8_t ) val ;
}
yyjson_val * spaceBeforeUnit = yyjson_obj_get ( val , "spaceBeforeUnit" );
if ( spaceBeforeUnit ) {
int value ;
const char * error = ffJsonConfigParseEnum ( spaceBeforeUnit , & value , ( FFKeyValuePair []) {
{ "default" , FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always" , FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never" , FF_SPACE_BEFORE_UNIT_NEVER },
{},
});
if ( error ) {
return error ;
}
options -> durationSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) value ;
options -> freqSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) value ;
options -> percentSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) value ;
options -> sizeSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) value ;
options -> tempSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) value ;
}
2026-03-29 09:28:49 +08:00
} else {
2023-10-26 10:26:15 +08:00
return "Unknown display property" ;
2026-03-29 09:28:49 +08:00
}
2023-10-26 10:26:15 +08:00
}
return NULL ;
}
2026-03-29 09:28:49 +08:00
static inline void optionCheckString ( const char * key , const char * value , FFstrbuf * buffer ) {
if ( value == NULL ) {
2023-10-26 10:26:15 +08:00
fprintf ( stderr , "Error: usage: %s <str> \n " , key );
exit ( 477 );
}
2026-03-29 09:28:49 +08:00
ffStrbufEnsureFree ( buffer , 63 ); // This is not needed, as ffStrbufSetS will resize capacity if needed, but giving a higher start should improve performance
2023-10-26 10:26:15 +08:00
}
2026-03-29 09:28:49 +08:00
bool ffOptionsParseDisplayCommandLine ( FFOptionsDisplay * options , const char * key , const char * value ) {
if ( ffStrEqualsIgnCase ( key , "--stat" )) {
if ( ffOptionParseBoolean ( value )) {
2024-08-12 16:16:47 +08:00
options -> stat = 0 ;
2023-10-26 10:26:15 +08:00
options -> showErrors = true ;
2026-03-29 09:28:49 +08:00
} else if ( value ) {
2024-08-12 16:16:47 +08:00
char * end ;
uint32_t num = ( uint32_t ) strtoul ( value , & end , 10 );
2026-03-29 09:28:49 +08:00
if ( * end == '\0' ) {
2024-08-12 16:16:47 +08:00
options -> stat = ( int32_t ) num ;
options -> showErrors = true ;
2026-03-29 09:28:49 +08:00
} else {
2024-08-12 16:16:47 +08:00
options -> stat = - 1 ;
2026-03-29 09:28:49 +08:00
}
} else {
2024-08-12 16:16:47 +08:00
options -> stat = - 1 ;
2026-03-29 09:28:49 +08:00
}
} else if ( ffStrEqualsIgnCase ( key , "--pipe" )) {
2023-10-26 10:26:15 +08:00
options -> pipe = ffOptionParseBoolean ( value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( key , "--show-errors" )) {
2023-10-26 10:26:15 +08:00
options -> showErrors = ffOptionParseBoolean ( value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( key , "--debug" ))
#ifndef NDEBUG
2025-03-15 19:49:51 +08:00
options -> debugMode = ffOptionParseBoolean ( value );
2026-03-29 09:28:49 +08:00
#else
2025-08-28 09:32:01 +08:00
{
fprintf ( stderr , "--debug is only available in debug builds \n " );
exit ( 477 );
}
2026-03-29 09:28:49 +08:00
#endif
else if ( ffStrEqualsIgnCase ( key , "--disable-linewrap" )) {
2023-10-26 10:26:15 +08:00
options -> disableLinewrap = ffOptionParseBoolean ( value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( key , "--hide-cursor" )) {
2023-10-26 10:26:15 +08:00
options -> hideCursor = ffOptionParseBoolean ( value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( key , "--separator" )) {
2023-10-26 10:26:15 +08:00
ffOptionParseString ( key , value , & options -> keyValueSeparator );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( key , "--color" )) {
2023-10-26 10:26:15 +08:00
optionCheckString ( key , value , & options -> colorKeys );
ffOptionParseColor ( value , & options -> colorKeys );
ffStrbufSet ( & options -> colorTitle , & options -> colorKeys );
2026-03-29 09:28:49 +08:00
} else if ( ffStrStartsWithIgnCase ( key , "--color-" )) {
2023-10-26 10:26:15 +08:00
const char * subkey = key + strlen ( "--color-" );
2026-03-29 09:28:49 +08:00
if ( ffStrEqualsIgnCase ( subkey , "keys" )) {
2023-10-26 10:26:15 +08:00
optionCheckString ( key , value , & options -> colorKeys );
ffOptionParseColor ( value , & options -> colorKeys );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "title" )) {
2023-10-26 10:26:15 +08:00
optionCheckString ( key , value , & options -> colorTitle );
ffOptionParseColor ( value , & options -> colorTitle );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "output" )) {
2024-05-08 15:01:57 +08:00
optionCheckString ( key , value , & options -> colorOutput );
ffOptionParseColor ( value , & options -> colorOutput );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "separator" )) {
2024-05-28 16:13:06 +08:00
optionCheckString ( key , value , & options -> colorSeparator );
ffOptionParseColor ( value , & options -> colorSeparator );
2026-03-29 09:28:49 +08:00
} else {
2023-10-26 10:26:15 +08:00
return false ;
2026-03-29 09:28:49 +08:00
}
} else if ( ffStrStartsWithIgnCase ( key , "--key-" )) {
2024-07-24 15:12:25 +08:00
const char * subkey = key + strlen ( "--key-" );
2026-03-29 09:28:49 +08:00
if ( ffStrEqualsIgnCase ( subkey , "width" )) {
2024-07-24 15:12:25 +08:00
options -> keyWidth = ( uint16_t ) ffOptionParseUInt32 ( key , value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "type" )) {
2026-03-30 10:27:23 +08:00
options -> keyType = ( FFModuleKeyType ) ffOptionParseEnum ( key , value , ( FFKeyValuePair []) { { "none" , FF_MODULE_KEY_TYPE_NONE }, { "string" , FF_MODULE_KEY_TYPE_STRING }, { "icon" , FF_MODULE_KEY_TYPE_ICON }, { "both" , FF_MODULE_KEY_TYPE_BOTH }, { "both-0" , FF_MODULE_KEY_TYPE_BOTH_0 }, { "both-1" , FF_MODULE_KEY_TYPE_BOTH_1 }, { "both-2" , FF_MODULE_KEY_TYPE_BOTH_2 }, { "both-3" , FF_MODULE_KEY_TYPE_BOTH_3 }, { "both-4" , FF_MODULE_KEY_TYPE_BOTH_4 }, {} });
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "padding-left" )) {
2024-07-24 15:12:25 +08:00
options -> keyPaddingLeft = ( uint16_t ) ffOptionParseUInt32 ( key , value );
2026-03-29 09:28:49 +08:00
} else {
2024-07-24 15:12:25 +08:00
return false ;
2026-03-29 09:28:49 +08:00
}
} else if ( ffStrEqualsIgnCase ( key , "--bright-color" )) {
2023-10-26 10:26:15 +08:00
options -> brightColor = ffOptionParseBoolean ( value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( key , "--binary-prefix" )) {
2024-07-22 10:51:27 +08:00
fprintf ( stderr , "--binary-prefix has been renamed to --size-binary-prefix \n " );
exit ( 477 );
2026-03-29 09:28:49 +08:00
} else if ( ffStrStartsWithIgnCase ( key , "--duration-" )) {
2025-07-30 14:30:36 +08:00
const char * subkey = key + strlen ( "--duration-" );
2026-03-29 09:28:49 +08:00
if ( ffStrEqualsIgnCase ( subkey , "abbreviation" )) {
2025-07-30 14:30:36 +08:00
options -> durationAbbreviation = ffOptionParseBoolean ( value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "space-before-unit" )) {
2025-07-30 14:30:36 +08:00
options -> durationSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) ffOptionParseEnum ( key , value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "default" , FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always" , FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never" , FF_SPACE_BEFORE_UNIT_NEVER },
2026-03-29 09:28:49 +08:00
{},
});
} else {
2025-07-30 14:30:36 +08:00
return false ;
2024-07-22 10:51:27 +08:00
}
2026-03-29 09:28:49 +08:00
} else if ( ffStrStartsWithIgnCase ( key , "--size-" )) {
const char * subkey = key + strlen ( "--size-" );
if ( ffStrEqualsIgnCase ( subkey , "binary-prefix" )) {
2026-03-30 10:27:23 +08:00
options -> sizeBinaryPrefix = ( FFSizeBinaryPrefixType ) ffOptionParseEnum ( key , value , ( FFKeyValuePair []) { { "iec" , FF_SIZE_BINARY_PREFIX_TYPE_IEC }, { "si" , FF_SIZE_BINARY_PREFIX_TYPE_SI }, { "jedec" , FF_SIZE_BINARY_PREFIX_TYPE_JEDEC }, {} });
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "ndigits" )) {
2026-04-30 09:27:05 +08:00
uint32_t num = ffOptionParseUInt32 ( key , value );
if ( num > 9 ) {
fprintf ( stderr , "Error: %s must be between 0 and 9 \n " , key );
exit ( 479 );
}
options -> sizeNdigits = ( uint8_t ) num ;
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "max-prefix" )) {
2026-04-30 09:27:05 +08:00
options -> sizeMaxPrefix = ( uint8_t ) ffOptionParseEnum (
key ,
value ,
( FFKeyValuePair []) {
{ "B" , 0 },
{ "kB" , 1 },
{ "MB" , 2 },
{ "GB" , 3 },
{ "TB" , 4 },
{ "PB" , 5 },
{ "EB" , 6 },
{ "ZB" , 7 },
{ "YB" , 8 },
{},
});
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "space-before-unit" )) {
2025-07-30 14:30:36 +08:00
options -> sizeSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) ffOptionParseEnum ( key , value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "default" , FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always" , FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never" , FF_SPACE_BEFORE_UNIT_NEVER },
2026-03-29 09:28:49 +08:00
{},
});
} else {
2024-07-22 10:51:27 +08:00
return false ;
2026-03-29 09:28:49 +08:00
}
} else if ( ffStrStartsWithIgnCase ( key , "--temp-" )) {
2024-05-09 08:46:52 +08:00
const char * subkey = key + strlen ( "--temp-" );
2026-03-29 09:28:49 +08:00
if ( ffStrEqualsIgnCase ( subkey , "unit" )) {
2024-05-09 08:46:52 +08:00
options -> tempUnit = ( FFTemperatureUnit ) ffOptionParseEnum ( key , value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "DEFAULT" , FF_TEMPERATURE_UNIT_DEFAULT },
{ "D" , FF_TEMPERATURE_UNIT_DEFAULT },
{ "CELSIUS" , FF_TEMPERATURE_UNIT_CELSIUS },
{ "C" , FF_TEMPERATURE_UNIT_CELSIUS },
{ "FAHRENHEIT" , FF_TEMPERATURE_UNIT_FAHRENHEIT },
{ "F" , FF_TEMPERATURE_UNIT_FAHRENHEIT },
{ "KELVIN" , FF_TEMPERATURE_UNIT_KELVIN },
{ "K" , FF_TEMPERATURE_UNIT_KELVIN },
2026-03-29 09:28:49 +08:00
{},
});
} else if ( ffStrEqualsIgnCase ( subkey , "ndigits" )) {
2024-02-27 13:11:39 +08:00
options -> tempNdigits = ( uint8_t ) ffOptionParseUInt32 ( key , value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "color-green" )) {
2024-02-27 13:11:39 +08:00
ffOptionParseColor ( value , & options -> tempColorGreen );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "color-yellow" )) {
2024-02-27 13:11:39 +08:00
ffOptionParseColor ( value , & options -> tempColorYellow );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "color-red" )) {
2024-02-27 13:11:39 +08:00
ffOptionParseColor ( value , & options -> tempColorRed );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "space-before-unit" )) {
2025-07-30 14:30:36 +08:00
options -> tempSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) ffOptionParseEnum ( key , value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "default" , FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always" , FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never" , FF_SPACE_BEFORE_UNIT_NEVER },
2026-03-29 09:28:49 +08:00
{},
});
} else {
2024-02-26 10:46:13 +08:00
return false ;
2026-03-29 09:28:49 +08:00
}
} else if ( ffStrStartsWithIgnCase ( key , "--percent-" )) {
2024-01-20 19:59:13 +08:00
const char * subkey = key + strlen ( "--percent-" );
2026-03-29 09:28:49 +08:00
if ( ffStrEqualsIgnCase ( subkey , "type" )) {
2024-01-20 19:59:13 +08:00
options -> percentType = ( uint8_t ) ffOptionParseUInt32 ( key , value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "ndigits" )) {
2024-01-20 19:59:13 +08:00
options -> percentNdigits = ( uint8_t ) ffOptionParseUInt32 ( key , value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "color-green" )) {
2024-01-20 19:59:13 +08:00
ffOptionParseColor ( value , & options -> percentColorGreen );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "color-yellow" )) {
2024-01-20 19:59:13 +08:00
ffOptionParseColor ( value , & options -> percentColorYellow );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "color-red" )) {
2024-01-20 19:59:13 +08:00
ffOptionParseColor ( value , & options -> percentColorRed );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "space-before-unit" )) {
2025-07-30 14:30:36 +08:00
options -> percentSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) ffOptionParseEnum ( key , value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "default" , FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always" , FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never" , FF_SPACE_BEFORE_UNIT_NEVER },
2026-03-29 09:28:49 +08:00
{},
});
} else if ( ffStrEqualsIgnCase ( subkey , "width" )) {
2025-07-30 15:06:16 +08:00
options -> percentWidth = ( uint8_t ) ffOptionParseUInt32 ( key , value );
2026-03-29 09:28:49 +08:00
} else {
2024-01-20 19:59:13 +08:00
return false ;
2026-03-29 09:28:49 +08:00
}
} else if ( ffStrEqualsIgnCase ( key , "--fraction-ndigits" )) {
2025-07-16 10:30:45 +08:00
options -> fractionNdigits = ( int8_t ) ffOptionParseInt32 ( key , value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( key , "--fraction-trailing-zeros" )) {
2025-09-03 14:20:23 +08:00
options -> fractionTrailingZeros = ( FFFractionTrailingZerosType ) ffOptionParseEnum ( key , value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "default" , FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT },
{ "always" , FF_FRACTION_TRAILING_ZEROS_TYPE_ALWAYS },
{ "never" , FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER },
2026-03-29 09:28:49 +08:00
{},
});
} else if ( ffStrEqualsIgnCase ( key , "--no-buffer" )) {
2023-10-26 10:26:15 +08:00
options -> noBuffer = ffOptionParseBoolean ( value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrStartsWithIgnCase ( key , "--bar-" )) {
2023-10-26 10:26:15 +08:00
const char * subkey = key + strlen ( "--bar-" );
2026-03-29 09:28:49 +08:00
if ( ffStrEqualsIgnCase ( subkey , "char-elapsed" )) {
2023-10-26 10:26:15 +08:00
ffOptionParseString ( key , value , & options -> barCharElapsed );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "char-total" )) {
2023-10-26 10:26:15 +08:00
ffOptionParseString ( key , value , & options -> barCharTotal );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "width" )) {
2023-10-26 10:26:15 +08:00
options -> barWidth = ( uint8_t ) ffOptionParseUInt32 ( key , value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "border-left" )) {
2024-06-06 16:36:57 +08:00
ffOptionParseString ( key , value , & options -> barBorderLeft );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "border-right" )) {
2024-06-06 16:36:57 +08:00
ffOptionParseString ( key , value , & options -> barBorderRight );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "border-left-elapsed" )) {
2025-08-01 10:51:26 +08:00
ffOptionParseString ( key , value , & options -> barBorderLeftElapsed );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "border-right-elapsed" )) {
2025-08-01 10:51:26 +08:00
ffOptionParseString ( key , value , & options -> barBorderRightElapsed );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "color-elapsed" )) {
if ( ! value ) {
2025-08-04 16:46:28 +08:00
ffStrbufClear ( & options -> barColorElapsed );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( value , "auto" )) {
2025-08-04 16:46:28 +08:00
ffStrbufSetStatic ( & options -> barColorElapsed , "auto" );
2026-03-29 09:28:49 +08:00
} else {
2025-08-04 16:46:28 +08:00
ffOptionParseColor ( value , & options -> barColorElapsed );
2026-03-29 09:28:49 +08:00
}
} else if ( ffStrEqualsIgnCase ( subkey , "color-total" )) {
2025-08-01 13:50:02 +08:00
ffOptionParseColor ( value , & options -> barColorTotal );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "color-border" )) {
2025-08-01 13:50:02 +08:00
ffOptionParseColor ( value , & options -> barColorBorder );
2026-03-29 09:28:49 +08:00
} else {
2023-10-26 10:26:15 +08:00
return false ;
2026-03-29 09:28:49 +08:00
}
} else if ( ffStrStartsWithIgnCase ( key , "--freq-" )) {
2024-07-17 14:42:09 +08:00
const char * subkey = key + strlen ( "--freq-" );
2026-03-29 09:28:49 +08:00
if ( ffStrEqualsIgnCase ( subkey , "ndigits" )) {
2024-07-17 14:42:09 +08:00
options -> freqNdigits = ( int8_t ) ffOptionParseInt32 ( key , value );
2026-03-29 09:28:49 +08:00
} else if ( ffStrEqualsIgnCase ( subkey , "space-before-unit" )) {
2025-07-30 14:30:36 +08:00
options -> freqSpaceBeforeUnit = ( FFSpaceBeforeUnitType ) ffOptionParseEnum ( key , value , ( FFKeyValuePair []) {
2026-03-30 10:27:23 +08:00
{ "default" , FF_SPACE_BEFORE_UNIT_DEFAULT },
{ "always" , FF_SPACE_BEFORE_UNIT_ALWAYS },
{ "never" , FF_SPACE_BEFORE_UNIT_NEVER },
2026-03-29 09:28:49 +08:00
{},
});
} else {
2024-07-23 09:55:48 +08:00
return false ;
2026-03-29 09:28:49 +08:00
}
} else {
2023-10-26 10:26:15 +08:00
return false ;
2026-03-29 09:28:49 +08:00
}
2023-10-26 10:26:15 +08:00
return true ;
}
2026-03-29 09:28:49 +08:00
void ffOptionsInitDisplay ( FFOptionsDisplay * options ) {
2023-10-26 10:26:15 +08:00
ffStrbufInit ( & options -> colorKeys );
ffStrbufInit ( & options -> colorTitle );
2024-05-08 15:01:57 +08:00
ffStrbufInit ( & options -> colorOutput );
2024-05-28 16:13:06 +08:00
ffStrbufInit ( & options -> colorSeparator );
2024-06-04 14:23:30 +08:00
options -> brightColor = ! instance . state . terminalLightTheme ;
2023-10-26 10:26:15 +08:00
ffStrbufInitStatic ( & options -> keyValueSeparator , ": " );
options -> showErrors = false ;
2024-05-05 20:14:10 +08:00
options -> pipe = ! isatty ( STDOUT_FILENO ) || !! getenv ( "NO_COLOR" );
2023-10-26 10:26:15 +08:00
2026-03-29 09:28:49 +08:00
#ifdef NDEBUG
2023-10-26 10:26:15 +08:00
options -> disableLinewrap = ! options -> pipe ;
2026-03-29 09:28:49 +08:00
#else
2023-10-26 10:26:15 +08:00
options -> disableLinewrap = false ;
2026-03-14 22:27:36 +08:00
options -> debugMode = !! getenv ( "FF_DEBUG" );
2026-03-29 09:28:49 +08:00
#endif
2023-10-26 10:26:15 +08:00
2025-07-30 14:30:36 +08:00
options -> durationSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT ;
2024-04-25 14:18:25 +08:00
options -> hideCursor = false ;
2024-07-22 10:59:23 +08:00
options -> sizeBinaryPrefix = FF_SIZE_BINARY_PREFIX_TYPE_IEC ;
2023-10-26 10:26:15 +08:00
options -> sizeNdigits = 2 ;
2025-08-06 21:57:05 +08:00
options -> sizeMaxPrefix = 8 ; // YB
2025-07-30 14:30:36 +08:00
options -> sizeSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT ;
2024-08-12 16:16:47 +08:00
options -> stat = - 1 ;
2023-10-26 10:26:15 +08:00
options -> noBuffer = false ;
options -> keyWidth = 0 ;
2024-07-24 15:12:25 +08:00
options -> keyPaddingLeft = 0 ;
2024-07-24 11:13:37 +08:00
options -> keyType = FF_MODULE_KEY_TYPE_STRING ;
2023-10-26 10:26:15 +08:00
2025-02-14 10:31:13 +08:00
options -> tempUnit = FF_TEMPERATURE_UNIT_DEFAULT ;
2024-02-27 13:11:39 +08:00
options -> tempNdigits = 1 ;
ffStrbufInitStatic ( & options -> tempColorGreen , FF_COLOR_FG_GREEN );
2024-06-04 14:23:30 +08:00
ffStrbufInitStatic ( & options -> tempColorYellow , instance . state . terminalLightTheme ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_LIGHT_YELLOW );
ffStrbufInitStatic ( & options -> tempColorRed , instance . state . terminalLightTheme ? FF_COLOR_FG_RED : FF_COLOR_FG_LIGHT_RED );
2025-07-30 14:30:36 +08:00
options -> tempSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT ;
2024-02-26 10:46:13 +08:00
2023-10-26 10:26:15 +08:00
ffStrbufInitStatic ( & options -> barCharElapsed , "■" );
ffStrbufInitStatic ( & options -> barCharTotal , "-" );
2024-06-06 16:36:57 +08:00
ffStrbufInitStatic ( & options -> barBorderLeft , "[ " );
ffStrbufInitStatic ( & options -> barBorderRight , " ]" );
2025-08-01 10:51:26 +08:00
ffStrbufInit ( & options -> barBorderLeftElapsed );
ffStrbufInit ( & options -> barBorderRightElapsed );
2025-08-01 15:12:30 +08:00
ffStrbufInitStatic ( & options -> barColorElapsed , "auto" );
2025-08-01 13:50:02 +08:00
ffStrbufInitStatic ( & options -> barColorTotal , instance . state . terminalLightTheme ? FF_COLOR_FG_WHITE : FF_COLOR_FG_LIGHT_WHITE );
ffStrbufInitStatic ( & options -> barColorBorder , instance . state . terminalLightTheme ? FF_COLOR_FG_WHITE : FF_COLOR_FG_LIGHT_WHITE );
2023-10-26 10:26:15 +08:00
options -> barWidth = 10 ;
2025-08-01 13:50:02 +08:00
2025-07-30 14:30:36 +08:00
options -> durationAbbreviation = false ;
options -> durationSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT ;
2026-04-15 10:09:33 +08:00
options -> percentType = FF_PERCENTAGE_TYPE_NUM_BIT | FF_PERCENTAGE_TYPE_NUM_COLOR_BIT ;
2023-10-26 10:26:15 +08:00
options -> percentNdigits = 0 ;
2024-01-20 19:59:13 +08:00
ffStrbufInitStatic ( & options -> percentColorGreen , FF_COLOR_FG_GREEN );
2024-06-04 14:23:30 +08:00
ffStrbufInitStatic ( & options -> percentColorYellow , instance . state . terminalLightTheme ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_LIGHT_YELLOW );
ffStrbufInitStatic ( & options -> percentColorRed , instance . state . terminalLightTheme ? FF_COLOR_FG_RED : FF_COLOR_FG_LIGHT_RED );
2025-07-30 14:30:36 +08:00
options -> percentSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT ;
2025-07-30 15:06:16 +08:00
options -> percentWidth = 0 ;
2025-07-30 14:30:36 +08:00
2024-07-17 14:42:09 +08:00
options -> freqNdigits = 2 ;
2025-07-30 14:30:36 +08:00
options -> freqSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT ;
2025-09-03 09:58:40 +08:00
options -> fractionNdigits = 2 ;
2025-09-02 14:12:58 +08:00
options -> fractionTrailingZeros = FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT ;
2024-07-15 11:00:15 +08:00
2026-04-14 10:41:18 +08:00
ffListInit ( & options -> constants );
2023-10-26 10:26:15 +08:00
}
2026-03-29 09:28:49 +08:00
void ffOptionsDestroyDisplay ( FFOptionsDisplay * options ) {
2023-10-26 10:26:15 +08:00
ffStrbufDestroy ( & options -> colorKeys );
ffStrbufDestroy ( & options -> colorTitle );
2024-05-08 15:01:57 +08:00
ffStrbufDestroy ( & options -> colorOutput );
2024-05-28 16:13:06 +08:00
ffStrbufDestroy ( & options -> colorSeparator );
2023-10-26 10:26:15 +08:00
ffStrbufDestroy ( & options -> keyValueSeparator );
ffStrbufDestroy ( & options -> barCharElapsed );
ffStrbufDestroy ( & options -> barCharTotal );
2026-03-29 09:28:49 +08:00
FF_LIST_FOR_EACH ( FFstrbuf , item , options -> constants ) {
2024-07-15 11:00:15 +08:00
ffStrbufDestroy ( item );
2026-03-29 09:28:49 +08:00
}
2024-07-15 11:00:15 +08:00
ffListDestroy ( & options -> constants );
2023-10-26 10:26:15 +08:00
}
2023-10-26 11:02:08 +08:00
2026-03-29 09:28:49 +08:00
void ffOptionsGenerateDisplayJsonConfig ( FFdata * data , FFOptionsDisplay * options ) {
2026-01-15 15:03:38 +08:00
yyjson_mut_doc * doc = data -> resultDoc ;
2025-08-04 16:46:28 +08:00
yyjson_mut_val * obj = yyjson_mut_obj_add_obj ( doc , doc -> root , "display" );
2023-10-26 11:02:08 +08:00
2026-03-29 09:28:49 +08:00
if ( options -> stat <= 0 ) {
2025-08-04 16:46:28 +08:00
yyjson_mut_obj_add_bool ( doc , obj , "stat" , options -> stat == 0 );
2026-03-29 09:28:49 +08:00
} else {
2025-08-04 16:46:28 +08:00
yyjson_mut_obj_add_int ( doc , obj , "stat" , options -> stat );
2026-03-29 09:28:49 +08:00
}
2023-10-26 11:02:08 +08:00
2025-08-04 16:46:28 +08:00
yyjson_mut_obj_add_bool ( doc , obj , "pipe" , options -> pipe );
yyjson_mut_obj_add_bool ( doc , obj , "showErrors" , options -> showErrors );
2023-10-26 11:02:08 +08:00
2025-08-04 16:46:28 +08:00
yyjson_mut_obj_add_bool ( doc , obj , "disableLinewrap" , options -> disableLinewrap );
2023-10-26 11:02:08 +08:00
2025-08-04 16:46:28 +08:00
yyjson_mut_obj_add_bool ( doc , obj , "hideCursor" , options -> hideCursor );
2023-10-26 11:02:08 +08:00
2025-08-04 16:46:28 +08:00
yyjson_mut_obj_add_strbuf ( doc , obj , "separator" , & options -> keyValueSeparator );
2023-10-26 11:02:08 +08:00
2025-08-04 16:46:28 +08:00
{
yyjson_mut_val * color = yyjson_mut_obj_add_obj ( doc , obj , "color" );
yyjson_mut_obj_add_strbuf ( doc , color , "keys" , & options -> colorKeys );
yyjson_mut_obj_add_strbuf ( doc , color , "title" , & options -> colorTitle );
yyjson_mut_obj_add_strbuf ( doc , color , "output" , & options -> colorOutput );
yyjson_mut_obj_add_strbuf ( doc , color , "separator" , & options -> colorSeparator );
}
2023-10-26 11:02:08 +08:00
2025-08-04 16:46:28 +08:00
yyjson_mut_obj_add_bool ( doc , obj , "brightColor" , options -> brightColor );
2023-10-26 11:02:08 +08:00
{
2025-08-04 16:46:28 +08:00
yyjson_mut_val * duration = yyjson_mut_obj_add_obj ( doc , obj , "duration" );
yyjson_mut_obj_add_bool ( doc , duration , "abbreviation" , options -> durationAbbreviation );
2026-03-29 09:28:49 +08:00
switch ( options -> durationSpaceBeforeUnit ) {
2025-08-04 16:46:28 +08:00
case FF_SPACE_BEFORE_UNIT_DEFAULT :
yyjson_mut_obj_add_str ( doc , duration , "spaceBeforeUnit" , "default" );
break ;
case FF_SPACE_BEFORE_UNIT_ALWAYS :
yyjson_mut_obj_add_str ( doc , duration , "spaceBeforeUnit" , "always" );
break ;
case FF_SPACE_BEFORE_UNIT_NEVER :
yyjson_mut_obj_add_str ( doc , duration , "spaceBeforeUnit" , "never" );
break ;
2023-10-26 11:02:08 +08:00
}
}
{
2025-08-04 16:46:28 +08:00
yyjson_mut_val * size = yyjson_mut_obj_add_obj ( doc , obj , "size" );
2026-03-29 09:28:49 +08:00
yyjson_mut_obj_add_str ( doc , size , "maxPrefix" , (( const char * []) {
"B" ,
"kB" ,
"MB" ,
"GB" ,
"TB" ,
"PB" ,
"EB" ,
"ZB" ,
"YB" ,
})[ options -> sizeMaxPrefix ]);
switch ( options -> sizeBinaryPrefix ) {
2025-08-04 16:46:28 +08:00
case FF_SIZE_BINARY_PREFIX_TYPE_IEC :
yyjson_mut_obj_add_str ( doc , size , "binaryPrefix" , "iec" );
break ;
case FF_SIZE_BINARY_PREFIX_TYPE_SI :
yyjson_mut_obj_add_str ( doc , size , "binaryPrefix" , "si" );
break ;
case FF_SIZE_BINARY_PREFIX_TYPE_JEDEC :
yyjson_mut_obj_add_str ( doc , size , "binaryPrefix" , "jedec" );
break ;
}
yyjson_mut_obj_add_uint ( doc , size , "ndigits" , options -> sizeNdigits );
2026-03-29 09:28:49 +08:00
switch ( options -> sizeSpaceBeforeUnit ) {
2025-08-04 16:46:28 +08:00
case FF_SPACE_BEFORE_UNIT_DEFAULT :
yyjson_mut_obj_add_str ( doc , size , "spaceBeforeUnit" , "default" );
break ;
case FF_SPACE_BEFORE_UNIT_ALWAYS :
yyjson_mut_obj_add_str ( doc , size , "spaceBeforeUnit" , "always" );
break ;
case FF_SPACE_BEFORE_UNIT_NEVER :
yyjson_mut_obj_add_str ( doc , size , "spaceBeforeUnit" , "never" );
break ;
2024-07-22 10:59:23 +08:00
}
2023-10-26 11:02:08 +08:00
}
{
2025-08-04 16:46:28 +08:00
yyjson_mut_val * temperature = yyjson_mut_obj_add_obj ( doc , obj , "temp" );
2026-03-29 09:28:49 +08:00
switch ( options -> tempUnit ) {
2025-08-04 16:46:28 +08:00
case FF_TEMPERATURE_UNIT_DEFAULT :
yyjson_mut_obj_add_str ( doc , temperature , "unit" , "D" );
break ;
case FF_TEMPERATURE_UNIT_CELSIUS :
2026-04-15 09:38:59 +08:00
yyjson_mut_obj_add_str ( doc , temperature , "unit" , "C" );
2025-08-04 16:46:28 +08:00
break ;
case FF_TEMPERATURE_UNIT_FAHRENHEIT :
2026-04-15 09:38:59 +08:00
yyjson_mut_obj_add_str ( doc , temperature , "unit" , "F" );
2025-08-04 16:46:28 +08:00
break ;
case FF_TEMPERATURE_UNIT_KELVIN :
2026-04-15 09:38:59 +08:00
yyjson_mut_obj_add_str ( doc , temperature , "unit" , "K" );
2025-08-04 16:46:28 +08:00
break ;
}
yyjson_mut_obj_add_uint ( doc , temperature , "ndigits" , options -> tempNdigits );
{
yyjson_mut_val * color = yyjson_mut_obj_add_obj ( doc , temperature , "color" );
yyjson_mut_obj_add_strbuf ( doc , color , "green" , & options -> tempColorGreen );
yyjson_mut_obj_add_strbuf ( doc , color , "yellow" , & options -> tempColorYellow );
yyjson_mut_obj_add_strbuf ( doc , color , "red" , & options -> tempColorRed );
}
2026-03-29 09:28:49 +08:00
switch ( options -> tempSpaceBeforeUnit ) {
2025-08-04 16:46:28 +08:00
case FF_SPACE_BEFORE_UNIT_DEFAULT :
yyjson_mut_obj_add_str ( doc , temperature , "spaceBeforeUnit" , "default" );
break ;
case FF_SPACE_BEFORE_UNIT_ALWAYS :
yyjson_mut_obj_add_str ( doc , temperature , "spaceBeforeUnit" , "always" );
break ;
case FF_SPACE_BEFORE_UNIT_NEVER :
yyjson_mut_obj_add_str ( doc , temperature , "spaceBeforeUnit" , "never" );
break ;
2024-02-26 10:46:13 +08:00
}
2023-10-26 11:02:08 +08:00
}
2023-10-29 00:17:24 +08:00
{
2025-08-04 16:46:28 +08:00
yyjson_mut_val * percent = yyjson_mut_obj_add_obj ( doc , obj , "percent" );
{
yyjson_mut_val * type = yyjson_mut_obj_add_arr ( doc , percent , "type" );
2026-03-29 09:28:49 +08:00
if ( options -> percentType & FF_PERCENTAGE_TYPE_NUM_BIT ) {
2025-08-04 16:46:28 +08:00
yyjson_mut_arr_add_str ( doc , type , "num" );
2026-03-29 09:28:49 +08:00
}
if ( options -> percentType & FF_PERCENTAGE_TYPE_BAR_BIT ) {
2026-04-15 09:38:59 +08:00
yyjson_mut_arr_add_str ( doc , type , "bar" );
2026-03-29 09:28:49 +08:00
}
if ( options -> percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT ) {
2025-08-04 16:46:28 +08:00
yyjson_mut_arr_add_str ( doc , type , "hide-others" );
2026-03-29 09:28:49 +08:00
}
if ( options -> percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT ) {
2025-08-04 16:46:28 +08:00
yyjson_mut_arr_add_str ( doc , type , "num-color" );
2026-03-29 09:28:49 +08:00
}
if ( options -> percentType & FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT ) {
2025-08-04 16:46:28 +08:00
yyjson_mut_arr_add_str ( doc , type , "bar-monochrome" );
2026-03-29 09:28:49 +08:00
}
2025-08-04 16:46:28 +08:00
}
yyjson_mut_obj_add_uint ( doc , percent , "ndigits" , options -> percentNdigits );
{
yyjson_mut_val * color = yyjson_mut_obj_add_obj ( doc , percent , "color" );
yyjson_mut_obj_add_strbuf ( doc , color , "green" , & options -> percentColorGreen );
yyjson_mut_obj_add_strbuf ( doc , color , "yellow" , & options -> percentColorYellow );
yyjson_mut_obj_add_strbuf ( doc , color , "red" , & options -> percentColorRed );
}
2026-03-29 09:28:49 +08:00
switch ( options -> percentSpaceBeforeUnit ) {
2025-08-04 16:46:28 +08:00
case FF_SPACE_BEFORE_UNIT_DEFAULT :
yyjson_mut_obj_add_str ( doc , percent , "spaceBeforeUnit" , "default" );
break ;
case FF_SPACE_BEFORE_UNIT_ALWAYS :
yyjson_mut_obj_add_str ( doc , percent , "spaceBeforeUnit" , "always" );
break ;
case FF_SPACE_BEFORE_UNIT_NEVER :
yyjson_mut_obj_add_str ( doc , percent , "spaceBeforeUnit" , "never" );
break ;
}
yyjson_mut_obj_add_uint ( doc , percent , "width" , options -> percentWidth );
2023-10-29 00:17:24 +08:00
}
2023-10-26 11:02:08 +08:00
{
2025-08-04 16:46:28 +08:00
yyjson_mut_val * bar = yyjson_mut_obj_add_obj ( doc , obj , "bar" );
yyjson_mut_val * char_ = yyjson_mut_obj_add_obj ( doc , bar , "char" );
yyjson_mut_obj_add_strbuf ( doc , char_ , "elapsed" , & options -> barCharElapsed );
yyjson_mut_obj_add_strbuf ( doc , char_ , "total" , & options -> barCharTotal );
yyjson_mut_val * border = yyjson_mut_obj_add_obj ( doc , bar , "border" );
yyjson_mut_obj_add_strbuf ( doc , border , "left" , & options -> barBorderLeft );
yyjson_mut_obj_add_strbuf ( doc , border , "right" , & options -> barBorderRight );
yyjson_mut_obj_add_strbuf ( doc , border , "leftElapsed" , & options -> barBorderLeftElapsed );
yyjson_mut_obj_add_strbuf ( doc , border , "rightElapsed" , & options -> barBorderRightElapsed );
yyjson_mut_val * color = yyjson_mut_obj_add_obj ( doc , bar , "color" );
yyjson_mut_obj_add_strbuf ( doc , color , "elapsed" , & options -> barColorElapsed );
yyjson_mut_obj_add_strbuf ( doc , color , "total" , & options -> barColorTotal );
yyjson_mut_obj_add_strbuf ( doc , color , "border" , & options -> barColorBorder );
yyjson_mut_obj_add_uint ( doc , bar , "width" , options -> barWidth );
2023-10-26 11:02:08 +08:00
}
2025-08-04 16:46:28 +08:00
{
yyjson_mut_val * fraction = yyjson_mut_obj_add_obj ( doc , obj , "fraction" );
2023-10-26 11:02:08 +08:00
2026-03-29 09:28:49 +08:00
if ( options -> fractionNdigits < 0 ) {
2025-08-04 16:46:28 +08:00
yyjson_mut_obj_add_null ( doc , fraction , "ndigits" );
2026-03-29 09:28:49 +08:00
} else {
2025-08-04 16:46:28 +08:00
yyjson_mut_obj_add_uint ( doc , fraction , "ndigits" , ( uint8_t ) options -> fractionNdigits );
2026-03-29 09:28:49 +08:00
}
2026-04-15 09:38:59 +08:00
switch ( options -> fractionTrailingZeros ) {
case FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT :
yyjson_mut_obj_add_str ( doc , fraction , "trailingZeros" , "default" );
break ;
case FF_FRACTION_TRAILING_ZEROS_TYPE_ALWAYS :
yyjson_mut_obj_add_str ( doc , fraction , "trailingZeros" , "always" );
break ;
case FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER :
yyjson_mut_obj_add_str ( doc , fraction , "trailingZeros" , "never" );
break ;
}
2025-08-04 16:46:28 +08:00
}
2023-10-26 11:02:08 +08:00
2025-08-04 16:46:28 +08:00
yyjson_mut_obj_add_bool ( doc , obj , "noBuffer" , options -> noBuffer );
2024-07-24 11:13:37 +08:00
2025-08-04 16:46:28 +08:00
{
yyjson_mut_val * key = yyjson_mut_obj_add_obj ( doc , obj , "key" );
yyjson_mut_obj_add_uint ( doc , key , "width" , options -> keyWidth );
2026-03-29 09:28:49 +08:00
switch (( uint8_t ) options -> keyType ) {
2025-08-04 16:46:28 +08:00
case FF_MODULE_KEY_TYPE_NONE :
yyjson_mut_obj_add_str ( doc , key , "type" , "none" );
break ;
case FF_MODULE_KEY_TYPE_STRING :
yyjson_mut_obj_add_str ( doc , key , "type" , "string" );
break ;
case FF_MODULE_KEY_TYPE_ICON :
yyjson_mut_obj_add_str ( doc , key , "type" , "icon" );
break ;
2026-04-15 09:38:59 +08:00
case FF_MODULE_KEY_TYPE_BOTH_0 :
yyjson_mut_obj_add_str ( doc , key , "type" , "both-0" );
break ;
case FF_MODULE_KEY_TYPE_BOTH_1 : // alias: both
2025-08-04 16:46:28 +08:00
yyjson_mut_obj_add_str ( doc , key , "type" , "both" );
break ;
2026-04-15 09:38:59 +08:00
case FF_MODULE_KEY_TYPE_BOTH_2 :
yyjson_mut_obj_add_str ( doc , key , "type" , "both-2" );
break ;
case FF_MODULE_KEY_TYPE_BOTH_3 :
yyjson_mut_obj_add_str ( doc , key , "type" , "both-3" );
break ;
case FF_MODULE_KEY_TYPE_BOTH_4 :
yyjson_mut_obj_add_str ( doc , key , "type" , "both-4" );
break ;
2025-08-04 16:46:28 +08:00
}
yyjson_mut_obj_add_uint ( doc , key , "paddingLeft" , options -> keyPaddingLeft );
}
2024-07-24 15:12:25 +08:00
2024-07-17 14:42:09 +08:00
{
2025-08-04 16:46:28 +08:00
yyjson_mut_val * freq = yyjson_mut_obj_add_obj ( doc , obj , "freq" );
yyjson_mut_obj_add_int ( doc , freq , "ndigits" , options -> freqNdigits );
2026-04-15 09:38:59 +08:00
switch ( options -> freqSpaceBeforeUnit ) {
2025-08-04 16:46:28 +08:00
case FF_SPACE_BEFORE_UNIT_DEFAULT :
yyjson_mut_obj_add_str ( doc , freq , "spaceBeforeUnit" , "default" );
break ;
case FF_SPACE_BEFORE_UNIT_ALWAYS :
yyjson_mut_obj_add_str ( doc , freq , "spaceBeforeUnit" , "always" );
break ;
case FF_SPACE_BEFORE_UNIT_NEVER :
yyjson_mut_obj_add_str ( doc , freq , "spaceBeforeUnit" , "never" );
break ;
}
2024-07-17 14:42:09 +08:00
}
2025-08-04 16:46:28 +08:00
{
yyjson_mut_val * constants = yyjson_mut_obj_add_arr ( doc , obj , "constants" );
2026-03-29 09:28:49 +08:00
FF_LIST_FOR_EACH ( FFstrbuf , item , options -> constants ) {
2025-08-04 16:46:28 +08:00
yyjson_mut_arr_add_strbuf ( doc , constants , item );
2026-03-29 09:28:49 +08:00
}
2025-08-04 16:46:28 +08:00
}
2023-10-26 11:02:08 +08:00
}