diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2951e78c5..287db4ea3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -173,11 +173,15 @@ jobs: id: runcmd with: arch: armv7 - distro: ubuntu22.04 + distro: ubuntu20.04 githubToken: ${{ github.token }} run: | uname -a - apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev directx-headers-dev rpm + apt-get update && apt-get install -y wget + # CMake installed by apt has bug `list sub-command REMOVE_ITEM requires two or more arguments` + wget --no-check-certificate https://apt.kitware.com/ubuntu/pool/main/c/cmake/{cmake_3.29.2-0kitware1ubuntu20.04.1_armhf.deb,cmake-data_3.29.2-0kitware1ubuntu20.04.1_all.deb} + dpkg -i *.deb + apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev rpm cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . cmake --build . --target package --verbose -j4 ./fastfetch --list-features diff --git a/CHANGELOG.md b/CHANGELOG.md index 336410b70..eee4448a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,29 @@ +# 2.11.4 + +Changes: + +* Fastfetch will print a colorless ascii logo in `--pipe` mode for better `lolcat` compatibility. `fastfetch | lolcat` should work and no `--pipe false` needed. + * Previously the logo would be disabled in `--pipe` mode. +* `--os-file` was removed and CMake option `-DCUSTOM_OS_RELEASE_PATH=/path/to/os-release` was added. This option should not used in most cases. + +Bugfixes: + +* Fix possible out-of-bound memory access (#868) +* Fix Apple Terminal detection (macOS, Terminal) +* Fix doubled output in custom formation (#852) +* Fix deprecation warning for macOS 14.0 hopefully (#860, macOS, Camera) +* Fix memory leaks when passing informative options +* Fix JSON config `size.ndigits` doesn't work + +Features: + +* Enable `--pipe` mode if environment variable `$NO_COLOR` is set +* Support Armbian and Proxmox distro detection (OS, Linux) + +Logo: + +* Add Armbian + # 2.11.3 Hotfix for nix (https://github.com/NixOS/nixpkgs/issues/308849#issuecomment-2093962376) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f62fda0b..90dc678d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.11.3 + VERSION 2.11.4 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" @@ -80,6 +80,7 @@ option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions if (LINUX) set(CUSTOM_PCI_IDS_PATH "" CACHE STRING "Custom path to file pci.ids, defaults to `/usr/share/hwdata/pci.ids`") set(CUSTOM_AMDGPU_IDS_PATH "" CACHE STRING "Custom path to file amdgpu.ids, defaults to `/usr/share/libdrm/amdgpu.ids`") + set(CUSTOM_OS_RELEASE_PATH "" CACHE STRING "Custom path to file os-release, defaults to `/etc/os-release`") endif() #################### @@ -789,6 +790,10 @@ if(NOT "${CUSTOM_AMDGPU_IDS_PATH}" STREQUAL "") message(STATUS "Custom file path of amdgpu.ids: ${CUSTOM_AMDGPU_IDS_PATH}") target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_AMDGPU_IDS_PATH=${CUSTOM_AMDGPU_IDS_PATH}) endif() +if(NOT "${CUSTOM_OS_RELEASE_PATH}" STREQUAL "") + message(STATUS "Custom file path of os_release: ${CUSTOM_OS_RELEASE_PATH}") + target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_OS_RELEASE_PATH=${CUSTOM_OS_RELEASE_PATH}) +endif() function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME) if(NOT ENABLE_${VARNAME}) @@ -1153,7 +1158,15 @@ if(LINUX) set(CPACK_DEBIAN_PACKAGE_SECTION, "utils") set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") - set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6") + + if(NOT IS_MUSL) + EXECUTE_PROCESS ( + COMMAND getconf GNU_LIBC_VERSION + OUTPUT_VARIABLE GLIBC_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + STRING (REPLACE "glibc " "" GLIBC_VERSION ${GLIBC_VERSION}) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= ${GLIBC_VERSION})") + endif() endif() find_program(HAVE_RPMBUILD "rpmbuild") diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md deleted file mode 100644 index ae4668a78..000000000 --- a/DEVELOPMENT.md +++ /dev/null @@ -1,34 +0,0 @@ -# Development help - -This file is not an official documentation! -Here i just add things that are easy to forget. - -## Features i am planning to implement - -### Specific - -- [ ] Split the project in different libs / executables, all linking static by default: - - `libffdetect`: contains all the detection stuff. To be used by anything that needs system information - - `libffprint`: contains the printing functions, logos, format etc - - `fastfetch` and `flashfetch`: Executables, that initialize the config of libffprint. Fist one at runtime, second one at compile time -- [ ] Make LocalIP module more configurable -- [ ] Automatic migrate old config files to newer versions -- [ ] ZSH completions -- [ ] Fish completions -- [ ] Make CPU usage detection much faster and more accurate -- [ ] Detect CPU usage in a common detection method and expose it both to the cpuUsage module and the cpu format string -- [ ] Per session caching - -### General -- More presets -- More logos -- More package managers -- More DE detections -- More WM theme detections -- More terminal font detections -- Performance optimizations -- More module specific options -- Better error handling, especially the messages shown when using --show-errors -- Using package managers libraries for package count detection instead own. E.g. using libalpm instead of counting files in /var/lib/pacman/local -- Better documentation (especially default config file and the various --help options. Colored output?) -- General feature parity with neofetch, to demonstrate supremity of c diff --git a/README.md b/README.md index cc1cc5281..f2087551d 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/ Some distros packaged an outdated fastfetch version. Older version is not supported, please always ensure that the latest version is used. * Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (for Ubuntu 22.04 or newer) -* Debian / Ubuntu: Download `fastfetch-linux-.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and `dpkg -i fastfetch-linux-.deb` (for Ubuntu 20.04 or newer and Debian 11 or newer). +* Debian / Ubuntu: Download `fastfetch-linux-.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer). * Arch Linux: `sudo pacman -S fastfetch` * Fedora: `sudo dnf install fastfetch` * Gentoo: `sudo emerge --ask app-misc/fastfetch` diff --git a/doc/json_schema.json b/doc/json_schema.json index e9ea50c26..65d80d8aa 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -294,10 +294,6 @@ "type": "string", "description": "The name of the player to use for module Media and Player. Linux only" }, - "osFile": { - "type": "string", - "description": "Set the path to the file containing OS information. Linux only" - }, "dsForceDrm": { "description": "Force display detection to use DRM. Linux only", "oneOf": [ diff --git a/presets/examples/5.jsonc b/presets/examples/5.jsonc index d8545dd77..064d70be3 100644 --- a/presets/examples/5.jsonc +++ b/presets/examples/5.jsonc @@ -9,8 +9,7 @@ "modules": [ { "type": "theme", - "key": "T", - "format": "{7}" + "key": "T" }, { "type": "icons", diff --git a/presets/neofetch.jsonc b/presets/neofetch.jsonc index b7bbaac47..3b731347c 100644 --- a/presets/neofetch.jsonc +++ b/presets/neofetch.jsonc @@ -1,16 +1,16 @@ { "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + "display": { + "size": { + "maxPrefix": "MB", + "ndigits": 0 + } + }, "modules": [ "title", "separator", - { - "type": "os", - "format": "{3} {12}" - }, - { - "type": "host", - "format": "{/2}{-}{/}{2}{?3} {3}{?}" - }, + "os", + "host", "kernel", "uptime", "packages", @@ -23,10 +23,7 @@ "de", "wm", "wmtheme", - { - "type": "theme", - "format": "{?1}{1}{?3} {3}{?} [Plasma], {?}{7}" - }, + "theme", "icons", "terminal", { diff --git a/src/common/commandoption.c b/src/common/commandoption.c index e05cdbf92..d1824d0fc 100644 --- a/src/common/commandoption.c +++ b/src/common/commandoption.c @@ -11,7 +11,7 @@ bool ffParseModuleOptions(const char* key, const char* value) { - if (!ffStrStartsWith(key, "--") || !isalpha(key[2])) return false; + if (!ffStrStartsWith(key, "--") || !ffCharIsEnglishAlphabet(key[2])) return false; for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(key[2]) - 'A']; *modules; ++modules) { @@ -102,7 +102,7 @@ static void parseStructureCommand( } } - if(isalpha(line[0])) + if(ffCharIsEnglishAlphabet(line[0])) { for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(line[0]) - 'A']; *modules; ++modules) { diff --git a/src/common/jsonconfig.c b/src/common/jsonconfig.c index 3131cd750..de34b2b10 100644 --- a/src/common/jsonconfig.c +++ b/src/common/jsonconfig.c @@ -94,7 +94,7 @@ static inline void genJsonResult(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal, yyjson_mut_doc* jsonDoc) { - if(!isalpha(type[0])) return false; + if(!ffCharIsEnglishAlphabet(type[0])) return false; for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(type[0]) - 'A']; *modules; ++modules) { diff --git a/src/data/help_color.txt b/src/data/help_color.txt index a28d89eb6..a05ef5d7c 100644 --- a/src/data/help_color.txt +++ b/src/data/help_color.txt @@ -3,7 +3,8 @@ Usage: fastfetch --color must be a color encoding as ANSI escape sequences. It is inserted between "ESC[" and "m". Infos about them can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters. Examples: - --color 35: sets the color to magenta. `--color magenta` is also supported - --color 4;92: sets the color to bright Green with underline - --color 5;104: blinking text on a blue background + --color 35: sets the color to magenta. `--color magenta` is also supported + --color 38;5;38: sets the color to 38th color of ANSI 256 colors + --color 4;92: sets the color to bright Green with underline + --color 5;104: blinking text on a blue background If no color is set, the main color of the logo will be used. diff --git a/src/detection/camera/camera_apple.m b/src/detection/camera/camera_apple.m index a3da90540..66e18a7d6 100644 --- a/src/detection/camera/camera_apple.m +++ b/src/detection/camera/camera_apple.m @@ -3,10 +3,27 @@ #import +// warning: 'AVCaptureDeviceTypeExternalUnknown' is deprecated +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + const char* ffDetectCamera(FFlist* result) { FF_SUPPRESS_IO(); // #822 - AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera, AVCaptureDeviceTypeExternalUnknown] + + AVCaptureDeviceType deviceType; + + #ifdef MAC_OS_VERSION_14_0 + if (@available(macOS 14.0, *)) + { + deviceType = AVCaptureDeviceTypeExternal; + } + else + #endif + { + deviceType = AVCaptureDeviceTypeExternalUnknown; + } + + AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera, deviceType] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified]; if (!session) diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index 9d0ad5185..2e8d3bc92 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -2,11 +2,15 @@ #include "common/properties.h" #include "common/parsing.h" #include "common/io/io.h" +#include "common/processing.h" #include "util/stringUtils.h" #include #include +#define FF_STR_INDIR(x) #x +#define FF_STR(x) FF_STR_INDIR(x) + static inline bool allRelevantValuesSet(const FFOSResult* result) { return result->id.length > 0 @@ -139,14 +143,46 @@ static void getDebianVersion(FFOSResult* result) ffStrbufSet(&result->versionID, &debianVersion); } +static bool detectDebianDerived(FFOSResult* result) +{ + if (ffStrbufStartsWithS(&result->prettyName, "Armbian ")) // Armbian 24.2.1 bookworm + { + ffStrbufSetS(&result->name, "Armbian"); + ffStrbufSetS(&result->id, "armbian"); + ffStrbufSetS(&result->idLike, "debian"); + ffStrbufClear(&result->versionID); + uint32_t versionStart = ffStrbufFirstIndexC(&result->prettyName, ' ') + 1; + uint32_t versionEnd = ffStrbufNextIndexC(&result->prettyName, versionStart, ' '); + ffStrbufSetNS(&result->versionID, versionEnd - versionStart, result->prettyName.chars + versionStart); + return true; + } + else if (ffPathExists("/usr/bin/pveversion", FF_PATHTYPE_FILE)) + { + ffStrbufSetS(&result->id, "pve"); + ffStrbufSetS(&result->idLike, "debian"); + ffStrbufSetS(&result->name, "Proxmox VE"); + ffStrbufClear(&result->versionID); + if (ffProcessAppendStdOut(&result->versionID, (char* const[]) { + "/usr/bin/pveversion", + NULL, + }) == NULL) // pve-manager/8.2.2/9355359cd7afbae4 (running kernel: 6.8.4-2-pve) + { + ffStrbufSubstrBeforeLastC(&result->versionID, '/'); + ffStrbufSubstrAfterFirstC(&result->versionID, '/'); + } + ffStrbufSetF(&result->prettyName, "Proxmox VE %s", result->versionID.chars); + return true; + } + return false; +} + static void detectOS(FFOSResult* os) { - if(instance.config.general.osFile.length > 0) - { - parseLsbRelease(instance.config.general.osFile.chars, os); - parseOsRelease(instance.config.general.osFile.chars, os); - return; - } + #ifdef FF_CUSTOM_OS_RELEASE_PATH + parseOsRelease(FF_STR(FF_CUSTOM_OS_RELEASE_PATH), os); + parseLsbRelease(FF_STR(FF_CUSTOM_OS_RELEASE_PATH), os); + return; + #endif if(instance.config.general.escapeBedrock && parseOsRelease(FASTFETCH_TARGET_DIR_ROOT "/bedrock" FASTFETCH_TARGET_DIR_ETC "/bedrock-release", os)) { @@ -193,5 +229,8 @@ void ffDetectOSImpl(FFOSResult* os) if(ffStrbufIgnCaseEqualS(&os->id, "ubuntu")) getUbuntuFlavour(os); else if(ffStrbufIgnCaseEqualS(&os->id, "debian")) - getDebianVersion(os); + { + if (!detectDebianDerived(os)) + getDebianVersion(os); + } } diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 58c551e20..b2ad822dd 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -519,6 +519,11 @@ static void setTerminalInfoDetails(FFTerminalResult* result) else if(ffStrbufEqualS(&result->processName, "iTerm.app") || ffStrbufStartsWithS(&result->processName, "iTermServer-")) ffStrbufInitStatic(&result->prettyName, "iTerm"); + else if(ffStrbufEndsWithS(&result->exePath, "Terminal.app/Contents/MacOS/Terminal")) + { + ffStrbufSetStatic(&result->processName, "Apple_Terminal"); // for terminal font detection + ffStrbufInitStatic(&result->prettyName, "Apple Terminal"); + } else if(ffStrbufEqualS(&result->processName, "Apple_Terminal")) ffStrbufInitStatic(&result->prettyName, "Apple Terminal"); else if(ffStrbufEqualS(&result->processName, "WarpTerminal")) diff --git a/src/fastfetch.c b/src/fastfetch.c index 629c4dad0..a57b0a3f4 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -249,7 +249,7 @@ static void printCommandHelp(const char* command) puts(FASTFETCH_DATATEXT_HELP_COLOR); else if(ffStrEqualsIgnCase(command, "format")) puts(FASTFETCH_DATATEXT_HELP_FORMAT); - else if(isalpha(command[0]) && ffStrEndsWithIgnCase(command, "-format")) // -format + else if(ffCharIsEnglishAlphabet(command[0]) && ffStrEndsWithIgnCase(command, "-format")) // -format printCommandFormatHelp(command); else if(!printSpecificCommandHelp(command)) fprintf(stderr, "Error: No specific help for command '%s' provided\n", command); @@ -863,6 +863,7 @@ static void writeConfigFile(FFdata* data, const FFstrbuf* filename) int main(int argc, char** argv) { ffInitInstance(); + atexit(ffDestroyInstance); //Data stores things only needed for the configuration of fastfetch FFdata data = { @@ -888,6 +889,4 @@ int main(int argc, char** argv) ffStrbufDestroy(&customValue->value); } ffListDestroy(&data.customValues); - - ffDestroyInstance(); } diff --git a/src/logo/ascii/armbian.txt b/src/logo/ascii/armbian.txt new file mode 100644 index 000000000..d9699f3a3 --- /dev/null +++ b/src/logo/ascii/armbian.txt @@ -0,0 +1,22 @@ + .. + `:]x**j-,' + .,+t***********z\<" + ?******************; + '*n` .'`^,;;,^`'. ,cc. + -<. .[l + // ^^ ^^ \\ + !^ $2^^$1 ": + 'tt}` $2!~]rj_$1 ")t/. + Itttt?' $2~~]rr]$1 `{tttt, + \tttttt!""I$2_]r($1"""~tttttt1 + '_tttttttttttt$2)f$1tttttttttttti. + \*ztttttttttttttttttttttttttf**[ +l**c)tttttttttttttttttttttttt(z**, +.z*x.`tttttttttttttttttttttttt.`u*n +>` (tttttttttttttttttttttt] "I + ,tttttttttttttttttttttt` + ./ttttt$2f$1tttttttt$2f$1ttttt( + 'I)$2))(\()($1tt$2))|\()($1{;' + $2.~~~~~~~|)~~~~~~~<$1 + '$2[)))))1$1|($2)))))))$1? + $2",,," ",,,^ diff --git a/src/logo/ascii/armbian2.txt b/src/logo/ascii/armbian2.txt new file mode 100644 index 000000000..774e2b9b4 --- /dev/null +++ b/src/logo/ascii/armbian2.txt @@ -0,0 +1,14 @@ + █ █ █ █ █ █ █ █ █ █ █ + ███████████████████████ +▄▄██ ██▄▄ +▄▄██ ███████████ ██▄▄ +▄▄██ ██ ██ ██▄▄ +▄▄██ ██ ██ ██▄▄ +▄▄██ ██ ██ ██▄▄ +▄▄██ █████████████ ██▄▄ +▄▄██ ██ ██ ██▄▄ +▄▄██ ██ ██ ██▄▄ +▄▄██ ██ ██ ██▄▄ +▄▄██ ██▄▄ + ███████████████████████ + █ █ █ █ █ █ █ █ █ █ █ diff --git a/src/logo/ascii/ubuntu.txt b/src/logo/ascii/ubuntu.txt index 0947f04fc..6d93f5ca0 100644 --- a/src/logo/ascii/ubuntu.txt +++ b/src/logo/ascii/ubuntu.txt @@ -18,4 +18,3 @@ .:ooooooolc:. .ooooooooooo' .':loooooo; ,oooooooooc ..';::c' .;loooo:' - . \ No newline at end of file diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 3b0d2ab18..51474d34d 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -376,6 +376,24 @@ static const FFlogo A[] = { .colorKeys = FF_COLOR_FG_CYAN, .colorTitle = FF_COLOR_FG_CYAN, }, + // Armbian + { + .names = {"Armbian"}, + .lines = FASTFETCH_DATATEXT_LOGO_ARMBIAN, + .colors = { + FF_COLOR_FG_WHITE, + FF_COLOR_FG_RED, + }, + }, + // Armbian2 + { + .names = {"Armbian2"}, + .type = FF_LOGO_LINE_TYPE_ALTER_BIT, + .lines = FASTFETCH_DATATEXT_LOGO_ARMBIAN2, + .colors = { + FF_COLOR_FG_RED, + }, + }, // Artix { .names = {"artix", "artixlinux", "artix-linux"}, @@ -3336,7 +3354,7 @@ static const FFlogo P[] = { }, // Proxmox { - .names = {"proxmox"}, + .names = {"Proxmox", "pve"}, .lines = FASTFETCH_DATATEXT_LOGO_PROXMOX, .colors = { FF_COLOR_FG_WHITE, diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 8ae04408a..a64a3d5e5 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -842,6 +842,13 @@ static bool printImageIfExistsSlowPath(FFLogoType type, bool printError) bool ffLogoPrintImageIfExists(FFLogoType type, bool printError) { + if(instance.config.display.pipe) + { + if(printError) + fputs("Logo: Image logo is not supported in pipe mode\n", stderr); + return false; + } + if(!ffPathExists(instance.config.logo.source.chars, FF_PATHTYPE_FILE)) { if(printError) diff --git a/src/logo/logo.c b/src/logo/logo.c index d9af22a90..c78926339 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -61,7 +61,7 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(2048); - if (instance.config.display.brightColor) + if (!instance.config.display.pipe && instance.config.display.brightColor) ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_BOLT); ffStrbufAppendNC(&result, options->paddingTop, '\n'); @@ -70,7 +70,7 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) instance.state.logoHeight = options->paddingTop; //Use logoColor[0] as the default color - if(doColorReplacement) + if(doColorReplacement && !instance.config.display.pipe) ffStrbufAppendF(&result, "\e[%sm", options->colors[0].chars); while(*data != '\0') @@ -143,19 +143,27 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) continue; } - //Map the number to an array index, so that '1' -> 0, '2' -> 1, etc. - int index = ((int) *data) - 49; - - //If the index is valid, print the color. Otherwise continue as normal - if(index < 0 || index >= FASTFETCH_LOGO_MAX_COLORS) + if(!instance.config.display.pipe) { - ffStrbufAppendC(&result, '$'); - ++currentlineLength; - //Don't continue here, we want to print the current char as unicode + //Map the number to an array index, so that '1' -> 0, '2' -> 1, etc. + int index = ((int) *data) - 49; + + //If the index is valid, print the color. Otherwise continue as normal + if(index < 0 || index >= FASTFETCH_LOGO_MAX_COLORS) + { + ffStrbufAppendC(&result, '$'); + ++currentlineLength; + //Don't continue here, we want to print the current char as unicode + } + else + { + ffStrbufAppendF(&result, "\e[%sm", options->colors[index].chars); + ++data; + continue; + } } else { - ffStrbufAppendF(&result, "\e[%sm", options->colors[index].chars); ++data; continue; } @@ -188,7 +196,8 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) } } - ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET); + if(!instance.config.display.pipe) + ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET); if(!options->separate) { @@ -460,10 +469,10 @@ static void logoPrintKnownType(void) void ffLogoPrint(void) { - //In pipe mode, we don't have a logo or padding. + //When generate JSON result, we don't have a logo or padding. //We also don't need to set main color, because it won't be printed anyway. //So we can return quickly here. - if(instance.config.display.pipe || instance.state.resultDoc) + if(instance.state.resultDoc) { instance.state.logoHeight = 0; instance.state.logoWidth = 0; diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 872f91111..556d01e49 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -16,9 +16,6 @@ static inline uint8_t max(uint8_t a, uint8_t b) void ffPrintColors(FFColorsOptions* options) { - if(instance.config.display.pipe) - return; - bool flag = false; FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(128); @@ -28,7 +25,8 @@ void ffPrintColors(FFColorsOptions* options) // 3%d: Set the foreground color for(uint8_t i = options->block.range[0]; i <= min(options->block.range[1], 7); i++) { - ffStrbufAppendF(&result, "\e[3%dm", i); + if(!instance.config.display.pipe) + ffStrbufAppendF(&result, "\e[3%dm", i); for (uint8_t j = 0; j < options->block.width; j++) ffStrbufAppendS(&result, "█"); } @@ -40,7 +38,8 @@ void ffPrintColors(FFColorsOptions* options) if(options->paddingLeft > 0) ffPrintCharTimes(' ', options->paddingLeft); - ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET); + if(!instance.config.display.pipe) + ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET); ffStrbufPutTo(&result, stdout); ffStrbufClear(&result); } @@ -49,7 +48,8 @@ void ffPrintColors(FFColorsOptions* options) // 9%d: Set the foreground to the bright color for(uint8_t i = max(options->block.range[0], 8); i <= options->block.range[1]; i++) { - ffStrbufAppendF(&result, "\e[1;9%dm", i - 8); + if(!instance.config.display.pipe) + ffStrbufAppendF(&result, "\e[1;9%dm", i - 8); for (uint8_t j = 0; j < options->block.width; j++) ffStrbufAppendS(&result, "█"); } @@ -82,7 +82,8 @@ void ffPrintColors(FFColorsOptions* options) if(options->paddingLeft > 0) ffPrintCharTimes(' ', options->paddingLeft); - ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET); + if(!instance.config.display.pipe) + ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET); ffStrbufPutTo(&result, stdout); } diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index 81e5aa416..47a83f77e 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -8,7 +8,8 @@ void ffPrintCustom(FFCustomOptions* options) { ffPrintLogoAndKey(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&options->moduleArgs.outputFormat, stdout); - puts(FASTFETCH_TEXT_MODIFIER_RESET); + if(!instance.config.display.pipe) + puts(FASTFETCH_TEXT_MODIFIER_RESET); } bool ffParseCustomCommandOptions(FFCustomOptions* options, const char* key, const char* value) diff --git a/src/options/display.c b/src/options/display.c index f5683fc21..2ef919fc0 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -92,7 +92,7 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va } yyjson_val* ndigits = yyjson_obj_get(val, "ndigits"); - if (ndigits) options->percentNdigits = (uint8_t) yyjson_get_uint(ndigits); + if (ndigits) options->sizeNdigits = (uint8_t) yyjson_get_uint(ndigits); } else if (ffStrEqualsIgnCase(key, "temp")) { @@ -350,7 +350,7 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) ffStrbufInitStatic(&options->keyValueSeparator, ": "); options->showErrors = false; - options->pipe = !isatty(STDOUT_FILENO); + options->pipe = !isatty(STDOUT_FILENO) || !!getenv("NO_COLOR"); #ifdef NDEBUG options->disableLinewrap = !options->pipe; diff --git a/src/options/display.h b/src/options/display.h index a56a224e7..eb3a7c68c 100644 --- a/src/options/display.h +++ b/src/options/display.h @@ -27,7 +27,7 @@ typedef struct FFOptionsDisplay FFstrbuf keyValueSeparator; bool stat; - bool pipe; //disables logo and all escape sequences + bool pipe; //disables all escape sequences bool showErrors; bool disableLinewrap; bool hideCursor; diff --git a/src/options/general.c b/src/options/general.c index 7cec888f7..f27dce3e5 100644 --- a/src/options/general.c +++ b/src/options/general.c @@ -27,8 +27,6 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va options->escapeBedrock = yyjson_get_bool(val); else if (ffStrEqualsIgnCase(key, "playerName")) ffStrbufSetS(&options->playerName, yyjson_get_str(val)); - else if (ffStrEqualsIgnCase(key, "osFile")) - ffStrbufSetS(&options->osFile, yyjson_get_str(val)); else if (ffStrEqualsIgnCase(key, "dsForceDrm")) { if (yyjson_is_str(val)) @@ -79,8 +77,6 @@ bool ffOptionsParseGeneralCommandLine(FFOptionsGeneral* options, const char* key options->escapeBedrock = ffOptionParseBoolean(value); else if(ffStrEqualsIgnCase(key, "--player-name")) ffOptionParseString(key, value, &options->playerName); - else if (ffStrEqualsIgnCase(key, "--os-file")) - ffOptionParseString(key, value, &options->osFile); else if(ffStrEqualsIgnCase(key, "--ds-force-drm")) { if (ffOptionParseBoolean(value)) @@ -109,7 +105,6 @@ void ffOptionsInitGeneral(FFOptionsGeneral* options) #if defined(__linux__) || defined(__FreeBSD__) options->escapeBedrock = true; ffStrbufInit(&options->playerName); - ffStrbufInit(&options->osFile); options->dsForceDrm = FF_DS_FORCE_DRM_TYPE_FALSE; #elif defined(_WIN32) options->wmiTimeout = 5000; @@ -120,7 +115,6 @@ void ffOptionsDestroyGeneral(FF_MAYBE_UNUSED FFOptionsGeneral* options) { #if defined(__linux__) || defined(__FreeBSD__) ffStrbufDestroy(&options->playerName); - ffStrbufDestroy(&options->osFile); #endif } @@ -145,9 +139,6 @@ void ffOptionsGenerateGeneralJsonConfig(FFOptionsGeneral* options, yyjson_mut_do if (!ffStrbufEqual(&options->playerName, &defaultOptions.playerName)) yyjson_mut_obj_add_strbuf(doc, obj, "playerName", &options->playerName); - if (!ffStrbufEqual(&options->osFile, &defaultOptions.osFile)) - yyjson_mut_obj_add_strbuf(doc, obj, "osFile", &options->osFile); - if (options->dsForceDrm != defaultOptions.dsForceDrm) { switch (options->dsForceDrm) diff --git a/src/options/general.h b/src/options/general.h index 98667c2f8..0ab8ee5a7 100644 --- a/src/options/general.h +++ b/src/options/general.h @@ -17,7 +17,6 @@ typedef struct FFOptionsGeneral // Module options that cannot be put in module option structure #if defined(__linux__) || defined(__FreeBSD__) FFstrbuf playerName; - FFstrbuf osFile; bool escapeBedrock; FFDsForceDrmType dsForceDrm; #elif defined(_WIN32) diff --git a/src/util/stringUtils.h b/src/util/stringUtils.h index dd5d7e5ba..ad24057b5 100644 --- a/src/util/stringUtils.h +++ b/src/util/stringUtils.h @@ -69,3 +69,8 @@ static inline bool ffStrContainsC(const char* str, char compareTo) { return strchr(str, compareTo) != NULL; } + +static inline bool ffCharIsEnglishAlphabet(char c) +{ + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); +} diff --git a/src/util/textModifier.h b/src/util/textModifier.h index f282d31d5..3ff9db082 100644 --- a/src/util/textModifier.h +++ b/src/util/textModifier.h @@ -5,6 +5,6 @@ #define FASTFETCH_TEXT_MODIFIER_BOLT "\033[1m" #define FASTFETCH_TEXT_MODIFIER_ERROR "\033[1;31m" -#define FASTFETCH_TEXT_MODIFIER_RESET "\033[0m" +#define FASTFETCH_TEXT_MODIFIER_RESET "\033[m" #endif