mirror of
https://github.com/tmux/tmux.git
synced 2024-11-17 09:58:52 +00:00
Add a session, pane and user mouse range types for the status line and
add format variables for mouse_status_line and mouse_status_range so they can be associated with different commands in the key bindings. GitHub issue 3652.
This commit is contained in:
parent
d9942c769e
commit
8636848e63
12
cmd.c
12
cmd.c
@ -813,10 +813,14 @@ cmd_mouse_pane(struct mouse_event *m, struct session **sp,
|
||||
|
||||
if ((wl = cmd_mouse_window(m, sp)) == NULL)
|
||||
return (NULL);
|
||||
if ((wp = window_pane_find_by_id(m->wp)) == NULL)
|
||||
return (NULL);
|
||||
if (!window_has_pane(wl->window, wp))
|
||||
return (NULL);
|
||||
if (m->wp == -1)
|
||||
wp = wl->window->active;
|
||||
else {
|
||||
if ((wp = window_pane_find_by_id(m->wp)) == NULL)
|
||||
return (NULL);
|
||||
if (!window_has_pane(wl->window, wp))
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (wlp != NULL)
|
||||
*wlp = wl;
|
||||
|
@ -33,6 +33,7 @@ struct format_range {
|
||||
|
||||
enum style_range_type type;
|
||||
u_int argument;
|
||||
char string[16];
|
||||
|
||||
TAILQ_ENTRY(format_range) entry;
|
||||
};
|
||||
@ -44,9 +45,18 @@ format_is_type(struct format_range *fr, struct style *sy)
|
||||
{
|
||||
if (fr->type != sy->range_type)
|
||||
return (0);
|
||||
if (fr->type == STYLE_RANGE_WINDOW &&
|
||||
fr->argument != sy->range_argument)
|
||||
return (0);
|
||||
switch (fr->type) {
|
||||
case STYLE_RANGE_NONE:
|
||||
case STYLE_RANGE_LEFT:
|
||||
case STYLE_RANGE_RIGHT:
|
||||
return (1);
|
||||
case STYLE_RANGE_PANE:
|
||||
case STYLE_RANGE_WINDOW:
|
||||
case STYLE_RANGE_SESSION:
|
||||
return (fr->argument == sy->range_argument);
|
||||
case STYLE_RANGE_USER:
|
||||
return (strcmp(fr->string, sy->range_string) == 0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -942,6 +952,8 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
||||
|
||||
fr->type = sy.range_type;
|
||||
fr->argument = sy.range_argument;
|
||||
strlcpy(fr->string, sy.range_string,
|
||||
sizeof fr->string);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1013,13 +1025,39 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
||||
sr = xcalloc(1, sizeof *sr);
|
||||
sr->type = fr->type;
|
||||
sr->argument = fr->argument;
|
||||
strlcpy(sr->string, fr->string, sizeof sr->string);
|
||||
sr->start = fr->start;
|
||||
sr->end = fr->end;
|
||||
TAILQ_INSERT_TAIL(srs, sr, entry);
|
||||
|
||||
log_debug("%s: range %d|%u at %u-%u", __func__, sr->type,
|
||||
sr->argument, sr->start, sr->end);
|
||||
|
||||
switch (sr->type) {
|
||||
case STYLE_RANGE_NONE:
|
||||
break;
|
||||
case STYLE_RANGE_LEFT:
|
||||
log_debug("%s: range left at %u-%u", __func__,
|
||||
sr->start, sr->end);
|
||||
break;
|
||||
case STYLE_RANGE_RIGHT:
|
||||
log_debug("%s: range right at %u-%u", __func__,
|
||||
sr->start, sr->end);
|
||||
break;
|
||||
case STYLE_RANGE_PANE:
|
||||
log_debug("%s: range pane|%%%u at %u-%u", __func__,
|
||||
sr->argument, sr->start, sr->end);
|
||||
break;
|
||||
case STYLE_RANGE_WINDOW:
|
||||
log_debug("%s: range window|%u at %u-%u", __func__,
|
||||
sr->argument, sr->start, sr->end);
|
||||
break;
|
||||
case STYLE_RANGE_SESSION:
|
||||
log_debug("%s: range session|$%u at %u-%u", __func__,
|
||||
sr->argument, sr->start, sr->end);
|
||||
break;
|
||||
case STYLE_RANGE_USER:
|
||||
log_debug("%s: range user|%u at %u-%u", __func__,
|
||||
sr->argument, sr->start, sr->end);
|
||||
break;
|
||||
}
|
||||
format_free_range(&frs, fr);
|
||||
}
|
||||
|
||||
|
72
format.c
72
format.c
@ -1191,6 +1191,72 @@ format_cb_mouse_line(struct format_tree *ft)
|
||||
return (format_grid_line(gd, gd->hsize + y));
|
||||
}
|
||||
|
||||
/* Callback for mouse_status_line. */
|
||||
static void *
|
||||
format_cb_mouse_status_line(struct format_tree *ft)
|
||||
{
|
||||
char *value;
|
||||
u_int y;
|
||||
|
||||
if (!ft->m.valid)
|
||||
return (NULL);
|
||||
if (ft->c == NULL || (~ft->c->tty.flags & TTY_STARTED))
|
||||
return (NULL);
|
||||
|
||||
if (ft->m.statusat == 0 && ft->m.y < ft->m.statuslines) {
|
||||
y = ft->m.y;
|
||||
} else if (ft->m.statusat > 0 && ft->m.y >= (u_int)ft->m.statusat) {
|
||||
y = ft->m.y - ft->m.statusat;
|
||||
} else
|
||||
return (NULL);
|
||||
xasprintf(&value, "%u", y);
|
||||
return (value);
|
||||
|
||||
}
|
||||
|
||||
/* Callback for mouse_status_range. */
|
||||
static void *
|
||||
format_cb_mouse_status_range(struct format_tree *ft)
|
||||
{
|
||||
struct style_range *sr;
|
||||
u_int x, y;
|
||||
|
||||
if (!ft->m.valid)
|
||||
return (NULL);
|
||||
if (ft->c == NULL || (~ft->c->tty.flags & TTY_STARTED))
|
||||
return (NULL);
|
||||
|
||||
if (ft->m.statusat == 0 && ft->m.y < ft->m.statuslines) {
|
||||
x = ft->m.x;
|
||||
y = ft->m.y;
|
||||
} else if (ft->m.statusat > 0 && ft->m.y >= (u_int)ft->m.statusat) {
|
||||
x = ft->m.x;
|
||||
y = ft->m.y - ft->m.statusat;
|
||||
} else
|
||||
return (NULL);
|
||||
|
||||
sr = status_get_range(ft->c, x, y);
|
||||
if (sr == NULL)
|
||||
return (NULL);
|
||||
switch (sr->type) {
|
||||
case STYLE_RANGE_NONE:
|
||||
return (NULL);
|
||||
case STYLE_RANGE_LEFT:
|
||||
return (xstrdup("left"));
|
||||
case STYLE_RANGE_RIGHT:
|
||||
return (xstrdup("right"));
|
||||
case STYLE_RANGE_PANE:
|
||||
return (xstrdup("pane"));
|
||||
case STYLE_RANGE_WINDOW:
|
||||
return (xstrdup("window"));
|
||||
case STYLE_RANGE_SESSION:
|
||||
return (xstrdup("session"));
|
||||
case STYLE_RANGE_USER:
|
||||
return (xstrdup(sr->string));
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Callback for alternate_on. */
|
||||
static void *
|
||||
format_cb_alternate_on(struct format_tree *ft)
|
||||
@ -2848,6 +2914,12 @@ static const struct format_table_entry format_table[] = {
|
||||
{ "mouse_standard_flag", FORMAT_TABLE_STRING,
|
||||
format_cb_mouse_standard_flag
|
||||
},
|
||||
{ "mouse_status_line", FORMAT_TABLE_STRING,
|
||||
format_cb_mouse_status_line
|
||||
},
|
||||
{ "mouse_status_range", FORMAT_TABLE_STRING,
|
||||
format_cb_mouse_status_range
|
||||
},
|
||||
{ "mouse_utf8_flag", FORMAT_TABLE_STRING,
|
||||
format_cb_mouse_utf8_flag
|
||||
},
|
||||
|
@ -564,9 +564,9 @@ static key_code
|
||||
server_client_check_mouse(struct client *c, struct key_event *event)
|
||||
{
|
||||
struct mouse_event *m = &event->m;
|
||||
struct session *s = c->session;
|
||||
struct winlink *wl;
|
||||
struct window_pane *wp;
|
||||
struct session *s = c->session, *fs;
|
||||
struct winlink *fwl;
|
||||
struct window_pane *wp, *fwp;
|
||||
u_int x, y, b, sx, sy, px, py;
|
||||
int ignore = 0;
|
||||
key_code key;
|
||||
@ -672,6 +672,7 @@ have_event:
|
||||
/* Save the session. */
|
||||
m->s = s->id;
|
||||
m->w = -1;
|
||||
m->wp = -1;
|
||||
m->ignore = ignore;
|
||||
|
||||
/* Is this on the status line? */
|
||||
@ -688,18 +689,42 @@ have_event:
|
||||
case STYLE_RANGE_NONE:
|
||||
return (KEYC_UNKNOWN);
|
||||
case STYLE_RANGE_LEFT:
|
||||
log_debug("mouse range: left");
|
||||
where = STATUS_LEFT;
|
||||
break;
|
||||
case STYLE_RANGE_RIGHT:
|
||||
log_debug("mouse range: right");
|
||||
where = STATUS_RIGHT;
|
||||
break;
|
||||
case STYLE_RANGE_WINDOW:
|
||||
wl = winlink_find_by_index(&s->windows,
|
||||
sr->argument);
|
||||
if (wl == NULL)
|
||||
case STYLE_RANGE_PANE:
|
||||
fwp = window_pane_find_by_id(sr->argument);
|
||||
if (fwp == NULL)
|
||||
return (KEYC_UNKNOWN);
|
||||
m->w = wl->window->id;
|
||||
m->wp = sr->argument;
|
||||
|
||||
log_debug("mouse range: pane %%%u", m->wp);
|
||||
where = STATUS;
|
||||
break;
|
||||
case STYLE_RANGE_WINDOW:
|
||||
fwl = winlink_find_by_index(&s->windows,
|
||||
sr->argument);
|
||||
if (fwl == NULL)
|
||||
return (KEYC_UNKNOWN);
|
||||
m->w = fwl->window->id;
|
||||
|
||||
log_debug("mouse range: window @%u", m->w);
|
||||
where = STATUS;
|
||||
break;
|
||||
case STYLE_RANGE_SESSION:
|
||||
fs = session_find_by_id(sr->argument);
|
||||
if (fs == NULL)
|
||||
return (KEYC_UNKNOWN);
|
||||
m->s = sr->argument;
|
||||
|
||||
log_debug("mouse range: session $%u", m->s);
|
||||
where = STATUS;
|
||||
break;
|
||||
case STYLE_RANGE_USER:
|
||||
where = STATUS;
|
||||
break;
|
||||
}
|
||||
|
64
style.c
64
style.c
@ -37,11 +37,18 @@ static struct style style_default = {
|
||||
STYLE_ALIGN_DEFAULT,
|
||||
STYLE_LIST_OFF,
|
||||
|
||||
STYLE_RANGE_NONE, 0,
|
||||
STYLE_RANGE_NONE, 0, "",
|
||||
|
||||
STYLE_DEFAULT_BASE
|
||||
};
|
||||
|
||||
/* Set range string. */
|
||||
static void
|
||||
style_set_range_string(struct style *sy, const char *s)
|
||||
{
|
||||
strlcpy(sy->range_string, s, sizeof sy->range_string);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse an embedded style of the form "fg=colour,bg=colour,bright,...". Note
|
||||
* that this adds onto the given style, so it must have been initialized
|
||||
@ -104,32 +111,67 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
|
||||
} else if (strcasecmp(tmp, "norange") == 0) {
|
||||
sy->range_type = style_default.range_type;
|
||||
sy->range_argument = style_default.range_type;
|
||||
strlcpy(sy->range_string, style_default.range_string,
|
||||
sizeof sy->range_string);
|
||||
} else if (end > 6 && strncasecmp(tmp, "range=", 6) == 0) {
|
||||
found = strchr(tmp + 6, '|');
|
||||
if (found != NULL) {
|
||||
*found++ = '\0';
|
||||
if (*found == '\0')
|
||||
goto error;
|
||||
for (cp = found; *cp != '\0'; cp++) {
|
||||
if (!isdigit((u_char)*cp))
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (strcasecmp(tmp + 6, "left") == 0) {
|
||||
if (found != NULL)
|
||||
goto error;
|
||||
sy->range_type = STYLE_RANGE_LEFT;
|
||||
sy->range_argument = 0;
|
||||
style_set_range_string(sy, "");
|
||||
} else if (strcasecmp(tmp + 6, "right") == 0) {
|
||||
if (found != NULL)
|
||||
goto error;
|
||||
sy->range_type = STYLE_RANGE_RIGHT;
|
||||
sy->range_argument = 0;
|
||||
style_set_range_string(sy, "");
|
||||
} else if (strcasecmp(tmp + 6, "pane") == 0) {
|
||||
if (found == NULL)
|
||||
goto error;
|
||||
if (*found != '%' || found[1] == '\0')
|
||||
goto error;
|
||||
for (cp = found + 1; *cp != '\0'; cp++) {
|
||||
if (!isdigit((u_char)*cp))
|
||||
goto error;
|
||||
}
|
||||
sy->range_type = STYLE_RANGE_PANE;
|
||||
sy->range_argument = atoi(found + 1);
|
||||
style_set_range_string(sy, "");
|
||||
} else if (strcasecmp(tmp + 6, "window") == 0) {
|
||||
if (found == NULL)
|
||||
goto error;
|
||||
for (cp = found; *cp != '\0'; cp++) {
|
||||
if (!isdigit((u_char)*cp))
|
||||
goto error;
|
||||
}
|
||||
sy->range_type = STYLE_RANGE_WINDOW;
|
||||
sy->range_argument = atoi(found);
|
||||
style_set_range_string(sy, "");
|
||||
} else if (strcasecmp(tmp + 6, "session") == 0) {
|
||||
if (found == NULL)
|
||||
goto error;
|
||||
if (*found != '$' || found[1] == '\0')
|
||||
goto error;
|
||||
for (cp = found + 1; *cp != '\0'; cp++) {
|
||||
if (!isdigit((u_char)*cp))
|
||||
goto error;
|
||||
}
|
||||
sy->range_type = STYLE_RANGE_SESSION;
|
||||
sy->range_argument = atoi(found + 1);
|
||||
style_set_range_string(sy, "");
|
||||
} else if (strcasecmp(tmp + 6, "user") == 0) {
|
||||
if (found == NULL)
|
||||
goto error;
|
||||
sy->range_type = STYLE_RANGE_USER;
|
||||
sy->range_argument = 0;
|
||||
style_set_range_string(sy, found);
|
||||
}
|
||||
} else if (strcasecmp(tmp, "noalign") == 0)
|
||||
sy->align = style_default.align;
|
||||
@ -222,9 +264,19 @@ style_tostring(struct style *sy)
|
||||
tmp = "left";
|
||||
else if (sy->range_type == STYLE_RANGE_RIGHT)
|
||||
tmp = "right";
|
||||
else if (sy->range_type == STYLE_RANGE_WINDOW) {
|
||||
else if (sy->range_type == STYLE_RANGE_PANE) {
|
||||
snprintf(b, sizeof b, "pane|%%%u", sy->range_argument);
|
||||
tmp = b;
|
||||
} else if (sy->range_type == STYLE_RANGE_WINDOW) {
|
||||
snprintf(b, sizeof b, "window|%u", sy->range_argument);
|
||||
tmp = b;
|
||||
} else if (sy->range_type == STYLE_RANGE_SESSION) {
|
||||
snprintf(b, sizeof b, "session|$%u",
|
||||
sy->range_argument);
|
||||
tmp = b;
|
||||
} else if (sy->range_type == STYLE_RANGE_USER) {
|
||||
snprintf(b, sizeof b, "user|%s", sy->range_string);
|
||||
tmp = b;
|
||||
}
|
||||
off += xsnprintf(s + off, sizeof s - off, "%srange=%s", comma,
|
||||
tmp);
|
||||
|
46
tmux.1
46
tmux.1
@ -5443,6 +5443,8 @@ The following variables are available, where appropriate:
|
||||
.It Li "mouse_line" Ta "" Ta "Line under mouse, if any"
|
||||
.It Li "mouse_sgr_flag" Ta "" Ta "Pane mouse SGR flag"
|
||||
.It Li "mouse_standard_flag" Ta "" Ta "Pane mouse standard flag"
|
||||
.It Li "mouse_status_line" Ta "" Ta "Status line on which mouse event took place"
|
||||
.It Li "mouse_status_range" Ta "" Ta "Range type or argument of mouse event on status line"
|
||||
.It Li "mouse_utf8_flag" Ta "" Ta "Pane mouse UTF-8 flag"
|
||||
.It Li "mouse_word" Ta "" Ta "Word under mouse, if any"
|
||||
.It Li "mouse_x" Ta "" Ta "Mouse X position, if any"
|
||||
@ -5681,26 +5683,56 @@ Only one default may be pushed (each
|
||||
replaces the previous saved default).
|
||||
.It Xo Ic range=left ,
|
||||
.Ic range=right ,
|
||||
.Ic range=session|X ,
|
||||
.Ic range=window|X ,
|
||||
.Ic range=pane|X ,
|
||||
.Ic range=user|X ,
|
||||
.Ic norange
|
||||
.Xc
|
||||
Mark a range in the
|
||||
Mark a range for mouse events in the
|
||||
.Ic status-format
|
||||
option.
|
||||
When a mouse event occurs in the
|
||||
.Ic range=left
|
||||
and
|
||||
or
|
||||
.Ic range=right
|
||||
are the text used for the
|
||||
range, the
|
||||
.Ql StatusLeft
|
||||
and
|
||||
.Ql StatusRight
|
||||
mouse keys.
|
||||
key bindings are triggered.
|
||||
.Pp
|
||||
.Ic range=session|X ,
|
||||
.Ic range=window|X
|
||||
is the range for a window passed to the
|
||||
and
|
||||
.Ic range=pane|X
|
||||
are ranges for a session, window or pane.
|
||||
These trigger the
|
||||
.Ql Status
|
||||
mouse key, where
|
||||
mouse key with the target session, window or pane given by the
|
||||
.Ql X
|
||||
is a window index.
|
||||
argument.
|
||||
.Ql X
|
||||
is a session ID, window index in the current session or a pane ID.
|
||||
For these, the
|
||||
.Ic mouse_status_range
|
||||
format variable will be set to
|
||||
.Ql session ,
|
||||
.Ql window
|
||||
or
|
||||
.Ql pane .
|
||||
.Pp
|
||||
.Ic range=user|X
|
||||
is a user-defined range; it triggers the
|
||||
.Ql Status
|
||||
mouse key.
|
||||
The argument
|
||||
.Ql X
|
||||
will be available in the
|
||||
.Ic mouse_status_range
|
||||
format variable.
|
||||
.Ql X
|
||||
must be at most 15 bytes in length.
|
||||
.El
|
||||
.Pp
|
||||
Examples are:
|
||||
|
7
tmux.h
7
tmux.h
@ -795,11 +795,15 @@ enum style_range_type {
|
||||
STYLE_RANGE_NONE,
|
||||
STYLE_RANGE_LEFT,
|
||||
STYLE_RANGE_RIGHT,
|
||||
STYLE_RANGE_WINDOW
|
||||
STYLE_RANGE_PANE,
|
||||
STYLE_RANGE_WINDOW,
|
||||
STYLE_RANGE_SESSION,
|
||||
STYLE_RANGE_USER
|
||||
};
|
||||
struct style_range {
|
||||
enum style_range_type type;
|
||||
u_int argument;
|
||||
char string[16];
|
||||
|
||||
u_int start;
|
||||
u_int end; /* not included */
|
||||
@ -826,6 +830,7 @@ struct style {
|
||||
|
||||
enum style_range_type range_type;
|
||||
u_int range_argument;
|
||||
char range_string[16];
|
||||
|
||||
enum style_default_type default_type;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user