Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
99 changes: 96 additions & 3 deletions fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@
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);
Expand Down Expand Up @@ -75,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"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1142,6 +1157,32 @@ 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;
}
continue;
}

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;
}
continue;
}

// Match field name
for (int i = 0; field_map[i].name; i++) {
if (strcasecmp(line, field_map[i].name) == 0) {
Expand Down Expand Up @@ -3554,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

Expand Down Expand Up @@ -3899,6 +3940,42 @@ static void set_distro_colors(const char *distro) {
}
}

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;
}
}

switch (config_v_alignment) {
default:
case V_ALIGN_TOP:
*vertical = 0;
break;
case V_ALIGN_CENTER:
*vertical = term_rows / 2 - render_height / 2;
break;
case V_ALIGN_BOTTOM:
*vertical = term_rows - (render_height);
break;
}

switch (config_h_alignment) {
default:
case H_ALIGN_LEFT:
*horizontal = 0;
break;
case H_ALIGN_CENTER:
*horizontal = term_cols / 2 - (anim_width + GAP + max) / 2;
break;
case H_ALIGN_RIGHT:
*horizontal= term_cols - (anim_width + GAP + max);
break;
}
}

int main(int argc, char **argv) {
char distro[64] = "";
const char *logo_name = NULL;
Expand Down Expand Up @@ -4061,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])
Expand Down Expand Up @@ -4292,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);
Expand Down Expand Up @@ -4395,10 +4474,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);
Expand All @@ -4424,7 +4507,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;
Expand Down