From 016b1e6961f475852a6a7cb0ef1ab7d722845893 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 8 Feb 2025 22:11:41 +0800 Subject: [PATCH] Format: support syntax of `{$ENV_VAR}` in custom format Fix #1541 --- .github/workflows/ci.yml | 30 +++++++++++++++--------------- CHANGELOG.md | 2 ++ src/common/format.c | 31 ++++++++++++++++++++----------- src/data/help_format.txt | 2 ++ tests/format.c | 22 ++++++++++++++++++++++ 5 files changed, 61 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f3879ba..f3df5753 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: run: ldd fastfetch - name: run tests - run: ctest + run: ctest --output-on-failure linux-amd64: name: Linux-amd64 @@ -111,7 +111,7 @@ jobs: run: ldd fastfetch - name: run tests - run: ctest + run: ctest --output-on-failure - name: get fastfetch version id: ffversion @@ -150,7 +150,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -189,7 +189,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -225,7 +225,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -260,7 +260,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -295,7 +295,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -334,7 +334,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure shell: alpine.sh {0} - name: upload artifacts @@ -390,7 +390,7 @@ jobs: run: otool -L fastfetch - name: run tests - run: ctest + run: ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -422,7 +422,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure cpack - name: upload artifacts @@ -460,7 +460,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -495,7 +495,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -531,7 +531,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -567,7 +567,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -626,7 +626,7 @@ jobs: run: ldd fastfetch - name: run tests - run: ctest + run: ctest --output-on-failure - name: create zip archive run: 7z a -tzip -mx9 -bd -y fastfetch-windows-amd64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets diff --git a/CHANGELOG.md b/CHANGELOG.md index 760e5cbc..d7ba9f4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/common/format.c b/src/common/format.c index 19564a3f..204c1d8d 100644 --- a/src/common/format.c +++ b/src/common/format.c @@ -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; } diff --git a/src/data/help_format.txt b/src/data/help_format.txt index 0c77ba86..5a66086e 100644 --- a/src/data/help_format.txt +++ b/src/data/help_format.txt @@ -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. diff --git a/tests/format.c b/tests/format.c index 6b7d0a72..0e94cec8 100644 --- a/tests/format.c +++ b/tests/format.c @@ -2,6 +2,8 @@ #include "util/textModifier.h" #include "fastfetch.h" +#include + static void verify(const char* format, const char* arg, const char* expected, int lineNo) { FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate(); @@ -113,6 +115,26 @@ int main(void) VERIFY("output({?1}OK{?}{/1}NOT OK{/})", "", "output(NOT OK)"); } + #ifndef _WIN32 // Windows doesn't have setenv + { + ffListInit(&instance.config.display.constants, sizeof(FFstrbuf)); + ffStrbufInitStatic(ffListAdd(&instance.config.display.constants), "CONST1"); + ffStrbufInitStatic(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); + } + #endif + //Success puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET); }