From f34fb5042d40c186583f9e3009d8a1dd71d07d43 Mon Sep 17 00:00:00 2001 From: Doan Luu Duc Tai Date: Tue, 8 Sep 2026 14:46:47 -0500 Subject: Initial commit --- src/fetch.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 src/fetch.c (limited to 'src/fetch.c') diff --git a/src/fetch.c b/src/fetch.c new file mode 100644 index 0000000..270089e --- /dev/null +++ b/src/fetch.c @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * vfetch - neofetch but the ascii part is a video + * + * Copyright (C) 2026 Doan Luu Duc Tai + * + */ + +#include "fetch.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" + +static VfetchError try_fastfetch(AppState *state, const VfetchArgs *args) { + VfetchError err = + run_command_fork_output("fastfetch --logo none --pipe false", + &state->live_fetch_output, + args->debug); + if (err == VFETCH_SUCCESS) { + state->fetch_command = g_strdup("fastfetch --logo none --pipe false"); + if (!state->fetch_command) { + return VFETCH_ERROR_MEMORY_ALLOCATION; + } + } + + return err; +} + +static VfetchError try_neofetch(AppState *state, const VfetchArgs *args) { + log_verbose(state, + args->verbose, + args->debug, + "fastfetch failed, trying neofetch..."); + + VfetchError err = run_command_fork_output( + "neofetch --off", &state->live_fetch_output, args->debug); + if (err == VFETCH_SUCCESS) { + state->fetch_command = g_strdup("neofetch --off"); + if (!state->fetch_command) { + err = VFETCH_ERROR_MEMORY_ALLOCATION; + return err; + } + } + + return err; +} + +static VfetchError set_fetch_unavailable(void) { + (void)fputs("\nERROR: Neither 'fastfetch' nor 'neofetch' could be found in " + "your system's PATH.\n\n", + stderr); + (void)fputs(" Action Required:\n", stderr); + (void)fputs(" - Please install either 'fastfetch' or 'neofetch'.\n", + stderr); + (void)fputs(" - Alternatively, to disable the system information display, " + "use the '--fetch-tool none' flag.\n\n", + stderr); + + return VFETCH_ERROR_COMMAND_FAILED; +} + +static VfetchError fail_fetch_unavailable_override(const char *tool_name) { + (void)fprintf(stderr, + "\nERROR: The specified fetch tool ('%s') is not available in " + "your system's PATH.\n\n", + tool_name); + (void)fputs(" Action Required:\n", stderr); + (void)fputs( + " - Please install the tool or correct the --fetch-tool argument.\n", + stderr); + (void)fputs(" - To disable the system information display, use " + "'--fetch-tool none'.\n\n", + stderr); + + return VFETCH_ERROR_COMMAND_FAILED; +} + +static VfetchError handle_fetch_override(AppState *state, + const VfetchArgs *args) { + log_verbose(state, + args->verbose, + args->debug, + "User specified fetch tool: '%s'", + args->fetch_tool_arg); + + if (strcmp(args->fetch_tool_arg, "fastfetch") == 0) { + if (try_fastfetch(state, args) != VFETCH_SUCCESS) { + return fail_fetch_unavailable_override("fastfetch"); + } + } else if (strcmp(args->fetch_tool_arg, "neofetch") == 0) { + if (try_neofetch(state, args) != VFETCH_SUCCESS) { + return fail_fetch_unavailable_override("neofetch"); + } + } + + return VFETCH_SUCCESS; +} + +static VfetchError handle_fetch_fallback(AppState *state, + const VfetchArgs *args) { + log_verbose(state, + args->verbose, + args->debug, + "No fetch tool specified, using fallback logic."); + + if (try_fastfetch(state, args) == VFETCH_SUCCESS) { + return VFETCH_SUCCESS; + } + if (try_neofetch(state, args) == VFETCH_SUCCESS) { + return VFETCH_SUCCESS; + } + + return set_fetch_unavailable(); +} + +VfetchError initialize_fetch_utility(AppState *state, const VfetchArgs *args) { + log_verbose( + state, args->verbose, args->debug, "Initializing fetch utility..."); + + if (args->fetch_tool_arg) { + return handle_fetch_override(state, args); + } + + return handle_fetch_fallback(state, args); +} + +VfetchError start_fetch_thread(AppState *state, VfetchArgs *args) { + if (args->fetch_tool_arg && strcmp(args->fetch_tool_arg, "none") == 0) { + state->fetch_command = g_strdup("echo"); + state->live_fetch_output = g_strdup(""); + if (!state->fetch_command || !state->live_fetch_output) { + return VFETCH_ERROR_MEMORY_ALLOCATION; + } + return VFETCH_SUCCESS; + } + + if (!state->fetch_command) { + VfetchError err = initialize_fetch_utility(state, args); + if (err) { + return err; + } + } + + atomic_store_explicit(&state->last_fetch_lines, + count_lines(state->live_fetch_output), + memory_order_relaxed); + + return VFETCH_SUCCESS; +} + +#define K_DEFAULT_TERMINAL_WIDTH 80 +void render_fetch_panel(char *screen_buffer, + size_t screen_buffer_size, + size_t *current_len, + AppState *state, + const VfetchArgs *args) { + struct winsize window_size = {0}; + char *fetch_output_copy = NULL; + + size_t terminal_width = K_DEFAULT_TERMINAL_WIDTH; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &window_size) == 0 && + window_size.ws_col > 0) { + terminal_width = window_size.ws_col; + } + + (void)pthread_mutex_lock(&state->fetch_mutex); + if (state->live_fetch_output) { + fetch_output_copy = g_strdup(state->live_fetch_output); + } + size_t current_fetch_lines = + atomic_load_explicit(&state->last_fetch_lines, memory_order_relaxed); + size_t prev_fetch_lines = state->previous_fetch_lines; + state->previous_fetch_lines = current_fetch_lines; + (void)pthread_mutex_unlock(&state->fetch_mutex); + + uint32_t fetch_x = args->pad_x + args->width + 4; + size_t clear_width = terminal_width > fetch_x ? terminal_width - fetch_x : 0; + size_t lines_to_clear = (prev_fetch_lines > current_fetch_lines) + ? prev_fetch_lines + : current_fetch_lines; + if (lines_to_clear > 0 && clear_width > 0) { + Rect rect_to_clear = {.height = lines_to_clear, + .width = clear_width, + .start_x = fetch_x, + .start_y = args->pad_y}; + clear_rect_in_buffer( + screen_buffer, screen_buffer_size, current_len, &rect_to_clear); + } + + const char *fetch_output_to_draw = + fetch_output_copy ? fetch_output_copy : "..."; + append_block_to_buffer(screen_buffer, + screen_buffer_size, + current_len, + fetch_x, + args->pad_y, + fetch_output_to_draw, + strlen(fetch_output_to_draw)); + + g_free(fetch_output_copy); +} +#undef K_DEFAULT_TERMINAL_WIDTH -- cgit v1.2.3