fix: align topbar/sidebar so the top-right is not a dead hole
ci / tcc-check (push) Failing after 38s
ci / linux (aarch64, 0) (push) Skipped
ci / linux (x86, 1) (push) Skipped
ci / linux (x86_64, 1) (push) Skipped
ci / windows (push) Skipped

Topbar spans the full width; seat deck starts under it. Compact badge
and a seat chip on the right of the chrome. Hermit 1.0.2.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
WHC
2026-10-29 22:08:58 +08:00
co-authored by Cursor
parent f29c1000b6
commit 15c6c4a02a
2 changed files with 77 additions and 18 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
#define CST_VERSION_MAJOR 1
#define CST_VERSION_MINOR 0
#define CST_VERSION_PATCH 1
#define CST_VERSION_PATCH 2
#define CST_VERSION_STR_(x) #x
#define CST_VERSION_STR(x) CST_VERSION_STR_(x)
+76 -17
View File
@@ -2791,8 +2791,28 @@ static void draw_hermit_badge(WINDOW *win, int y, int x, const tui_t *t) {
return;
}
}
const char *b = hermit_mini_badge(st, t->spin, g_ascii);
draw_ansi_at(win, y, x, (int)strlen(b), b, CP_TOOL, 0, 0);
/* Compact topbar mark — avoid wide ║║ which reads as an orange slab. */
const char *b;
if (g_ascii) {
b = (st == HERMIT_ST_CODING) ? ">_" : "<>";
} else {
switch (st) {
case HERMIT_ST_QUESTION:
b = "◇?";
break;
case HERMIT_ST_ERROR:
b = "◇!";
break;
case HERMIT_ST_CODING:
b = ">_";
break;
default:
b = "◇";
break;
}
}
(void)t;
draw_ansi_at(win, y, x, 2, b, CP_TOOL, 0, 0);
}
static const char *const TIPS[] = {
@@ -2971,7 +2991,7 @@ static void draw_side(tui_t *t) {
char line[512];
int bottom = h - 3; /* where + version */
/* SEAT — local role + instance + short realm fp */
/* SEAT — role on one line; instance + realm indented under it */
draw_ansi_at(s, y++, x, mw, "seat", CP_SIDE_MUTED, 0, 0);
{
char sid[64] = {0};
@@ -2980,21 +3000,28 @@ static void draw_side(tui_t *t) {
const char *role = !sess ? "logged-out" : chair ? "chair" : "member";
int pair = !sess ? CP_SIDE_MUTED
: chair ? CP_SIDE_SUCCESS : CP_SIDE_PRIMARY;
int dx = x + draw_ansi_at(s, y, x, 2, seat_pulse_dot(t), pair, 0, 0);
snprintf(line, sizeof(line), "%s", role);
dx += draw_ansi_at(s, y, dx + 1, mw - (dx + 1 - x), line, pair, 1, 0);
int dx = x;
dx += draw_ansi_at(s, y, dx, 2, seat_pulse_dot(t), pair, 0, 0);
dx += draw_ansi_at(s, y, dx, 1, " ", pair, 0, 0);
draw_ansi_at(s, y, dx, mw - (dx - x), role, pair, 1, 0);
y++;
int ix = x + 2; /* align under role text, past the pulse */
int imw = mw - 2;
if (imw < 6) {
ix = x;
imw = mw;
}
if (!sid[0])
cst_parliament_default_instance(sid, sizeof(sid));
if (sid[0] && y < bottom) {
size_t fit = utf8_fit_cols(sid, strlen(sid), mw);
size_t fit = utf8_fit_cols(sid, strlen(sid), imw);
snprintf(line, sizeof(line), "%.*s", (int)fit, sid);
draw_ansi_at(s, y++, x, mw, line, CP_SIDE_MUTED, 0, 0);
draw_ansi_at(s, y++, ix, imw, line, CP_SIDE_MUTED, 0, 0);
}
char fp[9];
if (realm_fp_short(fp) == 0 && y < bottom) {
snprintf(line, sizeof(line), "realm %.8s", fp);
draw_ansi_at(s, y++, x, mw, line, CP_SIDE_MUTED, 0, 0);
draw_ansi_at(s, y++, ix, imw, line, CP_SIDE_MUTED, 0, 0);
}
}
y++;
@@ -3301,27 +3328,56 @@ static void draw_topbar(tui_t *t) {
if (hexish)
title = "New session";
}
/* Hermit badge + title + model. Role lives only in the Seat Deck. */
/* Badge + brand + title on the left; model then seat chip on the right. */
int x = 1;
draw_hermit_badge(w, 0, x, t);
x += 4;
x += 3;
x += draw_ansi_at(w, 0, x, 6, "Hermit", CP_TOPBAR_ACCENT, 1, 0);
x += draw_ansi_at(w, 0, x, 1, " ", CP_TOPBAR_MUTED, 0, 0);
int model_room = 0;
char seat_chip[48] = "";
int seat_w = 0;
{
char sid[64] = {0};
int sess = cst_parliament_session_ok(sid, sizeof(sid));
int chair = sess && cst_parliament_is_chair();
if (cst_parliament_is_active()) {
snprintf(seat_chip, sizeof(seat_chip), "%s %s",
seat_pulse_dot(t),
!sess ? "login" : chair ? "chair" : "member");
seat_w = utf8_cols(seat_chip, strlen(seat_chip)) + 2;
}
}
char mid[160] = "";
int model_room = 0;
if (cfg) {
snprintf(mid, sizeof(mid), "%.40s%s%.20s", cfg->model,
cfg->provider[0] ? " · " : "", cfg->provider);
model_room = utf8_cols(mid, strlen(mid)) + 2;
}
int title_max = bw - x - 1 - model_room;
int title_max = bw - x - 1 - model_room - seat_w;
if (title_max < 8)
title_max = 8;
size_t tfit = utf8_fit_cols(title, strlen(title), title_max);
snprintf(left, sizeof(left), "%.*s", (int)tfit, title);
x += draw_ansi_at(w, 0, x, bw - x, left, CP_TOPBAR, 1, 0);
if (mid[0] && x + 2 < bw)
draw_ansi_at(w, 0, x + 2, bw - (x + 2), mid, CP_TOPBAR_MUTED, 0, 0);
int right = bw - 1;
if (seat_chip[0]) {
int sw = utf8_cols(seat_chip, strlen(seat_chip));
int sx = right - sw;
if (sx > x + 2) {
int pair = strstr(seat_chip, "chair") ? CP_TOPBAR_ACCENT : CP_TOPBAR_MUTED;
draw_ansi_at(w, 0, sx, sw, seat_chip, pair, 0, 0);
right = sx - 2;
}
}
if (mid[0] && x + 2 < right) {
int mw = utf8_cols(mid, strlen(mid));
int mx = right - mw;
if (mx < x + 2)
mx = x + 2;
draw_ansi_at(w, 0, mx, right - mx + 1, mid, CP_TOPBAR_MUTED, 0, 0);
}
wrefresh(w);
}
@@ -3698,8 +3754,10 @@ static void layout(tui_t *t) {
t->todo_rows = 1 + (total < TODO_PANEL_MAX ? total : TODO_PANEL_MAX);
t->log_x = 1;
t->log_y = topbar;
/* Topbar spans the full width so the sidebar does not leave a dead
* hole next to "Hermit …" in the top-right corner. */
if (topbar)
t->header = tui_newwin(1, mw, 0, 0);
t->header = tui_newwin(1, t->cols, 0, 0);
int log_h = t->in_y - 1 - t->todo_rows - t->log_y;
if (log_h < 1) {
t->todo_rows = 0;
@@ -3709,8 +3767,9 @@ static void layout(tui_t *t) {
if (t->todo_rows)
t->todow = tui_newwin(t->todo_rows, mw - 2, t->log_y + log_h, 1);
t->status = tui_newwin(1, mw - 2, t->rows - 1, 1);
/* Sidebar starts under the topbar, aligned with the transcript. */
if (t->side_w)
t->side = tui_newwin(t->rows, t->side_w, 0, mw);
t->side = tui_newwin(t->rows - topbar, t->side_w, topbar, mw);
}
t->input = tui_newwin(t->in_h, t->in_w, t->in_y, t->in_x);
if (HAS_COLOR()) {