From 4d9d714bf43138c170ae9928f0a61a35f5b023ad Mon Sep 17 00:00:00 2001 From: sisev Date: Fri, 28 Aug 2026 16:34:56 +0200 Subject: [PATCH 1/4] added v_aligment and h_alignment option --- fetch.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/fetch.c b/fetch.c index c3a1052..cd37bee 100644 --- a/fetch.c +++ b/fetch.c @@ -33,6 +33,19 @@ static struct termios orig_termios; static int termios_saved = 0; +enum v_alignment +{ + V_ALIGN_TOP, + V_ALIGN_CENTER, + V_ALIGN_BOTTOM +}; +enum h_alignment +{ + H_ALIGN_LEFT, + H_ALIGN_CENTER, + H_ALIGN_RIGHT +}; + static void cleanup(void) { if (termios_saved) tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios); @@ -898,6 +911,8 @@ static char config_logo_inner[32] = ""; #define MAX_EXTRA_DISKS 8 static char extra_disks[MAX_EXTRA_DISKS][128]; static int extra_disk_count = 0; +static enum v_alignment config_v_alignment = V_ALIGN_TOP; +static enum h_alignment config_h_alignment = H_ALIGN_LEFT; // Light direction presets static float light_x = 0.4082f, light_y = 0.8165f, light_z = -0.4082f; @@ -1142,6 +1157,34 @@ static void load_config(void) { continue; } + if (strncmp(line, "v_alignment=", 12) == 0) { + char* val = line + 12; + strip_inline_hint(val); + if (strcmp(val, "top") == 0) { + config_v_alignment = V_ALIGN_TOP; + } + else if (strcmp(val, "center") == 0) { + config_v_alignment = V_ALIGN_CENTER; + } + else if (strcmp(val, "bottom") == 0) { + config_v_alignment = V_ALIGN_BOTTOM; + } + } + + if (strncmp(line, "h_alignment=", 12) == 0) { + char* val = line + 12; + strip_inline_hint(val); + if (strcmp(val, "left") == 0) { + config_h_alignment = H_ALIGN_LEFT; + } + else if (strcmp(val, "center") == 0) { + config_h_alignment = H_ALIGN_CENTER; + } + else if (strcmp(val, "right") == 0) { + config_h_alignment = H_ALIGN_RIGHT; + } + } + // Match field name for (int i = 0; field_map[i].name; i++) { if (strcasecmp(line, field_map[i].name) == 0) { @@ -3899,6 +3942,46 @@ static void set_distro_colors(const char *distro) { } } +void get_alignment_padding(int* vertical, int* horizontal) { + size_t max = 0; + for (int i = 0; i < fetch_line_count; i++) { + size_t len = visible_width(fetch_lines[i]); + if (len > max) { + max = len; + } + } + + int term_height; + int term_width; + get_term_size(&term_height, &term_width); + + switch (config_v_alignment) + { + default: + case V_ALIGN_TOP: + *vertical = 0; + break; + case V_ALIGN_CENTER: + *vertical = term_height / 2 - render_height / 2; + break; + case V_ALIGN_BOTTOM: + *vertical = term_height - (render_height); + } + + switch (config_h_alignment) + { + default: + case H_ALIGN_LEFT: + *horizontal = 0; + break; + case H_ALIGN_CENTER: + *horizontal = term_width / 2 - (anim_width + GAP + max) / 2; + break; + case H_ALIGN_RIGHT: + *horizontal= term_width - (anim_width + GAP + max); + } +} + int main(int argc, char **argv) { char distro[64] = ""; const char *logo_name = NULL; @@ -4395,10 +4478,14 @@ int main(int argc, char **argv) { } } + int top_padding; + int left_padding; + get_alignment_padding(&top_padding, &left_padding); + // Batch entire frame into a single write (reuse buffer across frames) static char *out_buf = NULL; static size_t out_cap = 0; - size_t need = (render_height + stacked_info_rows + 2) * 2048u + 64; + size_t need = (render_height + stacked_info_rows + 2) * (2048u + left_padding) + 64 + top_padding; if (need > out_cap) { free(out_buf); out_buf = malloc(need); @@ -4424,7 +4511,17 @@ int main(int argc, char **argv) { int inner_len = strlen(color_inner); int outer_len = strlen(color_outer); + if (top_padding > 0) { + memset(p, '\n', top_padding); + p += top_padding; + } + for (int i = 0; i < render_height && p + 8 < end; i++) { + if (left_padding > 0) { + memset(p, ' ', left_padding); + p += left_padding; + } + if (!use_color) { for (int j = 0; j < aw && p + 8 < end; j++) { int c = 0; From 78b894b10bd57c645910b6f0f8fad1fbe7fa91bb Mon Sep 17 00:00:00 2001 From: sisev Date: Fri, 28 Aug 2026 16:42:04 +0200 Subject: [PATCH 2/4] added new fields to README documentation --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 31ade7e..dac530e 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,8 @@ colors # size=1.0 (logo scale, e.g. 2.0 for double size) # depth=1.0 (3D extrusion depth, e.g. 3.0 for chunkier look) # height=36 (override render height in rows) +# v_alignment=top (top, center, bottom) +# h_alignment=left (left, center, right) ``` ## Options From b40a0dcf0a42a48ed89002e368c4efd0864bcb75 Mon Sep 17 00:00:00 2001 From: siseval <133139140+ost2@users.noreply.github.com> Date: Sat, 29 Aug 2026 17:52:31 +0200 Subject: [PATCH 3/4] fixed styling and cache terminal size --- fetch.c | 58 +++++++++++++++++++++++++++------------------------------ 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/fetch.c b/fetch.c index cd37bee..fd32bce 100644 --- a/fetch.c +++ b/fetch.c @@ -33,14 +33,12 @@ static struct termios orig_termios; static int termios_saved = 0; -enum v_alignment -{ +enum v_alignment { V_ALIGN_TOP, V_ALIGN_CENTER, V_ALIGN_BOTTOM }; -enum h_alignment -{ +enum h_alignment { H_ALIGN_LEFT, H_ALIGN_CENTER, H_ALIGN_RIGHT @@ -88,6 +86,8 @@ static int anim_width = ANIM_WIDTH; // canvas columns, shrinks on narrow termina static int layout_stacked = 0; // info below the logo instead of beside it static int info_clip_cols = -1; // clip info lines to this many visible columns static int stacked_info_rows = 0; // info lines shown in stacked layout +static int term_cols = 0; +static int term_rows = 0; #define PI 3.14159265f #ifndef FETCH_VERSION #define FETCH_VERSION "dev" @@ -1158,31 +1158,29 @@ static void load_config(void) { } if (strncmp(line, "v_alignment=", 12) == 0) { - char* val = line + 12; + char *val = line + 12; strip_inline_hint(val); if (strcmp(val, "top") == 0) { config_v_alignment = V_ALIGN_TOP; - } - else if (strcmp(val, "center") == 0) { + } else if (strcmp(val, "center") == 0) { config_v_alignment = V_ALIGN_CENTER; - } - else if (strcmp(val, "bottom") == 0) { + } else if (strcmp(val, "bottom") == 0) { config_v_alignment = V_ALIGN_BOTTOM; } + continue; } if (strncmp(line, "h_alignment=", 12) == 0) { - char* val = line + 12; + char *val = line + 12; strip_inline_hint(val); if (strcmp(val, "left") == 0) { config_h_alignment = H_ALIGN_LEFT; - } - else if (strcmp(val, "center") == 0) { + } else if (strcmp(val, "center") == 0) { config_h_alignment = H_ALIGN_CENTER; - } - else if (strcmp(val, "right") == 0) { + } else if (strcmp(val, "right") == 0) { config_h_alignment = H_ALIGN_RIGHT; } + continue; } // Match field name @@ -3942,43 +3940,39 @@ static void set_distro_colors(const char *distro) { } } -void get_alignment_padding(int* vertical, int* horizontal) { +static void get_alignment_padding(int* vertical, int* horizontal) { size_t max = 0; for (int i = 0; i < fetch_line_count; i++) { - size_t len = visible_width(fetch_lines[i]); - if (len > max) { - max = len; - } + size_t len = visible_width(fetch_lines[i]); + if (len > max) { + max = len; + } } - int term_height; - int term_width; - get_term_size(&term_height, &term_width); - - switch (config_v_alignment) - { + switch (config_v_alignment) { default: case V_ALIGN_TOP: *vertical = 0; break; case V_ALIGN_CENTER: - *vertical = term_height / 2 - render_height / 2; + *vertical = term_rows / 2 - render_height / 2; break; case V_ALIGN_BOTTOM: - *vertical = term_height - (render_height); + *vertical = term_rows - (render_height); + break; } - switch (config_h_alignment) - { + switch (config_h_alignment) { default: case H_ALIGN_LEFT: *horizontal = 0; break; case H_ALIGN_CENTER: - *horizontal = term_width / 2 - (anim_width + GAP + max) / 2; + *horizontal = term_cols / 2 - (anim_width + GAP + max) / 2; break; case H_ALIGN_RIGHT: - *horizontal= term_width - (anim_width + GAP + max); + *horizontal= term_cols - (anim_width + GAP + max); + break; } } @@ -4144,6 +4138,7 @@ int main(int argc, char **argv) { config_defaults(); load_config(); + get_term_size(&term_rows, &term_cols); // Shading: CLI flags, then config, then the ascii default if (!shading && config_shading[0]) @@ -4384,6 +4379,7 @@ int main(int argc, char **argv) { printf("\033[2J"); fflush(stdout); } + get_term_size(&term_rows, &term_cols); } // Refresh fast dynamic fields every ~1 second (20 frames). // Only uptime/memory/swap — they're pure /proc reads, no popen, From 0bdd814b92dacab9c3f5be94a4547238c0935b17 Mon Sep 17 00:00:00 2001 From: siseval <133139140+ost2@users.noreply.github.com> Date: Sat, 29 Aug 2026 18:13:29 +0200 Subject: [PATCH 4/4] used cached terminal size in apply_layout --- fetch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fetch.c b/fetch.c index fd32bce..a4e01b1 100644 --- a/fetch.c +++ b/fetch.c @@ -3595,8 +3595,8 @@ static const char *cell_glyph(int row, int col, int smax, int *color_out) { // shrink the canvas to keep the info intact; phone-width ones stack the // info below the logo. Info lines clip instead of wrapping. static void apply_layout(int show_info) { - int rows = 0, cols = 0; - get_term_size(&rows, &cols); + int rows = term_rows; + int cols = term_cols; if (rows > 1) rows--; // leave 1 row margin to prevent scroll-jitter @@ -4370,6 +4370,7 @@ int main(int argc, char **argv) { // Handle terminal resize: recompute the same layout as startup if (term_resized) { term_resized = 0; + get_term_size(&term_rows, &term_cols); int old_h = render_height, old_w = anim_width; int old_stacked = layout_stacked, old_clip = info_clip_cols; apply_layout(show_info); @@ -4379,7 +4380,6 @@ int main(int argc, char **argv) { printf("\033[2J"); fflush(stdout); } - get_term_size(&term_rows, &term_cols); } // Refresh fast dynamic fields every ~1 second (20 frames). // Only uptime/memory/swap — they're pure /proc reads, no popen,