Skip to content

Commit

Permalink
Format: support syntax of {$ENV_VAR} in custom format
Browse files Browse the repository at this point in the history
Fix #1541
  • Loading branch information
CarterLi committed Feb 8, 2025
1 parent 486ade0 commit 6460e96
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Features:
* Capitalize `{type}`'s first letter in custom format (#1543, Display)
* Support model name detection for s390x (CPU, Linux)
* Support more Armbian variants detection (#1547, OS, Linux)
* Support the syntax of `{$ENV_VAR}` in custom format, which will be replaced by the value of the environment variable `ENV_VAR` (#1541)
* This is another way to pass 3rd-party data to fastfetch besides `Custom` module.

Logo:
* Update arch_old
Expand Down
31 changes: 20 additions & 11 deletions src/common/format.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,24 +259,33 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n
continue;
}

//test for constant, if so evaluate it
//test for constant or env var, if so evaluate it
if (firstChar == '$')
{
char* pend = NULL;
int32_t indexSigned = (int32_t) strtol(placeholderValue.chars + 1, &pend, 10);
uint32_t index = (uint32_t) indexSigned;
bool backward = indexSigned < 0;

if (indexSigned == 0 || *pend != '\0' || instance.config.display.constants.length < index)
if (pend == placeholderValue.chars + 1)
{
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
continue;
// treat placeholder as an environment variable
char* envValue = getenv(placeholderValue.chars + 1);
if (envValue)
ffStrbufAppendS(buffer, envValue);
else
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
}
else
{
// treat placeholder as a constant
uint32_t index = (uint32_t) (indexSigned < 0 ? (int32_t) instance.config.display.constants.length + indexSigned : indexSigned - 1);

FFstrbuf* item = FF_LIST_GET(FFstrbuf, instance.config.display.constants, backward
? instance.config.display.constants.length - index
: index - 1);
ffStrbufAppend(buffer, item);
if (*pend != '\0' || instance.config.display.constants.length <= index)
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
else
{
FFstrbuf* item = FF_LIST_GET(FFstrbuf, instance.config.display.constants, index);
ffStrbufAppend(buffer, item);
}
}
continue;
}

Expand Down
2 changes: 2 additions & 0 deletions src/data/help_format.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ In 2.24.0 or newer, `{~startIndex,endIndex}` can be specified to slice a string.
If an index is omitted, 0 is used. For example, both `{~,0}` `{~0,}` and `{~,}` are same as `{~0,0}` and will always generate a empty string.
If `,endIndex` is omitted or greater than the length of the string, the length of string is used.

In 2.36.0 or newer, `{$NUM}` can be specified to reference a constant defined in `display.constants`. `{$ENV_VAR}` can be specified to reference an environment variable.

If the value index is missing, meaning the placeholder is "{}", an internal counter sets the value index.
This means that the format string "Values: {1} ({2})" is equivalent to "Values: {} ({})".
Note that this counter only counts empty placeholders, so the format string "{2} {} {}" will contain the second value, then the first, and then the second again.
Expand Down
18 changes: 18 additions & 0 deletions tests/format.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,24 @@ int main(void)
VERIFY("output({?1}OK{?}{/1}NOT OK{/})", "", "output(NOT OK)");
}

{
ffListInit(&instance.config.display.constants, sizeof(FFstrbuf));
ffStrbufSetStatic(ffListAdd(&instance.config.display.constants), "CONST1");
ffStrbufSetStatic(ffListAdd(&instance.config.display.constants), "CONST2");
setenv("FF_TEST", "ENVVAR", 1);
VERIFY("output({$FF_TEST})", "", "output(ENVVAR)");
VERIFY("output({$1})", "", "output(CONST1)");
VERIFY("output({$FF_TEST}{$1})", "", "output(ENVVARCONST1)");
VERIFY("output({$1}{$FF_TEST})", "", "output(CONST1ENVVAR)");
VERIFY("output({$FF_TEST}{$FF_TEST})", "", "output(ENVVARENVVAR)");
VERIFY("output({$1}{$-1})", "", "output(CONST1CONST2)");

VERIFY("output({$FF_INVAL})", "", "output({$FF_INVAL})");
VERIFY("output({$9}{$0}${-9})", "", "output({$9}{$0}${-9})");
VERIFY("output({$1NO})", "", "output({$1NO})");
ffListDestroy(&instance.config.display.constants);
}

//Success
puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET);
}

0 comments on commit 6460e96

Please sign in to comment.