Add option to show arrows for active pane indicator, GitHub issue 3022

from Marcel Partap.
pull/3079/head
nicm 2022-02-01 14:46:41 +00:00
parent 7a4ba6d4a5
commit 7e34645fcb
4 changed files with 86 additions and 20 deletions

View File

@ -64,6 +64,9 @@ static const char *options_table_cursor_style_list[] = {
static const char *options_table_pane_status_list[] = { static const char *options_table_pane_status_list[] = {
"off", "top", "bottom", NULL "off", "top", "bottom", NULL
}; };
static const char *options_table_pane_border_indicators_list[] = {
"off", "colour", "arrows", "both", NULL
};
static const char *options_table_pane_border_lines_list[] = { static const char *options_table_pane_border_lines_list[] = {
"single", "double", "heavy", "simple", "number", NULL "single", "double", "heavy", "simple", "number", NULL
}; };
@ -971,6 +974,15 @@ const struct options_table_entry options_table[] = {
.text = "Format of text in the pane status lines." .text = "Format of text in the pane status lines."
}, },
{ .name = "pane-border-indicators",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_WINDOW,
.choices = options_table_pane_border_indicators_list,
.default_num = PANE_BORDER_COLOUR,
.text = "Whether to indicate the active pane by colouring border or "
"displaying arrow markers."
},
{ .name = "pane-border-lines", { .name = "pane-border-lines",
.type = OPTIONS_TABLE_CHOICE, .type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_WINDOW, .scope = OPTIONS_TABLE_WINDOW,

View File

@ -34,11 +34,16 @@ static void screen_redraw_set_context(struct client *,
#define START_ISOLATE "\342\201\246" #define START_ISOLATE "\342\201\246"
#define END_ISOLATE "\342\201\251" #define END_ISOLATE "\342\201\251"
/* Border in relation to a pane. */
enum screen_redraw_border_type { enum screen_redraw_border_type {
SCREEN_REDRAW_OUTSIDE, SCREEN_REDRAW_OUTSIDE,
SCREEN_REDRAW_INSIDE, SCREEN_REDRAW_INSIDE,
SCREEN_REDRAW_BORDER SCREEN_REDRAW_BORDER_LEFT,
SCREEN_REDRAW_BORDER_RIGHT,
SCREEN_REDRAW_BORDER_TOP,
SCREEN_REDRAW_BORDER_BOTTOM
}; };
#define BORDER_MARKERS " +,.-"
/* Get cell border character. */ /* Get cell border character. */
static void static void
@ -102,64 +107,74 @@ static enum screen_redraw_border_type
screen_redraw_pane_border(struct window_pane *wp, u_int px, u_int py, screen_redraw_pane_border(struct window_pane *wp, u_int px, u_int py,
int pane_status) int pane_status)
{ {
u_int ex = wp->xoff + wp->sx, ey = wp->yoff + wp->sy; struct options *oo = wp->window->options;
int split = 0;
u_int ex = wp->xoff + wp->sx, ey = wp->yoff + wp->sy;
/* Inside pane. */ /* Inside pane. */
if (px >= wp->xoff && px < ex && py >= wp->yoff && py < ey) if (px >= wp->xoff && px < ex && py >= wp->yoff && py < ey)
return (SCREEN_REDRAW_INSIDE); return (SCREEN_REDRAW_INSIDE);
/* Get pane indicator. */
switch (options_get_number(oo, "pane-border-indicators")) {
case PANE_BORDER_COLOUR:
case PANE_BORDER_BOTH:
split = 1;
break;
}
/* Left/right borders. */ /* Left/right borders. */
if (pane_status == PANE_STATUS_OFF) { if (pane_status == PANE_STATUS_OFF) {
if (screen_redraw_two_panes(wp->window, 0)) { if (screen_redraw_two_panes(wp->window, 0) && split) {
if (wp->xoff == 0 && px == wp->sx && py <= wp->sy / 2) if (wp->xoff == 0 && px == wp->sx && py <= wp->sy / 2)
return (SCREEN_REDRAW_BORDER); return (SCREEN_REDRAW_BORDER_RIGHT);
if (wp->xoff != 0 && if (wp->xoff != 0 &&
px == wp->xoff - 1 && px == wp->xoff - 1 &&
py > wp->sy / 2) py > wp->sy / 2)
return (SCREEN_REDRAW_BORDER); return (SCREEN_REDRAW_BORDER_LEFT);
} else { } else {
if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= ey) { if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= ey) {
if (wp->xoff != 0 && px == wp->xoff - 1) if (wp->xoff != 0 && px == wp->xoff - 1)
return (SCREEN_REDRAW_BORDER); return (SCREEN_REDRAW_BORDER_LEFT);
if (px == ex) if (px == ex)
return (SCREEN_REDRAW_BORDER); return (SCREEN_REDRAW_BORDER_RIGHT);
} }
} }
} else { } else {
if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= ey) { if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= ey) {
if (wp->xoff != 0 && px == wp->xoff - 1) if (wp->xoff != 0 && px == wp->xoff - 1)
return (SCREEN_REDRAW_BORDER); return (SCREEN_REDRAW_BORDER_LEFT);
if (px == ex) if (px == ex)
return (SCREEN_REDRAW_BORDER); return (SCREEN_REDRAW_BORDER_RIGHT);
} }
} }
/* Top/bottom borders. */ /* Top/bottom borders. */
if (pane_status == PANE_STATUS_OFF) { if (pane_status == PANE_STATUS_OFF) {
if (screen_redraw_two_panes(wp->window, 1)) { if (screen_redraw_two_panes(wp->window, 1) && split) {
if (wp->yoff == 0 && py == wp->sy && px <= wp->sx / 2) if (wp->yoff == 0 && py == wp->sy && px <= wp->sx / 2)
return (SCREEN_REDRAW_BORDER); return (SCREEN_REDRAW_BORDER_BOTTOM);
if (wp->yoff != 0 && if (wp->yoff != 0 &&
py == wp->yoff - 1 && py == wp->yoff - 1 &&
px > wp->sx / 2) px > wp->sx / 2)
return (SCREEN_REDRAW_BORDER); return (SCREEN_REDRAW_BORDER_TOP);
} else { } else {
if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) { if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) {
if (wp->yoff != 0 && py == wp->yoff - 1) if (wp->yoff != 0 && py == wp->yoff - 1)
return (SCREEN_REDRAW_BORDER); return (SCREEN_REDRAW_BORDER_TOP);
if (py == ey) if (py == ey)
return (SCREEN_REDRAW_BORDER); return (SCREEN_REDRAW_BORDER_BOTTOM);
} }
} }
} else if (pane_status == PANE_STATUS_TOP) { } else if (pane_status == PANE_STATUS_TOP) {
if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) { if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) {
if (wp->yoff != 0 && py == wp->yoff - 1) if (wp->yoff != 0 && py == wp->yoff - 1)
return (SCREEN_REDRAW_BORDER); return (SCREEN_REDRAW_BORDER_TOP);
} }
} else { } else {
if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) { if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) {
if (py == ey) if (py == ey)
return (SCREEN_REDRAW_BORDER); return (SCREEN_REDRAW_BORDER_BOTTOM);
} }
} }
@ -189,10 +204,10 @@ screen_redraw_cell_border(struct client *c, u_int px, u_int py, int pane_status)
switch (screen_redraw_pane_border(wp, px, py, pane_status)) { switch (screen_redraw_pane_border(wp, px, py, pane_status)) {
case SCREEN_REDRAW_INSIDE: case SCREEN_REDRAW_INSIDE:
return (0); return (0);
case SCREEN_REDRAW_BORDER:
return (1);
case SCREEN_REDRAW_OUTSIDE: case SCREEN_REDRAW_OUTSIDE:
break; break;
default:
return (1);
} }
} }
@ -346,7 +361,7 @@ screen_redraw_check_is(u_int px, u_int py, int pane_status,
enum screen_redraw_border_type border; enum screen_redraw_border_type border;
border = screen_redraw_pane_border(wp, px, py, pane_status); border = screen_redraw_pane_border(wp, px, py, pane_status);
if (border == SCREEN_REDRAW_BORDER) if (border != SCREEN_REDRAW_INSIDE && border != SCREEN_REDRAW_OUTSIDE)
return (1); return (1);
return (0); return (0);
} }
@ -637,11 +652,12 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
struct options *oo = w->options; struct options *oo = w->options;
struct tty *tty = &c->tty; struct tty *tty = &c->tty;
struct format_tree *ft; struct format_tree *ft;
struct window_pane *wp; struct window_pane *wp, *active = server_client_get_pane(c);
struct grid_cell gc; struct grid_cell gc;
const struct grid_cell *tmp; const struct grid_cell *tmp;
struct overlay_ranges r; struct overlay_ranges r;
u_int cell_type, x = ctx->ox + i, y = ctx->oy + j; u_int cell_type, x = ctx->ox + i, y = ctx->oy + j;
int arrows = 0, border;
int pane_status = ctx->pane_status, isolates; int pane_status = ctx->pane_status, isolates;
if (c->overlay_check != NULL) { if (c->overlay_check != NULL) {
@ -689,6 +705,32 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
tty_cursor(tty, i, j); tty_cursor(tty, i, j);
if (isolates) if (isolates)
tty_puts(tty, END_ISOLATE); tty_puts(tty, END_ISOLATE);
switch (options_get_number(oo, "pane-border-indicators")) {
case PANE_BORDER_ARROWS:
case PANE_BORDER_BOTH:
arrows = 1;
break;
}
if (wp != NULL && arrows) {
border = screen_redraw_pane_border(active, x, y, pane_status);
if (((i == wp->xoff + 1 &&
(cell_type == CELL_LEFTRIGHT ||
(cell_type == CELL_TOPJOIN &&
border == SCREEN_REDRAW_BORDER_BOTTOM) ||
(cell_type == CELL_BOTTOMJOIN &&
border == SCREEN_REDRAW_BORDER_TOP))) ||
(j == wp->yoff + 1 &&
(cell_type == CELL_TOPBOTTOM ||
(cell_type == CELL_LEFTJOIN &&
border == SCREEN_REDRAW_BORDER_RIGHT) ||
(cell_type == CELL_RIGHTJOIN &&
border == SCREEN_REDRAW_BORDER_LEFT)))) &&
screen_redraw_check_is(x, y, pane_status, active))
utf8_set(&gc.data, BORDER_MARKERS[border]);
}
tty_cell(tty, &gc, &grid_default_cell, NULL); tty_cell(tty, &gc, &grid_default_cell, NULL);
if (isolates) if (isolates)
tty_puts(tty, START_ISOLATE); tty_puts(tty, START_ISOLATE);

6
tmux.1
View File

@ -4223,6 +4223,12 @@ but set the starting index for pane numbers.
.It Ic pane-border-format Ar format .It Ic pane-border-format Ar format
Set the text shown in pane border status lines. Set the text shown in pane border status lines.
.Pp .Pp
.It Xo Ic pane-border-indicators
.Op Ic off | colour | arrows | both
.Xc
Indicate active pane by colouring only half of the border in windows with
exactly two panes, by displaying arrow markers, by drawing both or neither.
.Pp
.It Ic pane-border-lines Ar type .It Ic pane-border-lines Ar type
Set the type of characters used for drawing pane borders. Set the type of characters used for drawing pane borders.
.Ar type .Ar type

6
tmux.h
View File

@ -842,6 +842,12 @@ enum pane_lines {
PANE_LINES_NUMBER PANE_LINES_NUMBER
}; };
/* Pane border indicator option. */
#define PANE_BORDER_OFF 0
#define PANE_BORDER_COLOUR 1
#define PANE_BORDER_ARROWS 2
#define PANE_BORDER_BOTH 3
/* Screen redraw context. */ /* Screen redraw context. */
struct screen_redraw_ctx { struct screen_redraw_ctx {
struct client *c; struct client *c;