mirror of
https://github.com/tmux/tmux.git
synced 2026-09-18 11:04:46 +00:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81f88f8517 | ||
|
|
4eafb27b89 | ||
|
|
4fc4644652 | ||
|
|
e7f414416f | ||
|
|
3b8e25fef4 | ||
|
|
64e83caf04 | ||
|
|
762e503978 | ||
|
|
c809aea278 | ||
|
|
1596f9c9f5 | ||
|
|
2f28d9a168 | ||
|
|
baac29debc | ||
|
|
2c4df765c5 | ||
|
|
2d9afa6348 | ||
|
|
bae5c14941 | ||
|
|
9cf8de099c | ||
|
|
f98aaf544d | ||
|
|
78afc24736 | ||
|
|
83e4534387 | ||
|
|
dabaae1534 | ||
|
|
cc87db74c7 | ||
|
|
aa1f0653e9 | ||
|
|
8771b6051f | ||
|
|
bbd4768bb6 |
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
@@ -63,7 +63,7 @@ tmux -vv -Ltest -f/dev/null new
|
|||||||
|
|
||||||
Or if you need your configuration:
|
Or if you need your configuration:
|
||||||
|
|
||||||
~~~bash
|
~~~base
|
||||||
tmux kill-server
|
tmux kill-server
|
||||||
tmux -vv new
|
tmux -vv new
|
||||||
~~~
|
~~~
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -7,8 +7,6 @@
|
|||||||
*~
|
*~
|
||||||
.deps/
|
.deps/
|
||||||
.dirstamp
|
.dirstamp
|
||||||
.serena/
|
|
||||||
AGENTS.md
|
|
||||||
Makefile
|
Makefile
|
||||||
Makefile.in
|
Makefile.in
|
||||||
aclocal.m4
|
aclocal.m4
|
||||||
|
|||||||
1
CHANGES
1
CHANGES
@@ -5,6 +5,7 @@ CHANGES FROM 3.6b TO 3.7
|
|||||||
the same escape sequence support). Floating panes are created with the
|
the same escape sequence support). Floating panes are created with the
|
||||||
new-pane command, bound to * by default.
|
new-pane command, bound to * by default.
|
||||||
|
|
||||||
|
This is an early release of this feature and they are relatively limited.
|
||||||
Currently floating panes can only be moved and resized using the mouse. The
|
Currently floating panes can only be moved and resized using the mouse. The
|
||||||
default second status line (if status-format is set to 2) has changed to show
|
default second status line (if status-format is set to 2) has changed to show
|
||||||
a list of panes. Many obvious features are not yet available for floating
|
a list of panes. Many obvious features are not yet available for floating
|
||||||
|
|||||||
@@ -184,8 +184,6 @@ dist_tmux_SOURCES = \
|
|||||||
paste.c \
|
paste.c \
|
||||||
popup.c \
|
popup.c \
|
||||||
proc.c \
|
proc.c \
|
||||||
prompt.c \
|
|
||||||
prompt-history.c \
|
|
||||||
regsub.c \
|
regsub.c \
|
||||||
resize.c \
|
resize.c \
|
||||||
screen-redraw.c \
|
screen-redraw.c \
|
||||||
@@ -211,14 +209,12 @@ dist_tmux_SOURCES = \
|
|||||||
tty.c \
|
tty.c \
|
||||||
utf8-combined.c \
|
utf8-combined.c \
|
||||||
utf8.c \
|
utf8.c \
|
||||||
window-border.c \
|
|
||||||
window-buffer.c \
|
window-buffer.c \
|
||||||
window-client.c \
|
window-client.c \
|
||||||
window-clock.c \
|
window-clock.c \
|
||||||
window-copy.c \
|
window-copy.c \
|
||||||
window-customize.c \
|
window-customize.c \
|
||||||
window-tree.c \
|
window-tree.c \
|
||||||
window-visible.c \
|
|
||||||
window.c \
|
window.c \
|
||||||
xmalloc.c \
|
xmalloc.c \
|
||||||
xmalloc.h
|
xmalloc.h
|
||||||
|
|||||||
@@ -998,7 +998,7 @@ args_string_percentage(const char *value, long long minval, long long maxval,
|
|||||||
copy = xstrdup(value);
|
copy = xstrdup(value);
|
||||||
copy[valuelen - 1] = '\0';
|
copy[valuelen - 1] = '\0';
|
||||||
|
|
||||||
ll = strtonum(copy, 0, 1000, &errstr);
|
ll = strtonum(copy, 0, 100, &errstr);
|
||||||
free(copy);
|
free(copy);
|
||||||
if (errstr != NULL) {
|
if (errstr != NULL) {
|
||||||
*cause = xstrdup(errstr);
|
*cause = xstrdup(errstr);
|
||||||
@@ -1066,7 +1066,7 @@ args_string_percentage_and_expand(const char *value, long long minval,
|
|||||||
copy[valuelen - 1] = '\0';
|
copy[valuelen - 1] = '\0';
|
||||||
|
|
||||||
f = format_single_from_target(item, copy);
|
f = format_single_from_target(item, copy);
|
||||||
ll = strtonum(f, 0, 1000, &errstr);
|
ll = strtonum(f, 0, 100, &errstr);
|
||||||
free(f);
|
free(f);
|
||||||
free(copy);
|
free(copy);
|
||||||
if (errstr != NULL) {
|
if (errstr != NULL) {
|
||||||
|
|||||||
2
cfg.c
2
cfg.c
@@ -56,7 +56,7 @@ cfg_done(__unused struct cmdq_item *item, __unused void *data)
|
|||||||
if (cfg_item != NULL)
|
if (cfg_item != NULL)
|
||||||
cmdq_continue(cfg_item);
|
cmdq_continue(cfg_item);
|
||||||
|
|
||||||
prompt_load_history();
|
status_prompt_load_history();
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
w->active = wp;
|
w->active = wp;
|
||||||
w->latest = tc;
|
w->latest = tc;
|
||||||
|
|
||||||
if (name == NULL) {
|
if (name != NULL) {
|
||||||
newname = default_window_name(w);
|
newname = default_window_name(w);
|
||||||
window_set_name(w, newname, WINDOW_NAME_FORBID);
|
window_set_name(w, newname, WINDOW_NAME_FORBID);
|
||||||
free(newname);
|
free(newname);
|
||||||
|
|||||||
@@ -318,7 +318,6 @@ cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
grid_clear_history(wp->base.grid);
|
grid_clear_history(wp->base.grid);
|
||||||
if (args_has(args, 'H'))
|
if (args_has(args, 'H'))
|
||||||
screen_reset_hyperlinks(wp->screen);
|
screen_reset_hyperlinks(wp->screen);
|
||||||
server_redraw_window(wp->window);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ const struct cmd_entry cmd_choose_tree_entry = {
|
|||||||
.name = "choose-tree",
|
.name = "choose-tree",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "F:f:GhK:kNO:rst:wyZ", 0, 1, cmd_choose_tree_args_parse },
|
.args = { "F:f:GK:NO:rst:wyZ", 0, 1, cmd_choose_tree_args_parse },
|
||||||
.usage = "[-GhkNrswZ] [-F format] [-f filter] [-K key-format] "
|
.usage = "[-GNrswZ] [-F format] [-f filter] [-K key-format] "
|
||||||
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
|
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
@@ -47,8 +47,8 @@ const struct cmd_entry cmd_choose_client_entry = {
|
|||||||
.name = "choose-client",
|
.name = "choose-client",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "F:f:hiK:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
|
.args = { "F:f:K:NO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
|
||||||
.usage = "[-hikNrZ] [-F format] [-f filter] [-K key-format] "
|
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
|
||||||
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
|
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
@@ -61,8 +61,8 @@ const struct cmd_entry cmd_choose_buffer_entry = {
|
|||||||
.name = "choose-buffer",
|
.name = "choose-buffer",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "F:f:K:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
|
.args = { "F:f:K:NO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
|
||||||
.usage = "[-kNrZ] [-F format] [-f filter] [-K key-format] "
|
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
|
||||||
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
|
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
@@ -75,8 +75,8 @@ const struct cmd_entry cmd_customize_mode_entry = {
|
|||||||
.name = "customize-mode",
|
.name = "customize-mode",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "F:f:kNt:yZ", 0, 0, NULL },
|
.args = { "F:f:Nt:yZ", 0, 0, NULL },
|
||||||
.usage = "[-kNZ] [-F format] [-f filter] " CMD_TARGET_PANE_USAGE,
|
.usage = "[-NZ] [-F format] [-f filter] " CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
|
|||||||
@@ -34,16 +34,16 @@ static enum args_parse_type cmd_command_prompt_args_parse(struct args *,
|
|||||||
static enum cmd_retval cmd_command_prompt_exec(struct cmd *,
|
static enum cmd_retval cmd_command_prompt_exec(struct cmd *,
|
||||||
struct cmdq_item *);
|
struct cmdq_item *);
|
||||||
|
|
||||||
static enum prompt_result cmd_command_prompt_callback(struct client *, void *,
|
static int cmd_command_prompt_callback(struct client *, void *,
|
||||||
const char *, enum prompt_key_result);
|
const char *, int);
|
||||||
static void cmd_command_prompt_free(void *);
|
static void cmd_command_prompt_free(void *);
|
||||||
|
|
||||||
const struct cmd_entry cmd_command_prompt_entry = {
|
const struct cmd_entry cmd_command_prompt_entry = {
|
||||||
.name = "command-prompt",
|
.name = "command-prompt",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "1CbeFiklI:NPp:t:T:", 0, 1, cmd_command_prompt_args_parse },
|
.args = { "1CbeFiklI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
|
||||||
.usage = "[-1CbeFiklNP] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
.usage = "[-1CbeFiklN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
||||||
" [-T prompt-type] [template]",
|
" [-T prompt-type] [template]",
|
||||||
|
|
||||||
.flags = CMD_CLIENT_TFLAG,
|
.flags = CMD_CLIENT_TFLAG,
|
||||||
@@ -62,8 +62,6 @@ struct cmd_command_prompt_cdata {
|
|||||||
int flags;
|
int flags;
|
||||||
enum prompt_type prompt_type;
|
enum prompt_type prompt_type;
|
||||||
|
|
||||||
struct window_pane *wp;
|
|
||||||
|
|
||||||
struct cmd_command_prompt_prompt *prompts;
|
struct cmd_command_prompt_prompt *prompts;
|
||||||
u_int count;
|
u_int count;
|
||||||
u_int current;
|
u_int current;
|
||||||
@@ -89,15 +87,10 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct cmd_command_prompt_cdata *cdata;
|
struct cmd_command_prompt_cdata *cdata;
|
||||||
char *tmp, *prompts, *prompt, *next_prompt;
|
char *tmp, *prompts, *prompt, *next_prompt;
|
||||||
char *inputs = NULL, *next_input;
|
char *inputs = NULL, *next_input;
|
||||||
struct window_pane *wp = target->wp;
|
|
||||||
u_int count = args_count(args);
|
u_int count = args_count(args);
|
||||||
int wait = !args_has(args, 'b'), space = 1;
|
int wait = !args_has(args, 'b'), space = 1;
|
||||||
int pane = args_has(args, 'P');
|
|
||||||
|
|
||||||
if (pane) {
|
if (tc->prompt_string != NULL)
|
||||||
if (wp == NULL || window_pane_has_prompt(wp))
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
} else if (tc->prompt != NULL)
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
if (args_has(args, 'i'))
|
if (args_has(args, 'i'))
|
||||||
wait = 0;
|
wait = 0;
|
||||||
@@ -105,8 +98,6 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cdata = xcalloc(1, sizeof *cdata);
|
cdata = xcalloc(1, sizeof *cdata);
|
||||||
if (wait)
|
if (wait)
|
||||||
cdata->item = item;
|
cdata->item = item;
|
||||||
if (pane)
|
|
||||||
cdata->wp = wp;
|
|
||||||
cdata->state = args_make_commands_prepare(self, item, 0, "%1", wait,
|
cdata->state = args_make_commands_prepare(self, item, 0, "%1", wait,
|
||||||
args_has(args, 'F'));
|
args_has(args, 'F'));
|
||||||
|
|
||||||
@@ -155,7 +146,7 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((type = args_get(args, 'T')) != NULL) {
|
if ((type = args_get(args, 'T')) != NULL) {
|
||||||
cdata->prompt_type = prompt_type(type);
|
cdata->prompt_type = status_prompt_type(type);
|
||||||
if (cdata->prompt_type == PROMPT_TYPE_INVALID) {
|
if (cdata->prompt_type == PROMPT_TYPE_INVALID) {
|
||||||
cmdq_error(item, "unknown type: %s", type);
|
cmdq_error(item, "unknown type: %s", type);
|
||||||
cmd_command_prompt_free(cdata);
|
cmd_command_prompt_free(cdata);
|
||||||
@@ -176,27 +167,18 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cdata->flags |= PROMPT_BSPACE_EXIT;
|
cdata->flags |= PROMPT_BSPACE_EXIT;
|
||||||
if (args_has(args, 'C'))
|
if (args_has(args, 'C'))
|
||||||
cdata->flags |= PROMPT_NOFREEZE;
|
cdata->flags |= PROMPT_NOFREEZE;
|
||||||
if (pane) {
|
status_prompt_set(tc, target, cdata->prompts[0].prompt,
|
||||||
cdata->flags |= PROMPT_ISPANE;
|
cdata->prompts[0].input, cmd_command_prompt_callback,
|
||||||
window_pane_set_prompt(wp, tc, target, cdata->prompts[0].prompt,
|
cmd_command_prompt_free, cdata, cdata->flags, cdata->prompt_type);
|
||||||
cdata->prompts[0].input, cmd_command_prompt_callback,
|
|
||||||
cmd_command_prompt_free, cdata, cdata->flags,
|
|
||||||
cdata->prompt_type);
|
|
||||||
} else {
|
|
||||||
status_prompt_set(tc, target, cdata->prompts[0].prompt,
|
|
||||||
cdata->prompts[0].input, cmd_command_prompt_callback,
|
|
||||||
cmd_command_prompt_free, cdata, cdata->flags,
|
|
||||||
cdata->prompt_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wait)
|
if (!wait)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
return (CMD_RETURN_WAIT);
|
return (CMD_RETURN_WAIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum prompt_result
|
static int
|
||||||
cmd_command_prompt_callback(struct client *c, void *data, const char *s,
|
cmd_command_prompt_callback(struct client *c, void *data, const char *s,
|
||||||
enum prompt_key_result key)
|
int done)
|
||||||
{
|
{
|
||||||
struct cmd_command_prompt_cdata *cdata = data;
|
struct cmd_command_prompt_cdata *cdata = data;
|
||||||
char *error;
|
char *error;
|
||||||
@@ -206,30 +188,26 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s,
|
|||||||
int argc = 0;
|
int argc = 0;
|
||||||
char **argv = NULL;
|
char **argv = NULL;
|
||||||
|
|
||||||
if (s == NULL || key == PROMPT_KEY_MOVE)
|
if (s == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (key == PROMPT_KEY_CLOSE) {
|
if (done) {
|
||||||
if (cdata->flags & PROMPT_INCREMENTAL)
|
if (cdata->flags & PROMPT_INCREMENTAL)
|
||||||
goto out;
|
goto out;
|
||||||
cmd_append_argv(&cdata->argc, &cdata->argv, s);
|
cmd_append_argv(&cdata->argc, &cdata->argv, s);
|
||||||
if (++cdata->current != cdata->count) {
|
if (++cdata->current != cdata->count) {
|
||||||
prompt = &cdata->prompts[cdata->current];
|
prompt = &cdata->prompts[cdata->current];
|
||||||
if (cdata->wp != NULL) {
|
status_prompt_update(c, prompt->prompt, prompt->input);
|
||||||
window_pane_update_prompt(cdata->wp,
|
return (1);
|
||||||
prompt->prompt, prompt->input);
|
|
||||||
} else
|
|
||||||
status_prompt_update(c, prompt->prompt,
|
|
||||||
prompt->input);
|
|
||||||
return (PROMPT_CONTINUE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
argc = cdata->argc;
|
argc = cdata->argc;
|
||||||
argv = cmd_copy_argv(cdata->argc, cdata->argv);
|
argv = cmd_copy_argv(cdata->argc, cdata->argv);
|
||||||
if (key != PROMPT_KEY_CLOSE)
|
if (!done)
|
||||||
cmd_append_argv(&argc, &argv, s);
|
cmd_append_argv(&argc, &argv, s);
|
||||||
else {
|
|
||||||
|
if (done) {
|
||||||
cmd_free_argv(cdata->argc, cdata->argv);
|
cmd_free_argv(cdata->argc, cdata->argv);
|
||||||
cdata->argc = argc;
|
cdata->argc = argc;
|
||||||
cdata->argv = cmd_copy_argv(argc, argv);
|
cdata->argv = cmd_copy_argv(argc, argv);
|
||||||
@@ -248,20 +226,13 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s,
|
|||||||
}
|
}
|
||||||
cmd_free_argv(argc, argv);
|
cmd_free_argv(argc, argv);
|
||||||
|
|
||||||
/*
|
if (c->prompt_inputcb != cmd_command_prompt_callback)
|
||||||
* An incremental prompt fires its callback on every edit but must stay
|
return (1);
|
||||||
* open for further typing; only an explicit close (handled above) ends
|
|
||||||
* it.
|
|
||||||
*/
|
|
||||||
if (cdata->flags & PROMPT_INCREMENTAL)
|
|
||||||
return (PROMPT_CONTINUE);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (item != NULL) {
|
if (item != NULL)
|
||||||
cdata->item = NULL;
|
|
||||||
cmdq_continue(item);
|
cmdq_continue(item);
|
||||||
}
|
return (0);
|
||||||
return (PROMPT_CLOSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -270,11 +241,6 @@ cmd_command_prompt_free(void *data)
|
|||||||
struct cmd_command_prompt_cdata *cdata = data;
|
struct cmd_command_prompt_cdata *cdata = data;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
if (cdata->item != NULL) {
|
|
||||||
cmdq_continue(cdata->item);
|
|
||||||
cdata->item = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < cdata->count; i++) {
|
for (i = 0; i < cdata->count; i++) {
|
||||||
free(cdata->prompts[i].prompt);
|
free(cdata->prompts[i].prompt);
|
||||||
free(cdata->prompts[i].input);
|
free(cdata->prompts[i].input);
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ static enum args_parse_type cmd_confirm_before_args_parse(struct args *,
|
|||||||
static enum cmd_retval cmd_confirm_before_exec(struct cmd *,
|
static enum cmd_retval cmd_confirm_before_exec(struct cmd *,
|
||||||
struct cmdq_item *);
|
struct cmdq_item *);
|
||||||
|
|
||||||
static enum prompt_result cmd_confirm_before_callback(struct client *, void *,
|
static int cmd_confirm_before_callback(struct client *, void *,
|
||||||
const char *, enum prompt_key_result);
|
const char *, int);
|
||||||
static void cmd_confirm_before_free(void *);
|
static void cmd_confirm_before_free(void *);
|
||||||
|
|
||||||
const struct cmd_entry cmd_confirm_before_entry = {
|
const struct cmd_entry cmd_confirm_before_entry = {
|
||||||
@@ -118,9 +118,9 @@ cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_WAIT);
|
return (CMD_RETURN_WAIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum prompt_result
|
static int
|
||||||
cmd_confirm_before_callback(struct client *c, void *data, const char *s,
|
cmd_confirm_before_callback(struct client *c, void *data, const char *s,
|
||||||
__unused enum prompt_key_result key)
|
__unused int done)
|
||||||
{
|
{
|
||||||
struct cmd_confirm_before_data *cdata = data;
|
struct cmd_confirm_before_data *cdata = data;
|
||||||
struct cmdq_item *item = cdata->item, *new_item;
|
struct cmdq_item *item = cdata->item, *new_item;
|
||||||
@@ -151,7 +151,7 @@ out:
|
|||||||
cmdq_get_client(item)->retval = retcode;
|
cmdq_get_client(item)->retval = retcode;
|
||||||
cmdq_continue(item);
|
cmdq_continue(item);
|
||||||
}
|
}
|
||||||
return (PROMPT_CLOSE);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -48,16 +48,6 @@ struct cmd_display_panes_data {
|
|||||||
struct args_command_state *state;
|
struct args_command_state *state;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cmd_display_panes_ctx {
|
|
||||||
struct client *c;
|
|
||||||
int ox;
|
|
||||||
int oy;
|
|
||||||
u_int sx;
|
|
||||||
u_int sy;
|
|
||||||
u_int statuslines;
|
|
||||||
int statustop;
|
|
||||||
};
|
|
||||||
|
|
||||||
static enum args_parse_type
|
static enum args_parse_type
|
||||||
cmd_display_panes_args_parse(__unused struct args *args, __unused u_int idx,
|
cmd_display_panes_args_parse(__unused struct args *args, __unused u_int idx,
|
||||||
__unused char **cause)
|
__unused char **cause)
|
||||||
@@ -66,7 +56,7 @@ cmd_display_panes_args_parse(__unused struct args *args, __unused u_int idx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_display_panes_put(struct cmd_display_panes_ctx *ctx,
|
cmd_display_panes_put(struct screen_redraw_ctx *ctx,
|
||||||
struct window_pane *wp, u_int cx, u_int cy, const char *buf, size_t len)
|
struct window_pane *wp, u_int cx, u_int cy, const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
struct client *c = ctx->c;
|
struct client *c = ctx->c;
|
||||||
@@ -75,7 +65,8 @@ cmd_display_panes_put(struct cmd_display_panes_ctx *ctx,
|
|||||||
struct visible_range *ri;
|
struct visible_range *ri;
|
||||||
u_int i, j;
|
u_int i, j;
|
||||||
|
|
||||||
r = window_visible_ranges(wp, ctx->ox + cx, ctx->oy + cy, len, NULL);
|
r = screen_redraw_get_visible_ranges(wp, ctx->ox + cx, ctx->oy + cy,
|
||||||
|
len, NULL);
|
||||||
for (i = 0; i < r->used; i++) {
|
for (i = 0; i < r->used; i++) {
|
||||||
ri = &r->ranges[i];
|
ri = &r->ranges[i];
|
||||||
for (j = ri->px; j < ri->px + ri->nx; j++) {
|
for (j = ri->px; j < ri->px + ri->nx; j++) {
|
||||||
@@ -86,43 +77,7 @@ cmd_display_panes_put(struct cmd_display_panes_ctx *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_display_panes_draw_format(struct cmd_display_panes_ctx *ctx,
|
cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
|
||||||
struct window_pane *wp, u_int xoff, u_int yoff, u_int sx,
|
|
||||||
const struct grid_cell *gc)
|
|
||||||
{
|
|
||||||
struct client *c = ctx->c;
|
|
||||||
struct tty *tty = &c->tty;
|
|
||||||
struct session *s = c->session;
|
|
||||||
struct screen *sc = wp->screen, screen;
|
|
||||||
struct screen_write_ctx sctx;
|
|
||||||
struct visible_ranges *r;
|
|
||||||
struct visible_range *ri;
|
|
||||||
const char *format;
|
|
||||||
char *expanded;
|
|
||||||
u_int i, px = ctx->ox + xoff;
|
|
||||||
|
|
||||||
format = options_get_string(s->options, "display-panes-format");
|
|
||||||
expanded = format_single(NULL, format, c, s, s->curw, wp);
|
|
||||||
|
|
||||||
screen_init(&screen, sx, 1, 0);
|
|
||||||
screen_write_start(&sctx, &screen);
|
|
||||||
screen_write_fast_copy(&sctx, sc, 0, sc->grid->hsize, sx, 1);
|
|
||||||
screen_write_cursormove(&sctx, 0, 0, 0);
|
|
||||||
format_draw(&sctx, gc, sx, expanded, NULL, 0);
|
|
||||||
screen_write_stop(&sctx);
|
|
||||||
free(expanded);
|
|
||||||
|
|
||||||
r = window_visible_ranges(wp, px, wp->yoff, sx, NULL);
|
|
||||||
for (i = 0; i < r->used; i++) {
|
|
||||||
ri = &r->ranges[i];
|
|
||||||
tty_draw_line(tty, &screen, ri->px - px, 0, ri->nx,
|
|
||||||
ri->px - ctx->ox, yoff, NULL);
|
|
||||||
}
|
|
||||||
screen_free(&screen);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_display_panes_draw_pane(struct cmd_display_panes_ctx *ctx,
|
|
||||||
struct window_pane *wp)
|
struct window_pane *wp)
|
||||||
{
|
{
|
||||||
struct client *c = ctx->c;
|
struct client *c = ctx->c;
|
||||||
@@ -133,10 +88,9 @@ cmd_display_panes_draw_pane(struct cmd_display_panes_ctx *ctx,
|
|||||||
struct grid_cell fgc, bgc;
|
struct grid_cell fgc, bgc;
|
||||||
u_int pane, idx, px, py, i, j, xoff, yoff, sx, sy;
|
u_int pane, idx, px, py, i, j, xoff, yoff, sx, sy;
|
||||||
u_int cx, cy;
|
u_int cx, cy;
|
||||||
const char *name;
|
int colour, active_colour;
|
||||||
struct format_tree *ft;
|
char buf[16], lbuf[16], rbuf[16], *ptr;
|
||||||
char buf[16], lbuf[16], *ptr;
|
size_t len, llen, rlen;
|
||||||
size_t len, llen;
|
|
||||||
|
|
||||||
if (wp->xoff + (int)wp->sx <= ctx->ox ||
|
if (wp->xoff + (int)wp->sx <= ctx->ox ||
|
||||||
wp->xoff >= ctx->ox + (int)ctx->sx ||
|
wp->xoff >= ctx->ox + (int)ctx->sx ||
|
||||||
@@ -192,24 +146,27 @@ cmd_display_panes_draw_pane(struct cmd_display_panes_ctx *ctx,
|
|||||||
|
|
||||||
if (sx < len)
|
if (sx < len)
|
||||||
return;
|
return;
|
||||||
if (w->active == wp)
|
colour = options_get_number(oo, "display-panes-colour");
|
||||||
name = "display-panes-active-colour";
|
active_colour = options_get_number(oo, "display-panes-active-colour");
|
||||||
else
|
|
||||||
name = "display-panes-colour";
|
|
||||||
ft = format_create_defaults(NULL, c, s, NULL, wp);
|
|
||||||
style_apply(&fgc, oo, name, ft);
|
|
||||||
format_free(ft);
|
|
||||||
|
|
||||||
|
memcpy(&fgc, &grid_default_cell, sizeof fgc);
|
||||||
memcpy(&bgc, &grid_default_cell, sizeof bgc);
|
memcpy(&bgc, &grid_default_cell, sizeof bgc);
|
||||||
bgc.bg = fgc.fg;
|
if (w->active == wp) {
|
||||||
|
fgc.fg = active_colour;
|
||||||
|
bgc.bg = active_colour;
|
||||||
|
} else {
|
||||||
|
fgc.fg = colour;
|
||||||
|
bgc.bg = colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
rlen = xsnprintf(rbuf, sizeof rbuf, "%ux%u", wp->sx, wp->sy);
|
||||||
if (pane > 9 && pane < 35)
|
if (pane > 9 && pane < 35)
|
||||||
llen = xsnprintf(lbuf, sizeof lbuf, "%c", 'a' + (pane - 10));
|
llen = xsnprintf(lbuf, sizeof lbuf, "%c", 'a' + (pane - 10));
|
||||||
else
|
else
|
||||||
llen = 0;
|
llen = 0;
|
||||||
|
|
||||||
if (sx < len * 6 || sy < 5) {
|
if (sx < len * 6 || sy < 5) {
|
||||||
tty_attributes(tty, &fgc, NULL);
|
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
|
||||||
if (sx >= len + llen + 1) {
|
if (sx >= len + llen + 1) {
|
||||||
len += llen + 1;
|
len += llen + 1;
|
||||||
cx = xoff + px - len / 2;
|
cx = xoff + px - len / 2;
|
||||||
@@ -230,7 +187,7 @@ cmd_display_panes_draw_pane(struct cmd_display_panes_ctx *ctx,
|
|||||||
px -= len * 3;
|
px -= len * 3;
|
||||||
py -= 2;
|
py -= 2;
|
||||||
|
|
||||||
tty_attributes(tty, &bgc, NULL);
|
tty_attributes(tty, &bgc, &grid_default_cell, NULL, NULL);
|
||||||
for (ptr = buf; *ptr != '\0'; ptr++) {
|
for (ptr = buf; *ptr != '\0'; ptr++) {
|
||||||
if (*ptr < '0' || *ptr > '9')
|
if (*ptr < '0' || *ptr > '9')
|
||||||
continue;
|
continue;
|
||||||
@@ -250,9 +207,13 @@ cmd_display_panes_draw_pane(struct cmd_display_panes_ctx *ctx,
|
|||||||
|
|
||||||
if (sy <= 6)
|
if (sy <= 6)
|
||||||
goto out;
|
goto out;
|
||||||
cmd_display_panes_draw_format(ctx, wp, xoff, yoff, sx, &fgc);
|
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
|
||||||
|
if (rlen != 0 && sx >= rlen) {
|
||||||
|
cx = xoff + sx - rlen;
|
||||||
|
cy = yoff;
|
||||||
|
cmd_display_panes_put(ctx, wp, cx, cy, rbuf, rlen);
|
||||||
|
}
|
||||||
if (llen != 0) {
|
if (llen != 0) {
|
||||||
tty_attributes(tty, &fgc, NULL);
|
|
||||||
cx = xoff + sx / 2 + len * 3 - llen - 1;
|
cx = xoff + sx / 2 + len * 3 - llen - 1;
|
||||||
cy = yoff + py + 5;
|
cy = yoff + py + 5;
|
||||||
cmd_display_panes_put(ctx, wp, cx, cy, lbuf, llen);
|
cmd_display_panes_put(ctx, wp, cx, cy, lbuf, llen);
|
||||||
@@ -263,30 +224,17 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_display_panes_draw(struct client *c, __unused void *data)
|
cmd_display_panes_draw(struct client *c, __unused void *data,
|
||||||
|
struct screen_redraw_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct session *s = c->session;
|
struct window *w = c->session->curw->window;
|
||||||
struct window *w = s->curw->window;
|
struct window_pane *wp;
|
||||||
struct window_pane *wp;
|
|
||||||
struct cmd_display_panes_ctx ctx;
|
|
||||||
u_int lines;
|
|
||||||
|
|
||||||
log_debug("%s: %s @%u", __func__, c->name, w->id);
|
log_debug("%s: %s @%u", __func__, c->name, w->id);
|
||||||
|
|
||||||
memset(&ctx, 0, sizeof ctx);
|
|
||||||
ctx.c = c;
|
|
||||||
tty_window_offset(&c->tty, &ctx.ox, &ctx.oy, &ctx.sx, &ctx.sy);
|
|
||||||
if (options_get_number(s->options, "status-position") == 0) {
|
|
||||||
lines = status_line_size(c);
|
|
||||||
if (c->message_string != NULL || c->prompt != NULL)
|
|
||||||
lines = (lines == 0 ? 1 : lines);
|
|
||||||
ctx.statuslines = lines;
|
|
||||||
ctx.statustop = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
if (window_pane_is_visible(wp))
|
if (window_pane_visible(wp))
|
||||||
cmd_display_panes_draw_pane(&ctx, wp);
|
cmd_display_panes_draw_pane(ctx, wp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
16
cmd-find.c
16
cmd-find.c
@@ -147,18 +147,6 @@ cmd_find_session_better(struct session *s, struct session *than, int flags)
|
|||||||
return (timercmp(&s->activity_time, &than->activity_time, >));
|
return (timercmp(&s->activity_time, &than->activity_time, >));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can this session be usefully targeted? */
|
|
||||||
static int
|
|
||||||
cmd_find_session_valid(struct session *s)
|
|
||||||
{
|
|
||||||
if (!session_alive(s) ||
|
|
||||||
s->curw == NULL ||
|
|
||||||
s->curw->window == NULL ||
|
|
||||||
s->curw->window->active == NULL)
|
|
||||||
return (0);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find best session from a list, or all if list is NULL. */
|
/* Find best session from a list, or all if list is NULL. */
|
||||||
static struct session *
|
static struct session *
|
||||||
cmd_find_best_session(struct session **slist, u_int ssize, int flags)
|
cmd_find_best_session(struct session **slist, u_int ssize, int flags)
|
||||||
@@ -171,15 +159,11 @@ cmd_find_best_session(struct session **slist, u_int ssize, int flags)
|
|||||||
s = NULL;
|
s = NULL;
|
||||||
if (slist != NULL) {
|
if (slist != NULL) {
|
||||||
for (i = 0; i < ssize; i++) {
|
for (i = 0; i < ssize; i++) {
|
||||||
if (!cmd_find_session_valid(slist[i]))
|
|
||||||
continue;
|
|
||||||
if (cmd_find_session_better(slist[i], s, flags))
|
if (cmd_find_session_better(slist[i], s, flags))
|
||||||
s = slist[i];
|
s = slist[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
RB_FOREACH(s_loop, sessions, &sessions) {
|
RB_FOREACH(s_loop, sessions, &sessions) {
|
||||||
if (!cmd_find_session_valid(s_loop))
|
|
||||||
continue;
|
|
||||||
if (cmd_find_session_better(s_loop, s, flags))
|
if (cmd_find_session_better(s_loop, s, flags))
|
||||||
s = s_loop;
|
s = s_loop;
|
||||||
}
|
}
|
||||||
|
|||||||
329
cmd-join-pane.c
329
cmd-join-pane.c
@@ -30,9 +30,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static enum cmd_retval cmd_join_pane_exec(struct cmd *, struct cmdq_item *);
|
static enum cmd_retval cmd_join_pane_exec(struct cmd *, struct cmdq_item *);
|
||||||
static enum cmd_retval cmd_join_pane_mouse_update(struct cmdq_item *);
|
|
||||||
static void cmd_join_pane_mouse_move(struct client *,
|
|
||||||
struct mouse_event *);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_join_pane_entry = {
|
const struct cmd_entry cmd_join_pane_entry = {
|
||||||
.name = "join-pane",
|
.name = "join-pane",
|
||||||
@@ -52,10 +49,8 @@ const struct cmd_entry cmd_move_pane_entry = {
|
|||||||
.name = "move-pane",
|
.name = "move-pane",
|
||||||
.alias = "movep",
|
.alias = "movep",
|
||||||
|
|
||||||
.args = { "bdfhMvl:L::P:R::s:t:U::X:Y:z:", 0, 0, NULL },
|
.args = { "bdfhvp:l:s:t:", 0, 0, NULL },
|
||||||
.usage = "[-bdfhMv] [-D lines] [-l size] [-L columns] [-P position] "
|
.usage = "[-bdfhv] [-l size] " CMD_SRCDST_PANE_USAGE,
|
||||||
"[-R columns] " CMD_SRCDST_PANE_USAGE " [-U lines] "
|
|
||||||
"[-X x-position] [-Y y-position] [-z z-index]",
|
|
||||||
|
|
||||||
.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
|
.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
@@ -64,305 +59,6 @@ const struct cmd_entry cmd_move_pane_entry = {
|
|||||||
.exec = cmd_join_pane_exec
|
.exec = cmd_join_pane_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl,
|
|
||||||
struct window_pane *wp, const char *position)
|
|
||||||
{
|
|
||||||
struct window *w = wl->window;
|
|
||||||
struct layout_cell *lc = wp->layout_cell;
|
|
||||||
struct window_pane *owp;
|
|
||||||
int wx = w->sx, wy = w->sy, px = lc->sx;
|
|
||||||
int py = lc->sy, xoff = lc->xoff, yoff = lc->yoff;
|
|
||||||
int border = 1;
|
|
||||||
|
|
||||||
if (window_pane_get_pane_lines(wp) == PANE_LINES_NONE)
|
|
||||||
border = 0;
|
|
||||||
|
|
||||||
if (strcmp(position, "top-left") == 0) {
|
|
||||||
xoff = border;
|
|
||||||
yoff = border;
|
|
||||||
} else if (strcmp(position, "top-centre") == 0 ||
|
|
||||||
strcmp(position, "top-center") == 0) {
|
|
||||||
xoff = (wx - px) / 2;
|
|
||||||
yoff = border;
|
|
||||||
} else if (strcmp(position, "top-right") == 0) {
|
|
||||||
xoff = wx - px - border;
|
|
||||||
yoff = border;
|
|
||||||
} else if (strcmp(position, "centre-left") == 0 ||
|
|
||||||
strcmp(position, "center-left") == 0) {
|
|
||||||
xoff = border;
|
|
||||||
yoff = (wy - py) / 2;
|
|
||||||
} else if (strcmp(position, "centre") == 0 ||
|
|
||||||
strcmp(position, "center") == 0) {
|
|
||||||
xoff = (wx - px) / 2;
|
|
||||||
yoff = (wy - py) / 2;
|
|
||||||
} else if (strcmp(position, "centre-right") == 0 ||
|
|
||||||
strcmp(position, "center-right") == 0) {
|
|
||||||
xoff = wx - px - border;
|
|
||||||
yoff = (wy - py) / 2;
|
|
||||||
} else if (strcmp(position, "bottom-left") == 0) {
|
|
||||||
xoff = border;
|
|
||||||
yoff = wy - py - border;
|
|
||||||
} else if (strcmp(position, "bottom-centre") == 0 ||
|
|
||||||
strcmp(position, "bottom-center") == 0) {
|
|
||||||
xoff = (wx - px) / 2;
|
|
||||||
yoff = wy - py - border;
|
|
||||||
} else if (strcmp(position, "bottom-right") == 0) {
|
|
||||||
xoff = wx - px - border;
|
|
||||||
yoff = wy - py - border;
|
|
||||||
} else if (strcmp(position, "top-left-centre") == 0 ||
|
|
||||||
strcmp(position, "top-left-center") == 0) {
|
|
||||||
xoff = wx / 4 - px / 2;
|
|
||||||
yoff = wy / 4 - py / 2;
|
|
||||||
} else if (strcmp(position, "top-right-centre") == 0 ||
|
|
||||||
strcmp(position, "top-right-center") == 0) {
|
|
||||||
xoff = (3 * wx) / 4 - px / 2;
|
|
||||||
yoff = wy / 4 - py / 2;
|
|
||||||
} else if (strcmp(position, "bottom-left-centre") == 0 ||
|
|
||||||
strcmp(position, "bottom-left-center") == 0) {
|
|
||||||
xoff = wx / 4 - px / 2;
|
|
||||||
yoff = (3 * wy) / 4 - py / 2;
|
|
||||||
} else if (strcmp(position, "bottom-right-centre") == 0 ||
|
|
||||||
strcmp(position, "bottom-right-center") == 0) {
|
|
||||||
xoff = (3 * wx) / 4 - px / 2;
|
|
||||||
yoff = (3 * wy) / 4 - py / 2;
|
|
||||||
} else if (strcmp(position, "front") == 0) {
|
|
||||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
|
||||||
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
|
|
||||||
} else if (strcmp(position, "back") == 0) {
|
|
||||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
|
||||||
TAILQ_FOREACH(owp, &w->z_index, zentry) {
|
|
||||||
if (!window_pane_is_floating(owp))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (owp != NULL)
|
|
||||||
TAILQ_INSERT_BEFORE(owp, wp, zentry);
|
|
||||||
else
|
|
||||||
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
|
|
||||||
} else if (strcmp(position, "forward") == 0) {
|
|
||||||
owp = TAILQ_PREV(wp, window_panes_zindex, zentry);
|
|
||||||
if (owp != NULL) {
|
|
||||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
|
||||||
TAILQ_INSERT_BEFORE(owp, wp, zentry);
|
|
||||||
}
|
|
||||||
} else if (strcmp(position, "backward") == 0) {
|
|
||||||
owp = TAILQ_NEXT(wp, zentry);
|
|
||||||
if (owp != NULL && window_pane_is_floating(owp)) {
|
|
||||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
|
||||||
TAILQ_INSERT_AFTER(&w->z_index, owp, wp, zentry);
|
|
||||||
}
|
|
||||||
} else if (strcmp(position, "forward-loop") == 0) {
|
|
||||||
owp = TAILQ_PREV(wp, window_panes_zindex, zentry);
|
|
||||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
|
||||||
if (owp != NULL)
|
|
||||||
TAILQ_INSERT_BEFORE(owp, wp, zentry);
|
|
||||||
else {
|
|
||||||
TAILQ_FOREACH(owp, &w->z_index, zentry) {
|
|
||||||
if (!window_pane_is_floating(owp))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (owp != NULL)
|
|
||||||
TAILQ_INSERT_BEFORE(owp, wp, zentry);
|
|
||||||
else
|
|
||||||
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
|
|
||||||
}
|
|
||||||
} else if (strcmp(position, "backward-loop") == 0) {
|
|
||||||
owp = TAILQ_NEXT(wp, zentry);
|
|
||||||
if (owp != NULL && window_pane_is_floating(owp)) {
|
|
||||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
|
||||||
TAILQ_INSERT_AFTER(&w->z_index, owp, wp, zentry);
|
|
||||||
} else {
|
|
||||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
|
||||||
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cmdq_error(item, "unknown position: %s", position);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xoff != lc->xoff || yoff != lc->yoff) {
|
|
||||||
lc->xoff = xoff;
|
|
||||||
lc->yoff = yoff;
|
|
||||||
layout_fix_panes(w, NULL);
|
|
||||||
}
|
|
||||||
notify_window("window-layout-changed", w);
|
|
||||||
server_redraw_window(w);
|
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_join_pane_move(struct cmdq_item *item, struct args *args,
|
|
||||||
struct winlink *wl, struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct window *w = wl->window;
|
|
||||||
struct layout_cell *lc = wp->layout_cell;
|
|
||||||
const char *errstr, *argval;
|
|
||||||
const char flags[] = { 'U', 'D', 'L', 'R' };
|
|
||||||
char *cause = NULL, flag;
|
|
||||||
int xoff = lc->xoff, yoff = lc->yoff, adjust;
|
|
||||||
u_int i;
|
|
||||||
enum pane_lines lines = window_pane_get_pane_lines(wp);
|
|
||||||
|
|
||||||
if (args_has(args, 'X')) {
|
|
||||||
xoff = args_percentage_and_expand(args, 'X', -(int)w->sx,
|
|
||||||
w->sx, w->sx, item, &cause);
|
|
||||||
if (cause != NULL) {
|
|
||||||
cmdq_error(item, "position %s", cause);
|
|
||||||
free(cause);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
if (lines != PANE_LINES_NONE)
|
|
||||||
xoff += 1;
|
|
||||||
}
|
|
||||||
if (args_has(args, 'Y')) {
|
|
||||||
yoff = args_percentage_and_expand(args, 'Y', -(int)w->sy,
|
|
||||||
w->sy, w->sy, item, &cause);
|
|
||||||
if (cause != NULL) {
|
|
||||||
cmdq_error(item, "position %s", cause);
|
|
||||||
free(cause);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
if (lines != PANE_LINES_NONE)
|
|
||||||
yoff += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < nitems(flags); i++) {
|
|
||||||
flag = flags[i];
|
|
||||||
if (!args_has(args, flag))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
argval = args_get(args, flag);
|
|
||||||
if (argval == NULL)
|
|
||||||
argval = "1";
|
|
||||||
adjust = strtonum(argval, INT_MIN, INT_MAX, &errstr);
|
|
||||||
if (errstr != NULL) {
|
|
||||||
cmdq_error(item, "offset %s", errstr);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flag == 'U')
|
|
||||||
yoff -= adjust;
|
|
||||||
else if (flag == 'D')
|
|
||||||
yoff += adjust;
|
|
||||||
else if (flag == 'L')
|
|
||||||
xoff -= adjust;
|
|
||||||
else
|
|
||||||
xoff += adjust;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xoff != lc->xoff || yoff != lc->yoff) {
|
|
||||||
lc->xoff = xoff;
|
|
||||||
lc->yoff = yoff;
|
|
||||||
layout_fix_panes(w, NULL);
|
|
||||||
notify_window("window-layout-changed", w);
|
|
||||||
server_redraw_window(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_join_pane_mouse_update(struct cmdq_item *item)
|
|
||||||
{
|
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
|
||||||
struct key_event *event = cmdq_get_event(item);
|
|
||||||
struct client *c = cmdq_get_client(item);
|
|
||||||
struct session *s = target->s;
|
|
||||||
struct winlink *wl;
|
|
||||||
struct window *w;
|
|
||||||
struct window_pane *wp;
|
|
||||||
|
|
||||||
if (!event->m.valid)
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
wp = cmd_mouse_pane(&event->m, &s, &wl);
|
|
||||||
if (wp == NULL || c == NULL || c->session != s)
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
if (!window_pane_is_floating(wp))
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
|
|
||||||
w = wl->window;
|
|
||||||
window_redraw_active_switch(w, wp);
|
|
||||||
window_set_active_pane(w, wp, 1);
|
|
||||||
|
|
||||||
c->tty.mouse_drag_update = cmd_join_pane_mouse_move;
|
|
||||||
cmd_join_pane_mouse_move(c, &event->m);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_join_pane_mouse_move(struct client *c, struct mouse_event *m)
|
|
||||||
{
|
|
||||||
struct winlink *wl;
|
|
||||||
struct window *w;
|
|
||||||
struct window_pane *wp;
|
|
||||||
struct layout_cell *lc;
|
|
||||||
int y, ly, x, lx;
|
|
||||||
|
|
||||||
wp = cmd_mouse_pane(m, NULL, &wl);
|
|
||||||
if (wp == NULL) {
|
|
||||||
c->tty.mouse_drag_update = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
w = wl->window;
|
|
||||||
lc = wp->layout_cell;
|
|
||||||
|
|
||||||
y = m->y + m->oy; x = m->x + m->ox;
|
|
||||||
if (m->statusat == 0 && y >= (int)m->statuslines)
|
|
||||||
y -= m->statuslines;
|
|
||||||
else if (m->statusat > 0 && y >= m->statusat)
|
|
||||||
y = m->statusat - 1;
|
|
||||||
ly = m->ly + m->oy; lx = m->lx + m->ox;
|
|
||||||
if (m->statusat == 0 && ly >= (int)m->statuslines)
|
|
||||||
ly -= m->statuslines;
|
|
||||||
else if (m->statusat > 0 && ly >= m->statusat)
|
|
||||||
ly = m->statusat - 1;
|
|
||||||
|
|
||||||
if (x != lx || y != ly) {
|
|
||||||
lc->xoff += x - lx;
|
|
||||||
lc->yoff += y - ly;
|
|
||||||
layout_fix_panes(w, NULL);
|
|
||||||
server_redraw_window(w);
|
|
||||||
server_redraw_window_borders(w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_join_pane_zindex(struct cmdq_item *item, struct winlink *wl,
|
|
||||||
struct window_pane *wp, const char *s)
|
|
||||||
{
|
|
||||||
struct window *w = wl->window;
|
|
||||||
struct window_pane *owp;
|
|
||||||
const char *errstr;
|
|
||||||
u_int n, z;
|
|
||||||
|
|
||||||
z = strtonum(s, 0, UINT_MAX, &errstr);
|
|
||||||
if (errstr != NULL) {
|
|
||||||
cmdq_error(item, "z-index %s", errstr);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
TAILQ_FOREACH(owp, &w->z_index, zentry) {
|
|
||||||
if (!window_pane_is_floating(owp))
|
|
||||||
break;
|
|
||||||
if (n >= z)
|
|
||||||
break;
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (owp != NULL)
|
|
||||||
TAILQ_INSERT_BEFORE(owp, wp, zentry);
|
|
||||||
else
|
|
||||||
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
|
|
||||||
|
|
||||||
notify_window("window-layout-changed", w);
|
|
||||||
server_redraw_window(w);
|
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
@@ -374,7 +70,6 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct winlink *src_wl, *dst_wl;
|
struct winlink *src_wl, *dst_wl;
|
||||||
struct window *src_w, *dst_w;
|
struct window *src_w, *dst_w;
|
||||||
struct window_pane *src_wp, *dst_wp;
|
struct window_pane *src_wp, *dst_wp;
|
||||||
const char *s;
|
|
||||||
char *cause = NULL;
|
char *cause = NULL;
|
||||||
int flags = 0, dst_idx;
|
int flags = 0, dst_idx;
|
||||||
struct layout_cell *lc;
|
struct layout_cell *lc;
|
||||||
@@ -386,26 +81,6 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
dst_idx = dst_wl->idx;
|
dst_idx = dst_wl->idx;
|
||||||
server_unzoom_window(dst_w);
|
server_unzoom_window(dst_w);
|
||||||
|
|
||||||
if (cmd_get_entry(self) == &cmd_move_pane_entry) {
|
|
||||||
if (args_has(args, 'M'))
|
|
||||||
return (cmd_join_pane_mouse_update(item));
|
|
||||||
if (!window_pane_is_floating(dst_wp)) {
|
|
||||||
cmdq_error(item, "pane is not floating");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
if ((s = args_get(args, 'P')) != NULL)
|
|
||||||
return (cmd_join_pane_place(item, dst_wl, dst_wp, s));
|
|
||||||
if ((s = args_get(args, 'z')) != NULL)
|
|
||||||
return (cmd_join_pane_zindex(item, dst_wl, dst_wp, s));
|
|
||||||
if (args_has(args, 'X') ||
|
|
||||||
args_has(args, 'Y') ||
|
|
||||||
args_has(args, 'U') ||
|
|
||||||
args_has(args, 'D') ||
|
|
||||||
args_has(args, 'L') ||
|
|
||||||
args_has(args, 'R'))
|
|
||||||
return (cmd_join_pane_move(item, args, dst_wl, dst_wp));
|
|
||||||
}
|
|
||||||
|
|
||||||
src_wl = source->wl;
|
src_wl = source->wl;
|
||||||
src_wp = source->wp;
|
src_wp = source->wp;
|
||||||
src_w = src_wl->window;
|
src_w = src_wl->window;
|
||||||
|
|||||||
@@ -27,17 +27,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static enum cmd_retval cmd_kill_pane_exec(struct cmd *, struct cmdq_item *);
|
static enum cmd_retval cmd_kill_pane_exec(struct cmd *, struct cmdq_item *);
|
||||||
static enum cmd_retval cmd_kill_pane_all(struct cmdq_item *, const char *);
|
|
||||||
static int cmd_kill_pane_filter(struct cmdq_item *,
|
|
||||||
struct session *, struct winlink *,
|
|
||||||
struct window_pane *, const char *);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_kill_pane_entry = {
|
const struct cmd_entry cmd_kill_pane_entry = {
|
||||||
.name = "kill-pane",
|
.name = "kill-pane",
|
||||||
.alias = "killp",
|
.alias = "killp",
|
||||||
|
|
||||||
.args = { "af:t:", 0, 0, NULL },
|
.args = { "at:", 0, 0, NULL },
|
||||||
.usage = "[-a] [-f filter] " CMD_TARGET_PANE_USAGE,
|
.usage = "[-a] " CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
@@ -50,17 +46,22 @@ cmd_kill_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct window_pane *wp = target->wp;
|
struct winlink *wl = target->wl;
|
||||||
const char *filter = args_get(args, 'f');
|
struct window_pane *loopwp, *tmpwp, *wp = target->wp;
|
||||||
|
|
||||||
if (filter != NULL && !args_has(args, 'a')) {
|
if (args_has(args, 'a')) {
|
||||||
cmdq_error(item, "-f only valid with -a");
|
server_unzoom_window(wl->window);
|
||||||
return (CMD_RETURN_ERROR);
|
TAILQ_FOREACH_SAFE(loopwp, &wl->window->panes, entry, tmpwp) {
|
||||||
|
if (loopwp == wp)
|
||||||
|
continue;
|
||||||
|
server_client_remove_pane(loopwp);
|
||||||
|
layout_close_pane(loopwp);
|
||||||
|
window_remove_pane(wl->window, loopwp);
|
||||||
|
}
|
||||||
|
server_redraw_window(wl->window);
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args_has(args, 'a'))
|
|
||||||
return (cmd_kill_pane_all(item, filter));
|
|
||||||
|
|
||||||
if (wp == NULL) {
|
if (wp == NULL) {
|
||||||
cmdq_error(item, "no active pane to kill");
|
cmdq_error(item, "no active pane to kill");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
@@ -68,48 +69,3 @@ cmd_kill_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
server_kill_pane(wp);
|
server_kill_pane(wp);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_kill_pane_all(struct cmdq_item *item, const char *filter)
|
|
||||||
{
|
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
|
||||||
struct session *s = target->s;
|
|
||||||
struct winlink *wl = target->wl;
|
|
||||||
struct window_pane *wp = target->wp;
|
|
||||||
struct window_pane *loopwp, *tmpwp;
|
|
||||||
|
|
||||||
server_unzoom_window(wl->window);
|
|
||||||
TAILQ_FOREACH_SAFE(loopwp, &wl->window->panes, entry, tmpwp) {
|
|
||||||
if (loopwp == wp)
|
|
||||||
continue;
|
|
||||||
if (!cmd_kill_pane_filter(item, s, wl, loopwp, filter))
|
|
||||||
continue;
|
|
||||||
server_client_remove_pane(loopwp);
|
|
||||||
layout_close_pane(loopwp);
|
|
||||||
window_remove_pane(wl->window, loopwp);
|
|
||||||
}
|
|
||||||
server_redraw_window(wl->window);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
cmd_kill_pane_filter(struct cmdq_item *item, struct session *s,
|
|
||||||
struct winlink *wl, struct window_pane *wp, const char *filter)
|
|
||||||
{
|
|
||||||
struct format_tree *ft;
|
|
||||||
char *expanded;
|
|
||||||
int flag;
|
|
||||||
|
|
||||||
if (filter == NULL)
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
|
||||||
format_defaults(ft, NULL, s, wl, wp);
|
|
||||||
|
|
||||||
expanded = format_expand(ft, filter);
|
|
||||||
flag = format_true(expanded);
|
|
||||||
free(expanded);
|
|
||||||
|
|
||||||
format_free(ft);
|
|
||||||
return (flag);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,8 +18,6 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -30,16 +28,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static enum cmd_retval cmd_kill_session_exec(struct cmd *, struct cmdq_item *);
|
static enum cmd_retval cmd_kill_session_exec(struct cmd *, struct cmdq_item *);
|
||||||
static enum cmd_retval cmd_kill_session_all(struct cmdq_item *, const char *);
|
|
||||||
static int cmd_kill_session_filter(struct cmdq_item *,
|
|
||||||
struct session *, const char *);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_kill_session_entry = {
|
const struct cmd_entry cmd_kill_session_entry = {
|
||||||
.name = "kill-session",
|
.name = "kill-session",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "aCgf:t:", 0, 0, NULL },
|
.args = { "aCgt:", 0, 0, NULL },
|
||||||
.usage = "[-aCg] [-f filter] " CMD_TARGET_SESSION_USAGE,
|
.usage = "[-aCg] " CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_SESSION, 0 },
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
@@ -55,12 +50,6 @@ cmd_kill_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct session *s = target->s, *sloop, *stmp;
|
struct session *s = target->s, *sloop, *stmp;
|
||||||
struct session_group *sg;
|
struct session_group *sg;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
const char *filter = args_get(args, 'f');
|
|
||||||
|
|
||||||
if (filter != NULL && (!args_has(args, 'a') || args_has(args, 'C'))) {
|
|
||||||
cmdq_error(item, "-f only valid with -a");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args_has(args, 'C')) {
|
if (args_has(args, 'C')) {
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
@@ -68,9 +57,14 @@ cmd_kill_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
wl->flags &= ~WINLINK_ALERTFLAGS;
|
||||||
}
|
}
|
||||||
server_redraw_session(s);
|
server_redraw_session(s);
|
||||||
} else if (args_has(args, 'a'))
|
} else if (args_has(args, 'a')) {
|
||||||
return (cmd_kill_session_all(item, filter));
|
RB_FOREACH_SAFE(sloop, sessions, &sessions, stmp) {
|
||||||
else if (args_has(args, 'g') &&
|
if (sloop != s) {
|
||||||
|
server_destroy_session(sloop);
|
||||||
|
session_destroy(sloop, 1, __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (args_has(args, 'g') &&
|
||||||
(sg = session_group_contains(s)) != NULL) {
|
(sg = session_group_contains(s)) != NULL) {
|
||||||
TAILQ_FOREACH_SAFE(sloop, &sg->sessions, gentry, stmp) {
|
TAILQ_FOREACH_SAFE(sloop, &sg->sessions, gentry, stmp) {
|
||||||
server_destroy_session(sloop);
|
server_destroy_session(sloop);
|
||||||
@@ -82,42 +76,3 @@ cmd_kill_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_kill_session_all(struct cmdq_item *item, const char *filter)
|
|
||||||
{
|
|
||||||
struct session *s = cmdq_get_target(item)->s;
|
|
||||||
struct session *sloop, *stmp;
|
|
||||||
|
|
||||||
RB_FOREACH_SAFE(sloop, sessions, &sessions, stmp) {
|
|
||||||
if (sloop == s)
|
|
||||||
continue;
|
|
||||||
if (!cmd_kill_session_filter(item, sloop, filter))
|
|
||||||
continue;
|
|
||||||
server_destroy_session(sloop);
|
|
||||||
session_destroy(sloop, 1, __func__);
|
|
||||||
}
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
cmd_kill_session_filter(struct cmdq_item *item, struct session *s,
|
|
||||||
const char *filter)
|
|
||||||
{
|
|
||||||
struct format_tree *ft;
|
|
||||||
char *expanded;
|
|
||||||
int flag;
|
|
||||||
|
|
||||||
if (filter == NULL)
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
|
||||||
format_defaults(ft, NULL, s, NULL, NULL);
|
|
||||||
|
|
||||||
expanded = format_expand(ft, filter);
|
|
||||||
flag = format_true(expanded);
|
|
||||||
free(expanded);
|
|
||||||
|
|
||||||
format_free(ft);
|
|
||||||
return (flag);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,8 +18,6 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -27,16 +25,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static enum cmd_retval cmd_kill_window_exec(struct cmd *, struct cmdq_item *);
|
static enum cmd_retval cmd_kill_window_exec(struct cmd *, struct cmdq_item *);
|
||||||
static enum cmd_retval cmd_kill_window_all(struct cmdq_item *, const char *);
|
|
||||||
static int cmd_kill_window_filter(struct cmdq_item *,
|
|
||||||
struct session *, struct winlink *, const char *);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_kill_window_entry = {
|
const struct cmd_entry cmd_kill_window_entry = {
|
||||||
.name = "kill-window",
|
.name = "kill-window",
|
||||||
.alias = "killw",
|
.alias = "killw",
|
||||||
|
|
||||||
.args = { "af:t:", 0, 0, NULL },
|
.args = { "at:", 0, 0, NULL },
|
||||||
.usage = "[-a] [-f filter] " CMD_TARGET_WINDOW_USAGE,
|
.usage = "[-a] " CMD_TARGET_WINDOW_USAGE,
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_WINDOW, 0 },
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
@@ -62,15 +57,10 @@ cmd_kill_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct winlink *wl = target->wl;
|
struct winlink *wl = target->wl, *loop;
|
||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
struct session *s = target->s;
|
struct session *s = target->s;
|
||||||
const char *filter = args_get(args, 'f');
|
u_int found;
|
||||||
|
|
||||||
if (filter != NULL && !args_has(args, 'a')) {
|
|
||||||
cmdq_error(item, "-f only valid with -a");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd_get_entry(self) == &cmd_unlink_window_entry) {
|
if (cmd_get_entry(self) == &cmd_unlink_window_entry) {
|
||||||
if (!args_has(args, 'k') && !session_is_linked(s, w)) {
|
if (!args_has(args, 'k') && !session_is_linked(s, w)) {
|
||||||
@@ -82,76 +72,39 @@ cmd_kill_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args_has(args, 'a'))
|
if (args_has(args, 'a')) {
|
||||||
return (cmd_kill_window_all(item, filter));
|
if (RB_PREV(winlinks, &s->windows, wl) == NULL &&
|
||||||
|
RB_NEXT(winlinks, &s->windows, wl) == NULL)
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
|
/* Kill all windows except the current one. */
|
||||||
|
do {
|
||||||
|
found = 0;
|
||||||
|
RB_FOREACH(loop, winlinks, &s->windows) {
|
||||||
|
if (loop->window != wl->window) {
|
||||||
|
server_kill_window(loop->window, 0);
|
||||||
|
found++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (found != 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the current window appears in the session more than once,
|
||||||
|
* kill it as well.
|
||||||
|
*/
|
||||||
|
found = 0;
|
||||||
|
RB_FOREACH(loop, winlinks, &s->windows) {
|
||||||
|
if (loop->window == wl->window)
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
if (found > 1)
|
||||||
|
server_kill_window(wl->window, 0);
|
||||||
|
|
||||||
|
server_renumber_all();
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
server_kill_window(wl->window, 1);
|
server_kill_window(wl->window, 1);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_kill_window_all(struct cmdq_item *item, const char *filter)
|
|
||||||
{
|
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
|
||||||
struct session *s = target->s;
|
|
||||||
struct winlink *wl = target->wl;
|
|
||||||
struct winlink *loop;
|
|
||||||
u_int found, kill_current;
|
|
||||||
|
|
||||||
if (RB_PREV(winlinks, &s->windows, wl) == NULL &&
|
|
||||||
RB_NEXT(winlinks, &s->windows, wl) == NULL)
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
|
|
||||||
/* Kill all windows except the current one. */
|
|
||||||
do {
|
|
||||||
found = 0;
|
|
||||||
RB_FOREACH(loop, winlinks, &s->windows) {
|
|
||||||
if (loop->window != wl->window &&
|
|
||||||
cmd_kill_window_filter(item, s, loop, filter)) {
|
|
||||||
server_kill_window(loop->window, 0);
|
|
||||||
found++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (found != 0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the current window appears in the session more than once, kill it
|
|
||||||
* as well if it matches the filter.
|
|
||||||
*/
|
|
||||||
found = kill_current = 0;
|
|
||||||
RB_FOREACH(loop, winlinks, &s->windows) {
|
|
||||||
if (loop->window == wl->window) {
|
|
||||||
found++;
|
|
||||||
if (cmd_kill_window_filter(item, s, loop, filter))
|
|
||||||
kill_current = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (kill_current && found > 1)
|
|
||||||
server_kill_window(wl->window, 0);
|
|
||||||
|
|
||||||
server_renumber_all();
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
cmd_kill_window_filter(struct cmdq_item *item, struct session *s,
|
|
||||||
struct winlink *wl, const char *filter)
|
|
||||||
{
|
|
||||||
struct format_tree *ft;
|
|
||||||
char *expanded;
|
|
||||||
int flag;
|
|
||||||
|
|
||||||
if (filter == NULL)
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
|
||||||
format_defaults(ft, NULL, s, wl, NULL);
|
|
||||||
|
|
||||||
expanded = format_expand(ft, filter);
|
|
||||||
flag = format_true(expanded);
|
|
||||||
free(expanded);
|
|
||||||
|
|
||||||
format_free(ft);
|
|
||||||
return (flag);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -223,12 +223,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmd_list_keys_filter_key_list(filter_notes, filter_key, only, l,
|
cmd_list_keys_filter_key_list(filter_notes, filter_key, only, l,
|
||||||
&n);
|
&n);
|
||||||
}
|
}
|
||||||
if (filter_key && n == 0) {
|
if (single)
|
||||||
cmdq_error(item, "unknown key: %s", keystr);
|
|
||||||
free(prefix);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
if (single && n > 1)
|
|
||||||
n = 1;
|
n = 1;
|
||||||
|
|
||||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||||
@@ -242,7 +237,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmd_list_keys_format_add_key_binding(ft, l[i], prefix);
|
cmd_list_keys_format_add_key_binding(ft, l[i], prefix);
|
||||||
|
|
||||||
line = format_expand(ft, template);
|
line = format_expand(ft, template);
|
||||||
if (single && tc != NULL && (~tc->flags & CLIENT_CONTROL))
|
if ((single && tc != NULL) || n == 1)
|
||||||
status_message_set(tc, -1, 1, 0, 0, "%s", line);
|
status_message_set(tc, -1, 1, 0, 0, "%s", line);
|
||||||
else if (*line != '\0')
|
else if (*line != '\0')
|
||||||
cmdq_print(item, "%s", line);
|
cmdq_print(item, "%s", line);
|
||||||
|
|||||||
@@ -168,7 +168,6 @@ cmd_refresh_report(struct tty *tty, const char *value)
|
|||||||
{
|
{
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
u_int pane;
|
u_int pane;
|
||||||
int fg, bg;
|
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
char *copy, *split;
|
char *copy, *split;
|
||||||
|
|
||||||
@@ -185,14 +184,8 @@ cmd_refresh_report(struct tty *tty, const char *value)
|
|||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
fg = wp->control_fg;
|
tty_keys_colours(tty, split, strlen(split), &size, &wp->control_fg,
|
||||||
bg = wp->control_bg;
|
&wp->control_bg);
|
||||||
if (tty_keys_colours(tty, split, strlen(split), &size, &fg, &bg) == 0) {
|
|
||||||
if (bg != wp->control_bg)
|
|
||||||
wp->flags |= PANE_THEMECHANGED;
|
|
||||||
wp->control_fg = fg;
|
|
||||||
wp->control_bg = bg;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free(copy);
|
free(copy);
|
||||||
|
|||||||
@@ -31,18 +31,18 @@ static enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmdq_item *);
|
|||||||
|
|
||||||
static enum cmd_retval cmd_resize_pane_mouse_update(struct cmd *,
|
static enum cmd_retval cmd_resize_pane_mouse_update(struct cmd *,
|
||||||
struct cmdq_item *);
|
struct cmdq_item *);
|
||||||
static void cmd_resize_pane_mouse_resize_move_floating(
|
static void cmd_resize_pane_mouse_update_floating(struct client *,
|
||||||
struct client *, struct mouse_event *);
|
struct mouse_event *);
|
||||||
static void cmd_resize_pane_mouse_resize_tiled(struct client *,
|
static void cmd_resize_pane_mouse_update_tiled(struct client *,
|
||||||
struct mouse_event *);
|
struct mouse_event *);
|
||||||
|
|
||||||
const struct cmd_entry cmd_resize_pane_entry = {
|
const struct cmd_entry cmd_resize_pane_entry = {
|
||||||
.name = "resize-pane",
|
.name = "resize-pane",
|
||||||
.alias = "resizep",
|
.alias = "resizep",
|
||||||
|
|
||||||
.args = { "D::L::MR::Tt:U::x:y:Z", 0, 1, NULL },
|
.args = { "DLMRTt:Ux:y:Z", 0, 1, NULL },
|
||||||
.usage = "[-MTZ] [-D lines] [-L columns] [-R columns] [-U lines] "
|
.usage = "[-DLMRTUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " "
|
||||||
"[-x width] [-y height] " CMD_TARGET_PANE_USAGE,
|
"[adjustment]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
@@ -58,21 +58,17 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct window_pane *wp = target->wp;
|
struct window_pane *wp = target->wp;
|
||||||
struct winlink *wl = target->wl;
|
struct winlink *wl = target->wl;
|
||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
struct layout_cell *lc = wp->layout_cell;
|
const char *errstr;
|
||||||
enum layout_type type;
|
char *cause;
|
||||||
const char *errstr, *argval;
|
u_int adjust;
|
||||||
const char flags[4] = { 'U', 'D', 'L', 'R' };
|
int x, y, status;
|
||||||
char *cause = NULL, flag;
|
|
||||||
u_int opposite = 0;
|
|
||||||
int adjust, x, y, status;
|
|
||||||
long unsigned i;
|
|
||||||
struct grid *gd = wp->base.grid;
|
struct grid *gd = wp->base.grid;
|
||||||
|
|
||||||
if (args_has(args, 'T')) {
|
if (args_has(args, 'T')) {
|
||||||
if (!TAILQ_EMPTY(&wp->modes))
|
if (!TAILQ_EMPTY(&wp->modes))
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
adjust = screen_size_y(&wp->base) - 1 - wp->base.cy;
|
adjust = screen_size_y(&wp->base) - 1 - wp->base.cy;
|
||||||
if (adjust > (int)gd->hsize)
|
if (adjust > gd->hsize)
|
||||||
adjust = gd->hsize;
|
adjust = gd->hsize;
|
||||||
grid_remove_history(gd, adjust);
|
grid_remove_history(gd, adjust);
|
||||||
wp->base.cy += adjust;
|
wp->base.cy += adjust;
|
||||||
@@ -93,32 +89,33 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
server_unzoom_window(w);
|
server_unzoom_window(w);
|
||||||
|
|
||||||
|
if (args_count(args) == 0)
|
||||||
|
adjust = 1;
|
||||||
|
else {
|
||||||
|
adjust = strtonum(args_string(args, 0), 1, INT_MAX, &errstr);
|
||||||
|
if (errstr != NULL) {
|
||||||
|
cmdq_error(item, "adjustment %s", errstr);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (args_has(args, 'x')) {
|
if (args_has(args, 'x')) {
|
||||||
x = args_percentage(args, 'x', 0, PANE_MAXIMUM, w->sx, &cause);
|
x = args_percentage(args, 'x', 0, INT_MAX, w->sx, &cause);
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
cmdq_error(item, "width %s", cause);
|
cmdq_error(item, "width %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
if (window_pane_is_floating(wp)) {
|
layout_resize_pane_to(wp, LAYOUT_LEFTRIGHT, x);
|
||||||
layout_resize_floating_pane_to(wp, LAYOUT_LEFTRIGHT, x,
|
|
||||||
&cause);
|
|
||||||
if (cause != NULL) {
|
|
||||||
cmdq_error(item, "size %s", cause);
|
|
||||||
free(cause);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
layout_resize_pane_to(wp, LAYOUT_LEFTRIGHT, x);
|
|
||||||
}
|
}
|
||||||
if (args_has(args, 'y')) {
|
if (args_has(args, 'y')) {
|
||||||
y = args_percentage(args, 'y', 0, PANE_MAXIMUM, w->sy, &cause);
|
y = args_percentage(args, 'y', 0, INT_MAX, w->sy, &cause);
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
cmdq_error(item, "height %s", cause);
|
cmdq_error(item, "height %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
status = window_get_pane_status(w);
|
status = options_get_number(w->options, "pane-border-status");
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case PANE_STATUS_TOP:
|
case PANE_STATUS_TOP:
|
||||||
if (y != INT_MAX && wp->yoff == 1)
|
if (y != INT_MAX && wp->yoff == 1)
|
||||||
@@ -129,60 +126,18 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
y++;
|
y++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (window_pane_is_floating(wp)) {
|
layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y);
|
||||||
layout_resize_floating_pane_to(wp, LAYOUT_TOPBOTTOM, y,
|
|
||||||
&cause);
|
|
||||||
if (cause != NULL) {
|
|
||||||
cmdq_error(item, "size %s", cause);
|
|
||||||
free(cause);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < nitems(flags); i++) {
|
if (args_has(args, 'L'))
|
||||||
flag = flags[i];
|
layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust, 1);
|
||||||
if (!args_has(args, flag))
|
else if (args_has(args, 'R'))
|
||||||
continue;
|
layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust, 1);
|
||||||
|
else if (args_has(args, 'U'))
|
||||||
argval = args_get(args, flag);
|
layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust, 1);
|
||||||
if (argval == NULL)
|
else if (args_has(args, 'D'))
|
||||||
argval = "1";
|
layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust, 1);
|
||||||
|
server_redraw_window(wl->window);
|
||||||
adjust = strtonum(argval, INT_MIN, INT_MAX, &errstr);
|
|
||||||
if (errstr != NULL) {
|
|
||||||
cmdq_error(item, "adjustment %s", errstr);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
type = LAYOUT_TOPBOTTOM;
|
|
||||||
if (flag == 'L' || flag == 'R')
|
|
||||||
type = LAYOUT_LEFTRIGHT;
|
|
||||||
|
|
||||||
if (window_pane_is_floating(wp)) {
|
|
||||||
if (flag == 'L' || flag == 'U')
|
|
||||||
opposite = 1;
|
|
||||||
|
|
||||||
layout_resize_floating_pane(wp, type, adjust, opposite,
|
|
||||||
&cause);
|
|
||||||
if (cause != NULL) {
|
|
||||||
cmdq_error(item, "adjustment %s", cause);
|
|
||||||
free(cause);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (flag == 'L' || flag == 'U')
|
|
||||||
adjust = -adjust;
|
|
||||||
layout_resize_pane(wp, type, adjust, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lc->parent != NULL)
|
|
||||||
layout_fix_offsets(w);
|
|
||||||
layout_fix_panes(w, NULL);
|
|
||||||
notify_window("window-layout-changed", w);
|
|
||||||
server_redraw_window(w);
|
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
@@ -205,29 +160,21 @@ cmd_resize_pane_mouse_update(__unused struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
if (!window_pane_is_floating(wp)) {
|
if (!window_pane_is_floating(wp)) {
|
||||||
c->tty.mouse_drag_update = cmd_resize_pane_mouse_resize_tiled;
|
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_tiled;
|
||||||
cmd_resize_pane_mouse_resize_tiled(c, &event->m);
|
cmd_resize_pane_mouse_update_tiled(c, &event->m);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
window_redraw_active_switch(w, wp);
|
window_redraw_active_switch(w, wp);
|
||||||
window_set_active_pane(w, wp, 1);
|
window_set_active_pane(w, wp, 1);
|
||||||
|
|
||||||
c->tty.mouse_drag_update = cmd_resize_pane_mouse_resize_move_floating;
|
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_floating;
|
||||||
cmd_resize_pane_mouse_resize_move_floating(c, &event->m);
|
cmd_resize_pane_mouse_update_floating(c, &event->m);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Resizes or moves the pane by dragging. Resize a floating pane by dragging
|
|
||||||
* the borders or corners. Grabbing an edge only resizes that axis (special
|
|
||||||
* case). Moves the pane if dragging the top border. Since characters are
|
|
||||||
* generally rectangular, to make it easier to grab the corner, the character
|
|
||||||
* next to the corner is also considered the corner.
|
|
||||||
*/
|
|
||||||
static void
|
static void
|
||||||
cmd_resize_pane_mouse_resize_move_floating(struct client *c,
|
cmd_resize_pane_mouse_update_floating(struct client *c, struct mouse_event *m)
|
||||||
struct mouse_event *m)
|
|
||||||
{
|
{
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
@@ -353,7 +300,7 @@ cmd_resize_pane_mouse_resize_move_floating(struct client *c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_resize_pane_mouse_resize_tiled(struct client *c, struct mouse_event *m)
|
cmd_resize_pane_mouse_update_tiled(struct client *c, struct mouse_event *m)
|
||||||
{
|
{
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
|
|||||||
@@ -109,7 +109,6 @@ cmd_rotate_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
window_set_active_pane(w, wp, 1);
|
window_set_active_pane(w, wp, 1);
|
||||||
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
||||||
window_pop_zoom(w);
|
window_pop_zoom(w);
|
||||||
redraw_invalidate_scene(w);
|
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (args_has(args, 'm') || args_has(args, 'M')) {
|
if (args_has(args, 'm') || args_has(args, 'M')) {
|
||||||
if (args_has(args, 'm') && !window_pane_is_visible(wp))
|
if (args_has(args, 'm') && !window_pane_visible(wp))
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
if (server_check_marked())
|
if (server_check_marked())
|
||||||
lastwp = marked_pane.wp;
|
lastwp = marked_pane.wp;
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ cmd_send_keys_inject_key(struct cmdq_item *item, struct cmdq_item *after,
|
|||||||
struct key_table *table = NULL;
|
struct key_table *table = NULL;
|
||||||
struct key_binding *bd;
|
struct key_binding *bd;
|
||||||
struct key_event *event;
|
struct key_event *event;
|
||||||
struct cmdq_item *new_after = after;
|
|
||||||
|
|
||||||
if (args_has(args, 'K')) {
|
if (args_has(args, 'K')) {
|
||||||
if (tc == NULL)
|
if (tc == NULL)
|
||||||
@@ -78,16 +77,10 @@ cmd_send_keys_inject_key(struct cmdq_item *item, struct cmdq_item *after,
|
|||||||
event = xcalloc(1, sizeof *event);
|
event = xcalloc(1, sizeof *event);
|
||||||
event->key = key|KEYC_SENT;
|
event->key = key|KEYC_SENT;
|
||||||
memset(&event->m, 0, sizeof event->m);
|
memset(&event->m, 0, sizeof event->m);
|
||||||
if (after == NULL) {
|
if (server_client_handle_key(tc, event) == 0) {
|
||||||
if (server_client_handle_key(tc, event) != 0)
|
free(event->buf);
|
||||||
return (item);
|
free(event);
|
||||||
} else {
|
|
||||||
if (server_client_handle_key_after(tc, event, after,
|
|
||||||
&new_after) != 0)
|
|
||||||
return (new_after);
|
|
||||||
}
|
}
|
||||||
free(event->buf);
|
|
||||||
free(event);
|
|
||||||
return (item);
|
return (item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,10 +229,8 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
if (args_has(args, 'N') || args_has(args, 'R'))
|
if (args_has(args, 'N') || args_has(args, 'R'))
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
after = args_has(args, 'K') ? item : NULL;
|
|
||||||
for (; np != 0; np--)
|
for (; np != 0; np--)
|
||||||
after = cmd_send_keys_inject_key(item, after, args,
|
cmd_send_keys_inject_key(item, NULL, args, event->key);
|
||||||
event->key);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <grp.h>
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -38,71 +37,67 @@ const struct cmd_entry cmd_server_access_entry = {
|
|||||||
.name = "server-access",
|
.name = "server-access",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "adglrw", 0, 1, NULL },
|
.args = { "adlrw", 0, 1, NULL },
|
||||||
.usage = "[-adglrw] " CMD_TARGET_PANE_USAGE " [user|group]",
|
.usage = "[-adlrw] " CMD_TARGET_PANE_USAGE " [user]",
|
||||||
|
|
||||||
.flags = CMD_CLIENT_CANFAIL,
|
.flags = CMD_CLIENT_CANFAIL,
|
||||||
.exec = cmd_server_access_exec
|
.exec = cmd_server_access_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_server_access_deny(struct cmdq_item *item, id_t id, int flags,
|
cmd_server_access_deny(struct cmdq_item *item, struct passwd *pw)
|
||||||
const char *type, const char *name)
|
|
||||||
{
|
{
|
||||||
if (!server_acl_find(id, flags)) {
|
struct client *loop;
|
||||||
cmdq_error(item, "%s %s not found", type, name);
|
struct server_acl_user *user;
|
||||||
|
uid_t uid;
|
||||||
|
|
||||||
|
if ((user = server_acl_user_find(pw->pw_uid)) == NULL) {
|
||||||
|
cmdq_error(item, "user %s not found", pw->pw_name);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
server_acl_deny(id, flags);
|
TAILQ_FOREACH(loop, &clients, entry) {
|
||||||
|
uid = proc_get_peer_uid(loop->peer);
|
||||||
|
if (uid == server_acl_get_uid(user)) {
|
||||||
|
loop->exit_message = xstrdup("access not allowed");
|
||||||
|
loop->flags |= CLIENT_EXIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
server_acl_user_deny(pw->pw_uid);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_server_access_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_server_access_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct client *c = cmdq_get_target_client(item);
|
struct client *c = cmdq_get_target_client(item);
|
||||||
char *arg;
|
char *name;
|
||||||
const char *name = NULL, *type;
|
struct passwd *pw = NULL;
|
||||||
struct passwd *pw;
|
|
||||||
struct group *gr;
|
|
||||||
id_t id;
|
|
||||||
int flags = 0;
|
|
||||||
|
|
||||||
if (args_has(args, 'l')) {
|
if (args_has(args, 'l')) {
|
||||||
server_acl_display(item);
|
server_acl_display(item);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
if (args_count(args) == 0) {
|
if (args_count(args) == 0) {
|
||||||
cmdq_error(item, "missing user or group argument");
|
cmdq_error(item, "missing user argument");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
arg = format_single(item, args_string(args, 0), c, NULL, NULL, NULL);
|
name = format_single(item, args_string(args, 0), c, NULL, NULL, NULL);
|
||||||
if (args_has(args, 'g')) {
|
if (*name != '\0')
|
||||||
type = "group";
|
pw = getpwnam(name);
|
||||||
if ((gr = getgrnam(arg)) != NULL) {
|
if (pw == NULL) {
|
||||||
id = gr->gr_gid;
|
cmdq_error(item, "unknown user: %s", name);
|
||||||
name = gr->gr_name;
|
free(name);
|
||||||
flags |= SERVER_ACL_IS_GROUP;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
type = "user";
|
|
||||||
if ((pw = getpwnam(arg)) != NULL) {
|
|
||||||
id = pw->pw_uid;
|
|
||||||
name = pw->pw_name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (name == NULL) {
|
|
||||||
cmdq_error(item, "unknown %s: %s", type, arg);
|
|
||||||
free(arg);
|
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
free(arg);
|
free(name);
|
||||||
|
|
||||||
if ((~flags & SERVER_ACL_IS_GROUP) && (id == 0 || id == getuid())) {
|
if (pw->pw_uid == 0 || pw->pw_uid == getuid()) {
|
||||||
cmdq_error(item, "%s owns the server, can't change access",
|
cmdq_error(item, "%s owns the server, can't change access",
|
||||||
name);
|
pw->pw_name);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,35 +111,36 @@ cmd_server_access_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (args_has(args, 'd'))
|
if (args_has(args, 'd'))
|
||||||
return (cmd_server_access_deny(item, id, flags, type, name));
|
return (cmd_server_access_deny(item, pw));
|
||||||
if (args_has(args, 'a')) {
|
if (args_has(args, 'a')) {
|
||||||
if (server_acl_find(id, flags)) {
|
if (server_acl_user_find(pw->pw_uid) != NULL) {
|
||||||
cmdq_error(item, "%s %s is already added", type, name);
|
cmdq_error(item, "user %s is already added",
|
||||||
|
pw->pw_name);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
server_acl_allow(id, flags);
|
server_acl_user_allow(pw->pw_uid);
|
||||||
/* Do not return - allow -r or -w with -a. */
|
/* Do not return - allow -r or -w with -a. */
|
||||||
} else if (args_has(args, 'r') || args_has(args, 'w')) {
|
} else if (args_has(args, 'r') || args_has(args, 'w')) {
|
||||||
/* -r or -w implies -a if the entry does not exist. */
|
/* -r or -w implies -a if user does not exist. */
|
||||||
if (!server_acl_find(id, flags))
|
if (server_acl_user_find(pw->pw_uid) == NULL)
|
||||||
server_acl_allow(id, flags);
|
server_acl_user_allow(pw->pw_uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args_has(args, 'w')) {
|
if (args_has(args, 'w')) {
|
||||||
if (!server_acl_find(id, flags)) {
|
if (server_acl_user_find(pw->pw_uid) == NULL) {
|
||||||
cmdq_error(item, "%s %s not found", type, name);
|
cmdq_error(item, "user %s not found", pw->pw_name);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
server_acl_allow_write(id, flags);
|
server_acl_user_allow_write(pw->pw_uid);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args_has(args, 'r')) {
|
if (args_has(args, 'r')) {
|
||||||
if (!server_acl_find(id, flags)) {
|
if (server_acl_user_find(pw->pw_uid) == NULL) {
|
||||||
cmdq_error(item, "%s %s not found", type, name);
|
cmdq_error(item, "user %s not found", pw->pw_name);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
server_acl_deny_write(id, flags);
|
server_acl_user_deny_write(pw->pw_uid);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,44 +55,56 @@ cmd_show_prompt_history_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
const char *typestr = args_get(args, 'T');
|
const char *typestr = args_get(args, 'T');
|
||||||
enum prompt_type type;
|
enum prompt_type type;
|
||||||
u_int t, h;
|
u_int tidx, hidx;
|
||||||
const char *v;
|
|
||||||
|
|
||||||
if (cmd_get_entry(self) == &cmd_clear_prompt_history_entry) {
|
if (cmd_get_entry(self) == &cmd_clear_prompt_history_entry) {
|
||||||
if (typestr == NULL) {
|
if (typestr == NULL) {
|
||||||
for (t = 0; t < PROMPT_NTYPES; t++)
|
for (tidx = 0; tidx < PROMPT_NTYPES; tidx++) {
|
||||||
prompt_history_clear(t);
|
for (hidx = 0; hidx < status_prompt_hsize[tidx];
|
||||||
|
hidx++)
|
||||||
|
free(status_prompt_hlist[tidx][hidx]);
|
||||||
|
free(status_prompt_hlist[tidx]);
|
||||||
|
status_prompt_hlist[tidx] = NULL;
|
||||||
|
status_prompt_hsize[tidx] = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
type = prompt_type(typestr);
|
type = status_prompt_type(typestr);
|
||||||
if (type == PROMPT_TYPE_INVALID) {
|
if (type == PROMPT_TYPE_INVALID) {
|
||||||
cmdq_error(item, "invalid type: %s", typestr);
|
cmdq_error(item, "invalid type: %s", typestr);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
prompt_history_clear(type);
|
for (hidx = 0; hidx < status_prompt_hsize[type]; hidx++)
|
||||||
|
free(status_prompt_hlist[type][hidx]);
|
||||||
|
free(status_prompt_hlist[type]);
|
||||||
|
status_prompt_hlist[type] = NULL;
|
||||||
|
status_prompt_hsize[type] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typestr == NULL) {
|
if (typestr == NULL) {
|
||||||
for (t = 0; t < PROMPT_NTYPES; t++) {
|
for (tidx = 0; tidx < PROMPT_NTYPES; tidx++) {
|
||||||
typestr = prompt_type_string(t);
|
cmdq_print(item, "History for %s:\n",
|
||||||
cmdq_print(item, "History for %s:\n", typestr);
|
status_prompt_type_string(tidx));
|
||||||
for (h = 0; h < prompt_history_size(t); h++) {
|
for (hidx = 0; hidx < status_prompt_hsize[tidx];
|
||||||
v = prompt_history_get(t, h);
|
hidx++) {
|
||||||
cmdq_print(item, "%d: %s", h + 1, v);
|
cmdq_print(item, "%d: %s", hidx + 1,
|
||||||
|
status_prompt_hlist[tidx][hidx]);
|
||||||
}
|
}
|
||||||
cmdq_print(item, "%s", "");
|
cmdq_print(item, "%s", "");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
type = prompt_type(typestr);
|
type = status_prompt_type(typestr);
|
||||||
if (type == PROMPT_TYPE_INVALID) {
|
if (type == PROMPT_TYPE_INVALID) {
|
||||||
cmdq_error(item, "invalid type: %s", typestr);
|
cmdq_error(item, "invalid type: %s", typestr);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
cmdq_print(item, "History for %s:\n", prompt_type_string(type));
|
cmdq_print(item, "History for %s:\n",
|
||||||
for (h = 0; h < prompt_history_size(type); h++) {
|
status_prompt_type_string(type));
|
||||||
v = prompt_history_get(type, h);
|
for (hidx = 0; hidx < status_prompt_hsize[type]; hidx++) {
|
||||||
cmdq_print(item, "%d: %s", h + 1, v);
|
cmdq_print(item, "%d: %s", hidx + 1,
|
||||||
|
status_prompt_hlist[type][hidx]);
|
||||||
}
|
}
|
||||||
cmdq_print(item, "%s", "");
|
cmdq_print(item, "%s", "");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,12 +38,11 @@ const struct cmd_entry cmd_new_pane_entry = {
|
|||||||
.name = "new-pane",
|
.name = "new-pane",
|
||||||
.alias = "newp",
|
.alias = "newp",
|
||||||
|
|
||||||
.args = { "bB:c:de:EfF:hIkl:Lm:p:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL },
|
.args = { "bc:de:EfF:hIkl:Lm:p:PR:s:S:t:vx:X:y:Y:Z", 0, -1, NULL },
|
||||||
.usage = "[-bdefhIklPvWZ] [-B border-lines] "
|
.usage = "[-bdefhIklPvZ] [-c start-directory] [-e environment] "
|
||||||
"[-c start-directory] [-e environment] "
|
"[-F format] [-l size] [-m message] [-p percentage] "
|
||||||
"[-F format] [-l size] [-m message] [-p percentage] "
|
|
||||||
"[-s style] [-S active-border-style] "
|
"[-s style] [-S active-border-style] "
|
||||||
"[-R inactive-border-style] [-T title] [-x width] [-y height] "
|
"[-R inactive-border-style] [-x width] [-y height] "
|
||||||
"[-X x-position] [-Y y-position] " CMD_TARGET_PANE_USAGE " "
|
"[-X x-position] [-Y y-position] " CMD_TARGET_PANE_USAGE " "
|
||||||
"[shell-command [argument ...]]",
|
"[shell-command [argument ...]]",
|
||||||
|
|
||||||
@@ -57,11 +56,11 @@ const struct cmd_entry cmd_split_window_entry = {
|
|||||||
.name = "split-window",
|
.name = "split-window",
|
||||||
.alias = "splitw",
|
.alias = "splitw",
|
||||||
|
|
||||||
.args = { "bc:de:EfF:hIkl:m:p:PR:s:S:t:T:vWZ", 0, -1, NULL },
|
.args = { "bc:de:EfF:hIkl:m:p:PR:s:S:t:vZ", 0, -1, NULL },
|
||||||
.usage = "[-bdefhIklPvWZ] [-c start-directory] [-e environment] "
|
.usage = "[-bdefhIklPvZ] [-c start-directory] [-e environment] "
|
||||||
"[-F format] [-l size] [-m message] [-p percentage] "
|
"[-F format] [-l size] [-m message] [-p percentage] "
|
||||||
"[-s style] [-S active-border-style] "
|
"[-s style] [-S active-border-style] "
|
||||||
"[-R inactive-border-style] [-T title] " CMD_TARGET_PANE_USAGE " "
|
"[-R inactive-border-style] " CMD_TARGET_PANE_USAGE " "
|
||||||
"[shell-command [argument ...]]",
|
"[shell-command [argument ...]]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
@@ -85,11 +84,9 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct layout_cell *lc = NULL;
|
struct layout_cell *lc = NULL;
|
||||||
struct cmd_find_state fs;
|
struct cmd_find_state fs;
|
||||||
int input, empty, is_floating, flags = 0;
|
int input, empty, is_floating, flags = 0;
|
||||||
const char *template, *style, *value;
|
const char *template, *style;
|
||||||
char *cause = NULL, *cp, *title;
|
char *cause = NULL, *cp;
|
||||||
const struct options_table_entry *oe;
|
|
||||||
struct args_value *av;
|
struct args_value *av;
|
||||||
enum pane_lines lines;
|
|
||||||
u_int count = args_count(args);
|
u_int count = args_count(args);
|
||||||
|
|
||||||
if (cmd_get_entry(self) == &cmd_new_pane_entry)
|
if (cmd_get_entry(self) == &cmd_new_pane_entry)
|
||||||
@@ -117,24 +114,12 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (empty)
|
if (empty)
|
||||||
flags |= SPAWN_EMPTY;
|
flags |= SPAWN_EMPTY;
|
||||||
|
|
||||||
if ((value = args_get(args, 'B')) == NULL)
|
|
||||||
lines = window_get_pane_lines(w);
|
|
||||||
else {
|
|
||||||
oe = options_search("pane-border-lines");
|
|
||||||
lines = options_find_choice(oe, value, &cause);
|
|
||||||
if (cause != NULL) {
|
|
||||||
cmdq_error(item, "pane-border-lines %s", cause);
|
|
||||||
free(cause);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_floating)
|
if (is_floating)
|
||||||
lc = layout_get_floating_cell(item, args, lines, w, wp, &cause);
|
lc = layout_get_floating_cell(item, args, w, wp, &cause);
|
||||||
else
|
else
|
||||||
lc = layout_get_tiled_cell(item, args, w, wp, flags, &cause);
|
lc = layout_get_tiled_cell(item, args, w, wp, flags, &cause);
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "size or position %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
@@ -167,7 +152,10 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if ((new_wp = spawn_pane(&sc, &cause)) == NULL) {
|
if ((new_wp = spawn_pane(&sc, &cause)) == NULL) {
|
||||||
cmdq_error(item, "create pane failed: %s", cause);
|
cmdq_error(item, "create pane failed: %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
goto fail;
|
if (sc.argv != NULL)
|
||||||
|
cmd_free_argv(sc.argc, sc.argv);
|
||||||
|
environ_free(sc.environ);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
style = args_get(args, 's');
|
style = args_get(args, 's');
|
||||||
@@ -175,7 +163,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (options_set_string(new_wp->options, "window-style", 0,
|
if (options_set_string(new_wp->options, "window-style", 0,
|
||||||
"%s", style) == NULL) {
|
"%s", style) == NULL) {
|
||||||
cmdq_error(item, "bad style: %s", style);
|
cmdq_error(item, "bad style: %s", style);
|
||||||
goto fail;
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
options_set_string(new_wp->options, "window-active-style", 0,
|
options_set_string(new_wp->options, "window-active-style", 0,
|
||||||
"%s", style);
|
"%s", style);
|
||||||
@@ -187,7 +175,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (options_set_string(new_wp->options,
|
if (options_set_string(new_wp->options,
|
||||||
"pane-active-border-style", 0, "%s", style) == NULL) {
|
"pane-active-border-style", 0, "%s", style) == NULL) {
|
||||||
cmdq_error(item, "bad active border style: %s", style);
|
cmdq_error(item, "bad active border style: %s", style);
|
||||||
goto fail;
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
style = args_get(args, 'R');
|
style = args_get(args, 'R');
|
||||||
@@ -196,11 +184,9 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
"%s", style) == NULL) {
|
"%s", style) == NULL) {
|
||||||
cmdq_error(item, "bad inactive border style: %s",
|
cmdq_error(item, "bad inactive border style: %s",
|
||||||
style);
|
style);
|
||||||
goto fail;
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (args_has(args, 'B'))
|
|
||||||
options_set_number(new_wp->options, "pane-border-lines", lines);
|
|
||||||
if (args_has(args, 'k') || args_has(args, 'm')) {
|
if (args_has(args, 'k') || args_has(args, 'm')) {
|
||||||
options_set_number(new_wp->options, "remain-on-exit", 3);
|
options_set_number(new_wp->options, "remain-on-exit", 3);
|
||||||
if (args_has(args, 'm')) {
|
if (args_has(args, 'm')) {
|
||||||
@@ -209,12 +195,6 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
args_get(args, 'm'));
|
args_get(args, 'm'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (args_has(args, 'T')) {
|
|
||||||
title = format_single_from_target(item, args_get(args, 'T'));
|
|
||||||
screen_set_title(&new_wp->base, title, 0);
|
|
||||||
notify_pane("pane-title-changed", new_wp);
|
|
||||||
free(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input) {
|
if (input) {
|
||||||
switch (window_pane_start_input(new_wp, item, &cause)) {
|
switch (window_pane_start_input(new_wp, item, &cause)) {
|
||||||
@@ -225,7 +205,10 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
window_remove_pane(wp->window, new_wp);
|
window_remove_pane(wp->window, new_wp);
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
goto fail;
|
if (sc.argv != NULL)
|
||||||
|
cmd_free_argv(sc.argc, sc.argv);
|
||||||
|
environ_free(sc.environ);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
case 1:
|
case 1:
|
||||||
input = 0;
|
input = 0;
|
||||||
break;
|
break;
|
||||||
@@ -256,24 +239,5 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
environ_free(sc.environ);
|
environ_free(sc.environ);
|
||||||
if (input)
|
if (input)
|
||||||
return (CMD_RETURN_WAIT);
|
return (CMD_RETURN_WAIT);
|
||||||
|
|
||||||
if (args_has(args, 'W')) {
|
|
||||||
/*
|
|
||||||
* With -W, block this command queue item until the pane's
|
|
||||||
* command exits; window_pane_wait_finish will be called to
|
|
||||||
* continue it.
|
|
||||||
*/
|
|
||||||
new_wp->wait_item = item;
|
|
||||||
return (CMD_RETURN_WAIT);
|
|
||||||
}
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
fail:
|
|
||||||
if (sc.argv != NULL)
|
|
||||||
cmd_free_argv(sc.argc, sc.argv);
|
|
||||||
environ_free(sc.environ);
|
|
||||||
layout_destroy_cell(w, lc, &w->layout_root);
|
|
||||||
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,6 +114,10 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
dst_wp->layout_cell = src_lc;
|
dst_wp->layout_cell = src_lc;
|
||||||
dst_lc->wp = src_wp;
|
dst_lc->wp = src_wp;
|
||||||
src_wp->layout_cell = dst_lc;
|
src_wp->layout_cell = dst_lc;
|
||||||
|
if (window_pane_is_floating(src_wp) != window_pane_is_floating(dst_wp)) {
|
||||||
|
src_wp->layout_cell->flags ^= LAYOUT_CELL_FLOATING;
|
||||||
|
dst_wp->layout_cell->flags ^= LAYOUT_CELL_FLOATING;
|
||||||
|
}
|
||||||
|
|
||||||
src_wp->window = dst_w;
|
src_wp->window = dst_w;
|
||||||
options_set_parent(src_wp->options, dst_w->options);
|
options_set_parent(src_wp->options, dst_w->options);
|
||||||
@@ -149,11 +153,9 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
colour_palette_from_option(&src_wp->palette, src_wp->options);
|
colour_palette_from_option(&src_wp->palette, src_wp->options);
|
||||||
colour_palette_from_option(&dst_wp->palette, dst_wp->options);
|
colour_palette_from_option(&dst_wp->palette, dst_wp->options);
|
||||||
layout_fix_panes(src_w, NULL);
|
layout_fix_panes(src_w, NULL);
|
||||||
redraw_invalidate_scene(src_w);
|
|
||||||
server_redraw_window(src_w);
|
server_redraw_window(src_w);
|
||||||
}
|
}
|
||||||
layout_fix_panes(dst_w, NULL);
|
layout_fix_panes(dst_w, NULL);
|
||||||
redraw_invalidate_scene(dst_w);
|
|
||||||
server_redraw_window(dst_w);
|
server_redraw_window(dst_w);
|
||||||
|
|
||||||
notify_window("window-layout-changed", src_w);
|
notify_window("window-layout-changed", src_w);
|
||||||
|
|||||||
22
colour.c
22
colour.c
@@ -120,28 +120,6 @@ colour_force_rgb(int c)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dim colour by a percentage. */
|
|
||||||
int
|
|
||||||
colour_dim(int c, u_int dim)
|
|
||||||
{
|
|
||||||
u_char r, g, b;
|
|
||||||
|
|
||||||
if (dim == 0 || COLOUR_DEFAULT(c))
|
|
||||||
return (c);
|
|
||||||
if (dim >= 100)
|
|
||||||
return (colour_join_rgb(0, 0, 0));
|
|
||||||
|
|
||||||
c = colour_force_rgb(c);
|
|
||||||
if (c == -1)
|
|
||||||
return (-1);
|
|
||||||
colour_split_rgb(c, &r, &g, &b);
|
|
||||||
|
|
||||||
r = (r * (100 - dim)) / 100;
|
|
||||||
g = (g * (100 - dim)) / 100;
|
|
||||||
b = (b * (100 - dim)) / 100;
|
|
||||||
return (colour_join_rgb(r, g, b));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert colour to a string. */
|
/* Convert colour to a string. */
|
||||||
const char *
|
const char *
|
||||||
colour_tostring(int c)
|
colour_tostring(int c)
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ static int
|
|||||||
getopt_internal(int nargc, char * const *nargv, const char *options,
|
getopt_internal(int nargc, char * const *nargv, const char *options,
|
||||||
const struct option *long_options, int *idx, int flags)
|
const struct option *long_options, int *idx, int flags)
|
||||||
{
|
{
|
||||||
const char *oli; /* option letter list index */
|
char *oli; /* option letter list index */
|
||||||
int optchar, short_too;
|
int optchar, short_too;
|
||||||
static int posixly_correct = -1;
|
static int posixly_correct = -1;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# configure.ac
|
# configure.ac
|
||||||
|
|
||||||
AC_INIT([tmux], next-3.7)
|
AC_INIT([tmux], 3.7)
|
||||||
AC_PREREQ([2.60])
|
AC_PREREQ([2.60])
|
||||||
|
|
||||||
AC_CONFIG_AUX_DIR(etc)
|
AC_CONFIG_AUX_DIR(etc)
|
||||||
|
|||||||
@@ -224,14 +224,6 @@ control_notify_session_window_changed(struct session *s)
|
|||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
|
|
||||||
/*
|
|
||||||
* A deferred session-window-changed notification can fire after the
|
|
||||||
* session has been destroyed (which sets curw to NULL) but is kept
|
|
||||||
* alive by the notification's reference. Skip the notification.
|
|
||||||
*/
|
|
||||||
if (s->curw == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -152,8 +152,7 @@ environ_clear(struct environ *env, const char *name)
|
|||||||
void
|
void
|
||||||
environ_put(struct environ *env, const char *var, int flags)
|
environ_put(struct environ *env, const char *var, int flags)
|
||||||
{
|
{
|
||||||
char *name;
|
char *name, *value;
|
||||||
const char *value;
|
|
||||||
|
|
||||||
value = strchr(var, '=');
|
value = strchr(var, '=');
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
|
|||||||
320
format.c
320
format.c
@@ -117,10 +117,6 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
|
|||||||
#define FORMAT_NOT_NOT 0x100000
|
#define FORMAT_NOT_NOT 0x100000
|
||||||
#define FORMAT_REPEAT 0x200000
|
#define FORMAT_REPEAT 0x200000
|
||||||
#define FORMAT_QUOTE_ARGUMENTS 0x400000
|
#define FORMAT_QUOTE_ARGUMENTS 0x400000
|
||||||
#define FORMAT_RELATIVE 0x800000
|
|
||||||
#define FORMAT_CLIENT_TERMCAP 0x1000000
|
|
||||||
#define FORMAT_CLIENT_TERMFEAT 0x2000000
|
|
||||||
#define FORMAT_CLIENT_ENVIRON 0x4000000
|
|
||||||
|
|
||||||
/* Limit on recursion. */
|
/* Limit on recursion. */
|
||||||
#define FORMAT_LOOP_LIMIT 100
|
#define FORMAT_LOOP_LIMIT 100
|
||||||
@@ -128,9 +124,6 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
|
|||||||
/* Limit on time taken (milliseconds). */
|
/* Limit on time taken (milliseconds). */
|
||||||
#define FORMAT_TIME_LIMIT 100
|
#define FORMAT_TIME_LIMIT 100
|
||||||
|
|
||||||
/* How often to check the time in long loops. */
|
|
||||||
#define FORMAT_TIME_LOOP_CHECK 10000
|
|
||||||
|
|
||||||
/* Format expand flags. */
|
/* Format expand flags. */
|
||||||
#define FORMAT_EXPAND_TIME 0x1
|
#define FORMAT_EXPAND_TIME 0x1
|
||||||
#define FORMAT_EXPAND_NOJOBS 0x2
|
#define FORMAT_EXPAND_NOJOBS 0x2
|
||||||
@@ -576,7 +569,7 @@ format_cb_session_attached_list(struct format_tree *ft)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||||
evbuffer_free(buffer);
|
evbuffer_free(buffer);
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
@@ -715,7 +708,7 @@ format_cb_window_linked_sessions_list(struct format_tree *ft)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||||
evbuffer_free(buffer);
|
evbuffer_free(buffer);
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
@@ -769,7 +762,7 @@ format_cb_window_active_sessions_list(struct format_tree *ft)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||||
evbuffer_free(buffer);
|
evbuffer_free(buffer);
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
@@ -833,7 +826,7 @@ format_cb_window_active_clients_list(struct format_tree *ft)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||||
evbuffer_free(buffer);
|
evbuffer_free(buffer);
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
@@ -1008,7 +1001,7 @@ format_cb_pane_tabs(struct format_tree *ft)
|
|||||||
evbuffer_add_printf(buffer, "%u", i);
|
evbuffer_add_printf(buffer, "%u", i);
|
||||||
}
|
}
|
||||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||||
evbuffer_free(buffer);
|
evbuffer_free(buffer);
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
@@ -1023,7 +1016,7 @@ format_cb_pane_fg(struct format_tree *ft)
|
|||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
tty_default_colours(&gc, wp, NULL);
|
tty_default_colours(&gc, wp);
|
||||||
return (xstrdup(colour_tostring(gc.fg)));
|
return (xstrdup(colour_tostring(gc.fg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1060,7 +1053,7 @@ format_cb_pane_bg(struct format_tree *ft)
|
|||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
tty_default_colours(&gc, wp, NULL);
|
tty_default_colours(&gc, wp);
|
||||||
return (xstrdup(colour_tostring(gc.bg)));
|
return (xstrdup(colour_tostring(gc.bg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1092,7 +1085,7 @@ format_cb_session_group_list(struct format_tree *ft)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||||
evbuffer_free(buffer);
|
evbuffer_free(buffer);
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
@@ -1132,7 +1125,7 @@ format_cb_session_group_attached_list(struct format_tree *ft)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||||
evbuffer_free(buffer);
|
evbuffer_free(buffer);
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
@@ -1160,13 +1153,15 @@ static void *
|
|||||||
format_cb_pane_at_top(struct format_tree *ft)
|
format_cb_pane_at_top(struct format_tree *ft)
|
||||||
{
|
{
|
||||||
struct window_pane *wp = ft->wp;
|
struct window_pane *wp = ft->wp;
|
||||||
|
struct window *w;
|
||||||
int status, flag;
|
int status, flag;
|
||||||
char *value;
|
char *value;
|
||||||
|
|
||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
w = wp->window;
|
||||||
|
|
||||||
status = window_pane_get_pane_status(wp);
|
status = options_get_number(w->options, "pane-border-status");
|
||||||
if (status == PANE_STATUS_TOP)
|
if (status == PANE_STATUS_TOP)
|
||||||
flag = (wp->yoff == 1);
|
flag = (wp->yoff == 1);
|
||||||
else
|
else
|
||||||
@@ -1188,7 +1183,7 @@ format_cb_pane_at_bottom(struct format_tree *ft)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
w = wp->window;
|
w = wp->window;
|
||||||
|
|
||||||
status = window_pane_get_pane_status(wp);
|
status = options_get_number(w->options, "pane-border-status");
|
||||||
if (status == PANE_STATUS_BOTTOM)
|
if (status == PANE_STATUS_BOTTOM)
|
||||||
flag = (wp->yoff + (int)wp->sy == (int)w->sy - 1);
|
flag = (wp->yoff + (int)wp->sy == (int)w->sy - 1);
|
||||||
else
|
else
|
||||||
@@ -1477,33 +1472,6 @@ format_cb_client_cell_width(struct format_tree *ft)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback for client_colours. */
|
|
||||||
static void *
|
|
||||||
format_cb_client_colours(struct format_tree *ft)
|
|
||||||
{
|
|
||||||
struct tty_term *term;
|
|
||||||
u_int colours;
|
|
||||||
|
|
||||||
if (ft->c == NULL || (~ft->c->tty.flags & TTY_STARTED))
|
|
||||||
return (NULL);
|
|
||||||
term = ft->c->tty.term;
|
|
||||||
|
|
||||||
if (term->flags & TERM_RGBCOLOURS)
|
|
||||||
colours = 16777216;
|
|
||||||
else if (term->flags & TERM_256COLOURS)
|
|
||||||
colours = 256;
|
|
||||||
else {
|
|
||||||
colours = tty_term_number(term, TTYC_COLORS);
|
|
||||||
if (colours < 8)
|
|
||||||
colours = 2;
|
|
||||||
else if (colours < 16)
|
|
||||||
colours = 8;
|
|
||||||
else
|
|
||||||
colours = 16;
|
|
||||||
}
|
|
||||||
return (format_printf("%u", colours));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Callback for client_control_mode. */
|
/* Callback for client_control_mode. */
|
||||||
static void *
|
static void *
|
||||||
format_cb_client_control_mode(struct format_tree *ft)
|
format_cb_client_control_mode(struct format_tree *ft)
|
||||||
@@ -1883,6 +1851,15 @@ format_cb_keypad_flag(struct format_tree *ft)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback for loop_last_flag. */
|
||||||
|
static void *
|
||||||
|
format_cb_loop_last_flag(struct format_tree *ft)
|
||||||
|
{
|
||||||
|
if (ft->flags & FORMAT_LAST)
|
||||||
|
return (xstrdup("1"));
|
||||||
|
return (xstrdup("0"));
|
||||||
|
}
|
||||||
|
|
||||||
/* Callback for mouse_all_flag. */
|
/* Callback for mouse_all_flag. */
|
||||||
static void *
|
static void *
|
||||||
format_cb_mouse_all_flag(struct format_tree *ft)
|
format_cb_mouse_all_flag(struct format_tree *ft)
|
||||||
@@ -3241,9 +3218,6 @@ static const struct format_table_entry format_table[] = {
|
|||||||
{ "client_cell_width", FORMAT_TABLE_STRING,
|
{ "client_cell_width", FORMAT_TABLE_STRING,
|
||||||
format_cb_client_cell_width
|
format_cb_client_cell_width
|
||||||
},
|
},
|
||||||
{ "client_colours", FORMAT_TABLE_STRING,
|
|
||||||
format_cb_client_colours
|
|
||||||
},
|
|
||||||
{ "client_control_mode", FORMAT_TABLE_STRING,
|
{ "client_control_mode", FORMAT_TABLE_STRING,
|
||||||
format_cb_client_control_mode
|
format_cb_client_control_mode
|
||||||
},
|
},
|
||||||
@@ -3370,6 +3344,9 @@ static const struct format_table_entry format_table[] = {
|
|||||||
{ "last_window_index", FORMAT_TABLE_STRING,
|
{ "last_window_index", FORMAT_TABLE_STRING,
|
||||||
format_cb_last_window_index
|
format_cb_last_window_index
|
||||||
},
|
},
|
||||||
|
{ "loop_last_flag", FORMAT_TABLE_STRING,
|
||||||
|
format_cb_loop_last_flag
|
||||||
|
},
|
||||||
{ "mouse_all_flag", FORMAT_TABLE_STRING,
|
{ "mouse_all_flag", FORMAT_TABLE_STRING,
|
||||||
format_cb_mouse_all_flag
|
format_cb_mouse_all_flag
|
||||||
},
|
},
|
||||||
@@ -3797,7 +3774,7 @@ format_table_compare(const void *key0, const void *entry0)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get a format callback. */
|
/* Get a format callback. */
|
||||||
static const struct format_table_entry *
|
static struct format_table_entry *
|
||||||
format_table_get(const char *key)
|
format_table_get(const char *key)
|
||||||
{
|
{
|
||||||
return (bsearch(key, format_table, nitems(format_table),
|
return (bsearch(key, format_table, nitems(format_table),
|
||||||
@@ -4086,52 +4063,12 @@ format_pretty_time(time_t t, int seconds)
|
|||||||
return (xstrdup(s));
|
return (xstrdup(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make a relative time. */
|
|
||||||
static char *
|
|
||||||
format_relative_time(time_t t)
|
|
||||||
{
|
|
||||||
time_t now, age;
|
|
||||||
u_int d, h, m, s;
|
|
||||||
char out[32];
|
|
||||||
|
|
||||||
time(&now);
|
|
||||||
if (t > now)
|
|
||||||
return (NULL);
|
|
||||||
if (t == now)
|
|
||||||
return (xstrdup("0s"));
|
|
||||||
age = now - t;
|
|
||||||
|
|
||||||
d = age / 86400;
|
|
||||||
h = (age % 86400) / 3600;
|
|
||||||
m = (age % 3600) / 60;
|
|
||||||
s = age % 60;
|
|
||||||
|
|
||||||
if (d != 0) {
|
|
||||||
if (h != 0)
|
|
||||||
xsnprintf(out, sizeof out, "%ud%uh", d, h);
|
|
||||||
else
|
|
||||||
xsnprintf(out, sizeof out, "%ud", d);
|
|
||||||
} else if (h != 0) {
|
|
||||||
if (m != 0)
|
|
||||||
xsnprintf(out, sizeof out, "%uh%um", h, m);
|
|
||||||
else
|
|
||||||
xsnprintf(out, sizeof out, "%uh", h);
|
|
||||||
} else if (m != 0) {
|
|
||||||
if (s != 0)
|
|
||||||
xsnprintf(out, sizeof out, "%um%us", m, s);
|
|
||||||
else
|
|
||||||
xsnprintf(out, sizeof out, "%um", m);
|
|
||||||
} else
|
|
||||||
xsnprintf(out, sizeof out, "%us", s);
|
|
||||||
return (xstrdup(out));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find a format entry. */
|
/* Find a format entry. */
|
||||||
static char *
|
static char *
|
||||||
format_find(struct format_tree *ft, const char *key, int modifiers,
|
format_find(struct format_tree *ft, const char *key, int modifiers,
|
||||||
const char *time_format)
|
const char *time_format)
|
||||||
{
|
{
|
||||||
const struct format_table_entry *fte;
|
struct format_table_entry *fte;
|
||||||
void *value;
|
void *value;
|
||||||
struct format_entry *fe, fe_find;
|
struct format_entry *fe, fe_find;
|
||||||
struct environ_entry *envent;
|
struct environ_entry *envent;
|
||||||
@@ -4207,9 +4144,7 @@ found:
|
|||||||
}
|
}
|
||||||
if (t == 0)
|
if (t == 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
if (modifiers & FORMAT_RELATIVE)
|
if (modifiers & FORMAT_PRETTY)
|
||||||
found = format_relative_time(t);
|
|
||||||
else if (modifiers & FORMAT_PRETTY)
|
|
||||||
found = format_pretty_time(t, 0);
|
found = format_pretty_time(t, 0);
|
||||||
else {
|
else {
|
||||||
if (time_format != NULL) {
|
if (time_format != NULL) {
|
||||||
@@ -4258,14 +4193,10 @@ found:
|
|||||||
|
|
||||||
/* Check if format has not taken too long. */
|
/* Check if format has not taken too long. */
|
||||||
static int
|
static int
|
||||||
format_check_time(struct format_expand_state *es, u_int *check)
|
format_check_time(struct format_expand_state *es)
|
||||||
{
|
{
|
||||||
uint64_t t;
|
uint64_t t = get_timer();
|
||||||
|
|
||||||
if (check != NULL && ++*check % FORMAT_TIME_LOOP_CHECK != 0)
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
t = get_timer();
|
|
||||||
if (t - es->start_time < FORMAT_TIME_LIMIT)
|
if (t - es->start_time < FORMAT_TIME_LIMIT)
|
||||||
return (1);
|
return (1);
|
||||||
t -= es->start_time;
|
t -= es->start_time;
|
||||||
@@ -4276,24 +4207,21 @@ format_check_time(struct format_expand_state *es, u_int *check)
|
|||||||
|
|
||||||
/* Unescape escaped characters. */
|
/* Unescape escaped characters. */
|
||||||
static char *
|
static char *
|
||||||
format_unescape(struct format_expand_state *es, const char *s, size_t n)
|
format_unescape(struct format_expand_state *es, const char *s)
|
||||||
{
|
{
|
||||||
const char *end = s + n;
|
char *out, *cp;
|
||||||
char *out, *cp;
|
int brackets = 0;
|
||||||
int brackets = 0;
|
|
||||||
u_int check = 0;
|
|
||||||
|
|
||||||
cp = out = xmalloc(n + 1);
|
cp = out = xmalloc(strlen(s) + 1);
|
||||||
for (; s != end; s++) {
|
for (; *s != '\0'; s++) {
|
||||||
if (!format_check_time(es, &check)) {
|
if (!format_check_time(es)){
|
||||||
free(out);
|
free(out);
|
||||||
return (xstrdup(""));
|
return (xstrdup(""));
|
||||||
}
|
}
|
||||||
if (*s == '#' && s + 1 != end && s[1] == '{')
|
if (*s == '#' && s[1] == '{')
|
||||||
brackets++;
|
brackets++;
|
||||||
if (brackets == 0 &&
|
if (brackets == 0 &&
|
||||||
*s == '#' &&
|
*s == '#' &&
|
||||||
s + 1 != end &&
|
|
||||||
strchr(",#{}:", s[1]) != NULL) {
|
strchr(",#{}:", s[1]) != NULL) {
|
||||||
*cp++ = *++s;
|
*cp++ = *++s;
|
||||||
continue;
|
continue;
|
||||||
@@ -4312,11 +4240,10 @@ format_strip(struct format_expand_state *es, const char *s)
|
|||||||
{
|
{
|
||||||
char *out, *cp;
|
char *out, *cp;
|
||||||
int brackets = 0;
|
int brackets = 0;
|
||||||
u_int check = 0;
|
|
||||||
|
|
||||||
cp = out = xmalloc(strlen(s) + 1);
|
cp = out = xmalloc(strlen(s) + 1);
|
||||||
for (; *s != '\0'; s++) {
|
for (; *s != '\0'; s++) {
|
||||||
if (!format_check_time(es, &check)) {
|
if (!format_check_time(es)){
|
||||||
free(out);
|
free(out);
|
||||||
return (xstrdup(""));
|
return (xstrdup(""));
|
||||||
}
|
}
|
||||||
@@ -4340,10 +4267,9 @@ static const char *
|
|||||||
format_skip1(struct format_expand_state *es, const char *s, const char *end)
|
format_skip1(struct format_expand_state *es, const char *s, const char *end)
|
||||||
{
|
{
|
||||||
int brackets = 0;
|
int brackets = 0;
|
||||||
u_int check = 0;
|
|
||||||
|
|
||||||
for (; *s != '\0'; s++) {
|
for (; *s != '\0'; s++) {
|
||||||
if (es != NULL && !format_check_time(es, &check))
|
if (es != NULL && !format_check_time(es))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
if (*s == '#' && s[1] == '{')
|
if (*s == '#' && s[1] == '{')
|
||||||
brackets++;
|
brackets++;
|
||||||
@@ -4453,7 +4379,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Modifiers are a ; separated list of the forms:
|
* Modifiers are a ; separated list of the forms:
|
||||||
* l,m,C,a,b,c,d,I,n,t,w,q,E,T,S,W,P,R,<,>
|
* l,m,C,a,b,c,d,n,t,w,q,E,T,S,W,P,R,<,>
|
||||||
* =a
|
* =a
|
||||||
* =/a
|
* =/a
|
||||||
* =/a/
|
* =/a/
|
||||||
@@ -4494,7 +4420,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Now try single character with arguments. */
|
/* Now try single character with arguments. */
|
||||||
if (strchr("ImCLNPSst=pReqW", cp[0]) == NULL)
|
if (strchr("mCLNPSst=pReqW", cp[0]) == NULL)
|
||||||
break;
|
break;
|
||||||
c = cp[0];
|
c = cp[0];
|
||||||
|
|
||||||
@@ -4514,7 +4440,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
argv = xcalloc(1, sizeof *argv);
|
argv = xcalloc(1, sizeof *argv);
|
||||||
value = format_unescape(es, cp + 1, end - (cp + 1));
|
value = xstrndup(cp + 1, end - (cp + 1));
|
||||||
argv[0] = format_expand1(es, value);
|
argv[0] = format_expand1(es, value);
|
||||||
free(value);
|
free(value);
|
||||||
argc = 1;
|
argc = 1;
|
||||||
@@ -4538,7 +4464,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
|
|||||||
cp++;
|
cp++;
|
||||||
|
|
||||||
argv = xreallocarray(argv, argc + 1, sizeof *argv);
|
argv = xreallocarray(argv, argc + 1, sizeof *argv);
|
||||||
value = format_unescape(es, cp, end - cp);
|
value = xstrndup(cp, end - cp);
|
||||||
argv[argc++] = format_expand1(es, value);
|
argv[argc++] = format_expand1(es, value);
|
||||||
free(value);
|
free(value);
|
||||||
|
|
||||||
@@ -4701,19 +4627,17 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
|
|||||||
struct format_tree *nft;
|
struct format_tree *nft;
|
||||||
struct format_expand_state next;
|
struct format_expand_state next;
|
||||||
char *all, *active, *use, *expanded, *value;
|
char *all, *active, *use, *expanded, *value;
|
||||||
struct evbuffer *buffer;
|
size_t valuelen;
|
||||||
size_t size;
|
|
||||||
struct session *s, **l;
|
struct session *s, **l;
|
||||||
int i, n;
|
int i, n, last = 0;
|
||||||
|
|
||||||
if (format_choose(es, fmt, &all, &active, 0) != 0) {
|
if (format_choose(es, fmt, &all, &active, 0) != 0) {
|
||||||
all = xstrdup(fmt);
|
all = xstrdup(fmt);
|
||||||
active = NULL;
|
active = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = evbuffer_new();
|
value = xcalloc(1, 1);
|
||||||
if (buffer == NULL)
|
valuelen = 1;
|
||||||
fatalx("out of memory");
|
|
||||||
|
|
||||||
l = sort_get_sessions(&n, sc);
|
l = sort_get_sessions(&n, sc);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
@@ -4725,27 +4649,25 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
|
|||||||
use = active;
|
use = active;
|
||||||
else
|
else
|
||||||
use = all;
|
use = all;
|
||||||
nft = format_create(c, item, FORMAT_NONE, ft->flags);
|
if (i == n - 1)
|
||||||
format_add(nft, "loop_index", "%d", i);
|
last = FORMAT_LAST;
|
||||||
format_add(nft, "loop_last_flag", "%d", i == n - 1);
|
nft = format_create(c, item, FORMAT_NONE, ft->flags|last);
|
||||||
format_defaults(nft, ft->c, s, NULL, NULL);
|
format_defaults(nft, ft->c, s, NULL, NULL);
|
||||||
format_copy_state(&next, es, 0);
|
format_copy_state(&next, es, 0);
|
||||||
next.ft = nft;
|
next.ft = nft;
|
||||||
expanded = format_expand1(&next, use);
|
expanded = format_expand1(&next, use);
|
||||||
format_free(next.ft);
|
format_free(next.ft);
|
||||||
|
|
||||||
evbuffer_add(buffer, expanded, strlen(expanded));
|
valuelen += strlen(expanded);
|
||||||
|
value = xrealloc(value, valuelen);
|
||||||
|
|
||||||
|
strlcat(value, expanded, valuelen);
|
||||||
free(expanded);
|
free(expanded);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(active);
|
free(active);
|
||||||
free(all);
|
free(all);
|
||||||
|
|
||||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
|
||||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
|
||||||
else
|
|
||||||
value = xstrdup("");
|
|
||||||
evbuffer_free(buffer);
|
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4815,11 +4737,10 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
|||||||
struct format_tree *nft;
|
struct format_tree *nft;
|
||||||
struct format_expand_state next;
|
struct format_expand_state next;
|
||||||
char *all, *active, *use, *expanded, *value;
|
char *all, *active, *use, *expanded, *value;
|
||||||
struct evbuffer *buffer;
|
size_t valuelen;
|
||||||
size_t size;
|
|
||||||
struct winlink *wl, **l;
|
struct winlink *wl, **l;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
int i, n;
|
int i, n, last = 0;
|
||||||
|
|
||||||
if (ft->s == NULL) {
|
if (ft->s == NULL) {
|
||||||
format_log(es, "window loop but no session");
|
format_log(es, "window loop but no session");
|
||||||
@@ -4831,9 +4752,8 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
|||||||
active = NULL;
|
active = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = evbuffer_new();
|
value = xcalloc(1, 1);
|
||||||
if (buffer == NULL)
|
valuelen = 1;
|
||||||
fatalx("out of memory");
|
|
||||||
|
|
||||||
l = sort_get_winlinks_session(ft->s, &n, sc);
|
l = sort_get_winlinks_session(ft->s, &n, sc);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
@@ -4844,10 +4764,10 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
|||||||
use = active;
|
use = active;
|
||||||
else
|
else
|
||||||
use = all;
|
use = all;
|
||||||
|
if (i == n - 1)
|
||||||
|
last = FORMAT_LAST;
|
||||||
nft = format_create(c, item, FORMAT_WINDOW|w->id,
|
nft = format_create(c, item, FORMAT_WINDOW|w->id,
|
||||||
ft->flags);
|
ft->flags|last);
|
||||||
format_add(nft, "loop_index", "%d", i);
|
|
||||||
format_add(nft, "loop_last_flag", "%d", i == n - 1);
|
|
||||||
format_defaults(nft, ft->c, ft->s, wl, NULL);
|
format_defaults(nft, ft->c, ft->s, wl, NULL);
|
||||||
|
|
||||||
/* Add neighbor window data to the format tree. */
|
/* Add neighbor window data to the format tree. */
|
||||||
@@ -4865,18 +4785,16 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
|||||||
expanded = format_expand1(&next, use);
|
expanded = format_expand1(&next, use);
|
||||||
format_free(nft);
|
format_free(nft);
|
||||||
|
|
||||||
evbuffer_add(buffer, expanded, strlen(expanded));
|
valuelen += strlen(expanded);
|
||||||
|
value = xrealloc(value, valuelen);
|
||||||
|
|
||||||
|
strlcat(value, expanded, valuelen);
|
||||||
free(expanded);
|
free(expanded);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(active);
|
free(active);
|
||||||
free(all);
|
free(all);
|
||||||
|
|
||||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
|
||||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
|
||||||
else
|
|
||||||
value = xstrdup("");
|
|
||||||
evbuffer_free(buffer);
|
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4891,10 +4809,9 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
|
|||||||
struct format_tree *nft;
|
struct format_tree *nft;
|
||||||
struct format_expand_state next;
|
struct format_expand_state next;
|
||||||
char *all, *active, *use, *expanded, *value;
|
char *all, *active, *use, *expanded, *value;
|
||||||
struct evbuffer *buffer;
|
size_t valuelen;
|
||||||
size_t size;
|
|
||||||
struct window_pane *wp, **l;
|
struct window_pane *wp, **l;
|
||||||
int i, n;
|
int i, n, last = 0;
|
||||||
|
|
||||||
if (ft->w == NULL) {
|
if (ft->w == NULL) {
|
||||||
format_log(es, "pane loop but no window");
|
format_log(es, "pane loop but no window");
|
||||||
@@ -4906,9 +4823,8 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
|
|||||||
active = NULL;
|
active = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = evbuffer_new();
|
value = xcalloc(1, 1);
|
||||||
if (buffer == NULL)
|
valuelen = 1;
|
||||||
fatalx("out of memory");
|
|
||||||
|
|
||||||
l = sort_get_panes_window(ft->w, &n, sc);
|
l = sort_get_panes_window(ft->w, &n, sc);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
@@ -4918,28 +4834,26 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
|
|||||||
use = active;
|
use = active;
|
||||||
else
|
else
|
||||||
use = all;
|
use = all;
|
||||||
|
if (i == n - 1)
|
||||||
|
last = FORMAT_LAST;
|
||||||
nft = format_create(c, item, FORMAT_PANE|wp->id,
|
nft = format_create(c, item, FORMAT_PANE|wp->id,
|
||||||
ft->flags);
|
ft->flags|last);
|
||||||
format_add(nft, "loop_index", "%d", i);
|
|
||||||
format_add(nft, "loop_last_flag", "%d", i == n - 1);
|
|
||||||
format_defaults(nft, ft->c, ft->s, ft->wl, wp);
|
format_defaults(nft, ft->c, ft->s, ft->wl, wp);
|
||||||
format_copy_state(&next, es, 0);
|
format_copy_state(&next, es, 0);
|
||||||
next.ft = nft;
|
next.ft = nft;
|
||||||
expanded = format_expand1(&next, use);
|
expanded = format_expand1(&next, use);
|
||||||
format_free(nft);
|
format_free(nft);
|
||||||
|
|
||||||
evbuffer_add(buffer, expanded, strlen(expanded));
|
valuelen += strlen(expanded);
|
||||||
|
value = xrealloc(value, valuelen);
|
||||||
|
|
||||||
|
strlcat(value, expanded, valuelen);
|
||||||
free(expanded);
|
free(expanded);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(active);
|
free(active);
|
||||||
free(all);
|
free(all);
|
||||||
|
|
||||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
|
||||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
|
||||||
else
|
|
||||||
value = xstrdup("");
|
|
||||||
evbuffer_free(buffer);
|
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4954,36 +4868,32 @@ format_loop_clients(struct format_expand_state *es, const char *fmt)
|
|||||||
struct format_tree *nft;
|
struct format_tree *nft;
|
||||||
struct format_expand_state next;
|
struct format_expand_state next;
|
||||||
char *expanded, *value;
|
char *expanded, *value;
|
||||||
struct evbuffer *buffer;
|
size_t valuelen;
|
||||||
size_t size;
|
int i, n, last = 0;
|
||||||
int i, n;
|
|
||||||
|
|
||||||
buffer = evbuffer_new();
|
value = xcalloc(1, 1);
|
||||||
if (buffer == NULL)
|
valuelen = 1;
|
||||||
fatalx("out of memory");
|
|
||||||
|
|
||||||
l = sort_get_clients(&n, sc);
|
l = sort_get_clients(&n, sc);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
c = l[i];
|
c = l[i];
|
||||||
format_log(es, "client loop: %s", c->name);
|
format_log(es, "client loop: %s", c->name);
|
||||||
nft = format_create(c, item, 0, ft->flags);
|
if (i == n - 1)
|
||||||
format_add(nft, "loop_index", "%d", i);
|
last = FORMAT_LAST;
|
||||||
format_add(nft, "loop_last_flag", "%d", i == n - 1);
|
nft = format_create(c, item, 0, ft->flags|last);
|
||||||
format_defaults(nft, c, ft->s, ft->wl, ft->wp);
|
format_defaults(nft, c, ft->s, ft->wl, ft->wp);
|
||||||
format_copy_state(&next, es, 0);
|
format_copy_state(&next, es, 0);
|
||||||
next.ft = nft;
|
next.ft = nft;
|
||||||
expanded = format_expand1(&next, fmt);
|
expanded = format_expand1(&next, fmt);
|
||||||
format_free(nft);
|
format_free(nft);
|
||||||
|
|
||||||
evbuffer_add(buffer, expanded, strlen(expanded));
|
valuelen += strlen(expanded);
|
||||||
|
value = xrealloc(value, valuelen);
|
||||||
|
|
||||||
|
strlcat(value, expanded, valuelen);
|
||||||
free(expanded);
|
free(expanded);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
|
||||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
|
||||||
else
|
|
||||||
value = xstrdup("");
|
|
||||||
evbuffer_free(buffer);
|
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5149,9 +5059,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
struct format_modifier *list, *cmp = NULL, *search = NULL;
|
struct format_modifier *list, *cmp = NULL, *search = NULL;
|
||||||
struct format_modifier **sub = NULL, *mexp = NULL, *fm;
|
struct format_modifier **sub = NULL, *mexp = NULL, *fm;
|
||||||
struct format_modifier *bool_op_n = NULL;
|
struct format_modifier *bool_op_n = NULL;
|
||||||
u_int i, count, nsub = 0, nrep, check = 0;
|
u_int i, count, nsub = 0, nrep;
|
||||||
struct format_expand_state next;
|
struct format_expand_state next;
|
||||||
struct environ_entry *envent;
|
|
||||||
|
|
||||||
/* Set sorting defaults. */
|
/* Set sorting defaults. */
|
||||||
sc->order = SORT_ORDER;
|
sc->order = SORT_ORDER;
|
||||||
@@ -5234,29 +5143,16 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
case 'n':
|
case 'n':
|
||||||
modifiers |= FORMAT_LENGTH;
|
modifiers |= FORMAT_LENGTH;
|
||||||
break;
|
break;
|
||||||
case 'I':
|
|
||||||
if (fm->argc < 1)
|
|
||||||
break;
|
|
||||||
if (strchr(fm->argv[0], 'f') != NULL)
|
|
||||||
modifiers |= FORMAT_CLIENT_TERMFEAT;
|
|
||||||
if (strchr(fm->argv[0], 'c') != NULL)
|
|
||||||
modifiers |= FORMAT_CLIENT_TERMCAP;
|
|
||||||
if (strchr(fm->argv[0], 'e') != NULL)
|
|
||||||
modifiers |= FORMAT_CLIENT_ENVIRON;
|
|
||||||
break;
|
|
||||||
case 't':
|
case 't':
|
||||||
modifiers |= FORMAT_TIMESTRING;
|
modifiers |= FORMAT_TIMESTRING;
|
||||||
if (fm->argc < 1)
|
if (fm->argc < 1)
|
||||||
break;
|
break;
|
||||||
if (strchr(fm->argv[0], 'p') != NULL)
|
if (strchr(fm->argv[0], 'p') != NULL)
|
||||||
modifiers |= FORMAT_PRETTY;
|
modifiers |= FORMAT_PRETTY;
|
||||||
else if (strchr(fm->argv[0], 'r') != NULL)
|
|
||||||
modifiers |= FORMAT_RELATIVE;
|
|
||||||
else if (fm->argc >= 2 &&
|
else if (fm->argc >= 2 &&
|
||||||
strchr(fm->argv[0], 'f') != NULL) {
|
strchr(fm->argv[0], 'f') != NULL) {
|
||||||
free(time_format);
|
free(time_format);
|
||||||
time_format = format_strip(es,
|
time_format = format_strip(es, fm->argv[1]);
|
||||||
fm->argv[1]);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
@@ -5371,42 +5267,10 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look up client capability, feature or environment. */
|
|
||||||
if ((modifiers & FORMAT_CLIENT_TERMCAP) ||
|
|
||||||
(modifiers & FORMAT_CLIENT_TERMFEAT) ||
|
|
||||||
(modifiers & FORMAT_CLIENT_ENVIRON)) {
|
|
||||||
if (ft->c == NULL ||
|
|
||||||
ft->c->tty.term == NULL ||
|
|
||||||
ft->c->flags & CLIENT_UNATTACHEDFLAGS) {
|
|
||||||
value = xstrdup("");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (modifiers & FORMAT_CLIENT_TERMCAP) {
|
|
||||||
if (tty_term_has_name(ft->c->tty.term, copy))
|
|
||||||
value = xstrdup("1");
|
|
||||||
else
|
|
||||||
value = xstrdup("0");
|
|
||||||
}
|
|
||||||
if (modifiers & FORMAT_CLIENT_TERMFEAT) {
|
|
||||||
if (tty_feature_present(ft->c->tty.term, copy))
|
|
||||||
value = xstrdup("1");
|
|
||||||
else
|
|
||||||
value = xstrdup("0");
|
|
||||||
}
|
|
||||||
if (modifiers & FORMAT_CLIENT_ENVIRON) {
|
|
||||||
envent = environ_find(ft->c->environ, copy);
|
|
||||||
if (envent != NULL && envent->value != NULL)
|
|
||||||
value = xstrdup(envent->value);
|
|
||||||
else
|
|
||||||
value = xstrdup("");
|
|
||||||
}
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Is this a literal string? */
|
/* Is this a literal string? */
|
||||||
if (modifiers & FORMAT_LITERAL) {
|
if (modifiers & FORMAT_LITERAL) {
|
||||||
format_log(es, "literal string is '%s'", copy);
|
format_log(es, "literal string is '%s'", copy);
|
||||||
value = format_unescape(es, copy, strlen(copy));
|
value = format_unescape(es, copy);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5482,7 +5346,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
else {
|
else {
|
||||||
value = xstrdup("");
|
value = xstrdup("");
|
||||||
for (i = 0; i < nrep; i++) {
|
for (i = 0; i < nrep; i++) {
|
||||||
if (!format_check_time(es, &check)) {
|
if (!format_check_time(es)) {
|
||||||
free(right);
|
free(right);
|
||||||
free(left);
|
free(left);
|
||||||
free(value);
|
free(value);
|
||||||
@@ -5762,7 +5626,7 @@ format_expand1(struct format_expand_state *es, const char *fmt)
|
|||||||
int ch, brackets;
|
int ch, brackets;
|
||||||
char expanded[8192];
|
char expanded[8192];
|
||||||
|
|
||||||
if (fmt == NULL || *fmt == '\0' || !format_check_time(es, NULL))
|
if (fmt == NULL || *fmt == '\0' || !format_check_time(es))
|
||||||
return (xstrdup(""));
|
return (xstrdup(""));
|
||||||
|
|
||||||
if (es->loop == FORMAT_LOOP_LIMIT) {
|
if (es->loop == FORMAT_LOOP_LIMIT) {
|
||||||
|
|||||||
11
grid.c
11
grid.c
@@ -292,7 +292,7 @@ grid_free_line(struct grid *gd, u_int py)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Free several lines. */
|
/* Free several lines. */
|
||||||
void
|
static void
|
||||||
grid_free_lines(struct grid *gd, u_int py, u_int ny)
|
grid_free_lines(struct grid *gd, u_int py, u_int ny)
|
||||||
{
|
{
|
||||||
u_int yy;
|
u_int yy;
|
||||||
@@ -320,10 +320,6 @@ grid_create(u_int sx, u_int sy, u_int hlimit)
|
|||||||
gd->hsize = 0;
|
gd->hsize = 0;
|
||||||
gd->hlimit = hlimit;
|
gd->hlimit = hlimit;
|
||||||
|
|
||||||
gd->scroll_added = 0;
|
|
||||||
gd->scroll_collected = 0;
|
|
||||||
gd->scroll_generation = 0;
|
|
||||||
|
|
||||||
if (gd->sy != 0)
|
if (gd->sy != 0)
|
||||||
gd->linedata = xcalloc(gd->sy, sizeof *gd->linedata);
|
gd->linedata = xcalloc(gd->sy, sizeof *gd->linedata);
|
||||||
else
|
else
|
||||||
@@ -409,7 +405,6 @@ grid_collect_history(struct grid *gd, int all)
|
|||||||
grid_trim_history(gd, ny);
|
grid_trim_history(gd, ny);
|
||||||
|
|
||||||
gd->hsize -= ny;
|
gd->hsize -= ny;
|
||||||
gd->scroll_collected += ny;
|
|
||||||
if (gd->hscrolled > gd->hsize)
|
if (gd->hscrolled > gd->hsize)
|
||||||
gd->hscrolled = gd->hsize;
|
gd->hscrolled = gd->hsize;
|
||||||
}
|
}
|
||||||
@@ -447,7 +442,6 @@ grid_scroll_history(struct grid *gd, u_int bg)
|
|||||||
grid_compact_line(&gd->linedata[gd->hsize]);
|
grid_compact_line(&gd->linedata[gd->hsize]);
|
||||||
gd->linedata[gd->hsize].time = current_time;
|
gd->linedata[gd->hsize].time = current_time;
|
||||||
gd->hsize++;
|
gd->hsize++;
|
||||||
gd->scroll_added++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the history. */
|
/* Clear the history. */
|
||||||
@@ -458,7 +452,6 @@ grid_clear_history(struct grid *gd)
|
|||||||
|
|
||||||
gd->hscrolled = 0;
|
gd->hscrolled = 0;
|
||||||
gd->hsize = 0;
|
gd->hsize = 0;
|
||||||
gd->scroll_generation++;
|
|
||||||
|
|
||||||
gd->linedata = xreallocarray(gd->linedata, gd->sy,
|
gd->linedata = xreallocarray(gd->linedata, gd->sy,
|
||||||
sizeof *gd->linedata);
|
sizeof *gd->linedata);
|
||||||
@@ -496,7 +489,6 @@ grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower, u_int bg)
|
|||||||
/* Move the history offset down over the line. */
|
/* Move the history offset down over the line. */
|
||||||
gd->hscrolled++;
|
gd->hscrolled++;
|
||||||
gd->hsize++;
|
gd->hsize++;
|
||||||
gd->scroll_added++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expand line to fit to cell. */
|
/* Expand line to fit to cell. */
|
||||||
@@ -1518,7 +1510,6 @@ grid_reflow(struct grid *gd, u_int sx)
|
|||||||
free(gd->linedata);
|
free(gd->linedata);
|
||||||
gd->linedata = target->linedata;
|
gd->linedata = target->linedata;
|
||||||
free(target);
|
free(target);
|
||||||
gd->scroll_generation++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert to position based on wrapped lines. */
|
/* Convert to position based on wrapped lines. */
|
||||||
|
|||||||
@@ -450,11 +450,11 @@ sixel_scale(struct sixel_image *si, u_int xpixel, u_int ypixel, u_int ox,
|
|||||||
|
|
||||||
new->set_ra = si->set_ra;
|
new->set_ra = si->set_ra;
|
||||||
/* subtract offset */
|
/* subtract offset */
|
||||||
new->ra_x = si->ra_x > pox ? si->ra_x - pox : 0;
|
new->ra_x = new->ra_x > pox ? new->ra_x - pox : 0;
|
||||||
new->ra_y = si->ra_y > poy ? si->ra_y - poy : 0;
|
new->ra_y = new->ra_y > poy ? new->ra_y - poy : 0;
|
||||||
/* clamp to size */
|
/* clamp to size */
|
||||||
new->ra_x = new->ra_x < psx ? new->ra_x : psx;
|
new->ra_x = si->ra_x < psx ? si->ra_x : psx;
|
||||||
new->ra_y = new->ra_y < psy ? new->ra_y : psy;
|
new->ra_y = si->ra_y < psy ? si->ra_y : psy;
|
||||||
/* resize */
|
/* resize */
|
||||||
new->ra_x = new->ra_x * xpixel / si->xpixel;
|
new->ra_x = new->ra_x * xpixel / si->xpixel;
|
||||||
new->ra_y = new->ra_y * ypixel / si->ypixel;
|
new->ra_y = new->ra_y * ypixel / si->ypixel;
|
||||||
|
|||||||
@@ -483,7 +483,7 @@ input_key_vt10x(struct bufferevent *bev, key_code key)
|
|||||||
{
|
{
|
||||||
struct utf8_data ud;
|
struct utf8_data ud;
|
||||||
key_code onlykey;
|
key_code onlykey;
|
||||||
const char *p;
|
char *p;
|
||||||
static const char *standard_map[2] = {
|
static const char *standard_map[2] = {
|
||||||
"1!9(0)=+;:'\",<.>/-8? 2",
|
"1!9(0)=+;:'\",<.>/-8? 2",
|
||||||
"119900=+;;'',,..\x1f\x1f\x7f\x7f\0\0",
|
"119900=+;;'',,..\x1f\x1f\x7f\x7f\0\0",
|
||||||
@@ -806,7 +806,7 @@ input_key_mouse(struct window_pane *wp, struct mouse_event *m)
|
|||||||
return;
|
return;
|
||||||
if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
|
if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
|
||||||
return;
|
return;
|
||||||
if (!window_pane_is_visible(wp))
|
if (!window_pane_visible(wp))
|
||||||
return;
|
return;
|
||||||
if (!input_key_get_mouse(s, m, x, y, &buf, &len))
|
if (!input_key_get_mouse(s, m, x, y, &buf, &len))
|
||||||
return;
|
return;
|
||||||
|
|||||||
18
input.c
18
input.c
@@ -1365,7 +1365,7 @@ input_esc_dispatch(struct input_ctx *ictx)
|
|||||||
{
|
{
|
||||||
struct screen_write_ctx *sctx = &ictx->ctx;
|
struct screen_write_ctx *sctx = &ictx->ctx;
|
||||||
struct screen *s = sctx->s;
|
struct screen *s = sctx->s;
|
||||||
const struct input_table_entry *entry;
|
struct input_table_entry *entry;
|
||||||
|
|
||||||
if (ictx->flags & INPUT_DISCARD)
|
if (ictx->flags & INPUT_DISCARD)
|
||||||
return (0);
|
return (0);
|
||||||
@@ -1439,12 +1439,12 @@ input_esc_dispatch(struct input_ctx *ictx)
|
|||||||
static int
|
static int
|
||||||
input_csi_dispatch(struct input_ctx *ictx)
|
input_csi_dispatch(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
struct screen_write_ctx *sctx = &ictx->ctx;
|
struct screen_write_ctx *sctx = &ictx->ctx;
|
||||||
struct screen *s = sctx->s;
|
struct screen *s = sctx->s;
|
||||||
const struct input_table_entry *entry;
|
struct input_table_entry *entry;
|
||||||
struct options *oo;
|
struct options *oo;
|
||||||
int i, n, m, ek, set, p;
|
int i, n, m, ek, set, p;
|
||||||
u_int cx, bg = ictx->cell.cell.bg;
|
u_int cx, bg = ictx->cell.cell.bg;
|
||||||
|
|
||||||
if (ictx->flags & INPUT_DISCARD)
|
if (ictx->flags & INPUT_DISCARD)
|
||||||
return (0);
|
return (0);
|
||||||
@@ -3055,7 +3055,7 @@ input_osc_10(struct input_ctx *ictx, const char *p)
|
|||||||
return;
|
return;
|
||||||
c = window_pane_get_fg_control_client(wp);
|
c = window_pane_get_fg_control_client(wp);
|
||||||
if (c == -1) {
|
if (c == -1) {
|
||||||
tty_default_colours(&defaults, wp, NULL);
|
tty_default_colours(&defaults, wp);
|
||||||
if (COLOUR_DEFAULT(defaults.fg))
|
if (COLOUR_DEFAULT(defaults.fg))
|
||||||
c = window_pane_get_fg(wp);
|
c = window_pane_get_fg(wp);
|
||||||
else
|
else
|
||||||
@@ -3225,7 +3225,7 @@ static int
|
|||||||
input_osc_52_parse(struct input_ctx *ictx, const char *p, u_char **out,
|
input_osc_52_parse(struct input_ctx *ictx, const char *p, u_char **out,
|
||||||
int *outlen, char *clip)
|
int *outlen, char *clip)
|
||||||
{
|
{
|
||||||
const char *end;
|
char *end;
|
||||||
size_t len;
|
size_t len;
|
||||||
const char *allow = "cpqs01234567";
|
const char *allow = "cpqs01234567";
|
||||||
u_int i, j = 0;
|
u_int i, j = 0;
|
||||||
|
|||||||
@@ -25,10 +25,11 @@
|
|||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
#define DEFAULT_SESSION_MENU \
|
#define DEFAULT_SESSION_MENU \
|
||||||
" #{S/t:#{?#{&&:#{<:#{loop_index},6},#{!:#{session_active}}},'Switch To #[underscore]#{session_name}' '' {switch-client -t=#{session_id}#} ,}}" \
|
" 'Next' 'n' {switch-client -n}" \
|
||||||
|
" 'Previous' 'p' {switch-client -p}" \
|
||||||
" ''" \
|
" ''" \
|
||||||
" 'Renumber' 'N' {move-window -r}" \
|
" 'Renumber' 'N' {move-window -r}" \
|
||||||
" 'Rename' 'r' {command-prompt -I '#S' {rename-session -- '%%'}}" \
|
" 'Rename' 'r' {command-prompt -I \"#S\" {rename-session -- '%%'}}" \
|
||||||
" 'Detach' 'd' {detach-client}" \
|
" 'Detach' 'd' {detach-client}" \
|
||||||
" ''" \
|
" ''" \
|
||||||
" 'New Session' 's' {new-session}" \
|
" 'New Session' 's' {new-session}" \
|
||||||
@@ -64,7 +65,7 @@
|
|||||||
" ''" \
|
" ''" \
|
||||||
" '#{?#{&&:#{!:#{pane_floating_flag}},#{>:#{window_panes},1}},Swap Up,}' 'u' {swap-pane -U}" \
|
" '#{?#{&&:#{!:#{pane_floating_flag}},#{>:#{window_panes},1}},Swap Up,}' 'u' {swap-pane -U}" \
|
||||||
" '#{?#{&&:#{!:#{pane_floating_flag}},#{>:#{window_panes},1}},Swap Down,}' 'd' {swap-pane -D}" \
|
" '#{?#{&&:#{!:#{pane_floating_flag}},#{>:#{window_panes},1}},Swap Down,}' 'd' {swap-pane -D}" \
|
||||||
" '#{?#{!:#{pane_floating_flag}},#{?pane_marked_set,,-}Swap Marked,}' 's' {swap-pane}" \
|
" '#{?pane_marked_set,,-}Swap Marked' 's' {swap-pane}" \
|
||||||
" ''" \
|
" ''" \
|
||||||
" 'Kill' 'X' {kill-pane}" \
|
" 'Kill' 'X' {kill-pane}" \
|
||||||
" 'Respawn' 'R' {respawn-pane -k}" \
|
" 'Respawn' 'R' {respawn-pane -k}" \
|
||||||
@@ -405,10 +406,8 @@ key_bindings_init(void)
|
|||||||
"bind -N 'Choose a window from a list' w { choose-tree -Zw }",
|
"bind -N 'Choose a window from a list' w { choose-tree -Zw }",
|
||||||
"bind -N 'Kill the active pane' x { confirm-before -p\"kill-pane #P? (y/n)\" kill-pane }",
|
"bind -N 'Kill the active pane' x { confirm-before -p\"kill-pane #P? (y/n)\" kill-pane }",
|
||||||
"bind -N 'Zoom the active pane' z { resize-pane -Z }",
|
"bind -N 'Zoom the active pane' z { resize-pane -Z }",
|
||||||
"bind -N 'Move pane to top-left corner' '{' { resize-pane -x50% -y50%; move-pane -P top-left }",
|
"bind -N 'Swap the active pane with the pane above' '{' { swap-pane -U }",
|
||||||
"bind -N 'Move pane to top-right corner' '}' { resize-pane -x50% -y50%; move-pane -P top-right }",
|
"bind -N 'Swap the active pane with the pane below' '}' { swap-pane -D }",
|
||||||
"bind -N 'Move pane to bottom-left corner' 'M-{' { resize-pane -x50% -y50%; move-pane -P bottom-left }",
|
|
||||||
"bind -N 'Move pane to bottom-right corner' 'M-}' { resize-pane -x50% -y50%; move-pane -P bottom-right }",
|
|
||||||
"bind -N 'Show messages' '~' { show-messages }",
|
"bind -N 'Show messages' '~' { show-messages }",
|
||||||
"bind -N 'Enter copy mode and scroll up' PPage { copy-mode -u }",
|
"bind -N 'Enter copy mode and scroll up' PPage { copy-mode -u }",
|
||||||
"bind -N 'Select the pane above the active pane' -r Up { select-pane -U }",
|
"bind -N 'Select the pane above the active pane' -r Up { select-pane -U }",
|
||||||
@@ -430,13 +429,13 @@ key_bindings_init(void)
|
|||||||
"bind -N 'Move the visible part of the window left' -r S-Left { refresh-client -L 10 }",
|
"bind -N 'Move the visible part of the window left' -r S-Left { refresh-client -L 10 }",
|
||||||
"bind -N 'Move the visible part of the window right' -r S-Right { refresh-client -R 10 }",
|
"bind -N 'Move the visible part of the window right' -r S-Right { refresh-client -R 10 }",
|
||||||
"bind -N 'Reset so the visible part of the window follows the cursor' -r DC { refresh-client -c }",
|
"bind -N 'Reset so the visible part of the window follows the cursor' -r DC { refresh-client -c }",
|
||||||
"bind -N 'Resize the pane up by 5' -r M-Up if -F '#{?floating_pane_flag}' { resizep -D-5 } { resize-pane -U 5 }",
|
"bind -N 'Resize the pane up by 5' -r M-Up { resize-pane -U 5 }",
|
||||||
"bind -N 'Resize the pane down by 5' -r M-Down { resize-pane -D 5 }",
|
"bind -N 'Resize the pane down by 5' -r M-Down { resize-pane -D 5 }",
|
||||||
"bind -N 'Resize the pane left by 5' -r M-Left if -F '#{?floating_pane_flag}' { resizep -R-5 } { resize-pane -L 5 }",
|
"bind -N 'Resize the pane left by 5' -r M-Left { resize-pane -L 5 }",
|
||||||
"bind -N 'Resize the pane right by 5' -r M-Right resize-pane -R 5",
|
"bind -N 'Resize the pane right by 5' -r M-Right { resize-pane -R 5 }",
|
||||||
"bind -N 'Resize the pane up' -r C-Up if -F '#{?floating_pane_flag}' { resizep -D-1 } { resize-pane -U }",
|
"bind -N 'Resize the pane up' -r C-Up { resize-pane -U }",
|
||||||
"bind -N 'Resize the pane down' -r C-Down { resize-pane -D }",
|
"bind -N 'Resize the pane down' -r C-Down { resize-pane -D }",
|
||||||
"bind -N 'Resize the pane left' -r C-Left if -F '#{?floating_pane_flag}' { resizep -R-1 } { resize-pane -L }",
|
"bind -N 'Resize the pane left' -r C-Left { resize-pane -L }",
|
||||||
"bind -N 'Resize the pane right' -r C-Right { resize-pane -R }",
|
"bind -N 'Resize the pane right' -r C-Right { resize-pane -R }",
|
||||||
|
|
||||||
/* Menu keys */
|
/* Menu keys */
|
||||||
@@ -449,7 +448,6 @@ key_bindings_init(void)
|
|||||||
|
|
||||||
/* Mouse button 1 drag on pane. */
|
/* Mouse button 1 drag on pane. */
|
||||||
"bind -n MouseDrag1Pane { if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M } }",
|
"bind -n MouseDrag1Pane { if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M } }",
|
||||||
"bind -n M-MouseDrag1Pane { move-pane -M }",
|
|
||||||
|
|
||||||
/* Mouse wheel up on pane. */
|
/* Mouse wheel up on pane. */
|
||||||
"bind -n WheelUpPane { if -F '#{||:#{alternate_on},#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -e } }",
|
"bind -n WheelUpPane { if -F '#{||:#{alternate_on},#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -e } }",
|
||||||
@@ -468,7 +466,6 @@ key_bindings_init(void)
|
|||||||
|
|
||||||
/* Mouse button 1 drag on border. */
|
/* Mouse button 1 drag on border. */
|
||||||
"bind -n MouseDrag1Border { resize-pane -M }",
|
"bind -n MouseDrag1Border { resize-pane -M }",
|
||||||
"bind -n M-MouseDrag1Border { move-pane -M }",
|
|
||||||
|
|
||||||
/* Mouse button 1 down on status line. */
|
/* Mouse button 1 down on status line. */
|
||||||
"bind -n MouseDown1Status { switch-client -t= }",
|
"bind -n MouseDown1Status { switch-client -t= }",
|
||||||
@@ -485,8 +482,8 @@ key_bindings_init(void)
|
|||||||
"bind -n WheelUpStatus { previous-window }",
|
"bind -n WheelUpStatus { previous-window }",
|
||||||
|
|
||||||
/* Mouse button 3 down on status left. */
|
/* Mouse button 3 down on status left. */
|
||||||
"bind -n MouseDown3StatusLeft { run -C \"display-menu -t= -xM -yW -T '#[align=centre]#{session_name}' " DEFAULT_SESSION_MENU "\" }",
|
"bind -n MouseDown3StatusLeft { display-menu -t= -xM -yW -T '#[align=centre]#{session_name}' " DEFAULT_SESSION_MENU " }",
|
||||||
"bind -n M-MouseDown3StatusLeft { run -C \"display-menu -t= -xM -yW -T '#[align=centre]#{session_name}' " DEFAULT_SESSION_MENU "\" }",
|
"bind -n M-MouseDown3StatusLeft { display-menu -t= -xM -yW -T '#[align=centre]#{session_name}' " DEFAULT_SESSION_MENU " }",
|
||||||
|
|
||||||
/* Mouse button 3 down on status line. */
|
/* Mouse button 3 down on status line. */
|
||||||
"bind -n MouseDown3Status { display-menu -t= -xW -yW -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU "}",
|
"bind -n MouseDown3Status { display-menu -t= -xW -yW -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU "}",
|
||||||
@@ -514,8 +511,8 @@ key_bindings_init(void)
|
|||||||
"bind -Tcopy-mode M-l { send -X cursor-centre-horizontal }",
|
"bind -Tcopy-mode M-l { send -X cursor-centre-horizontal }",
|
||||||
"bind -Tcopy-mode C-n { send -X cursor-down }",
|
"bind -Tcopy-mode C-n { send -X cursor-down }",
|
||||||
"bind -Tcopy-mode C-p { send -X cursor-up }",
|
"bind -Tcopy-mode C-p { send -X cursor-up }",
|
||||||
"bind -Tcopy-mode C-r { command-prompt -P -T search -ip'(search up)' -I'#{pane_search_string}' { send -X search-backward-incremental -- '%%' } }",
|
"bind -Tcopy-mode C-r { command-prompt -T search -ip'(search up)' -I'#{pane_search_string}' { send -X search-backward-incremental -- '%%' } }",
|
||||||
"bind -Tcopy-mode C-s { command-prompt -P -T search -ip'(search down)' -I'#{pane_search_string}' { send -X search-forward-incremental -- '%%' } }",
|
"bind -Tcopy-mode C-s { command-prompt -T search -ip'(search down)' -I'#{pane_search_string}' { send -X search-forward-incremental -- '%%' } }",
|
||||||
"bind -Tcopy-mode C-v { send -X page-down }",
|
"bind -Tcopy-mode C-v { send -X page-down }",
|
||||||
"bind -Tcopy-mode C-w { send -X copy-pipe-and-cancel }",
|
"bind -Tcopy-mode C-w { send -X copy-pipe-and-cancel }",
|
||||||
"bind -Tcopy-mode Escape { send -X cancel }",
|
"bind -Tcopy-mode Escape { send -X cancel }",
|
||||||
@@ -523,18 +520,18 @@ key_bindings_init(void)
|
|||||||
"bind -Tcopy-mode Space { send -X page-down }",
|
"bind -Tcopy-mode Space { send -X page-down }",
|
||||||
"bind -Tcopy-mode , { send -X jump-reverse }",
|
"bind -Tcopy-mode , { send -X jump-reverse }",
|
||||||
"bind -Tcopy-mode \\; { send -X jump-again }",
|
"bind -Tcopy-mode \\; { send -X jump-again }",
|
||||||
"bind -Tcopy-mode F { command-prompt -P -1p'(jump backward)' { send -X jump-backward -- '%%' } }",
|
"bind -Tcopy-mode F { command-prompt -1p'(jump backward)' { send -X jump-backward -- '%%' } }",
|
||||||
"bind -Tcopy-mode N { send -X search-reverse }",
|
"bind -Tcopy-mode N { send -X search-reverse }",
|
||||||
"bind -Tcopy-mode P { send -X toggle-position }",
|
"bind -Tcopy-mode P { send -X toggle-position }",
|
||||||
"bind -Tcopy-mode R { send -X rectangle-toggle }",
|
"bind -Tcopy-mode R { send -X rectangle-toggle }",
|
||||||
"bind -Tcopy-mode T { command-prompt -P -1p'(jump to backward)' { send -X jump-to-backward -- '%%' } }",
|
"bind -Tcopy-mode T { command-prompt -1p'(jump to backward)' { send -X jump-to-backward -- '%%' } }",
|
||||||
"bind -Tcopy-mode X { send -X set-mark }",
|
"bind -Tcopy-mode X { send -X set-mark }",
|
||||||
"bind -Tcopy-mode f { command-prompt -P -1p'(jump forward)' { send -X jump-forward -- '%%' } }",
|
"bind -Tcopy-mode f { command-prompt -1p'(jump forward)' { send -X jump-forward -- '%%' } }",
|
||||||
"bind -Tcopy-mode g { command-prompt -P -p'(goto line)' { send -X goto-line -- '%%' } }",
|
"bind -Tcopy-mode g { command-prompt -p'(goto line)' { send -X goto-line -- '%%' } }",
|
||||||
"bind -Tcopy-mode n { send -X search-again }",
|
"bind -Tcopy-mode n { send -X search-again }",
|
||||||
"bind -Tcopy-mode q { send -X cancel }",
|
"bind -Tcopy-mode q { send -X cancel }",
|
||||||
"bind -Tcopy-mode r { send -X refresh-toggle }",
|
"bind -Tcopy-mode r { send -X refresh-from-pane }",
|
||||||
"bind -Tcopy-mode t { command-prompt -P -1p'(jump to forward)' { send -X jump-to-forward -- '%%' } }",
|
"bind -Tcopy-mode t { command-prompt -1p'(jump to forward)' { send -X jump-to-forward -- '%%' } }",
|
||||||
"bind -Tcopy-mode Home { send -X start-of-line }",
|
"bind -Tcopy-mode Home { send -X start-of-line }",
|
||||||
"bind -Tcopy-mode End { send -X end-of-line }",
|
"bind -Tcopy-mode End { send -X end-of-line }",
|
||||||
"bind -Tcopy-mode MouseDown1Pane select-pane",
|
"bind -Tcopy-mode MouseDown1Pane select-pane",
|
||||||
@@ -550,15 +547,15 @@ key_bindings_init(void)
|
|||||||
"bind -Tcopy-mode Down { send -X cursor-down }",
|
"bind -Tcopy-mode Down { send -X cursor-down }",
|
||||||
"bind -Tcopy-mode Left { send -X cursor-left }",
|
"bind -Tcopy-mode Left { send -X cursor-left }",
|
||||||
"bind -Tcopy-mode Right { send -X cursor-right }",
|
"bind -Tcopy-mode Right { send -X cursor-right }",
|
||||||
"bind -Tcopy-mode M-1 { command-prompt -P -Np'(repeat)' -I1 { send -N '%%' } }",
|
"bind -Tcopy-mode M-1 { command-prompt -Np'(repeat)' -I1 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode M-2 { command-prompt -P -Np'(repeat)' -I2 { send -N '%%' } }",
|
"bind -Tcopy-mode M-2 { command-prompt -Np'(repeat)' -I2 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode M-3 { command-prompt -P -Np'(repeat)' -I3 { send -N '%%' } }",
|
"bind -Tcopy-mode M-3 { command-prompt -Np'(repeat)' -I3 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode M-4 { command-prompt -P -Np'(repeat)' -I4 { send -N '%%' } }",
|
"bind -Tcopy-mode M-4 { command-prompt -Np'(repeat)' -I4 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode M-5 { command-prompt -P -Np'(repeat)' -I5 { send -N '%%' } }",
|
"bind -Tcopy-mode M-5 { command-prompt -Np'(repeat)' -I5 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode M-6 { command-prompt -P -Np'(repeat)' -I6 { send -N '%%' } }",
|
"bind -Tcopy-mode M-6 { command-prompt -Np'(repeat)' -I6 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode M-7 { command-prompt -P -Np'(repeat)' -I7 { send -N '%%' } }",
|
"bind -Tcopy-mode M-7 { command-prompt -Np'(repeat)' -I7 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode M-8 { command-prompt -P -Np'(repeat)' -I8 { send -N '%%' } }",
|
"bind -Tcopy-mode M-8 { command-prompt -Np'(repeat)' -I8 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode M-9 { command-prompt -P -Np'(repeat)' -I9 { send -N '%%' } }",
|
"bind -Tcopy-mode M-9 { command-prompt -Np'(repeat)' -I9 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode M-< { send -X history-top }",
|
"bind -Tcopy-mode M-< { send -X history-top }",
|
||||||
"bind -Tcopy-mode M-> { send -X history-bottom }",
|
"bind -Tcopy-mode M-> { send -X history-bottom }",
|
||||||
"bind -Tcopy-mode M-R { send -X top-line }",
|
"bind -Tcopy-mode M-R { send -X top-line }",
|
||||||
@@ -577,8 +574,6 @@ key_bindings_init(void)
|
|||||||
"bind -Tcopy-mode M-Down { send -X halfpage-down }",
|
"bind -Tcopy-mode M-Down { send -X halfpage-down }",
|
||||||
"bind -Tcopy-mode C-Up { send -X scroll-up }",
|
"bind -Tcopy-mode C-Up { send -X scroll-up }",
|
||||||
"bind -Tcopy-mode C-Down { send -X scroll-down }",
|
"bind -Tcopy-mode C-Down { send -X scroll-down }",
|
||||||
"bind -Tcopy-mode M-C-Up { send -X previous-prompt }",
|
|
||||||
"bind -Tcopy-mode M-C-Down { send -X next-prompt }",
|
|
||||||
|
|
||||||
/* Copy mode (vi) keys. */
|
/* Copy mode (vi) keys. */
|
||||||
"bind -Tcopy-mode-vi '#' { send -FX search-backward -- '#{copy_cursor_word}' }",
|
"bind -Tcopy-mode-vi '#' { send -FX search-backward -- '#{copy_cursor_word}' }",
|
||||||
@@ -599,25 +594,25 @@ key_bindings_init(void)
|
|||||||
"bind -Tcopy-mode-vi Space { send -X begin-selection }",
|
"bind -Tcopy-mode-vi Space { send -X begin-selection }",
|
||||||
"bind -Tcopy-mode-vi '$' { send -X end-of-line }",
|
"bind -Tcopy-mode-vi '$' { send -X end-of-line }",
|
||||||
"bind -Tcopy-mode-vi , { send -X jump-reverse }",
|
"bind -Tcopy-mode-vi , { send -X jump-reverse }",
|
||||||
"bind -Tcopy-mode-vi / { command-prompt -P -T search -p'(search down)' { send -X search-forward -- '%%' } }",
|
"bind -Tcopy-mode-vi / { command-prompt -T search -p'(search down)' { send -X search-forward -- '%%' } }",
|
||||||
"bind -Tcopy-mode-vi 0 { send -X start-of-line }",
|
"bind -Tcopy-mode-vi 0 { send -X start-of-line }",
|
||||||
"bind -Tcopy-mode-vi 1 { command-prompt -P -Np'(repeat)' -I1 { send -N '%%' } }",
|
"bind -Tcopy-mode-vi 1 { command-prompt -Np'(repeat)' -I1 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode-vi 2 { command-prompt -P -Np'(repeat)' -I2 { send -N '%%' } }",
|
"bind -Tcopy-mode-vi 2 { command-prompt -Np'(repeat)' -I2 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode-vi 3 { command-prompt -P -Np'(repeat)' -I3 { send -N '%%' } }",
|
"bind -Tcopy-mode-vi 3 { command-prompt -Np'(repeat)' -I3 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode-vi 4 { command-prompt -P -Np'(repeat)' -I4 { send -N '%%' } }",
|
"bind -Tcopy-mode-vi 4 { command-prompt -Np'(repeat)' -I4 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode-vi 5 { command-prompt -P -Np'(repeat)' -I5 { send -N '%%' } }",
|
"bind -Tcopy-mode-vi 5 { command-prompt -Np'(repeat)' -I5 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode-vi 6 { command-prompt -P -Np'(repeat)' -I6 { send -N '%%' } }",
|
"bind -Tcopy-mode-vi 6 { command-prompt -Np'(repeat)' -I6 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode-vi 7 { command-prompt -P -Np'(repeat)' -I7 { send -N '%%' } }",
|
"bind -Tcopy-mode-vi 7 { command-prompt -Np'(repeat)' -I7 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode-vi 8 { command-prompt -P -Np'(repeat)' -I8 { send -N '%%' } }",
|
"bind -Tcopy-mode-vi 8 { command-prompt -Np'(repeat)' -I8 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode-vi 9 { command-prompt -P -Np'(repeat)' -I9 { send -N '%%' } }",
|
"bind -Tcopy-mode-vi 9 { command-prompt -Np'(repeat)' -I9 { send -N '%%' } }",
|
||||||
"bind -Tcopy-mode-vi : { command-prompt -P -p'(goto line)' { send -X goto-line -- '%%' } }",
|
"bind -Tcopy-mode-vi : { command-prompt -p'(goto line)' { send -X goto-line -- '%%' } }",
|
||||||
"bind -Tcopy-mode-vi \\; { send -X jump-again }",
|
"bind -Tcopy-mode-vi \\; { send -X jump-again }",
|
||||||
"bind -Tcopy-mode-vi ? { command-prompt -P -T search -p'(search up)' { send -X search-backward -- '%%' } }",
|
"bind -Tcopy-mode-vi ? { command-prompt -T search -p'(search up)' { send -X search-backward -- '%%' } }",
|
||||||
"bind -Tcopy-mode-vi A { send -X append-selection-and-cancel }",
|
"bind -Tcopy-mode-vi A { send -X append-selection-and-cancel }",
|
||||||
"bind -Tcopy-mode-vi B { send -X previous-space }",
|
"bind -Tcopy-mode-vi B { send -X previous-space }",
|
||||||
"bind -Tcopy-mode-vi D { send -X copy-pipe-end-of-line-and-cancel }",
|
"bind -Tcopy-mode-vi D { send -X copy-pipe-end-of-line-and-cancel }",
|
||||||
"bind -Tcopy-mode-vi E { send -X next-space-end }",
|
"bind -Tcopy-mode-vi E { send -X next-space-end }",
|
||||||
"bind -Tcopy-mode-vi F { command-prompt -P -1p'(jump backward)' { send -X jump-backward -- '%%' } }",
|
"bind -Tcopy-mode-vi F { command-prompt -1p'(jump backward)' { send -X jump-backward -- '%%' } }",
|
||||||
"bind -Tcopy-mode-vi G { send -X history-bottom }",
|
"bind -Tcopy-mode-vi G { send -X history-bottom }",
|
||||||
"bind -Tcopy-mode-vi H { send -X top-line }",
|
"bind -Tcopy-mode-vi H { send -X top-line }",
|
||||||
"bind -Tcopy-mode-vi J { send -X scroll-down }",
|
"bind -Tcopy-mode-vi J { send -X scroll-down }",
|
||||||
@@ -626,14 +621,14 @@ key_bindings_init(void)
|
|||||||
"bind -Tcopy-mode-vi M { send -X middle-line }",
|
"bind -Tcopy-mode-vi M { send -X middle-line }",
|
||||||
"bind -Tcopy-mode-vi N { send -X search-reverse }",
|
"bind -Tcopy-mode-vi N { send -X search-reverse }",
|
||||||
"bind -Tcopy-mode-vi P { send -X toggle-position }",
|
"bind -Tcopy-mode-vi P { send -X toggle-position }",
|
||||||
"bind -Tcopy-mode-vi T { command-prompt -P -1p'(jump to backward)' { send -X jump-to-backward -- '%%' } }",
|
"bind -Tcopy-mode-vi T { command-prompt -1p'(jump to backward)' { send -X jump-to-backward -- '%%' } }",
|
||||||
"bind -Tcopy-mode-vi V { send -X select-line }",
|
"bind -Tcopy-mode-vi V { send -X select-line }",
|
||||||
"bind -Tcopy-mode-vi W { send -X next-space }",
|
"bind -Tcopy-mode-vi W { send -X next-space }",
|
||||||
"bind -Tcopy-mode-vi X { send -X set-mark }",
|
"bind -Tcopy-mode-vi X { send -X set-mark }",
|
||||||
"bind -Tcopy-mode-vi ^ { send -X back-to-indentation }",
|
"bind -Tcopy-mode-vi ^ { send -X back-to-indentation }",
|
||||||
"bind -Tcopy-mode-vi b { send -X previous-word }",
|
"bind -Tcopy-mode-vi b { send -X previous-word }",
|
||||||
"bind -Tcopy-mode-vi e { send -X next-word-end }",
|
"bind -Tcopy-mode-vi e { send -X next-word-end }",
|
||||||
"bind -Tcopy-mode-vi f { command-prompt -P -1p'(jump forward)' { send -X jump-forward -- '%%' } }",
|
"bind -Tcopy-mode-vi f { command-prompt -1p'(jump forward)' { send -X jump-forward -- '%%' } }",
|
||||||
"bind -Tcopy-mode-vi g { send -X history-top }",
|
"bind -Tcopy-mode-vi g { send -X history-top }",
|
||||||
"bind -Tcopy-mode-vi h { send -X cursor-left }",
|
"bind -Tcopy-mode-vi h { send -X cursor-left }",
|
||||||
"bind -Tcopy-mode-vi j { send -X cursor-down }",
|
"bind -Tcopy-mode-vi j { send -X cursor-down }",
|
||||||
@@ -643,8 +638,8 @@ key_bindings_init(void)
|
|||||||
"bind -Tcopy-mode-vi n { send -X search-again }",
|
"bind -Tcopy-mode-vi n { send -X search-again }",
|
||||||
"bind -Tcopy-mode-vi o { send -X other-end }",
|
"bind -Tcopy-mode-vi o { send -X other-end }",
|
||||||
"bind -Tcopy-mode-vi q { send -X cancel }",
|
"bind -Tcopy-mode-vi q { send -X cancel }",
|
||||||
"bind -Tcopy-mode-vi r { send -X refresh-toggle }",
|
"bind -Tcopy-mode-vi r { send -X refresh-from-pane }",
|
||||||
"bind -Tcopy-mode-vi t { command-prompt -P -1p'(jump to forward)' { send -X jump-to-forward -- '%%' } }",
|
"bind -Tcopy-mode-vi t { command-prompt -1p'(jump to forward)' { send -X jump-to-forward -- '%%' } }",
|
||||||
"bind -Tcopy-mode-vi v { send -X rectangle-toggle }",
|
"bind -Tcopy-mode-vi v { send -X rectangle-toggle }",
|
||||||
"bind -Tcopy-mode-vi w { send -X next-word }",
|
"bind -Tcopy-mode-vi w { send -X next-word }",
|
||||||
"bind -Tcopy-mode-vi '{' { send -X previous-paragraph }",
|
"bind -Tcopy-mode-vi '{' { send -X previous-paragraph }",
|
||||||
|
|||||||
@@ -379,8 +379,6 @@ layout_construct(struct layout_cell *lcparent, const char **layout,
|
|||||||
struct layout_cell *lcchild;
|
struct layout_cell *lcchild;
|
||||||
|
|
||||||
*lc = layout_construct_cell(lcparent, layout);
|
*lc = layout_construct_cell(lcparent, layout);
|
||||||
if (*lc == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
switch (**layout) {
|
switch (**layout) {
|
||||||
case ',':
|
case ',':
|
||||||
|
|||||||
407
layout.c
407
layout.c
@@ -20,25 +20,17 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The window layout is a tree of cells each of which can be one of: a
|
* The window layout is a tree of cells each of which can be one of: a
|
||||||
* left-right container for a list of cells, a top-bottom container for a list
|
* left-right container for a list of cells, a top-bottom container for a list
|
||||||
* of cells, or a container for a window pane. 'Node' will be used to refer to
|
* of cells, or a container for a window pane.
|
||||||
* a cell which contains a list of cells, and 'leaf' to refer to a cell that
|
|
||||||
* contains a window pane. A leaf is considered to be 'tiled' if it is to be
|
|
||||||
* drawn as a part of the tiled layout. A 'neighbour' is a sibling that is also
|
|
||||||
* tiled. A cell's 'split' size refers to the side that is shortened when
|
|
||||||
* splitting it, determined by the parent's type.
|
|
||||||
*
|
*
|
||||||
* Each window has a pointer to the root of its layout tree (containing its
|
* Each window has a pointer to the root of its layout tree (containing its
|
||||||
* panes), every pane has a pointer back to the cell containing it, and each
|
* panes), every pane has a pointer back to the cell containing it, and each
|
||||||
* cell a pointer to its parent cell. Every cell has a position in the root
|
* cell a pointer to its parent cell.
|
||||||
* layout tree. This position is retained through cell state changes such as
|
|
||||||
* floating or hiding.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static u_int layout_resize_check(struct window *, struct layout_cell *,
|
static u_int layout_resize_check(struct window *, struct layout_cell *,
|
||||||
@@ -248,49 +240,6 @@ layout_fix_zindexes(struct window *w, struct layout_cell *lc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
layout_cell_is_tiled(struct layout_cell *lc)
|
|
||||||
{
|
|
||||||
int is_leaf = lc->type == LAYOUT_WINDOWPANE;
|
|
||||||
int is_floating = lc->flags & LAYOUT_CELL_FLOATING;
|
|
||||||
|
|
||||||
return is_leaf && !is_floating;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
layout_cell_has_tiled_child(struct layout_cell *lc)
|
|
||||||
{
|
|
||||||
struct layout_cell *lcchild;
|
|
||||||
|
|
||||||
if (lc->type == LAYOUT_WINDOWPANE)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
|
||||||
if (layout_cell_is_tiled(lcchild) ||
|
|
||||||
layout_cell_has_tiled_child(lcchild))
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
layout_cell_is_first_tiled(struct layout_cell *lc)
|
|
||||||
{
|
|
||||||
struct layout_cell *lcchild, *lcparent = lc->parent;
|
|
||||||
|
|
||||||
if (lcparent == NULL)
|
|
||||||
return (layout_cell_is_tiled(lc));
|
|
||||||
|
|
||||||
TAILQ_FOREACH(lcchild, &lcparent->cells, entry) {
|
|
||||||
if (layout_cell_is_tiled(lcchild) ||
|
|
||||||
layout_cell_has_tiled_child(lcchild))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (lcchild == lc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Fix cell offsets for a child cell. */
|
/* Fix cell offsets for a child cell. */
|
||||||
static void
|
static void
|
||||||
layout_fix_offsets1(struct layout_cell *lc)
|
layout_fix_offsets1(struct layout_cell *lc)
|
||||||
@@ -301,8 +250,7 @@ layout_fix_offsets1(struct layout_cell *lc)
|
|||||||
if (lc->type == LAYOUT_LEFTRIGHT) {
|
if (lc->type == LAYOUT_LEFTRIGHT) {
|
||||||
xoff = lc->xoff;
|
xoff = lc->xoff;
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||||
if (!layout_cell_is_tiled(lcchild) &&
|
if (lcchild->flags & LAYOUT_CELL_FLOATING)
|
||||||
!layout_cell_has_tiled_child(lcchild))
|
|
||||||
continue;
|
continue;
|
||||||
lcchild->xoff = xoff;
|
lcchild->xoff = xoff;
|
||||||
lcchild->yoff = lc->yoff;
|
lcchild->yoff = lc->yoff;
|
||||||
@@ -313,8 +261,7 @@ layout_fix_offsets1(struct layout_cell *lc)
|
|||||||
} else {
|
} else {
|
||||||
yoff = lc->yoff;
|
yoff = lc->yoff;
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||||
if (!layout_cell_is_tiled(lcchild) &&
|
if (lcchild->flags & LAYOUT_CELL_FLOATING)
|
||||||
!layout_cell_has_tiled_child(lcchild))
|
|
||||||
continue;
|
continue;
|
||||||
lcchild->xoff = lc->xoff;
|
lcchild->xoff = lc->xoff;
|
||||||
lcchild->yoff = yoff;
|
lcchild->yoff = yoff;
|
||||||
@@ -345,15 +292,22 @@ layout_fix_offsets(struct window *w)
|
|||||||
static int
|
static int
|
||||||
layout_cell_is_top(struct window *w, struct layout_cell *lc)
|
layout_cell_is_top(struct window *w, struct layout_cell *lc)
|
||||||
{
|
{
|
||||||
struct layout_cell *next;
|
struct layout_cell *next, *edge;
|
||||||
|
|
||||||
while (lc != w->layout_root) {
|
while (lc != w->layout_root) {
|
||||||
next = lc->parent;
|
next = lc->parent;
|
||||||
if (next == NULL)
|
if (next == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
if (next->type == LAYOUT_TOPBOTTOM &&
|
if (next->type == LAYOUT_TOPBOTTOM) {
|
||||||
!layout_cell_is_first_tiled(lc))
|
edge = TAILQ_FIRST(&next->cells);
|
||||||
return (0);
|
while (edge != NULL) {
|
||||||
|
if (~edge->flags & LAYOUT_CELL_FLOATING)
|
||||||
|
break;
|
||||||
|
edge = TAILQ_NEXT(edge, entry);
|
||||||
|
}
|
||||||
|
if (lc != edge)
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
lc = next;
|
lc = next;
|
||||||
}
|
}
|
||||||
return (1);
|
return (1);
|
||||||
@@ -406,10 +360,9 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
|
|||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct layout_cell *lc;
|
struct layout_cell *lc;
|
||||||
int status, scrollbars, sb_pos, sb_w, sb_pad;
|
int status, scrollbars, sb_pos, sb_w, sb_pad;
|
||||||
int old_xoff, old_yoff, changed = 0;
|
u_int sx, sy;
|
||||||
u_int sx, sy, old_sx, old_sy;
|
|
||||||
|
|
||||||
status = window_get_pane_status(w);
|
status = options_get_number(w->options, "pane-border-status");
|
||||||
scrollbars = options_get_number(w->options, "pane-scrollbars");
|
scrollbars = options_get_number(w->options, "pane-scrollbars");
|
||||||
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
|
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
|
||||||
|
|
||||||
@@ -417,11 +370,6 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
|
|||||||
if ((lc = wp->layout_cell) == NULL || wp == skip)
|
if ((lc = wp->layout_cell) == NULL || wp == skip)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
old_xoff = wp->xoff;
|
|
||||||
old_yoff = wp->yoff;
|
|
||||||
old_sx = wp->sx;
|
|
||||||
old_sy = wp->sy;
|
|
||||||
|
|
||||||
wp->xoff = lc->xoff;
|
wp->xoff = lc->xoff;
|
||||||
wp->yoff = lc->yoff;
|
wp->yoff = lc->yoff;
|
||||||
sx = lc->sx;
|
sx = lc->sx;
|
||||||
@@ -442,7 +390,7 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
|
|||||||
if (sb_pad < 0)
|
if (sb_pad < 0)
|
||||||
sb_pad = 0;
|
sb_pad = 0;
|
||||||
if (sb_pos == PANE_SCROLLBARS_LEFT) {
|
if (sb_pos == PANE_SCROLLBARS_LEFT) {
|
||||||
if ((int)sx - sb_w - sb_pad < PANE_MINIMUM) {
|
if ((int)sx - sb_w < PANE_MINIMUM) {
|
||||||
wp->xoff = wp->xoff +
|
wp->xoff = wp->xoff +
|
||||||
(int)sx - PANE_MINIMUM;
|
(int)sx - PANE_MINIMUM;
|
||||||
sx = PANE_MINIMUM;
|
sx = PANE_MINIMUM;
|
||||||
@@ -459,15 +407,7 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
window_pane_resize(wp, sx, sy);
|
window_pane_resize(wp, sx, sy);
|
||||||
|
|
||||||
if (wp->xoff != old_xoff ||
|
|
||||||
wp->yoff != old_yoff ||
|
|
||||||
wp->sx != old_sx ||
|
|
||||||
wp->sy != old_sy)
|
|
||||||
changed = 1;
|
|
||||||
}
|
}
|
||||||
if (changed)
|
|
||||||
redraw_invalidate_scene(w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Count the number of available cells in a layout. */
|
/* Count the number of available cells in a layout. */
|
||||||
@@ -500,7 +440,7 @@ layout_resize_check(struct window *w, struct layout_cell *lc,
|
|||||||
u_int available, minimum;
|
u_int available, minimum;
|
||||||
int status, scrollbars;
|
int status, scrollbars;
|
||||||
|
|
||||||
status = window_get_pane_status(w);
|
status = options_get_number(w->options, "pane-border-status");
|
||||||
scrollbars = options_get_number(w->options, "pane-scrollbars");
|
scrollbars = options_get_number(w->options, "pane-scrollbars");
|
||||||
|
|
||||||
if (lc->type == LAYOUT_WINDOWPANE) {
|
if (lc->type == LAYOUT_WINDOWPANE) {
|
||||||
@@ -565,20 +505,13 @@ layout_resize_adjust(struct window *w, struct layout_cell *lc,
|
|||||||
/* Child cell runs in a different direction. */
|
/* Child cell runs in a different direction. */
|
||||||
if (lc->type != type) {
|
if (lc->type != type) {
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||||
if (!layout_cell_is_tiled(lcchild) &&
|
if (lcchild->flags & LAYOUT_CELL_FLOATING)
|
||||||
!layout_cell_has_tiled_child(lcchild))
|
|
||||||
continue;
|
continue;
|
||||||
layout_resize_adjust(w, lcchild, type, change);
|
layout_resize_adjust(w, lcchild, type, change);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If a node doesn't contain any tiled cells, there is nothing to do.
|
|
||||||
*/
|
|
||||||
if (!layout_cell_has_tiled_child(lc))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Child cell runs in the same direction. Adjust each child equally
|
* Child cell runs in the same direction. Adjust each child equally
|
||||||
* until no further change is possible.
|
* until no further change is possible.
|
||||||
@@ -587,8 +520,7 @@ layout_resize_adjust(struct window *w, struct layout_cell *lc,
|
|||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||||
if (change == 0)
|
if (change == 0)
|
||||||
break;
|
break;
|
||||||
if (!layout_cell_is_tiled(lcchild) &&
|
if (lcchild->flags & LAYOUT_CELL_FLOATING)
|
||||||
!layout_cell_has_tiled_child(lcchild))
|
|
||||||
continue;
|
continue;
|
||||||
if (change > 0) {
|
if (change > 0) {
|
||||||
layout_resize_adjust(w, lcchild, type, 1);
|
layout_resize_adjust(w, lcchild, type, 1);
|
||||||
@@ -603,57 +535,12 @@ layout_resize_adjust(struct window *w, struct layout_cell *lc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find and return the nearest neighbour to a cell in a specific direction. */
|
|
||||||
static struct layout_cell *
|
|
||||||
layout_cell_get_neighbour_direction(struct layout_cell *lc, int direction)
|
|
||||||
{
|
|
||||||
struct layout_cell *lcn = lc;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
if (direction)
|
|
||||||
lcn = TAILQ_NEXT(lcn, entry);
|
|
||||||
else
|
|
||||||
lcn = TAILQ_PREV(lcn, layout_cells, entry);
|
|
||||||
|
|
||||||
if (lcn == NULL ||
|
|
||||||
layout_cell_is_tiled(lcn) ||
|
|
||||||
layout_cell_has_tiled_child(lcn))
|
|
||||||
return (lcn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find and return the nearest neighbour. Prefers cells "after" the specified
|
|
||||||
* cell. This behavior defines how cell dimensions are redistributed when a cell
|
|
||||||
* is hidden/shown and floated/tiled.
|
|
||||||
*/
|
|
||||||
struct layout_cell *
|
|
||||||
layout_cell_get_neighbour(struct layout_cell *lc)
|
|
||||||
{
|
|
||||||
struct layout_cell *lcother, *lcparent = lc->parent;
|
|
||||||
int direction = 1;
|
|
||||||
|
|
||||||
if (lcparent == NULL)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
if (lc == TAILQ_LAST(&lcparent->cells, layout_cells))
|
|
||||||
direction = !direction;
|
|
||||||
|
|
||||||
lcother = layout_cell_get_neighbour_direction(lc, direction);
|
|
||||||
if (lcother == NULL)
|
|
||||||
lcother = layout_cell_get_neighbour_direction(lc, !direction);
|
|
||||||
|
|
||||||
return (lcother);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Destroy a cell and redistribute the space. */
|
/* Destroy a cell and redistribute the space. */
|
||||||
void
|
void
|
||||||
layout_destroy_cell(struct window *w, struct layout_cell *lc,
|
layout_destroy_cell(struct window *w, struct layout_cell *lc,
|
||||||
struct layout_cell **lcroot)
|
struct layout_cell **lcroot)
|
||||||
{
|
{
|
||||||
struct layout_cell *lcother = NULL, *lcparent;
|
struct layout_cell *lcother = NULL, *lcparent;
|
||||||
int change;
|
|
||||||
|
|
||||||
/* If no parent, this is the last pane in a window. */
|
/* If no parent, this is the last pane in a window. */
|
||||||
lcparent = lc->parent;
|
lcparent = lc->parent;
|
||||||
@@ -664,27 +551,27 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!layout_cell_is_tiled(lc)) {
|
if (~lc->flags & LAYOUT_CELL_FLOATING) {
|
||||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
/* Merge the space into the previous or next cell. */
|
||||||
layout_free_cell(lc);
|
if (lc == TAILQ_FIRST(&lcparent->cells))
|
||||||
goto out;
|
lcother = TAILQ_NEXT(lc, entry);
|
||||||
}
|
|
||||||
|
|
||||||
lcother = layout_cell_get_neighbour(lc);
|
|
||||||
if (lcother != NULL) {
|
|
||||||
if (lcparent->type == LAYOUT_LEFTRIGHT)
|
|
||||||
change = lc->sx + 1;
|
|
||||||
else
|
else
|
||||||
change = lc->sy + 1;
|
lcother = TAILQ_PREV(lc, layout_cells, entry);
|
||||||
layout_resize_adjust(w, lcother, lcparent->type, change);
|
}
|
||||||
} else
|
if (lcother != NULL && (~lcother->flags & LAYOUT_CELL_FLOATING)) {
|
||||||
layout_remove_tile(w, lcparent);
|
if (lcparent->type == LAYOUT_LEFTRIGHT) {
|
||||||
|
layout_resize_adjust(w, lcother, lcparent->type,
|
||||||
|
lc->sx + 1);
|
||||||
|
} else {
|
||||||
|
layout_resize_adjust(w, lcother, lcparent->type,
|
||||||
|
lc->sy + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Remove this from the parent's list. */
|
/* Remove this from the parent's list. */
|
||||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||||
layout_free_cell(lc);
|
layout_free_cell(lc);
|
||||||
|
|
||||||
out:
|
|
||||||
/*
|
/*
|
||||||
* If the parent now has one cell, remove the parent from the tree and
|
* If the parent now has one cell, remove the parent from the tree and
|
||||||
* replace it by that cell.
|
* replace it by that cell.
|
||||||
@@ -695,7 +582,7 @@ out:
|
|||||||
|
|
||||||
lc->parent = lcparent->parent;
|
lc->parent = lcparent->parent;
|
||||||
if (lc->parent == NULL) {
|
if (lc->parent == NULL) {
|
||||||
if (layout_cell_is_tiled(lc)) {
|
if (~lc->flags & LAYOUT_CELL_FLOATING) {
|
||||||
lc->xoff = 0;
|
lc->xoff = 0;
|
||||||
lc->yoff = 0;
|
lc->yoff = 0;
|
||||||
}
|
}
|
||||||
@@ -813,76 +700,6 @@ layout_resize_pane_to(struct window_pane *wp, enum layout_type type,
|
|||||||
layout_resize_pane(wp, type, change, 1);
|
layout_resize_pane(wp, type, change, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resize a floating pane to an absolute size. */
|
|
||||||
void
|
|
||||||
layout_resize_floating_pane_to(struct window_pane *wp, enum layout_type type,
|
|
||||||
u_int size, char **cause)
|
|
||||||
{
|
|
||||||
struct layout_cell *lc = wp->layout_cell;
|
|
||||||
|
|
||||||
if (~lc->flags & LAYOUT_CELL_FLOATING) {
|
|
||||||
*cause = xstrdup("pane is not floating");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window_pane_get_pane_lines(wp) != PANE_LINES_NONE &&
|
|
||||||
size >= PANE_MINIMUM + 2)
|
|
||||||
size -= 2;
|
|
||||||
if (size < PANE_MINIMUM || size > PANE_MAXIMUM) {
|
|
||||||
*cause = xstrdup("size is too big or too small");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == LAYOUT_TOPBOTTOM) {
|
|
||||||
if (lc->sy == size)
|
|
||||||
return;
|
|
||||||
lc->sy = size;
|
|
||||||
} else {
|
|
||||||
if (lc->sx == size)
|
|
||||||
return;
|
|
||||||
lc->sx = size;
|
|
||||||
}
|
|
||||||
redraw_invalidate_scene(wp->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Resize a floating pane relative to its current size. */
|
|
||||||
void
|
|
||||||
layout_resize_floating_pane(struct window_pane *wp, enum layout_type type,
|
|
||||||
int change, int opposite, char **cause)
|
|
||||||
{
|
|
||||||
struct layout_cell *lc = wp->layout_cell;
|
|
||||||
u_int size;
|
|
||||||
|
|
||||||
if (~lc->flags & LAYOUT_CELL_FLOATING) {
|
|
||||||
*cause = xstrdup("pane is not floating");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (change == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (type == LAYOUT_TOPBOTTOM) {
|
|
||||||
size = lc->sy + change;
|
|
||||||
if (size < PANE_MINIMUM || size > PANE_MAXIMUM) {
|
|
||||||
*cause = xstrdup("change is too big or too small");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lc->sy = size;
|
|
||||||
if (opposite)
|
|
||||||
lc->yoff -= change;
|
|
||||||
} else {
|
|
||||||
size = lc->sx + change;
|
|
||||||
if (size < PANE_MINIMUM || size > PANE_MAXIMUM) {
|
|
||||||
*cause = xstrdup("change is too big or too small");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lc->sx = size;
|
|
||||||
if (opposite)
|
|
||||||
lc->xoff -= change;
|
|
||||||
}
|
|
||||||
redraw_invalidate_scene(wp->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Resize a layout cell. */
|
|
||||||
void
|
void
|
||||||
layout_resize_layout(struct window *w, struct layout_cell *lc,
|
layout_resize_layout(struct window *w, struct layout_cell *lc,
|
||||||
enum layout_type type, int change, int opposite)
|
enum layout_type type, int change, int opposite)
|
||||||
@@ -916,7 +733,9 @@ void
|
|||||||
layout_resize_pane(struct window_pane *wp, enum layout_type type, int change,
|
layout_resize_pane(struct window_pane *wp, enum layout_type type, int change,
|
||||||
int opposite)
|
int opposite)
|
||||||
{
|
{
|
||||||
struct layout_cell *lc = wp->layout_cell, *lcparent;
|
struct layout_cell *lc, *lcparent;
|
||||||
|
|
||||||
|
lc = wp->layout_cell;
|
||||||
|
|
||||||
/* Find next parent of the same type. */
|
/* Find next parent of the same type. */
|
||||||
lcparent = lc->parent;
|
lcparent = lc->parent;
|
||||||
@@ -928,11 +747,8 @@ layout_resize_pane(struct window_pane *wp, enum layout_type type, int change,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* If this is the last cell, move back one. */
|
/* If this is the last cell, move back one. */
|
||||||
if (lc == TAILQ_LAST(&lcparent->cells, layout_cells)) {
|
if (lc == TAILQ_LAST(&lcparent->cells, layout_cells))
|
||||||
do
|
lc = TAILQ_PREV(lc, layout_cells, entry);
|
||||||
lc = TAILQ_PREV(lc, layout_cells, entry);
|
|
||||||
while (lc->flags & LAYOUT_CELL_FLOATING);
|
|
||||||
}
|
|
||||||
|
|
||||||
layout_resize_layout(wp->window, lc, type, change, opposite);
|
layout_resize_layout(wp->window, lc, type, change, opposite);
|
||||||
}
|
}
|
||||||
@@ -1131,8 +947,7 @@ layout_resize_child_cells(struct window *w, struct layout_cell *lc)
|
|||||||
count = 0;
|
count = 0;
|
||||||
previous = 0;
|
previous = 0;
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||||
if (!layout_cell_is_tiled(lcchild) &&
|
if (lcchild->flags & LAYOUT_CELL_FLOATING)
|
||||||
!layout_cell_has_tiled_child(lcchild))
|
|
||||||
continue;
|
continue;
|
||||||
count++;
|
count++;
|
||||||
if (lc->type == LAYOUT_LEFTRIGHT)
|
if (lc->type == LAYOUT_LEFTRIGHT)
|
||||||
@@ -1152,8 +967,7 @@ layout_resize_child_cells(struct window *w, struct layout_cell *lc)
|
|||||||
/* Resize children into the new size. */
|
/* Resize children into the new size. */
|
||||||
idx = 0;
|
idx = 0;
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||||
if (!layout_cell_is_tiled(lcchild) &&
|
if (lcchild->flags & LAYOUT_CELL_FLOATING)
|
||||||
!layout_cell_has_tiled_child(lcchild))
|
|
||||||
continue;
|
continue;
|
||||||
if (lc->type == LAYOUT_TOPBOTTOM) {
|
if (lc->type == LAYOUT_TOPBOTTOM) {
|
||||||
lcchild->sx = lc->sx;
|
lcchild->sx = lc->sx;
|
||||||
@@ -1199,7 +1013,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
|||||||
lc = wp->window->layout_root;
|
lc = wp->window->layout_root;
|
||||||
else
|
else
|
||||||
lc = wp->layout_cell;
|
lc = wp->layout_cell;
|
||||||
status = window_get_pane_status(wp->window);
|
status = options_get_number(wp->window->options, "pane-border-status");
|
||||||
scrollbars = options_get_number(wp->window->options, "pane-scrollbars");
|
scrollbars = options_get_number(wp->window->options, "pane-scrollbars");
|
||||||
|
|
||||||
/* Copy the old cell size. */
|
/* Copy the old cell size. */
|
||||||
@@ -1360,21 +1174,14 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
|||||||
* layout_assign_pane before much else happens!
|
* layout_assign_pane before much else happens!
|
||||||
*/
|
*/
|
||||||
struct layout_cell *
|
struct layout_cell *
|
||||||
layout_floating_pane(struct window *w, struct window_pane *wp, u_int sx,
|
layout_floating_pane(struct window *w, u_int sx, u_int sy, int ox, int oy)
|
||||||
u_int sy, int ox, int oy)
|
|
||||||
{
|
{
|
||||||
struct layout_cell *lc, *lcnew, *lcparent;
|
struct layout_cell *lc = w->layout_root, *lcnew, *lcparent;
|
||||||
|
|
||||||
if (wp == NULL)
|
if (lc->type == LAYOUT_WINDOWPANE) {
|
||||||
lc = w->layout_root;
|
|
||||||
else
|
|
||||||
lc = wp->layout_cell;
|
|
||||||
lcparent = lc->parent;
|
|
||||||
|
|
||||||
if (lcparent == NULL) {
|
|
||||||
/*
|
/*
|
||||||
* Adding a pane to a root that isn't node. Must create and
|
* Adding a pane to a root that doesn't have a container. Must
|
||||||
* insert a new root.
|
* create and insert a new root.
|
||||||
*/
|
*/
|
||||||
lcparent = layout_create_cell(NULL);
|
lcparent = layout_create_cell(NULL);
|
||||||
layout_make_node(lcparent, LAYOUT_TOPBOTTOM);
|
layout_make_node(lcparent, LAYOUT_TOPBOTTOM);
|
||||||
@@ -1384,10 +1191,11 @@ layout_floating_pane(struct window *w, struct window_pane *wp, u_int sx,
|
|||||||
/* Insert the old cell. */
|
/* Insert the old cell. */
|
||||||
lc->parent = lcparent;
|
lc->parent = lcparent;
|
||||||
TAILQ_INSERT_HEAD(&lcparent->cells, lc, entry);
|
TAILQ_INSERT_HEAD(&lcparent->cells, lc, entry);
|
||||||
}
|
} else
|
||||||
|
lcparent = w->layout_root;
|
||||||
|
|
||||||
lcnew = layout_create_cell(lcparent);
|
lcnew = layout_create_cell(lcparent);
|
||||||
TAILQ_INSERT_AFTER(&lcparent->cells, lc, lcnew, entry);
|
TAILQ_INSERT_TAIL(&lcparent->cells, lcnew, entry);
|
||||||
lcnew->flags |= LAYOUT_CELL_FLOATING;
|
lcnew->flags |= LAYOUT_CELL_FLOATING;
|
||||||
layout_set_size(lcnew, sx, sy, ox, oy);
|
layout_set_size(lcnew, sx, sy, ox, oy);
|
||||||
|
|
||||||
@@ -1428,7 +1236,7 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
|
|||||||
number++;
|
number++;
|
||||||
if (number <= 1)
|
if (number <= 1)
|
||||||
return (0);
|
return (0);
|
||||||
status = window_get_pane_status(w);
|
status = options_get_number(w->options, "pane-border-status");
|
||||||
|
|
||||||
if (parent->type == LAYOUT_LEFTRIGHT)
|
if (parent->type == LAYOUT_LEFTRIGHT)
|
||||||
size = parent->sx;
|
size = parent->sx;
|
||||||
@@ -1508,7 +1316,6 @@ layout_get_tiled_cell(struct cmdq_item *item, struct args *args,
|
|||||||
enum layout_type type;
|
enum layout_type type;
|
||||||
u_int curval;
|
u_int curval;
|
||||||
int size = -1;
|
int size = -1;
|
||||||
char *error = NULL;
|
|
||||||
|
|
||||||
if (window_pane_is_floating(wp)) {
|
if (window_pane_is_floating(wp)) {
|
||||||
*cause = xstrdup("can't split a floating pane");
|
*cause = xstrdup("can't split a floating pane");
|
||||||
@@ -1535,16 +1342,15 @@ layout_get_tiled_cell(struct cmdq_item *item, struct args *args,
|
|||||||
|
|
||||||
if (args_has(args, 'l')) {
|
if (args_has(args, 'l')) {
|
||||||
size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
|
size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
|
||||||
item, &error);
|
item, cause);
|
||||||
} else if (args_has(args, 'p')) {
|
} else if (args_has(args, 'p')) {
|
||||||
size = args_strtonum_and_expand(args, 'p', 0, 100, item,
|
size = args_strtonum_and_expand(args, 'p', 0, 100, item,
|
||||||
&error);
|
cause);
|
||||||
if (error == NULL)
|
if (*cause == NULL)
|
||||||
size = curval * size / 100;
|
size = curval * size / 100;
|
||||||
}
|
}
|
||||||
if (error != NULL) {
|
if (*cause != NULL) {
|
||||||
xasprintf(cause, "invalid tiled geometry %s", error);
|
*cause = xstrdup("invalid tiled geometry");
|
||||||
free(error);
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1564,53 +1370,35 @@ layout_get_tiled_cell(struct cmdq_item *item, struct args *args,
|
|||||||
/* Get a new floating cell. */
|
/* Get a new floating cell. */
|
||||||
struct layout_cell *
|
struct layout_cell *
|
||||||
layout_get_floating_cell(struct cmdq_item *item, struct args *args,
|
layout_get_floating_cell(struct cmdq_item *item, struct args *args,
|
||||||
enum pane_lines lines, struct window *w, struct window_pane *wp,
|
struct window *w, __unused struct window_pane *wp, char **cause)
|
||||||
char **cause)
|
|
||||||
{
|
{
|
||||||
struct layout_cell *lcnew;
|
struct layout_cell *lcnew;
|
||||||
int sx = w->sx / 2, sy = w->sy / 4;
|
int sx = w->sx / 2, sy = w->sy / 4;
|
||||||
int ox = INT_MAX, oy = INT_MAX;
|
int ox = INT_MAX, oy = INT_MAX;
|
||||||
char *error;
|
|
||||||
|
|
||||||
if (args_has(args, 'x')) {
|
if (args_has(args, 'x')) {
|
||||||
sx = args_percentage_and_expand(args, 'x', 0, PANE_MAXIMUM,
|
sx = args_percentage_and_expand(args, 'x', 0, w->sx - 1, w->sx,
|
||||||
w->sx, item, &error);
|
item, cause);
|
||||||
if (error != NULL) {
|
if (*cause != NULL)
|
||||||
xasprintf(cause, "position %s", error);
|
|
||||||
free(error);
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
|
||||||
if (lines != PANE_LINES_NONE)
|
|
||||||
sx -= 2;
|
|
||||||
}
|
}
|
||||||
if (args_has(args, 'y')) {
|
if (args_has(args, 'y')) {
|
||||||
sy = args_percentage_and_expand(args, 'y', 0, PANE_MAXIMUM,
|
sy = args_percentage_and_expand(args, 'y', 0, w->sy - 1, w->sy,
|
||||||
w->sy, item, &error);
|
item, cause);
|
||||||
if (error != NULL) {
|
if (*cause != NULL)
|
||||||
xasprintf(cause, "position %s", error);
|
|
||||||
free(error);
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
|
||||||
if (lines != PANE_LINES_NONE)
|
|
||||||
sy -= 2;
|
|
||||||
}
|
}
|
||||||
if (args_has(args, 'X')) {
|
if (args_has(args, 'X')) {
|
||||||
ox = args_percentage_and_expand(args, 'X', -sx, w->sx,
|
ox = args_percentage_and_expand(args, 'X', -sx, w->sx,
|
||||||
w->sx, item, &error);
|
w->sx, item, cause);
|
||||||
if (error != NULL) {
|
if (*cause != NULL)
|
||||||
xasprintf(cause, "size %s", error);
|
|
||||||
free(error);
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (args_has(args, 'Y')) {
|
if (args_has(args, 'Y')) {
|
||||||
oy = args_percentage_and_expand(args, 'Y', -sy, w->sy,
|
oy = args_percentage_and_expand(args, 'Y', -sy, w->sy,
|
||||||
w->sy, item, &error);
|
w->sy, item, cause);
|
||||||
if (error != NULL) {
|
if (*cause != NULL)
|
||||||
xasprintf(cause, "size %s", error);
|
|
||||||
free(error);
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ox == INT_MAX) {
|
if (ox == INT_MAX) {
|
||||||
@@ -1622,9 +1410,7 @@ layout_get_floating_cell(struct cmdq_item *item, struct args *args,
|
|||||||
ox = 4;
|
ox = 4;
|
||||||
}
|
}
|
||||||
w->last_new_pane_x = ox;
|
w->last_new_pane_x = ox;
|
||||||
} else
|
}
|
||||||
if (lines != PANE_LINES_NONE)
|
|
||||||
ox += 1;
|
|
||||||
if (oy == INT_MAX) {
|
if (oy == INT_MAX) {
|
||||||
if (w->last_new_pane_y == 0)
|
if (w->last_new_pane_y == 0)
|
||||||
oy = 2;
|
oy = 2;
|
||||||
@@ -1634,55 +1420,8 @@ layout_get_floating_cell(struct cmdq_item *item, struct args *args,
|
|||||||
oy = 2;
|
oy = 2;
|
||||||
}
|
}
|
||||||
w->last_new_pane_y = oy;
|
w->last_new_pane_y = oy;
|
||||||
} else
|
|
||||||
if (lines != PANE_LINES_NONE)
|
|
||||||
oy += 1;
|
|
||||||
|
|
||||||
if (sx < PANE_MINIMUM || sx > PANE_MAXIMUM) {
|
|
||||||
*cause = xstrdup("invalid width");
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
if (sy < PANE_MINIMUM || sy > PANE_MAXIMUM) {
|
|
||||||
*cause = xstrdup("invalid height");
|
|
||||||
return (NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lcnew = layout_floating_pane(w, wp, sx, sy, ox, oy);
|
lcnew = layout_floating_pane(w, sx, sy, ox, oy);
|
||||||
return (lcnew);
|
return (lcnew);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Removes a cell from the tiled layout by giving the cell's space to the
|
|
||||||
* nearest neighbour.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
layout_remove_tile(struct window *w, struct layout_cell *lc)
|
|
||||||
{
|
|
||||||
struct layout_cell *lcneighbour, *lcparent;
|
|
||||||
enum layout_type type;
|
|
||||||
int change;
|
|
||||||
|
|
||||||
if (lc->flags & LAYOUT_CELL_FLOATING)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
lcneighbour = layout_cell_get_neighbour(lc);
|
|
||||||
if (lcneighbour == NULL) {
|
|
||||||
if (lc->parent != NULL)
|
|
||||||
layout_remove_tile(w, lc->parent);
|
|
||||||
} else if ((lcparent = lcneighbour->parent) != NULL) {
|
|
||||||
type = lcparent->type;
|
|
||||||
/*
|
|
||||||
* Adding the size of the layout cell plus its border to the
|
|
||||||
* neighbour.
|
|
||||||
*/
|
|
||||||
if (type == LAYOUT_TOPBOTTOM)
|
|
||||||
change = lc->sy + 1;
|
|
||||||
else
|
|
||||||
change = lc->sx + 1;
|
|
||||||
layout_resize_adjust(w, lcneighbour, type, change);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Zeroing out the cell geometry until the cell is retiled. */
|
|
||||||
layout_set_size(lc, 0, 0, 0, 0);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|||||||
15
menu.c
15
menu.c
@@ -257,7 +257,8 @@ menu_reapply_styles(struct menu_data *md, struct client *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
menu_draw_cb(struct client *c, void *data)
|
menu_draw_cb(struct client *c, void *data,
|
||||||
|
__unused struct screen_redraw_ctx *rctx)
|
||||||
{
|
{
|
||||||
struct menu_data *md = data;
|
struct menu_data *md = data;
|
||||||
struct tty *tty = &c->tty;
|
struct tty *tty = &c->tty;
|
||||||
@@ -280,8 +281,10 @@ menu_draw_cb(struct client *c, void *data)
|
|||||||
&md->style_gc, &md->border_style_gc, &md->selected_style_gc);
|
&md->style_gc, &md->border_style_gc, &md->selected_style_gc);
|
||||||
screen_write_stop(&ctx);
|
screen_write_stop(&ctx);
|
||||||
|
|
||||||
for (i = 0; i < screen_size_y(&md->s); i++)
|
for (i = 0; i < screen_size_y(&md->s); i++) {
|
||||||
tty_draw_line(tty, s, 0, i, menu->width + 4, px, py + i, NULL);
|
tty_draw_line(tty, s, 0, i, menu->width + 4, px, py + i,
|
||||||
|
&grid_default_cell, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -437,7 +440,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while ((name == NULL || *name == '-') && md->choice != 0) {
|
while (name == NULL || *name == '-') {
|
||||||
md->choice--;
|
md->choice--;
|
||||||
name = menu->items[md->choice].name;
|
name = menu->items[md->choice].name;
|
||||||
}
|
}
|
||||||
@@ -447,7 +450,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event)
|
|||||||
case KEYC_HOME:
|
case KEYC_HOME:
|
||||||
md->choice = 0;
|
md->choice = 0;
|
||||||
name = menu->items[md->choice].name;
|
name = menu->items[md->choice].name;
|
||||||
while ((name == NULL || *name == '-') && md->choice != count - 1) {
|
while (name == NULL || *name == '-') {
|
||||||
md->choice++;
|
md->choice++;
|
||||||
name = menu->items[md->choice].name;
|
name = menu->items[md->choice].name;
|
||||||
}
|
}
|
||||||
@@ -457,7 +460,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event)
|
|||||||
case KEYC_END:
|
case KEYC_END:
|
||||||
md->choice = count - 1;
|
md->choice = count - 1;
|
||||||
name = menu->items[md->choice].name;
|
name = menu->items[md->choice].name;
|
||||||
while ((name == NULL || *name == '-') && md->choice != 0) {
|
while (name == NULL || *name == '-') {
|
||||||
md->choice--;
|
md->choice--;
|
||||||
name = menu->items[md->choice].name;
|
name = menu->items[md->choice].name;
|
||||||
}
|
}
|
||||||
|
|||||||
451
mode-tree.c
451
mode-tree.c
@@ -37,7 +37,6 @@ enum mode_tree_preview {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct mode_tree_item;
|
struct mode_tree_item;
|
||||||
struct mode_tree_prompt;
|
|
||||||
TAILQ_HEAD(mode_tree_list, mode_tree_item);
|
TAILQ_HEAD(mode_tree_list, mode_tree_item);
|
||||||
|
|
||||||
struct mode_tree_data {
|
struct mode_tree_data {
|
||||||
@@ -50,13 +49,12 @@ struct mode_tree_data {
|
|||||||
const struct menu_item *menu;
|
const struct menu_item *menu;
|
||||||
|
|
||||||
struct sort_criteria sort_crit;
|
struct sort_criteria sort_crit;
|
||||||
const char *view_name;
|
|
||||||
|
|
||||||
mode_tree_build_cb buildcb;
|
mode_tree_build_cb buildcb;
|
||||||
mode_tree_draw_cb drawcb;
|
mode_tree_draw_cb drawcb;
|
||||||
mode_tree_search_cb searchcb;
|
mode_tree_search_cb searchcb;
|
||||||
mode_tree_menu_cb menucb;
|
mode_tree_menu_cb menucb;
|
||||||
mode_tree_height_cb heightcb;
|
mode_tree_height_cb heightcb;
|
||||||
mode_tree_key_cb keycb;
|
mode_tree_key_cb keycb;
|
||||||
mode_tree_swap_cb swapcb;
|
mode_tree_swap_cb swapcb;
|
||||||
mode_tree_sort_cb sortcb;
|
mode_tree_sort_cb sortcb;
|
||||||
@@ -78,10 +76,6 @@ struct mode_tree_data {
|
|||||||
u_int current;
|
u_int current;
|
||||||
|
|
||||||
struct screen screen;
|
struct screen screen;
|
||||||
struct prompt *prompt;
|
|
||||||
struct mode_tree_prompt *prompt_data;
|
|
||||||
u_int prompt_cx;
|
|
||||||
int prompt_top;
|
|
||||||
|
|
||||||
int preview;
|
int preview;
|
||||||
char *search;
|
char *search;
|
||||||
@@ -89,7 +83,6 @@ struct mode_tree_data {
|
|||||||
int no_matches;
|
int no_matches;
|
||||||
enum mode_tree_search_dir search_dir;
|
enum mode_tree_search_dir search_dir;
|
||||||
int search_icase;
|
int search_icase;
|
||||||
int help;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mode_tree_item {
|
struct mode_tree_item {
|
||||||
@@ -129,25 +122,7 @@ struct mode_tree_menu {
|
|||||||
u_int line;
|
u_int line;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
static void mode_tree_free_items(struct mode_tree_list *);
|
||||||
* Wrapper around a prompt owned by a mode tree. The mode tree holds a reference
|
|
||||||
* while the prompt is alive; the wrapper callbacks forward to the caller's
|
|
||||||
* callbacks and drop that reference when the prompt is freed.
|
|
||||||
*/
|
|
||||||
struct mode_tree_prompt {
|
|
||||||
struct mode_tree_data *mtd;
|
|
||||||
struct client *c;
|
|
||||||
mode_tree_prompt_input_cb inputcb;
|
|
||||||
prompt_free_cb freecb;
|
|
||||||
void *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void mode_tree_free_items(struct mode_tree_list *);
|
|
||||||
static void mode_tree_draw_help(struct mode_tree_data *,
|
|
||||||
struct screen_write_ctx *);
|
|
||||||
static void mode_tree_draw_prompt(struct mode_tree_data *,
|
|
||||||
struct screen_write_ctx *);
|
|
||||||
static enum cmd_retval mode_tree_prompt_accept(struct cmdq_item *, void *);
|
|
||||||
|
|
||||||
static const struct menu_item mode_tree_menu_items[] = {
|
static const struct menu_item mode_tree_menu_items[] = {
|
||||||
{ "Scroll Left", '<', NULL },
|
{ "Scroll Left", '<', NULL },
|
||||||
@@ -159,31 +134,31 @@ static const struct menu_item mode_tree_menu_items[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const char* mode_tree_help_start[] = {
|
static const char* mode_tree_help_start[] = {
|
||||||
"#[bold] Up, k #[default]#[acs]x#[default] Move cursor up",
|
"\r\033[1m Up, k \033[0m\016x\017 \033[0mMove cursor up\n",
|
||||||
"#[bold] Down, j #[default]#[acs]x#[default] Move cursor down",
|
"\r\033[1m Down, j \033[0m\016x\017 \033[0mMove cursor down\n",
|
||||||
"#[bold] g #[default]#[acs]x#[default] Go to top",
|
"\r\033[1m g \033[0m\016x\017 \033[0mGo to top\n",
|
||||||
"#[bold] G #[default]#[acs]x#[default] Go to bottom",
|
"\r\033[1m G \033[0m\016x\017 \033[0mGo to bottom\n",
|
||||||
"#[bold] PPage, C-b #[default]#[acs]x#[default] Page up",
|
"\r\033[1m PPage, C-b \033[0m\016x\017 \033[0mPage up\n",
|
||||||
"#[bold] NPage, C-f #[default]#[acs]x#[default] Page down",
|
"\r\033[1m NPage, C-f \033[0m\016x\017 \033[0mPage down\n",
|
||||||
"#[bold] Left, h #[default]#[acs]x#[default] Collapse %1",
|
"\r\033[1m Left, h \033[0m\016x\017 \033[0mCollapse %1\n",
|
||||||
"#[bold] Right, l #[default]#[acs]x#[default] Expand %1",
|
"\r\033[1m Right, l \033[0m\016x\017 \033[0mExpand %1\n",
|
||||||
"#[bold] M-- #[default]#[acs]x#[default] Collapse all %1s",
|
"\r\033[1m M-- \033[0m\016x\017 \033[0mCollapse all %1s\n",
|
||||||
"#[bold] M-+ #[default]#[acs]x#[default] Expand all %1s",
|
"\r\033[1m M-+ \033[0m\016x\017 \033[0mExpand all %1s\n",
|
||||||
"#[bold] t #[default]#[acs]x#[default] Toggle %1 tag",
|
"\r\033[1m t \033[0m\016x\017 \033[0mToggle %1 tag\n",
|
||||||
"#[bold] T #[default]#[acs]x#[default] Untag all %1s",
|
"\r\033[1m T \033[0m\016x\017 \033[0mUntag all %1s\n",
|
||||||
"#[bold] C-t #[default]#[acs]x#[default] Tag all %1s",
|
"\r\033[1m C-t \033[0m\016x\017 \033[0mTag all %1s\n",
|
||||||
"#[bold] C-s #[default]#[acs]x#[default] Search forward",
|
"\r\033[1m C-s \033[0m\016x\017 \033[0mSearch forward\n",
|
||||||
"#[bold] C-r #[default]#[acs]x#[default] Search backward",
|
"\r\033[1m C-r \033[0m\016x\017 \033[0mSearch backward\n",
|
||||||
"#[bold] n #[default]#[acs]x#[default] Repeat search forward",
|
"\r\033[1m n \033[0m\016x\017 \033[0mRepeat search forward\n",
|
||||||
"#[bold] N #[default]#[acs]x#[default] Repeat search backward",
|
"\r\033[1m N \033[0m\016x\017 \033[0mRepeat search backward\n",
|
||||||
"#[bold] f #[default]#[acs]x#[default] Filter %1s",
|
"\r\033[1m f \033[0m\016x\017 \033[0mFilter %1s\n",
|
||||||
"#[bold] O #[default]#[acs]x#[default] Change sort order",
|
"\r\033[1m O \033[0m\016x\017 \033[0mChange sort order\n",
|
||||||
"#[bold] r #[default]#[acs]x#[default] Reverse sort order",
|
"\r\033[1m r \033[0m\016x\017 \033[0mReverse sort order\n",
|
||||||
"#[bold] v #[default]#[acs]x#[default] Toggle preview",
|
"\r\033[1m v \033[0m\016x\017 \033[0mToggle preview\n",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
static const char* mode_tree_help_end[] = {
|
static const char* mode_tree_help_end[] = {
|
||||||
"#[bold] q, Escape #[default]#[acs]x#[default] Exit mode",
|
"\r\033[1m q, Escape \033[0m\016x\017 \033[0mExit mode\033[H",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
#define MODE_TREE_HELP_DEFAULT_WIDTH 39
|
#define MODE_TREE_HELP_DEFAULT_WIDTH 39
|
||||||
@@ -403,13 +378,6 @@ mode_tree_get_current_name(struct mode_tree_data *mtd)
|
|||||||
return (mtd->line_list[mtd->current].item->name);
|
return (mtd->line_list[mtd->current].item->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
mode_tree_select_top(struct mode_tree_data *mtd)
|
|
||||||
{
|
|
||||||
mtd->current = 0;
|
|
||||||
mtd->offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mode_tree_expand_current(struct mode_tree_data *mtd)
|
mode_tree_expand_current(struct mode_tree_data *mtd)
|
||||||
{
|
{
|
||||||
@@ -537,9 +505,7 @@ mode_tree_start(struct window_pane *wp, struct args *args,
|
|||||||
mtd->modedata = modedata;
|
mtd->modedata = modedata;
|
||||||
mtd->menu = menu;
|
mtd->menu = menu;
|
||||||
|
|
||||||
if (drawcb == NULL)
|
if (args_has(args, 'N') > 1)
|
||||||
mtd->preview = MODE_TREE_PREVIEW_OFF;
|
|
||||||
else if (args_has(args, 'N') > 1)
|
|
||||||
mtd->preview = MODE_TREE_PREVIEW_BIG;
|
mtd->preview = MODE_TREE_PREVIEW_BIG;
|
||||||
else if (args_has(args, 'N'))
|
else if (args_has(args, 'N'))
|
||||||
mtd->preview = MODE_TREE_PREVIEW_OFF;
|
mtd->preview = MODE_TREE_PREVIEW_OFF;
|
||||||
@@ -671,7 +637,6 @@ mode_tree_free(struct mode_tree_data *mtd)
|
|||||||
if (mtd->zoomed == 0)
|
if (mtd->zoomed == 0)
|
||||||
server_unzoom_window(wp->window);
|
server_unzoom_window(wp->window);
|
||||||
|
|
||||||
mode_tree_clear_prompt(mtd);
|
|
||||||
mode_tree_free_items(&mtd->children);
|
mode_tree_free_items(&mtd->children);
|
||||||
mode_tree_clear_lines(mtd);
|
mode_tree_clear_lines(mtd);
|
||||||
screen_free(&mtd->screen);
|
screen_free(&mtd->screen);
|
||||||
@@ -735,12 +700,6 @@ mode_tree_add(struct mode_tree_data *mtd, struct mode_tree_item *parent,
|
|||||||
return (mti);
|
return (mti);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
mode_tree_view_name(struct mode_tree_data *mtd, const char *name)
|
|
||||||
{
|
|
||||||
mtd->view_name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mode_tree_draw_as_parent(struct mode_tree_item *mti)
|
mode_tree_draw_as_parent(struct mode_tree_item *mti)
|
||||||
{
|
{
|
||||||
@@ -925,12 +884,9 @@ mode_tree_draw(struct mode_tree_data *mtd)
|
|||||||
screen_write_box(&ctx, w, sy - h, BOX_LINES_DEFAULT, NULL, NULL);
|
screen_write_box(&ctx, w, sy - h, BOX_LINES_DEFAULT, NULL, NULL);
|
||||||
|
|
||||||
if (mtd->sort_crit.order_seq != NULL) {
|
if (mtd->sort_crit.order_seq != NULL) {
|
||||||
xasprintf(&text, " %s (sort: %s%s)%s%s%s", mti->name,
|
xasprintf(&text, " %s (sort: %s%s)", mti->name,
|
||||||
sort_order_to_string(mtd->sort_crit.order),
|
sort_order_to_string(mtd->sort_crit.order),
|
||||||
mtd->sort_crit.reversed ? ", reversed" : "",
|
mtd->sort_crit.reversed ? ", reversed" : "");
|
||||||
mtd->view_name == NULL ? "" : " (view: ",
|
|
||||||
mtd->view_name == NULL ? "" : mtd->view_name,
|
|
||||||
mtd->view_name == NULL ? "" : ")");
|
|
||||||
} else
|
} else
|
||||||
xasprintf(&text, " %s", mti->name);
|
xasprintf(&text, " %s", mti->name);
|
||||||
if (w - 2 >= strlen(text)) {
|
if (w - 2 >= strlen(text)) {
|
||||||
@@ -962,150 +918,10 @@ mode_tree_draw(struct mode_tree_data *mtd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (mtd->help)
|
screen_write_cursormove(&ctx, 0, mtd->current - mtd->offset, 0);
|
||||||
mode_tree_draw_help(mtd, &ctx);
|
|
||||||
if (mtd->prompt != NULL)
|
|
||||||
mode_tree_draw_prompt(mtd, &ctx);
|
|
||||||
else {
|
|
||||||
s->mode &= ~MODE_CURSOR;
|
|
||||||
screen_write_cursormove(&ctx, 0, mtd->current - mtd->offset, 0);
|
|
||||||
}
|
|
||||||
screen_write_stop(&ctx);
|
screen_write_stop(&ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
mode_tree_draw_prompt(struct mode_tree_data *mtd, struct screen_write_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct screen *s = &mtd->screen;
|
|
||||||
struct prompt_draw_data pdd;
|
|
||||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
|
||||||
u_int py;
|
|
||||||
|
|
||||||
if (sx == 0 || sy == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mtd->prompt_top)
|
|
||||||
py = 0;
|
|
||||||
else
|
|
||||||
py = sy - 1;
|
|
||||||
|
|
||||||
pdd.ctx = ctx;
|
|
||||||
pdd.cursor_x = &mtd->prompt_cx;
|
|
||||||
pdd.area_x = 0;
|
|
||||||
pdd.area_width = sx;
|
|
||||||
pdd.prompt_line = py;
|
|
||||||
|
|
||||||
s->mode |= MODE_CURSOR;
|
|
||||||
prompt_draw(mtd->prompt, &pdd);
|
|
||||||
screen_write_cursormove(ctx, mtd->prompt_cx, py, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
mode_tree_clear_prompt(struct mode_tree_data *mtd)
|
|
||||||
{
|
|
||||||
struct prompt *prompt = mtd->prompt;
|
|
||||||
|
|
||||||
if (mtd->prompt != NULL) {
|
|
||||||
mtd->prompt = NULL;
|
|
||||||
prompt_free(prompt);
|
|
||||||
mtd->screen.mode &= ~MODE_CURSOR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
mode_tree_has_prompt(struct mode_tree_data *mtd)
|
|
||||||
{
|
|
||||||
return (mtd->prompt != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
mode_tree_prompt_accept(struct cmdq_item *item, void *data)
|
|
||||||
{
|
|
||||||
struct mode_tree_data *mtd = data;
|
|
||||||
struct client *c = cmdq_get_client(item);
|
|
||||||
key_code key = 'y';
|
|
||||||
|
|
||||||
if (mtd->prompt != NULL && c != NULL)
|
|
||||||
mode_tree_key(mtd, c, &key, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
mode_tree_remove_ref(mtd);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum prompt_result
|
|
||||||
mode_tree_prompt_input_callback(void *data, const char *s,
|
|
||||||
enum prompt_key_result key)
|
|
||||||
{
|
|
||||||
struct mode_tree_prompt *mtp = data;
|
|
||||||
|
|
||||||
if (mtp->inputcb != NULL)
|
|
||||||
return (mtp->inputcb(mtp->c, mtp->data, s, key));
|
|
||||||
return (PROMPT_CLOSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
mode_tree_prompt_free_callback(void *data)
|
|
||||||
{
|
|
||||||
struct mode_tree_prompt *mtp = data;
|
|
||||||
|
|
||||||
if (mtp->mtd->prompt_data == mtp)
|
|
||||||
mtp->mtd->prompt_data = NULL;
|
|
||||||
if (mtp->freecb != NULL)
|
|
||||||
mtp->freecb(mtp->data);
|
|
||||||
mode_tree_remove_ref(mtp->mtd);
|
|
||||||
free(mtp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
mode_tree_set_prompt(struct mode_tree_data *mtd, struct client *c,
|
|
||||||
const char *prompt, const char *input, enum prompt_type type, int flags,
|
|
||||||
mode_tree_prompt_input_cb inputcb, prompt_free_cb freecb, void *data)
|
|
||||||
{
|
|
||||||
struct session *s;
|
|
||||||
struct options *oo;
|
|
||||||
struct prompt_create_data pd;
|
|
||||||
struct mode_tree_prompt *mtp;
|
|
||||||
|
|
||||||
if (c != NULL && c->session != NULL) {
|
|
||||||
s = c->session;
|
|
||||||
oo = s->options;
|
|
||||||
} else {
|
|
||||||
s = NULL;
|
|
||||||
oo = global_s_options;
|
|
||||||
}
|
|
||||||
|
|
||||||
mode_tree_clear_prompt(mtd);
|
|
||||||
|
|
||||||
mtp = xcalloc(1, sizeof *mtp);
|
|
||||||
mtp->mtd = mtd;
|
|
||||||
mtp->inputcb = inputcb;
|
|
||||||
mtp->freecb = freecb;
|
|
||||||
mtp->data = data;
|
|
||||||
|
|
||||||
mtd->references++;
|
|
||||||
mtd->prompt_top = options_get_number(oo, "status-position") == 0;
|
|
||||||
|
|
||||||
memset(&pd, 0, sizeof pd);
|
|
||||||
prompt_set_options(&pd, s);
|
|
||||||
pd.prompt = prompt;
|
|
||||||
pd.input = input;
|
|
||||||
pd.type = type;
|
|
||||||
pd.flags = flags|PROMPT_ISMODE;
|
|
||||||
pd.inputcb = mode_tree_prompt_input_callback;
|
|
||||||
pd.freecb = mode_tree_prompt_free_callback;
|
|
||||||
pd.data = mtp;
|
|
||||||
mtd->prompt = prompt_create(&pd);
|
|
||||||
mtd->prompt_data = mtp;
|
|
||||||
|
|
||||||
mode_tree_draw(mtd);
|
|
||||||
mtd->wp->flags |= PANE_REDRAW;
|
|
||||||
|
|
||||||
if ((flags & PROMPT_SINGLE) && (flags & PROMPT_ACCEPT) && c != NULL) {
|
|
||||||
mtd->references++;
|
|
||||||
cmdq_append(c, cmdq_get_callback(mode_tree_prompt_accept, mtd));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mode_tree_item *
|
static struct mode_tree_item *
|
||||||
mode_tree_search_backward(struct mode_tree_data *mtd)
|
mode_tree_search_backward(struct mode_tree_data *mtd)
|
||||||
{
|
{
|
||||||
@@ -1226,37 +1042,41 @@ mode_tree_search_set(struct mode_tree_data *mtd)
|
|||||||
mtd->wp->flags |= PANE_REDRAW;
|
mtd->wp->flags |= PANE_REDRAW;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum prompt_result
|
static int
|
||||||
mode_tree_search_callback(__unused struct client *c, void *data, const char *s,
|
mode_tree_search_callback(__unused struct client *c, void *data, const char *s,
|
||||||
enum prompt_key_result key)
|
__unused int done)
|
||||||
{
|
{
|
||||||
struct mode_tree_data *mtd = data;
|
struct mode_tree_data *mtd = data;
|
||||||
|
|
||||||
if (mtd->dead)
|
if (mtd->dead)
|
||||||
return (PROMPT_CLOSE);
|
return (0);
|
||||||
|
|
||||||
free(mtd->search);
|
free(mtd->search);
|
||||||
if (s == NULL || *s == '\0')
|
if (s == NULL || *s == '\0') {
|
||||||
mtd->search = NULL;
|
mtd->search = NULL;
|
||||||
else {
|
return (0);
|
||||||
mtd->search = xstrdup(s);
|
|
||||||
mtd->search_icase = mode_tree_is_lowercase(s);
|
|
||||||
mode_tree_search_set(mtd);
|
|
||||||
}
|
}
|
||||||
|
mtd->search = xstrdup(s);
|
||||||
|
mtd->search_icase = mode_tree_is_lowercase(s);
|
||||||
|
mode_tree_search_set(mtd);
|
||||||
|
|
||||||
if (key == PROMPT_KEY_HANDLED)
|
return (0);
|
||||||
return (PROMPT_CONTINUE);
|
|
||||||
return (PROMPT_CLOSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum prompt_result
|
static void
|
||||||
|
mode_tree_search_free(void *data)
|
||||||
|
{
|
||||||
|
mode_tree_remove_ref(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
mode_tree_filter_callback(__unused struct client *c, void *data, const char *s,
|
mode_tree_filter_callback(__unused struct client *c, void *data, const char *s,
|
||||||
enum prompt_key_result key)
|
__unused int done)
|
||||||
{
|
{
|
||||||
struct mode_tree_data *mtd = data;
|
struct mode_tree_data *mtd = data;
|
||||||
|
|
||||||
if (mtd->dead)
|
if (mtd->dead)
|
||||||
return (PROMPT_CLOSE);
|
return (0);
|
||||||
|
|
||||||
if (mtd->filter != NULL)
|
if (mtd->filter != NULL)
|
||||||
free(mtd->filter);
|
free(mtd->filter);
|
||||||
@@ -1269,20 +1089,13 @@ mode_tree_filter_callback(__unused struct client *c, void *data, const char *s,
|
|||||||
mode_tree_draw(mtd);
|
mode_tree_draw(mtd);
|
||||||
mtd->wp->flags |= PANE_REDRAW;
|
mtd->wp->flags |= PANE_REDRAW;
|
||||||
|
|
||||||
if (key == PROMPT_KEY_HANDLED)
|
return (0);
|
||||||
return (PROMPT_CONTINUE);
|
|
||||||
return (PROMPT_CLOSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mode_tree_clear_filter(struct mode_tree_data *mtd)
|
mode_tree_filter_free(void *data)
|
||||||
{
|
{
|
||||||
free(mtd->filter);
|
mode_tree_remove_ref(data);
|
||||||
mtd->filter = NULL;
|
|
||||||
|
|
||||||
mode_tree_build(mtd);
|
|
||||||
mode_tree_draw(mtd);
|
|
||||||
mtd->wp->flags |= PANE_REDRAW;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1352,28 +1165,12 @@ mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mode_tree_draw_help_line(struct screen_write_ctx *ctx,
|
mode_tree_display_help(__unused struct mode_tree_data *mtd, struct client *c)
|
||||||
const struct grid_cell *gc, const char *line, const char *item, u_int x,
|
|
||||||
u_int y, u_int w)
|
|
||||||
{
|
{
|
||||||
char *expanded;
|
struct session *s = c->session;
|
||||||
|
u_int px, py, w, h = 0;
|
||||||
expanded = cmd_template_replace(line, item, 1);
|
const char **line, **lines = NULL, *item = "item";
|
||||||
screen_write_cursormove(ctx, x, y, 0);
|
char *new_line;
|
||||||
screen_write_clearcharacter(ctx, w, gc->bg);
|
|
||||||
screen_write_cursormove(ctx, x, y, 0);
|
|
||||||
format_draw(ctx, gc, w, expanded, NULL, 0);
|
|
||||||
free(expanded);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
mode_tree_draw_help(struct mode_tree_data *mtd, struct screen_write_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct screen *s = &mtd->screen;
|
|
||||||
struct grid_cell gc;
|
|
||||||
const char **line, **lines = NULL, *item = "item";
|
|
||||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
|
||||||
u_int x, y, w, h = 0, box_w, box_h;
|
|
||||||
|
|
||||||
if (mtd->helpcb == NULL)
|
if (mtd->helpcb == NULL)
|
||||||
w = MODE_TREE_HELP_DEFAULT_WIDTH;
|
w = MODE_TREE_HELP_DEFAULT_WIDTH;
|
||||||
@@ -1389,32 +1186,33 @@ mode_tree_draw_help(struct mode_tree_data *mtd, struct screen_write_ctx *ctx)
|
|||||||
for (line = mode_tree_help_end; *line != NULL; line++)
|
for (line = mode_tree_help_end; *line != NULL; line++)
|
||||||
h++;
|
h++;
|
||||||
|
|
||||||
box_w = w + 2;
|
if (c->tty.sx < w || c->tty.sy < h)
|
||||||
box_h = h + 2;
|
|
||||||
if (sx < box_w || sy < box_h)
|
|
||||||
return;
|
return;
|
||||||
x = (sx - box_w) / 2;
|
px = (c->tty.sx - w) / 2;
|
||||||
y = (sy - box_h) / 2;
|
py = (c->tty.sy - h) / 2;
|
||||||
|
|
||||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
if (popup_display(POPUP_CLOSEANYKEY|POPUP_NOJOB, BOX_LINES_DEFAULT,
|
||||||
screen_write_cursormove(ctx, x, y, 0);
|
NULL, px, py, w, h, NULL, NULL, 0, NULL, NULL, NULL, c, s, NULL,
|
||||||
screen_write_box(ctx, box_w, box_h, BOX_LINES_DEFAULT, &gc, NULL);
|
NULL, NULL, NULL) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
y++;
|
popup_write(c, "\033[H\033[?25l\033[?7l\033)0", 17);
|
||||||
x++;
|
for (line = mode_tree_help_start; *line != NULL; line++) {
|
||||||
for (line = mode_tree_help_start; *line != NULL; line++, y++)
|
new_line = cmd_template_replace(*line, item, 1);
|
||||||
mode_tree_draw_help_line(ctx, &gc, *line, item, x, y, w);
|
popup_write(c, new_line, strlen(new_line));
|
||||||
for (line = lines; line != NULL && *line != NULL; line++, y++)
|
free(new_line);
|
||||||
mode_tree_draw_help_line(ctx, &gc, *line, item, x, y, w);
|
}
|
||||||
for (line = mode_tree_help_end; *line != NULL; line++, y++)
|
for (line = lines; line != NULL && *line != NULL; line++) {
|
||||||
mode_tree_draw_help_line(ctx, &gc, *line, item, x, y, w);
|
new_line = cmd_template_replace(*line, item, 1);
|
||||||
}
|
popup_write(c, new_line, strlen(new_line));
|
||||||
|
free(new_line);
|
||||||
static void
|
}
|
||||||
mode_tree_display_help(struct mode_tree_data *mtd)
|
for (line = mode_tree_help_end; *line != NULL; line++) {
|
||||||
{
|
new_line = cmd_template_replace(*line, item, 1);
|
||||||
mtd->help = 1;
|
popup_write(c, new_line, strlen(new_line));
|
||||||
mode_tree_draw(mtd);
|
free(new_line);
|
||||||
|
}
|
||||||
|
popup_write(c, "\033[H", 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -1423,77 +1221,14 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
|||||||
{
|
{
|
||||||
struct mode_tree_line *line;
|
struct mode_tree_line *line;
|
||||||
struct mode_tree_item *current, *parent, *mti;
|
struct mode_tree_item *current, *parent, *mti;
|
||||||
u_int i, x, y, py, sx;
|
u_int i, x, y;
|
||||||
int choice, preview;
|
int choice, preview;
|
||||||
enum prompt_key_result result;
|
|
||||||
int redraw;
|
|
||||||
struct prompt *prompt;
|
|
||||||
struct mode_tree_prompt *mtp;
|
|
||||||
|
|
||||||
if (mtd->line_size == 0) {
|
if (mtd->line_size == 0) {
|
||||||
*key = KEYC_NONE;
|
*key = KEYC_NONE;
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mtd->prompt != NULL) {
|
|
||||||
redraw = 0;
|
|
||||||
prompt = mtd->prompt;
|
|
||||||
|
|
||||||
mtp = mtd->prompt_data;
|
|
||||||
if (mtp != NULL)
|
|
||||||
mtp->c = c;
|
|
||||||
if (KEYC_IS_MOUSE(*key)) {
|
|
||||||
if (m == NULL ||
|
|
||||||
MOUSE_BUTTONS(m->b) != MOUSE_BUTTON_1 ||
|
|
||||||
MOUSE_DRAG(m->b) || MOUSE_RELEASE(m->b) ||
|
|
||||||
cmd_mouse_at(mtd->wp, m, &x, &y, 0) != 0)
|
|
||||||
result = PROMPT_KEY_NOT_HANDLED;
|
|
||||||
else {
|
|
||||||
sx = screen_size_x(&mtd->screen);
|
|
||||||
if (mtd->prompt_top)
|
|
||||||
py = 0;
|
|
||||||
else
|
|
||||||
py = screen_size_y(&mtd->screen) - 1;
|
|
||||||
if (y == py) {
|
|
||||||
result = prompt_mouse(prompt, x, 0, sx,
|
|
||||||
&redraw);
|
|
||||||
} else
|
|
||||||
result = PROMPT_KEY_NOT_HANDLED;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
result = prompt_key(prompt, *key, &redraw);
|
|
||||||
if (mtd->prompt_data == mtp && mtp != NULL)
|
|
||||||
mtp->c = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Only an explicit close or the prompt marking itself closed
|
|
||||||
* ends it; cursor movement and editing keep it open.
|
|
||||||
*/
|
|
||||||
if (mtd->prompt == prompt &&
|
|
||||||
(result == PROMPT_KEY_CLOSE || prompt_closed(prompt)))
|
|
||||||
mode_tree_clear_prompt(mtd);
|
|
||||||
|
|
||||||
if (redraw || mtd->prompt != prompt) {
|
|
||||||
mode_tree_draw(mtd);
|
|
||||||
mtd->wp->flags |= PANE_REDRAW;
|
|
||||||
}
|
|
||||||
if (result != PROMPT_KEY_NOT_HANDLED) {
|
|
||||||
*key = KEYC_NONE;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mtd->help) {
|
|
||||||
if (KEYC_IS_MOUSE(*key)) {
|
|
||||||
*key = KEYC_NONE;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
mtd->help = 0;
|
|
||||||
mode_tree_draw(mtd);
|
|
||||||
*key = KEYC_NONE;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KEYC_IS_MOUSE(*key) && m != NULL) {
|
if (KEYC_IS_MOUSE(*key) && m != NULL) {
|
||||||
if (cmd_mouse_at(mtd->wp, m, &x, &y, 0) != 0) {
|
if (cmd_mouse_at(mtd->wp, m, &x, &y, 0) != 0) {
|
||||||
*key = KEYC_NONE;
|
*key = KEYC_NONE;
|
||||||
@@ -1559,7 +1294,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
|||||||
return (1);
|
return (1);
|
||||||
case KEYC_F1:
|
case KEYC_F1:
|
||||||
case 'h'|KEYC_CTRL:
|
case 'h'|KEYC_CTRL:
|
||||||
mode_tree_display_help(mtd);
|
mode_tree_display_help(mtd, c);
|
||||||
break;
|
break;
|
||||||
case KEYC_UP:
|
case KEYC_UP:
|
||||||
case 'k':
|
case 'k':
|
||||||
@@ -1689,10 +1424,11 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
|||||||
case '?':
|
case '?':
|
||||||
case '/':
|
case '/':
|
||||||
case 's'|KEYC_CTRL:
|
case 's'|KEYC_CTRL:
|
||||||
|
mtd->references++;
|
||||||
mtd->search_dir = MODE_TREE_SEARCH_FORWARD;
|
mtd->search_dir = MODE_TREE_SEARCH_FORWARD;
|
||||||
mode_tree_set_prompt(mtd, c, "(search) ", "",
|
status_prompt_set(c, NULL, "(search) ", "",
|
||||||
PROMPT_TYPE_SEARCH, PROMPT_NOFORMAT,
|
mode_tree_search_callback, mode_tree_search_free, mtd,
|
||||||
mode_tree_search_callback, NULL, mtd);
|
PROMPT_NOFORMAT, PROMPT_TYPE_SEARCH);
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
mtd->search_dir = MODE_TREE_SEARCH_FORWARD;
|
mtd->search_dir = MODE_TREE_SEARCH_FORWARD;
|
||||||
@@ -1703,13 +1439,10 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
|||||||
mode_tree_search_set(mtd);
|
mode_tree_search_set(mtd);
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
mode_tree_set_prompt(mtd, c, "(filter) ", mtd->filter,
|
mtd->references++;
|
||||||
PROMPT_TYPE_SEARCH, PROMPT_NOFORMAT,
|
status_prompt_set(c, NULL, "(filter) ", mtd->filter,
|
||||||
mode_tree_filter_callback, NULL, mtd);
|
mode_tree_filter_callback, mode_tree_filter_free, mtd,
|
||||||
break;
|
PROMPT_NOFORMAT, PROMPT_TYPE_SEARCH);
|
||||||
case 'c':
|
|
||||||
mode_tree_clear_prompt(mtd);
|
|
||||||
mode_tree_clear_filter(mtd);
|
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
switch (mtd->preview) {
|
switch (mtd->preview) {
|
||||||
|
|||||||
@@ -70,13 +70,13 @@ static const char *options_table_pane_scrollbars_position_list[] = {
|
|||||||
"right", "left", NULL
|
"right", "left", NULL
|
||||||
};
|
};
|
||||||
static const char *options_table_pane_status_list[] = {
|
static const char *options_table_pane_status_list[] = {
|
||||||
"off", "top", "bottom", "top-floating", "bottom-floating", NULL
|
"off", "top", "bottom", NULL
|
||||||
};
|
};
|
||||||
static const char *options_table_pane_border_indicators_list[] = {
|
static const char *options_table_pane_border_indicators_list[] = {
|
||||||
"off", "colour", "arrows", "both", NULL
|
"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", "spaces", "none", NULL
|
"single", "double", "heavy", "simple", "number", "spaces", NULL
|
||||||
};
|
};
|
||||||
static const char *options_table_popup_border_lines_list[] = {
|
static const char *options_table_popup_border_lines_list[] = {
|
||||||
"single", "double", "heavy", "simple", "rounded", "padded", "none", NULL
|
"single", "double", "heavy", "simple", "rounded", "padded", "none", NULL
|
||||||
@@ -327,10 +327,9 @@ const struct options_table_entry options_table[] = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
{ .name = "cursor-colour",
|
{ .name = "cursor-colour",
|
||||||
.type = OPTIONS_TABLE_STRING,
|
.type = OPTIONS_TABLE_COLOUR,
|
||||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
||||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
.default_num = -1,
|
||||||
.default_str = "",
|
|
||||||
.text = "Colour of the cursor."
|
.text = "Colour of the cursor."
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -635,29 +634,19 @@ const struct options_table_entry options_table[] = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
{ .name = "display-panes-active-colour",
|
{ .name = "display-panes-active-colour",
|
||||||
.type = OPTIONS_TABLE_STRING,
|
.type = OPTIONS_TABLE_COLOUR,
|
||||||
.scope = OPTIONS_TABLE_SESSION,
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
.default_num = 1,
|
||||||
.default_str = "red",
|
|
||||||
.text = "Colour of the active pane for 'display-panes'."
|
.text = "Colour of the active pane for 'display-panes'."
|
||||||
},
|
},
|
||||||
|
|
||||||
{ .name = "display-panes-colour",
|
{ .name = "display-panes-colour",
|
||||||
.type = OPTIONS_TABLE_STRING,
|
.type = OPTIONS_TABLE_COLOUR,
|
||||||
.scope = OPTIONS_TABLE_SESSION,
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
.default_num = 4,
|
||||||
.default_str = "blue",
|
|
||||||
.text = "Colour of not active panes for 'display-panes'."
|
.text = "Colour of not active panes for 'display-panes'."
|
||||||
},
|
},
|
||||||
|
|
||||||
{ .name = "display-panes-format",
|
|
||||||
.type = OPTIONS_TABLE_STRING,
|
|
||||||
.scope = OPTIONS_TABLE_SESSION,
|
|
||||||
.default_str = "#[align=right]#{pane_width}x#{pane_height}",
|
|
||||||
.text = "Format of text shown by 'display-panes', expanded for each "
|
|
||||||
"pane."
|
|
||||||
},
|
|
||||||
|
|
||||||
{ .name = "display-panes-time",
|
{ .name = "display-panes-time",
|
||||||
.type = OPTIONS_TABLE_NUMBER,
|
.type = OPTIONS_TABLE_NUMBER,
|
||||||
.scope = OPTIONS_TABLE_SESSION,
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
@@ -741,7 +730,7 @@ const struct options_table_entry options_table[] = {
|
|||||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||||
.separator = ",",
|
.separator = ",",
|
||||||
.text = "Style of the command prompt when in command mode, if "
|
.text = "Style of the command prompt when in command mode, if "
|
||||||
"'status-keys' is set to 'vi'."
|
"'mode-keys' is set to 'vi'."
|
||||||
},
|
},
|
||||||
|
|
||||||
{ .name = "message-format",
|
{ .name = "message-format",
|
||||||
@@ -766,9 +755,7 @@ const struct options_table_entry options_table[] = {
|
|||||||
{ .name = "message-style",
|
{ .name = "message-style",
|
||||||
.type = OPTIONS_TABLE_STRING,
|
.type = OPTIONS_TABLE_STRING,
|
||||||
.scope = OPTIONS_TABLE_SESSION,
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
.default_str = "bg=yellow,fg=black,"
|
.default_str = "bg=yellow,fg=black,fill=yellow",
|
||||||
"#{?#{m/r:(^|#,)IS(PANE|MODE)($|#,),#{prompt_flags}},,"
|
|
||||||
"fill=yellow}",
|
|
||||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||||
.separator = ",",
|
.separator = ",",
|
||||||
.text = "Style of messages and the command prompt. "
|
.text = "Style of messages and the command prompt. "
|
||||||
@@ -993,10 +980,9 @@ const struct options_table_entry options_table[] = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
{ .name = "prompt-cursor-colour",
|
{ .name = "prompt-cursor-colour",
|
||||||
.type = OPTIONS_TABLE_STRING,
|
.type = OPTIONS_TABLE_COLOUR,
|
||||||
.scope = OPTIONS_TABLE_SESSION,
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
.default_num = -1,
|
||||||
.default_str = "",
|
|
||||||
.text = "Colour of the cursor when in the command prompt."
|
.text = "Colour of the cursor when in the command prompt."
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1148,10 +1134,9 @@ const struct options_table_entry options_table[] = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
{ .name = "clock-mode-colour",
|
{ .name = "clock-mode-colour",
|
||||||
.type = OPTIONS_TABLE_STRING,
|
.type = OPTIONS_TABLE_COLOUR,
|
||||||
.scope = OPTIONS_TABLE_WINDOW,
|
.scope = OPTIONS_TABLE_WINDOW,
|
||||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
.default_num = 4,
|
||||||
.default_str = "blue",
|
|
||||||
.text = "Colour of the clock in clock mode."
|
.text = "Colour of the clock in clock mode."
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1371,7 +1356,7 @@ const struct options_table_entry options_table[] = {
|
|||||||
|
|
||||||
{ .name = "pane-border-lines",
|
{ .name = "pane-border-lines",
|
||||||
.type = OPTIONS_TABLE_CHOICE,
|
.type = OPTIONS_TABLE_CHOICE,
|
||||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
.scope = OPTIONS_TABLE_WINDOW,
|
||||||
.choices = options_table_pane_border_lines_list,
|
.choices = options_table_pane_border_lines_list,
|
||||||
.default_num = PANE_LINES_SINGLE,
|
.default_num = PANE_LINES_SINGLE,
|
||||||
.text = "Type of characters used to draw pane border lines. Some of "
|
.text = "Type of characters used to draw pane border lines. Some of "
|
||||||
@@ -1380,7 +1365,7 @@ const struct options_table_entry options_table[] = {
|
|||||||
|
|
||||||
{ .name = "pane-border-status",
|
{ .name = "pane-border-status",
|
||||||
.type = OPTIONS_TABLE_CHOICE,
|
.type = OPTIONS_TABLE_CHOICE,
|
||||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
.scope = OPTIONS_TABLE_WINDOW,
|
||||||
.choices = options_table_pane_status_list,
|
.choices = options_table_pane_status_list,
|
||||||
.default_num = PANE_STATUS_OFF,
|
.default_num = PANE_STATUS_OFF,
|
||||||
.text = "Position of the pane status lines."
|
.text = "Position of the pane status lines."
|
||||||
|
|||||||
55
options.c
55
options.c
@@ -662,18 +662,6 @@ options_parse_get(struct options *oo, const char *s, int *idx, int only)
|
|||||||
return (o);
|
return (o);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct options_table_entry *
|
|
||||||
options_search(const char *name)
|
|
||||||
{
|
|
||||||
const struct options_table_entry *oe;
|
|
||||||
|
|
||||||
for (oe = options_table; oe->name != NULL; oe++) {
|
|
||||||
if (strcmp(oe->name, name) == 0)
|
|
||||||
return (oe);
|
|
||||||
}
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
options_match(const char *s, int *idx, int *ambiguous)
|
options_match(const char *s, int *idx, int *ambiguous)
|
||||||
{
|
{
|
||||||
@@ -989,12 +977,9 @@ struct style *
|
|||||||
options_string_to_style(struct options *oo, const char *name,
|
options_string_to_style(struct options *oo, const char *name,
|
||||||
struct format_tree *ft)
|
struct format_tree *ft)
|
||||||
{
|
{
|
||||||
struct options_entry *o;
|
struct options_entry *o;
|
||||||
const struct options_table_entry *oe;
|
const char *s;
|
||||||
const struct grid_cell *dgc = &grid_default_cell;
|
char *expanded;
|
||||||
const char *s;
|
|
||||||
char *expanded;
|
|
||||||
int failed;
|
|
||||||
|
|
||||||
o = options_get(oo, name);
|
o = options_get(oo, name);
|
||||||
if (o == NULL || !OPTIONS_IS_STRING(o))
|
if (o == NULL || !OPTIONS_IS_STRING(o))
|
||||||
@@ -1003,27 +988,20 @@ options_string_to_style(struct options *oo, const char *name,
|
|||||||
if (o->cached)
|
if (o->cached)
|
||||||
return (&o->style);
|
return (&o->style);
|
||||||
s = o->value.string;
|
s = o->value.string;
|
||||||
oe = o->tableentry;
|
|
||||||
log_debug("%s: %s is '%s'", __func__, name, s);
|
log_debug("%s: %s is '%s'", __func__, name, s);
|
||||||
|
|
||||||
style_set(&o->style, dgc);
|
style_set(&o->style, &grid_default_cell);
|
||||||
o->cached = (strstr(s, "#{") == NULL);
|
o->cached = (strstr(s, "#{") == NULL);
|
||||||
|
|
||||||
if (ft != NULL && !o->cached) {
|
if (ft != NULL && !o->cached) {
|
||||||
expanded = format_expand(ft, s);
|
expanded = format_expand(ft, s);
|
||||||
if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_COLOUR))
|
if (style_parse(&o->style, &grid_default_cell, expanded) != 0) {
|
||||||
failed = style_parse_colour(&o->style, dgc, expanded);
|
free(expanded);
|
||||||
else
|
|
||||||
failed = style_parse(&o->style, dgc, expanded);
|
|
||||||
free(expanded);
|
|
||||||
if (failed != 0)
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
}
|
||||||
|
free(expanded);
|
||||||
} else {
|
} else {
|
||||||
if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_COLOUR))
|
if (style_parse(&o->style, &grid_default_cell, s) != 0)
|
||||||
failed = style_parse_colour(&o->style, dgc, s);
|
|
||||||
else
|
|
||||||
failed = style_parse(&o->style, dgc, s);
|
|
||||||
if (failed != 0)
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
return (&o->style);
|
return (&o->style);
|
||||||
@@ -1051,12 +1029,6 @@ options_from_string_check(const struct options_table_entry *oe,
|
|||||||
xasprintf(cause, "invalid style: %s", value);
|
xasprintf(cause, "invalid style: %s", value);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if ((oe->flags & OPTIONS_TABLE_IS_COLOUR) &&
|
|
||||||
strstr(value, "#{") == NULL &&
|
|
||||||
style_parse_colour(&sy, &grid_default_cell, value) != 0) {
|
|
||||||
xasprintf(cause, "invalid colour: %s", value);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1247,15 +1219,6 @@ options_push_changes(const char *name)
|
|||||||
if (strcmp(name, "status") == 0 ||
|
if (strcmp(name, "status") == 0 ||
|
||||||
strcmp(name, "status-interval") == 0)
|
strcmp(name, "status-interval") == 0)
|
||||||
status_timer_start_all();
|
status_timer_start_all();
|
||||||
if (strcmp(name, "status") == 0 ||
|
|
||||||
strcmp(name, "status-position") == 0 ||
|
|
||||||
strcmp(name, "pane-border-indicators") == 0 ||
|
|
||||||
strcmp(name, "pane-border-lines") == 0 ||
|
|
||||||
strcmp(name, "pane-border-status") == 0 ||
|
|
||||||
strcmp(name, "pane-scrollbars") == 0 ||
|
|
||||||
strcmp(name, "pane-scrollbars-position") == 0 ||
|
|
||||||
strcmp(name, "pane-scrollbars-style") == 0)
|
|
||||||
redraw_invalidate_all_scenes();
|
|
||||||
if (strcmp(name, "monitor-silence") == 0)
|
if (strcmp(name, "monitor-silence") == 0)
|
||||||
alerts_reset_all();
|
alerts_reset_all();
|
||||||
if (strcmp(name, "window-style") == 0 ||
|
if (strcmp(name, "window-style") == 0 ||
|
||||||
|
|||||||
169
popup.c
169
popup.c
@@ -75,6 +75,12 @@ struct popup_data {
|
|||||||
u_int lb;
|
u_int lb;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct popup_editor {
|
||||||
|
char *path;
|
||||||
|
popup_finish_edit_cb cb;
|
||||||
|
void *arg;
|
||||||
|
};
|
||||||
|
|
||||||
static const struct menu_item popup_menu_items[] = {
|
static const struct menu_item popup_menu_items[] = {
|
||||||
{ "Close", 'q', NULL },
|
{ "Close", 'q', NULL },
|
||||||
{ "#{?buffer_name,Paste #[underscore]#{buffer_name},}", 'p', NULL },
|
{ "#{?buffer_name,Paste #[underscore]#{buffer_name},}", 'p', NULL },
|
||||||
@@ -88,6 +94,15 @@ static const struct menu_item popup_menu_items[] = {
|
|||||||
{ NULL, KEYC_NONE, NULL }
|
{ NULL, KEYC_NONE, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct menu_item popup_internal_menu_items[] = {
|
||||||
|
{ "Close", 'q', NULL },
|
||||||
|
{ "", KEYC_NONE, NULL },
|
||||||
|
{ "Fill Space", 'F', NULL },
|
||||||
|
{ "Centre", 'C', NULL },
|
||||||
|
|
||||||
|
{ NULL, KEYC_NONE, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
popup_free(struct popup_data *pd)
|
popup_free(struct popup_data *pd)
|
||||||
{
|
{
|
||||||
@@ -193,8 +208,7 @@ popup_init_ctx_cb(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
|
|||||||
|
|
||||||
memcpy(&ttyctx->defaults, &pd->defaults, sizeof ttyctx->defaults);
|
memcpy(&ttyctx->defaults, &pd->defaults, sizeof ttyctx->defaults);
|
||||||
ttyctx->flags &= ~TTY_CTX_WINDOW_BIGGER;
|
ttyctx->flags &= ~TTY_CTX_WINDOW_BIGGER;
|
||||||
ttyctx->style_ctx.defaults = &ttyctx->defaults;
|
ttyctx->palette = &pd->palette;
|
||||||
ttyctx->style_ctx.palette = &pd->palette;
|
|
||||||
ttyctx->redraw_cb = popup_redraw_cb;
|
ttyctx->redraw_cb = popup_redraw_cb;
|
||||||
ttyctx->set_client_cb = popup_set_client_cb;
|
ttyctx->set_client_cb = popup_set_client_cb;
|
||||||
ttyctx->arg = pd;
|
ttyctx->arg = pd;
|
||||||
@@ -273,15 +287,15 @@ popup_check_cb(struct client* c, void *data, u_int px, u_int py, u_int nx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
popup_draw_cb(struct client *c, void *data)
|
popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
|
||||||
{
|
{
|
||||||
struct popup_data *pd = data;
|
struct popup_data *pd = data;
|
||||||
struct tty *tty = &c->tty;
|
struct tty *tty = &c->tty;
|
||||||
struct screen s;
|
struct screen s;
|
||||||
struct screen_write_ctx ctx;
|
struct screen_write_ctx ctx;
|
||||||
u_int i, px = pd->px, py = pd->py;
|
u_int i, px = pd->px, py = pd->py;
|
||||||
|
struct colour_palette *palette = &pd->palette;
|
||||||
struct grid_cell defaults;
|
struct grid_cell defaults;
|
||||||
struct tty_style_ctx style_ctx;
|
|
||||||
|
|
||||||
popup_reapply_styles(pd);
|
popup_reapply_styles(pd);
|
||||||
|
|
||||||
@@ -307,13 +321,9 @@ popup_draw_cb(struct client *c, void *data)
|
|||||||
|
|
||||||
memcpy(&defaults, &pd->defaults, sizeof defaults);
|
memcpy(&defaults, &pd->defaults, sizeof defaults);
|
||||||
if (defaults.fg == 8)
|
if (defaults.fg == 8)
|
||||||
defaults.fg = pd->palette.fg;
|
defaults.fg = palette->fg;
|
||||||
if (defaults.bg == 8)
|
if (defaults.bg == 8)
|
||||||
defaults.bg = pd->palette.bg;
|
defaults.bg = palette->bg;
|
||||||
style_ctx.defaults = &defaults;
|
|
||||||
style_ctx.palette = &pd->palette;
|
|
||||||
style_ctx.dim = 0;
|
|
||||||
style_ctx.hyperlinks = s.hyperlinks;
|
|
||||||
|
|
||||||
if (pd->md != NULL) {
|
if (pd->md != NULL) {
|
||||||
c->overlay_check = menu_check_cb;
|
c->overlay_check = menu_check_cb;
|
||||||
@@ -322,13 +332,15 @@ popup_draw_cb(struct client *c, void *data)
|
|||||||
c->overlay_check = NULL;
|
c->overlay_check = NULL;
|
||||||
c->overlay_data = NULL;
|
c->overlay_data = NULL;
|
||||||
}
|
}
|
||||||
for (i = 0; i < pd->sy; i++)
|
for (i = 0; i < pd->sy; i++) {
|
||||||
tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, &style_ctx);
|
tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, &defaults,
|
||||||
|
palette);
|
||||||
|
}
|
||||||
screen_free(&s);
|
screen_free(&s);
|
||||||
if (pd->md != NULL) {
|
if (pd->md != NULL) {
|
||||||
c->overlay_check = NULL;
|
c->overlay_check = NULL;
|
||||||
c->overlay_data = NULL;
|
c->overlay_data = NULL;
|
||||||
menu_draw_cb(c, pd->md);
|
menu_draw_cb(c, pd->md, rctx);
|
||||||
}
|
}
|
||||||
c->overlay_check = popup_check_cb;
|
c->overlay_check = popup_check_cb;
|
||||||
c->overlay_data = pd;
|
c->overlay_data = pd;
|
||||||
@@ -635,7 +647,11 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
|
|||||||
|
|
||||||
menu:
|
menu:
|
||||||
pd->menu = menu_create("");
|
pd->menu = menu_create("");
|
||||||
menu_add_items(pd->menu, popup_menu_items, NULL, c, NULL);
|
if (pd->flags & POPUP_INTERNAL) {
|
||||||
|
menu_add_items(pd->menu, popup_internal_menu_items, NULL, c,
|
||||||
|
NULL);
|
||||||
|
} else
|
||||||
|
menu_add_items(pd->menu, popup_menu_items, NULL, c, NULL);
|
||||||
if (m->x >= (pd->menu->width + 4) / 2)
|
if (m->x >= (pd->menu->width + 4) / 2)
|
||||||
x = m->x - (pd->menu->width + 4) / 2;
|
x = m->x - (pd->menu->width + 4) / 2;
|
||||||
else
|
else
|
||||||
@@ -842,16 +858,127 @@ popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px,
|
|||||||
pd->psx = sx;
|
pd->psx = sx;
|
||||||
pd->psy = sy;
|
pd->psy = sy;
|
||||||
|
|
||||||
pd->job = job_run(shellcmd, argc, argv, env, s, cwd,
|
if (flags & POPUP_NOJOB)
|
||||||
popup_job_update_cb, popup_job_complete_cb, NULL, pd,
|
pd->ictx = input_init(NULL, NULL, &pd->palette, NULL);
|
||||||
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE|JOB_DEFAULTSHELL, jx, jy);
|
else {
|
||||||
if (pd->job == NULL) {
|
pd->job = job_run(shellcmd, argc, argv, env, s, cwd,
|
||||||
popup_free(pd);
|
popup_job_update_cb, popup_job_complete_cb, NULL, pd,
|
||||||
return (-1);
|
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE|JOB_DEFAULTSHELL, jx, jy);
|
||||||
|
if (pd->job == NULL) {
|
||||||
|
popup_free(pd);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
pd->ictx = input_init(NULL, job_get_event(pd->job),
|
||||||
|
&pd->palette, c);
|
||||||
}
|
}
|
||||||
pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette, c);
|
|
||||||
|
|
||||||
server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb,
|
server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb,
|
||||||
popup_draw_cb, popup_key_cb, popup_free_cb, popup_resize_cb, pd);
|
popup_draw_cb, popup_key_cb, popup_free_cb, popup_resize_cb, pd);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
popup_write(struct client *c, const char *data, size_t size)
|
||||||
|
{
|
||||||
|
struct popup_data *pd = c->overlay_data;
|
||||||
|
|
||||||
|
if (!popup_present(c))
|
||||||
|
return;
|
||||||
|
c->overlay_check = NULL;
|
||||||
|
c->overlay_data = NULL;
|
||||||
|
input_parse_screen(pd->ictx, &pd->s, popup_init_ctx_cb, pd, data, size);
|
||||||
|
c->overlay_check = popup_check_cb;
|
||||||
|
c->overlay_data = pd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
popup_editor_free(struct popup_editor *pe)
|
||||||
|
{
|
||||||
|
unlink(pe->path);
|
||||||
|
free(pe->path);
|
||||||
|
free(pe);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
popup_editor_close_cb(int status, void *arg)
|
||||||
|
{
|
||||||
|
struct popup_editor *pe = arg;
|
||||||
|
FILE *f;
|
||||||
|
char *buf = NULL;
|
||||||
|
off_t len = 0;
|
||||||
|
|
||||||
|
if (status != 0) {
|
||||||
|
pe->cb(NULL, 0, pe->arg);
|
||||||
|
popup_editor_free(pe);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
f = fopen(pe->path, "r");
|
||||||
|
if (f != NULL) {
|
||||||
|
fseeko(f, 0, SEEK_END);
|
||||||
|
len = ftello(f);
|
||||||
|
fseeko(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if (len == 0 ||
|
||||||
|
(uintmax_t)len > (uintmax_t)SIZE_MAX ||
|
||||||
|
(buf = malloc(len)) == NULL ||
|
||||||
|
fread(buf, len, 1, f) != 1) {
|
||||||
|
free(buf);
|
||||||
|
buf = NULL;
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
pe->cb(buf, len, pe->arg); /* callback now owns buffer */
|
||||||
|
popup_editor_free(pe);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
popup_editor(struct client *c, const char *buf, size_t len,
|
||||||
|
popup_finish_edit_cb cb, void *arg)
|
||||||
|
{
|
||||||
|
struct popup_editor *pe;
|
||||||
|
int fd;
|
||||||
|
FILE *f;
|
||||||
|
char *cmd;
|
||||||
|
char path[] = _PATH_TMP "tmux.XXXXXXXX";
|
||||||
|
const char *editor;
|
||||||
|
u_int px, py, sx, sy;
|
||||||
|
|
||||||
|
editor = options_get_string(global_options, "editor");
|
||||||
|
if (*editor == '\0')
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
fd = mkstemp(path);
|
||||||
|
if (fd == -1)
|
||||||
|
return (-1);
|
||||||
|
f = fdopen(fd, "w");
|
||||||
|
if (f == NULL)
|
||||||
|
return (-1);
|
||||||
|
if (fwrite(buf, len, 1, f) != 1) {
|
||||||
|
fclose(f);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
pe = xcalloc(1, sizeof *pe);
|
||||||
|
pe->path = xstrdup(path);
|
||||||
|
pe->cb = cb;
|
||||||
|
pe->arg = arg;
|
||||||
|
|
||||||
|
sx = c->tty.sx * 9 / 10;
|
||||||
|
sy = c->tty.sy * 9 / 10;
|
||||||
|
px = (c->tty.sx / 2) - (sx / 2);
|
||||||
|
py = (c->tty.sy / 2) - (sy / 2);
|
||||||
|
|
||||||
|
xasprintf(&cmd, "%s %s", editor, path);
|
||||||
|
if (popup_display(POPUP_INTERNAL|POPUP_CLOSEEXIT, BOX_LINES_DEFAULT,
|
||||||
|
NULL, px, py, sx, sy, NULL, cmd, 0, NULL, _PATH_TMP, NULL, c, NULL,
|
||||||
|
NULL, NULL, popup_editor_close_cb, pe) != 0) {
|
||||||
|
popup_editor_free(pe);
|
||||||
|
free(cmd);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
free(cmd);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|||||||
12
proc.c
12
proc.c
@@ -57,7 +57,6 @@ struct tmuxpeer {
|
|||||||
struct imsgbuf ibuf;
|
struct imsgbuf ibuf;
|
||||||
struct event event;
|
struct event event;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
|
||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
#define PEER_BAD 0x1
|
#define PEER_BAD 0x1
|
||||||
@@ -302,6 +301,7 @@ proc_add_peer(struct tmuxproc *tp, int fd,
|
|||||||
void (*dispatchcb)(struct imsg *, void *), void *arg)
|
void (*dispatchcb)(struct imsg *, void *), void *arg)
|
||||||
{
|
{
|
||||||
struct tmuxpeer *peer;
|
struct tmuxpeer *peer;
|
||||||
|
gid_t gid;
|
||||||
|
|
||||||
peer = xcalloc(1, sizeof *peer);
|
peer = xcalloc(1, sizeof *peer);
|
||||||
peer->parent = tp;
|
peer->parent = tp;
|
||||||
@@ -314,10 +314,8 @@ proc_add_peer(struct tmuxproc *tp, int fd,
|
|||||||
imsgbuf_allow_fdpass(&peer->ibuf);
|
imsgbuf_allow_fdpass(&peer->ibuf);
|
||||||
event_set(&peer->event, fd, EV_READ, proc_event_cb, peer);
|
event_set(&peer->event, fd, EV_READ, proc_event_cb, peer);
|
||||||
|
|
||||||
if (getpeereid(fd, &peer->uid, &peer->gid) != 0) {
|
if (getpeereid(fd, &peer->uid, &gid) != 0)
|
||||||
peer->uid = (uid_t)-1;
|
peer->uid = (uid_t)-1;
|
||||||
peer->gid = (gid_t)-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_debug("add peer %p: %d (%p)", peer, fd, arg);
|
log_debug("add peer %p: %d (%p)", peer, fd, arg);
|
||||||
TAILQ_INSERT_TAIL(&tp->peers, peer, entry);
|
TAILQ_INSERT_TAIL(&tp->peers, peer, entry);
|
||||||
@@ -386,9 +384,3 @@ proc_get_peer_uid(struct tmuxpeer *peer)
|
|||||||
{
|
{
|
||||||
return (peer->uid);
|
return (peer->uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
gid_t
|
|
||||||
proc_get_peer_gid(struct tmuxpeer *peer)
|
|
||||||
{
|
|
||||||
return (peer->gid);
|
|
||||||
}
|
|
||||||
|
|||||||
264
prompt-history.c
264
prompt-history.c
@@ -1,264 +0,0 @@
|
|||||||
/* $OpenBSD$ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
||||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
static char *prompt_find_history_file(void);
|
|
||||||
static void prompt_add_typed_history(char *);
|
|
||||||
|
|
||||||
/* Prompt history. */
|
|
||||||
static char **prompt_hlist[PROMPT_NTYPES];
|
|
||||||
static u_int prompt_hsize[PROMPT_NTYPES];
|
|
||||||
|
|
||||||
/* Find the history file to load/save from/to. */
|
|
||||||
static char *
|
|
||||||
prompt_find_history_file(void)
|
|
||||||
{
|
|
||||||
const char *home, *history_file;
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
history_file = options_get_string(global_options, "history-file");
|
|
||||||
if (*history_file == '\0')
|
|
||||||
return (NULL);
|
|
||||||
if (*history_file == '/')
|
|
||||||
return (xstrdup(history_file));
|
|
||||||
|
|
||||||
if (history_file[0] != '~' || history_file[1] != '/')
|
|
||||||
return (NULL);
|
|
||||||
if ((home = find_home()) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
xasprintf(&path, "%s%s", home, history_file + 1);
|
|
||||||
return (path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add loaded history item to the appropriate list. */
|
|
||||||
static void
|
|
||||||
prompt_add_typed_history(char *line)
|
|
||||||
{
|
|
||||||
char *typestr;
|
|
||||||
enum prompt_type type = PROMPT_TYPE_INVALID;
|
|
||||||
|
|
||||||
typestr = strsep(&line, ":");
|
|
||||||
if (line != NULL)
|
|
||||||
type = prompt_type(typestr);
|
|
||||||
if (type == PROMPT_TYPE_INVALID) {
|
|
||||||
/*
|
|
||||||
* Invalid types are not expected, but this provides backward
|
|
||||||
* compatibility with old history files.
|
|
||||||
*/
|
|
||||||
if (line != NULL)
|
|
||||||
*(--line) = ':';
|
|
||||||
prompt_add_history(typestr, PROMPT_TYPE_COMMAND);
|
|
||||||
} else
|
|
||||||
prompt_add_history(line, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load prompt history from file. */
|
|
||||||
void
|
|
||||||
prompt_load_history(void)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
char *history_file, *line, *tmp;
|
|
||||||
size_t length;
|
|
||||||
|
|
||||||
if ((history_file = prompt_find_history_file()) == NULL)
|
|
||||||
return;
|
|
||||||
log_debug("loading history from %s", history_file);
|
|
||||||
|
|
||||||
f = fopen(history_file, "r");
|
|
||||||
if (f == NULL) {
|
|
||||||
log_debug("%s: %s", history_file, strerror(errno));
|
|
||||||
free(history_file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
free(history_file);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if ((line = fgetln(f, &length)) == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (length > 0) {
|
|
||||||
if (line[length - 1] == '\n') {
|
|
||||||
line[length - 1] = '\0';
|
|
||||||
prompt_add_typed_history(line);
|
|
||||||
} else {
|
|
||||||
tmp = xmalloc(length + 1);
|
|
||||||
memcpy(tmp, line, length);
|
|
||||||
tmp[length] = '\0';
|
|
||||||
prompt_add_typed_history(tmp);
|
|
||||||
free(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save prompt history to file. */
|
|
||||||
void
|
|
||||||
prompt_save_history(void)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
u_int i, type;
|
|
||||||
char *history_file;
|
|
||||||
|
|
||||||
if ((history_file = prompt_find_history_file()) == NULL)
|
|
||||||
return;
|
|
||||||
log_debug("saving history to %s", history_file);
|
|
||||||
|
|
||||||
f = fopen(history_file, "w");
|
|
||||||
if (f == NULL) {
|
|
||||||
log_debug("%s: %s", history_file, strerror(errno));
|
|
||||||
free(history_file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
free(history_file);
|
|
||||||
|
|
||||||
for (type = 0; type < PROMPT_NTYPES; type++) {
|
|
||||||
for (i = 0; i < prompt_hsize[type]; i++) {
|
|
||||||
fputs(prompt_type_string(type), f);
|
|
||||||
fputc(':', f);
|
|
||||||
fputs(prompt_hlist[type][i], f);
|
|
||||||
fputc('\n', f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get previous line from the history. */
|
|
||||||
const char *
|
|
||||||
prompt_up_history(u_int *idx, u_int type)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* History runs from 0 to size - 1. Index is from 0 to size. Zero is
|
|
||||||
* empty.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (type >= PROMPT_NTYPES)
|
|
||||||
return (NULL);
|
|
||||||
if (prompt_hsize[type] == 0 || idx[type] == prompt_hsize[type])
|
|
||||||
return (NULL);
|
|
||||||
idx[type]++;
|
|
||||||
return (prompt_hlist[type][prompt_hsize[type] - idx[type]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get next line from the history. */
|
|
||||||
const char *
|
|
||||||
prompt_down_history(u_int *idx, u_int type)
|
|
||||||
{
|
|
||||||
if (type >= PROMPT_NTYPES)
|
|
||||||
return ("");
|
|
||||||
if (prompt_hsize[type] == 0 || idx[type] == 0)
|
|
||||||
return ("");
|
|
||||||
idx[type]--;
|
|
||||||
if (idx[type] == 0)
|
|
||||||
return ("");
|
|
||||||
return (prompt_hlist[type][prompt_hsize[type] - idx[type]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add line to the history. */
|
|
||||||
void
|
|
||||||
prompt_add_history(const char *line, u_int type)
|
|
||||||
{
|
|
||||||
u_int i, oldsize, newsize, freecount, hlimit, new = 1;
|
|
||||||
size_t movesize;
|
|
||||||
|
|
||||||
if (type >= PROMPT_NTYPES)
|
|
||||||
return;
|
|
||||||
|
|
||||||
oldsize = prompt_hsize[type];
|
|
||||||
if (oldsize > 0 &&
|
|
||||||
strcmp(prompt_hlist[type][oldsize - 1], line) == 0)
|
|
||||||
new = 0;
|
|
||||||
|
|
||||||
hlimit = options_get_number(global_options, "prompt-history-limit");
|
|
||||||
if (hlimit > oldsize) {
|
|
||||||
if (new == 0)
|
|
||||||
return;
|
|
||||||
newsize = oldsize + new;
|
|
||||||
} else {
|
|
||||||
newsize = hlimit;
|
|
||||||
freecount = oldsize + new - newsize;
|
|
||||||
if (freecount > oldsize)
|
|
||||||
freecount = oldsize;
|
|
||||||
if (freecount == 0)
|
|
||||||
return;
|
|
||||||
for (i = 0; i < freecount; i++)
|
|
||||||
free(prompt_hlist[type][i]);
|
|
||||||
movesize = (oldsize - freecount) *
|
|
||||||
sizeof *prompt_hlist[type];
|
|
||||||
if (movesize > 0) {
|
|
||||||
memmove(&prompt_hlist[type][0],
|
|
||||||
&prompt_hlist[type][freecount], movesize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newsize == 0) {
|
|
||||||
free(prompt_hlist[type]);
|
|
||||||
prompt_hlist[type] = NULL;
|
|
||||||
} else if (newsize != oldsize) {
|
|
||||||
prompt_hlist[type] =
|
|
||||||
xreallocarray(prompt_hlist[type], newsize,
|
|
||||||
sizeof *prompt_hlist[type]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new == 1 && newsize > 0)
|
|
||||||
prompt_hlist[type][newsize - 1] = xstrdup(line);
|
|
||||||
prompt_hsize[type] = newsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get history size. */
|
|
||||||
u_int
|
|
||||||
prompt_history_size(enum prompt_type type)
|
|
||||||
{
|
|
||||||
if (type >= PROMPT_NTYPES)
|
|
||||||
return (0);
|
|
||||||
return (prompt_hsize[type]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get history entry. */
|
|
||||||
const char *
|
|
||||||
prompt_history_get(enum prompt_type type, u_int idx)
|
|
||||||
{
|
|
||||||
if (type >= PROMPT_NTYPES)
|
|
||||||
return (NULL);
|
|
||||||
if (idx >= prompt_hsize[type])
|
|
||||||
return (NULL);
|
|
||||||
return (prompt_hlist[type][idx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear prompt history. */
|
|
||||||
void
|
|
||||||
prompt_history_clear(enum prompt_type type)
|
|
||||||
{
|
|
||||||
u_int idx;
|
|
||||||
|
|
||||||
if (type >= PROMPT_NTYPES)
|
|
||||||
return;
|
|
||||||
for (idx = 0; idx < prompt_hsize[type]; idx++)
|
|
||||||
free(prompt_hlist[type][idx]);
|
|
||||||
free(prompt_hlist[type]);
|
|
||||||
prompt_hlist[type] = NULL;
|
|
||||||
prompt_hsize[type] = 0;
|
|
||||||
}
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Name validation policy.
|
|
||||||
|
|
||||||
PATH=/bin:/usr/bin
|
|
||||||
TERM=screen
|
|
||||||
|
|
||||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
||||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
|
|
||||||
fail()
|
|
||||||
{
|
|
||||||
echo "$*"
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
must_fail()
|
|
||||||
{
|
|
||||||
"$@" >/dev/null 2>&1 && fail "unexpected success: $*"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
must_equal()
|
|
||||||
{
|
|
||||||
got=$1
|
|
||||||
want=$2
|
|
||||||
|
|
||||||
[ "$got" = "$want" ] || fail "got '$got', expected '$want'"
|
|
||||||
}
|
|
||||||
|
|
||||||
$TMUX new-session -d -x 80 -y 24 || exit 1
|
|
||||||
$TMUX set-option -qg allow-set-title on || exit 1
|
|
||||||
$TMUX set-option -qg allow-rename on || exit 1
|
|
||||||
$TMUX set-option -qg automatic-rename off || exit 1
|
|
||||||
|
|
||||||
# Commands reject ':' and '.' for sessions and windows, but allow '#'.
|
|
||||||
$TMUX rename-session 'session#ok' || fail "session name with # rejected"
|
|
||||||
must_equal "$($TMUX display-message -p '#{session_name}')" 'session#ok'
|
|
||||||
must_fail $TMUX rename-session 'session:bad'
|
|
||||||
must_fail $TMUX rename-session 'session.bad'
|
|
||||||
|
|
||||||
$TMUX rename-window 'window#ok' || fail "window name with # rejected"
|
|
||||||
must_equal "$($TMUX display-message -p '#{window_name}')" 'window#ok'
|
|
||||||
must_fail $TMUX rename-window 'window:bad'
|
|
||||||
must_fail $TMUX rename-window 'window.bad'
|
|
||||||
|
|
||||||
$TMUX set-option -q @name 'format#ok' || exit 1
|
|
||||||
$TMUX rename-session '#{@name}' || fail "format in session name not expanded"
|
|
||||||
must_equal "$($TMUX display-message -p '#{session_name}')" 'format#ok'
|
|
||||||
$TMUX rename-window '#{@name}' || fail "format in window name not expanded"
|
|
||||||
must_equal "$($TMUX display-message -p '#{window_name}')" 'format#ok'
|
|
||||||
must_fail $TMUX rename-session '#{session_name}:bad'
|
|
||||||
must_fail $TMUX rename-window '#{window_name}.bad'
|
|
||||||
pid=$($TMUX display-message -p '#{pid}')
|
|
||||||
|
|
||||||
created=$($TMUX new-session -dP -F '#{session_id}:#{window_id}' \
|
|
||||||
-s 'new-session#ok' -n 'new-window#ok') || \
|
|
||||||
fail "new-session name with # rejected"
|
|
||||||
created_session=${created%:*}
|
|
||||||
created_window=${created#*:}
|
|
||||||
must_equal "$($TMUX display-message -pt "$created_session" '#{session_name}')" \
|
|
||||||
'new-session#ok'
|
|
||||||
must_equal "$($TMUX display-message -pt "$created_window" '#{window_name}')" \
|
|
||||||
'new-window#ok'
|
|
||||||
$TMUX kill-session -t "$created_session"
|
|
||||||
|
|
||||||
must_fail $TMUX new-session -d -s 'new-session:bad'
|
|
||||||
must_fail $TMUX new-session -d -s 'new-session.bad'
|
|
||||||
must_fail $TMUX new-session -d -n 'new-window:bad'
|
|
||||||
must_fail $TMUX new-session -d -n 'new-window.bad'
|
|
||||||
|
|
||||||
created_window=$($TMUX new-window -dP -F '#{window_id}' \
|
|
||||||
-n 'created-window#ok') || \
|
|
||||||
fail "new-window name with # rejected"
|
|
||||||
must_equal "$($TMUX display-message -pt "$created_window" '#{window_name}')" \
|
|
||||||
'created-window#ok'
|
|
||||||
must_fail $TMUX new-window -d -n 'created-window:bad'
|
|
||||||
must_fail $TMUX new-window -d -n 'created-window.bad'
|
|
||||||
|
|
||||||
created=$($TMUX new-session -dP -F '#{session_id}:#{window_id}' \
|
|
||||||
-s 'new-session-#{pid}' -n 'new-window-#{pid}') || \
|
|
||||||
fail "format in new-session name not expanded"
|
|
||||||
created_session=${created%:*}
|
|
||||||
created_window=${created#*:}
|
|
||||||
must_equal "$($TMUX display-message -pt "$created_session" '#{session_name}')" \
|
|
||||||
"new-session-$pid"
|
|
||||||
must_equal "$($TMUX display-message -pt "$created_window" '#{window_name}')" \
|
|
||||||
"new-window-$pid"
|
|
||||||
$TMUX kill-session -t "$created_session"
|
|
||||||
|
|
||||||
created_window=$($TMUX new-window -dP -F '#{window_id}' -n '#{@name}') || \
|
|
||||||
fail "format in new-window name not expanded"
|
|
||||||
must_equal "$($TMUX display-message -pt "$created_window" '#{window_name}')" \
|
|
||||||
'format#ok'
|
|
||||||
must_fail $TMUX new-session -d -s 'new-session-#{pid}:bad'
|
|
||||||
must_fail $TMUX new-session -d -n 'new-window-#{pid}.bad'
|
|
||||||
must_fail $TMUX new-window -d -n '#{window_name}:bad'
|
|
||||||
|
|
||||||
# Invalid UTF-8 is never allowed for command names.
|
|
||||||
invalid=$(printf '\302')
|
|
||||||
must_fail $TMUX rename-session "bad${invalid}name"
|
|
||||||
must_fail $TMUX rename-window "bad${invalid}name"
|
|
||||||
must_fail $TMUX new-session -d -s "bad${invalid}name"
|
|
||||||
must_fail $TMUX new-session -d -n "bad${invalid}name"
|
|
||||||
must_fail $TMUX new-window -d -n "bad${invalid}name"
|
|
||||||
must_fail $TMUX set-buffer -b "bad${invalid}name" data
|
|
||||||
|
|
||||||
# Titles set by commands allow '#', ':' and '.'.
|
|
||||||
$TMUX select-pane -T 'title#:.ok' || fail "command title rejected"
|
|
||||||
must_equal "$($TMUX display-message -p '#{pane_title}')" 'title#:.ok'
|
|
||||||
|
|
||||||
# Buffer names allow '#', ':' and '.'.
|
|
||||||
$TMUX set-buffer -b 'buffer#:.ok' data || fail "buffer name rejected"
|
|
||||||
must_equal "$($TMUX list-buffers -F '#{buffer_name}')" 'buffer#:.ok'
|
|
||||||
|
|
||||||
# Window names from escape sequences reject '#', ':' and '.' by cleaning them.
|
|
||||||
$TMUX send-keys "printf '\\033kescape#:.ok\\033\\\\'" Enter || exit 1
|
|
||||||
sleep 1
|
|
||||||
must_equal "$($TMUX display-message -p '#{window_name}')" 'escape___ok'
|
|
||||||
|
|
||||||
# Titles from escape sequences reject only '#'.
|
|
||||||
$TMUX send-keys "printf '\\033]2;escape#:.ok\\007'" Enter || exit 1
|
|
||||||
sleep 1
|
|
||||||
must_equal "$($TMUX display-message -p '#{pane_title}')" 'escape_:.ok'
|
|
||||||
|
|
||||||
# Invalid UTF-8 from escape sequences is ignored.
|
|
||||||
$TMUX rename-window 'before-invalid' || exit 1
|
|
||||||
$TMUX send-keys "printf '\\033kbad\\302name\\033\\\\'" Enter || exit 1
|
|
||||||
sleep 1
|
|
||||||
must_equal "$($TMUX display-message -p '#{window_name}')" 'before-invalid'
|
|
||||||
|
|
||||||
$TMUX select-pane -T 'before-invalid-title' || exit 1
|
|
||||||
$TMUX send-keys "printf '\\033]2;bad\\302title\\007'" Enter || exit 1
|
|
||||||
sleep 1
|
|
||||||
must_equal "$($TMUX display-message -p '#{pane_title}')" 'before-invalid-title'
|
|
||||||
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
exit 0
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# command-alias expansion
|
|
||||||
|
|
||||||
PATH=/bin:/usr/bin
|
|
||||||
TERM=screen
|
|
||||||
|
|
||||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
||||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
|
|
||||||
$TMUX new-session -d -sfoo || exit 1
|
|
||||||
$TMUX split-window -d -tfoo:0.0 || exit 1
|
|
||||||
$TMUX set -s command-alias[100] zoom='resize-pane -Z' || exit 1
|
|
||||||
$TMUX zoom -tfoo:0.0 || exit 1
|
|
||||||
[ "$($TMUX display-message -p -tfoo:0.0 '#{window_zoomed_flag}')" = 1 ] || exit 1
|
|
||||||
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Test new-pane, resize-pane, and move-pane -x/-y/-X/-Y with floating panes.
|
|
||||||
# Verifies that size and position are correctly applied with the default border,
|
|
||||||
# with -B none, and with the pane-border-lines window option set to none. Also
|
|
||||||
# verifies that zero sizes are rejected.
|
|
||||||
#
|
|
||||||
# With a border, -x/-y/-X/-Y specify the onscreen footprint including the
|
|
||||||
# border: new-pane subtracts 2 from width/height and adds 1 to x/y-position
|
|
||||||
# so that the border lands on the specified screen coordinates. resize-pane
|
|
||||||
# -x/-y similarly subtracts 2 from the requested size. move-pane -X/-Y adds 1
|
|
||||||
# to the position. Without a border all values are used directly.
|
|
||||||
|
|
||||||
PATH=/bin:/usr/bin
|
|
||||||
TERM=screen
|
|
||||||
|
|
||||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
||||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
|
|
||||||
fail()
|
|
||||||
{
|
|
||||||
echo "$*" >&2
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
must_fail()
|
|
||||||
{
|
|
||||||
"$@" >/dev/null 2>&1 && fail "unexpected success: $*"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
must_equal()
|
|
||||||
{
|
|
||||||
got=$1
|
|
||||||
want=$2
|
|
||||||
[ "$got" = "$want" ] || fail "got '$got', expected '$want'"
|
|
||||||
}
|
|
||||||
|
|
||||||
$TMUX new-session -d -x 80 -y 24 || exit 1
|
|
||||||
|
|
||||||
# --- Default border (single-line) ---
|
|
||||||
|
|
||||||
# Explicit values: border subtracts 2 from size and adds 1 to position.
|
|
||||||
# -x 20 -> pane_width 18; -y 6 -> pane_height 4;
|
|
||||||
# -X 8 -> pane_left 9; -Y 3 -> pane_top 4.
|
|
||||||
id=$($TMUX new-pane -dPF '#{pane_id}' -x 20 -y 6 -X 8 -Y 3 'sleep 100') \
|
|
||||||
|| fail "new-pane with explicit geometry failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_width}')" 18
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_height}')" 4
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_left}')" 9
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_top}')" 4
|
|
||||||
|
|
||||||
# resize-pane with border: requested size decremented by 2.
|
|
||||||
$TMUX resize-pane -t "$id" -x 30 || fail "resize-pane -x 30 failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_width}')" 28
|
|
||||||
$TMUX resize-pane -t "$id" -y 10 || fail "resize-pane -y 10 failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_height}')" 8
|
|
||||||
|
|
||||||
# resize-pane with percentage and border.
|
|
||||||
# 75% of 80 = 60, 60 - 2 = 58; 75% of 24 = 18, 18 - 2 = 16.
|
|
||||||
$TMUX resize-pane -t "$id" -x 75% || fail "resize-pane -x 75% failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_width}')" 58
|
|
||||||
$TMUX resize-pane -t "$id" -y 75% || fail "resize-pane -y 75% failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_height}')" 16
|
|
||||||
$TMUX kill-pane -t "$id" || exit 1
|
|
||||||
|
|
||||||
# Percentage width, height and position with border.
|
|
||||||
# 50% of 80 = 40, 40-2 = 38; 50% of 24 = 12, 12-2 = 10.
|
|
||||||
# 10% of 80 = 8, 8+1 = 9; 10% of 24 = 2, 2+1 = 3.
|
|
||||||
id=$($TMUX new-pane -dPF '#{pane_id}' -x 50% -y 50% -X 10% -Y 10% 'sleep 100') \
|
|
||||||
|| fail "new-pane with percentage geometry failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_width}')" 38
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_height}')" 10
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_left}')" 9
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_top}')" 3
|
|
||||||
|
|
||||||
# move-pane -X/-Y with border: border lands at the given column/row, content
|
|
||||||
# is one cell inside. -X 5 -> pane_left 6; -Y 1 -> pane_top 2.
|
|
||||||
$TMUX move-pane -t "$id" -X 5 || fail "move-pane -X 5 failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_left}')" 6
|
|
||||||
$TMUX move-pane -t "$id" -Y 1 || fail "move-pane -Y 1 failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_top}')" 2
|
|
||||||
# 25% of 80 = 20, 20+1 = 21; 25% of 24 = 6, 6+1 = 7.
|
|
||||||
$TMUX move-pane -t "$id" -X 25% || fail "move-pane -X 25% failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_left}')" 21
|
|
||||||
$TMUX move-pane -t "$id" -Y 25% || fail "move-pane -Y 25% failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_top}')" 7
|
|
||||||
$TMUX kill-pane -t "$id" || exit 1
|
|
||||||
|
|
||||||
# --- -B none ---
|
|
||||||
|
|
||||||
# Without a border all values are used directly.
|
|
||||||
id=$($TMUX new-pane -dPF '#{pane_id}' -B none -x 20 -y 6 -X 8 -Y 3 'sleep 100') \
|
|
||||||
|| fail "new-pane -B none with explicit geometry failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_width}')" 20
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_height}')" 6
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_left}')" 8
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_top}')" 3
|
|
||||||
|
|
||||||
# resize-pane without border: size used directly.
|
|
||||||
$TMUX resize-pane -t "$id" -x 30 || fail "resize-pane -x 30 failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_width}')" 30
|
|
||||||
$TMUX resize-pane -t "$id" -y 10 || fail "resize-pane -y 10 failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_height}')" 10
|
|
||||||
|
|
||||||
# resize-pane with percentage, no border: 75% of 80 = 60; 75% of 24 = 18.
|
|
||||||
$TMUX resize-pane -t "$id" -x 75% || fail "resize-pane -x 75% failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_width}')" 60
|
|
||||||
$TMUX resize-pane -t "$id" -y 75% || fail "resize-pane -y 75% failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_height}')" 18
|
|
||||||
$TMUX kill-pane -t "$id" || exit 1
|
|
||||||
|
|
||||||
# Percentage geometry without border: 50% of 80 = 40; 10% of 80 = 8 etc.
|
|
||||||
id=$($TMUX new-pane -dPF '#{pane_id}' -B none -x 50% -y 50% -X 10% -Y 10% 'sleep 100') \
|
|
||||||
|| fail "new-pane -B none with percentage geometry failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_width}')" 40
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_height}')" 12
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_left}')" 8
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_top}')" 2
|
|
||||||
|
|
||||||
# move-pane without border: -X/-Y set the content position directly.
|
|
||||||
# -X 5 -> pane_left 5; -Y 1 -> pane_top 1.
|
|
||||||
$TMUX move-pane -t "$id" -X 5 || fail "move-pane -X 5 failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_left}')" 5
|
|
||||||
$TMUX move-pane -t "$id" -Y 1 || fail "move-pane -Y 1 failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_top}')" 1
|
|
||||||
# 25% of 80 = 20; 25% of 24 = 6.
|
|
||||||
$TMUX move-pane -t "$id" -X 25% || fail "move-pane -X 25% failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_left}')" 20
|
|
||||||
$TMUX move-pane -t "$id" -Y 25% || fail "move-pane -Y 25% failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_top}')" 6
|
|
||||||
$TMUX kill-pane -t "$id" || exit 1
|
|
||||||
|
|
||||||
# --- Window option pane-border-lines none ---
|
|
||||||
|
|
||||||
$TMUX set-option -w pane-border-lines none || exit 1
|
|
||||||
|
|
||||||
# Inherits none from window option: same behaviour as -B none.
|
|
||||||
id=$($TMUX new-pane -dPF '#{pane_id}' -x 20 -y 6 -X 8 -Y 3 'sleep 100') \
|
|
||||||
|| fail "new-pane with window pane-border-lines none failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_width}')" 20
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_height}')" 6
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_left}')" 8
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_top}')" 3
|
|
||||||
|
|
||||||
$TMUX resize-pane -t "$id" -x 30 || fail "resize-pane -x 30 failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_width}')" 30
|
|
||||||
$TMUX resize-pane -t "$id" -y 10 || fail "resize-pane -y 10 failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_height}')" 10
|
|
||||||
|
|
||||||
$TMUX resize-pane -t "$id" -x 75% || fail "resize-pane -x 75% failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_width}')" 60
|
|
||||||
$TMUX resize-pane -t "$id" -y 75% || fail "resize-pane -y 75% failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_height}')" 18
|
|
||||||
$TMUX kill-pane -t "$id" || exit 1
|
|
||||||
|
|
||||||
id=$($TMUX new-pane -dPF '#{pane_id}' -x 50% -y 50% -X 10% -Y 10% 'sleep 100') \
|
|
||||||
|| fail "new-pane with window pane-border-lines none and percentages failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_width}')" 40
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_height}')" 12
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_left}')" 8
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_top}')" 2
|
|
||||||
|
|
||||||
# move-pane with window pane-border-lines none: same behaviour as -B none.
|
|
||||||
$TMUX move-pane -t "$id" -X 5 || fail "move-pane -X 5 failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_left}')" 5
|
|
||||||
$TMUX move-pane -t "$id" -Y 1 || fail "move-pane -Y 1 failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_top}')" 1
|
|
||||||
$TMUX move-pane -t "$id" -X 25% || fail "move-pane -X 25% failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_left}')" 20
|
|
||||||
$TMUX move-pane -t "$id" -Y 25% || fail "move-pane -Y 25% failed"
|
|
||||||
must_equal "$($TMUX display-message -p -t "$id" '#{pane_top}')" 6
|
|
||||||
$TMUX kill-pane -t "$id" || exit 1
|
|
||||||
|
|
||||||
# --- Invalid sizes ---
|
|
||||||
|
|
||||||
# Zero width and height must be rejected by new-pane with the default border.
|
|
||||||
$TMUX set-option -w -u pane-border-lines || exit 1
|
|
||||||
must_fail $TMUX new-pane -d -x 0 -y 6 -X 8 -Y 3 'sleep 100'
|
|
||||||
must_fail $TMUX new-pane -d -x 20 -y 0 -X 8 -Y 3 'sleep 100'
|
|
||||||
|
|
||||||
# Zero width and height must be rejected by resize-pane.
|
|
||||||
id=$($TMUX new-pane -dPF '#{pane_id}' -x 20 -y 6 -X 8 -Y 3 'sleep 100') \
|
|
||||||
|| fail "new-pane for resize-pane invalid size tests failed"
|
|
||||||
must_fail $TMUX resize-pane -t "$id" -x 0
|
|
||||||
must_fail $TMUX resize-pane -t "$id" -y 0
|
|
||||||
$TMUX kill-pane -t "$id" || exit 1
|
|
||||||
|
|
||||||
# Same rejections apply with no border.
|
|
||||||
$TMUX set-option -w pane-border-lines none || exit 1
|
|
||||||
must_fail $TMUX new-pane -d -x 0 -y 6 -X 8 -Y 3 'sleep 100'
|
|
||||||
must_fail $TMUX new-pane -d -x 20 -y 0 -X 8 -Y 3 'sleep 100'
|
|
||||||
|
|
||||||
id=$($TMUX new-pane -dPF '#{pane_id}' -x 20 -y 6 -X 8 -Y 3 'sleep 100') \
|
|
||||||
|| fail "new-pane for resize-pane invalid size tests (no border) failed"
|
|
||||||
must_fail $TMUX resize-pane -t "$id" -x 0
|
|
||||||
must_fail $TMUX resize-pane -t "$id" -y 0
|
|
||||||
$TMUX kill-pane -t "$id" || exit 1
|
|
||||||
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
exit 0
|
|
||||||
@@ -67,7 +67,6 @@ $TMUX set @true 1 || exit 1
|
|||||||
$TMUX set @false 0 || exit 1
|
$TMUX set @false 0 || exit 1
|
||||||
$TMUX set @warm Summer || exit 1
|
$TMUX set @warm Summer || exit 1
|
||||||
$TMUX set @cold Winter || exit 1
|
$TMUX set @cold Winter || exit 1
|
||||||
$TMUX set @v 'foo:bar' || exit 1
|
|
||||||
|
|
||||||
# Plain string without substitutions et al
|
# Plain string without substitutions et al
|
||||||
test_format "abc xyz" "abc xyz"
|
test_format "abc xyz" "abc xyz"
|
||||||
@@ -75,8 +74,6 @@ test_format "abc xyz" "abc xyz"
|
|||||||
# Test basic escapes for "#", "{", "#{" "}", "#}", ","
|
# Test basic escapes for "#", "{", "#{" "}", "#}", ","
|
||||||
test_format "##" "#"
|
test_format "##" "#"
|
||||||
test_format "#," ","
|
test_format "#," ","
|
||||||
test_format "#{s/#:/_/:@v}" "foo_bar"
|
|
||||||
test_format "#{s/o/#:/:@v}" "f:::bar"
|
|
||||||
test_format "{" "{"
|
test_format "{" "{"
|
||||||
test_format "##{" "#{"
|
test_format "##{" "#{"
|
||||||
test_format "#}" "}"
|
test_format "#}" "}"
|
||||||
|
|||||||
@@ -1,300 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
PATH=/bin:/usr/bin
|
|
||||||
TERM=screen
|
|
||||||
LC_ALL=C.UTF-8
|
|
||||||
LANG=C.UTF-8
|
|
||||||
export TERM LC_ALL LANG
|
|
||||||
|
|
||||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
||||||
OUT="$TEST_TMUX -Ltest -f/dev/null" # outer (host for the client)
|
|
||||||
IN="$TEST_TMUX -Ltest2 -f/dev/null" # inner (under test)
|
|
||||||
|
|
||||||
$OUT kill-server 2>/dev/null
|
|
||||||
$IN kill-server 2>/dev/null
|
|
||||||
trap "$OUT kill-server 2>/dev/null; $IN kill-server 2>/dev/null" EXIT
|
|
||||||
|
|
||||||
fail() {
|
|
||||||
echo "[FAIL] $1"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Capture the outer pane: what the inner client rendered. No -e, so we match
|
|
||||||
# plain visible text, not styles or escape sequences.
|
|
||||||
capture() {
|
|
||||||
$OUT capture-pane -p
|
|
||||||
}
|
|
||||||
|
|
||||||
# The "(search) ..." prompt row of a mode prompt.
|
|
||||||
search_row() {
|
|
||||||
capture | grep '(search)' | head -1
|
|
||||||
}
|
|
||||||
|
|
||||||
# The inner status line is the last row of the outer capture (status is at the
|
|
||||||
# bottom). Used to assert a prompt is in the pane and not on the status line.
|
|
||||||
status_line() {
|
|
||||||
capture | tail -1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Inner mode must still be a tree mode (the prompt did not close or crash it).
|
|
||||||
in_tree_mode() {
|
|
||||||
[ "$($IN display-message -p '#{pane_mode}')" = "tree-mode" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Small settle for the key -> inner server -> inner client -> outer pane round
|
|
||||||
# trip to redraw before we capture. Matches the short waits other regress tests
|
|
||||||
# use; we do not depend on exact timing beyond the redraw completing.
|
|
||||||
settle() {
|
|
||||||
sleep 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# Assert the mode search prompt currently shows exactly "(search) <want>".
|
|
||||||
search_is() {
|
|
||||||
want=$1; msg=$2
|
|
||||||
search_row | grep -qF "(search) $want" || \
|
|
||||||
fail "$msg (wanted '(search) $want', got '$(search_row)')"
|
|
||||||
}
|
|
||||||
|
|
||||||
# --- Inner session under test. ---------------------------------------------
|
|
||||||
#
|
|
||||||
# Two windows so the tree has content; status on so we can distinguish the pane
|
|
||||||
# from the status line; fixed size and manual sizing so the layout is stable.
|
|
||||||
# A root-table key opens a status-line command prompt whose accept action writes
|
|
||||||
# the final buffer into @r, so we can recover it exactly.
|
|
||||||
$IN new -d -x80 -y24 "sh -c 'exec sleep 1000'" || exit 1
|
|
||||||
$IN set -g status on || exit 1
|
|
||||||
$IN set -g status-position bottom || exit 1
|
|
||||||
$IN set -g status-keys emacs || exit 1
|
|
||||||
$IN set -g window-size manual || exit 1
|
|
||||||
$IN new-window -d "sh -c 'exec sleep 1000'" || exit 1
|
|
||||||
$IN bind -n M-r command-prompt -p ">" "set -g @r '%%'" || exit 1
|
|
||||||
|
|
||||||
# --- Outer session: attach the inner one inside its pane. -------------------
|
|
||||||
$OUT new -d -x80 -y24 || exit 1
|
|
||||||
$OUT set -g status off || exit 1
|
|
||||||
$OUT set -g window-size manual || exit 1
|
|
||||||
$OUT send-keys -l "$IN attach" || exit 1
|
|
||||||
$OUT send-keys Enter || exit 1
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# ===========================================================================
|
|
||||||
# Mode prompt (choose-tree search): the thorough engine vehicle.
|
|
||||||
# ===========================================================================
|
|
||||||
|
|
||||||
$IN choose-tree || exit 1
|
|
||||||
settle
|
|
||||||
in_tree_mode || fail "choose-tree did not enter tree-mode"
|
|
||||||
|
|
||||||
# --- 1. Search prompt is drawn in the pane, not on the status line. ---
|
|
||||||
$IN send-keys C-s || exit 1
|
|
||||||
settle
|
|
||||||
search_row | grep -q '(search)' || fail "search prompt not drawn in the pane"
|
|
||||||
status_line | grep -q '(search)' && \
|
|
||||||
fail "search prompt drawn on the status line, not in the pane"
|
|
||||||
|
|
||||||
# --- 2. emacs editing: insert and delete at middle, start and end. ---
|
|
||||||
# Cursor position is checked behaviourally: move, insert a marker, read the row.
|
|
||||||
# This needs no cursor coordinates and fails if a movement/edit key is wrong.
|
|
||||||
|
|
||||||
# Middle insert: "abcd", Left Left (cursor between b and c), insert X -> abXcd.
|
|
||||||
$IN send-keys -l "abcd" || exit 1
|
|
||||||
settle
|
|
||||||
search_is "abcd" "literal input not shown in search prompt"
|
|
||||||
$IN send-keys Left Left || exit 1
|
|
||||||
$IN send-keys -l "X" || exit 1
|
|
||||||
settle
|
|
||||||
search_is "abXcd" "middle insert wrong (Left/insert)"
|
|
||||||
|
|
||||||
# Middle delete: BSpace removes X (before cursor), DC removes c (at cursor).
|
|
||||||
$IN send-keys BSpace || exit 1
|
|
||||||
$IN send-keys DC || exit 1
|
|
||||||
settle
|
|
||||||
search_is "abd" "middle delete wrong (BSpace/Delete)"
|
|
||||||
|
|
||||||
# Clear, then start/end insert with C-a and C-e.
|
|
||||||
$IN send-keys C-u || exit 1
|
|
||||||
$IN send-keys -l "mno" || exit 1
|
|
||||||
$IN send-keys C-a || exit 1
|
|
||||||
$IN send-keys -l "S" || exit 1
|
|
||||||
$IN send-keys C-e || exit 1
|
|
||||||
$IN send-keys -l "E" || exit 1
|
|
||||||
settle
|
|
||||||
search_is "SmnoE" "C-a/C-e start/end insert wrong"
|
|
||||||
|
|
||||||
# Word kill: "hello world", C-w removes the last word leaving "hello " (with the
|
|
||||||
# separating space). capture-pane trims trailing spaces, so make the space
|
|
||||||
# visible by inserting a marker after it: the buffer becomes "hello Z".
|
|
||||||
$IN send-keys C-u || exit 1
|
|
||||||
$IN send-keys -l "hello world" || exit 1
|
|
||||||
$IN send-keys C-w || exit 1
|
|
||||||
$IN send-keys -l "Z" || exit 1
|
|
||||||
settle
|
|
||||||
search_is "hello Z" "C-w did not kill a word"
|
|
||||||
|
|
||||||
# C-a then C-k kills the whole line.
|
|
||||||
$IN send-keys C-a || exit 1
|
|
||||||
$IN send-keys C-k || exit 1
|
|
||||||
settle
|
|
||||||
search_row | grep -q '(search) [^ ]' && fail "C-a C-k did not clear the line"
|
|
||||||
|
|
||||||
# --- 3. Editing kept the prompt open the whole time. ---
|
|
||||||
in_tree_mode || fail "editing keys closed the mode"
|
|
||||||
search_row | grep -q '(search)' || fail "editing keys closed the prompt"
|
|
||||||
|
|
||||||
# --- 4. Unicode wide character: insert, render, delete as one unit. ---
|
|
||||||
$IN send-keys C-u || exit 1
|
|
||||||
$IN send-keys -l "a中b" || exit 1
|
|
||||||
settle
|
|
||||||
search_is "a中b" "wide character not shown"
|
|
||||||
# Left moves over "b" (one column); BSpace deletes the wide "中" as a single
|
|
||||||
# width-2 unit, leaving "ab".
|
|
||||||
$IN send-keys Left || exit 1
|
|
||||||
$IN send-keys BSpace || exit 1
|
|
||||||
settle
|
|
||||||
search_is "ab" "wide character not deleted as one unit"
|
|
||||||
|
|
||||||
# --- 5. Control character: quote-next inserts it literally, shown as ^G. ---
|
|
||||||
$IN send-keys C-u || exit 1
|
|
||||||
$IN send-keys -l "a" || exit 1
|
|
||||||
$IN send-keys C-v || exit 1 # quote next key
|
|
||||||
$IN send-keys C-g || exit 1 # literal BEL -> displayed as ^G
|
|
||||||
$IN send-keys -l "b" || exit 1
|
|
||||||
settle
|
|
||||||
search_is "a^Gb" "control character not shown as ^G"
|
|
||||||
# Deleted as a single unit too.
|
|
||||||
$IN send-keys Left || exit 1
|
|
||||||
$IN send-keys BSpace || exit 1
|
|
||||||
settle
|
|
||||||
search_is "ab" "control character not deleted as one unit"
|
|
||||||
|
|
||||||
# --- 6. Kill and yank: C-w fills the yank buffer, C-y pastes it at the cursor. ---
|
|
||||||
# (prompt_key only fills the yank buffer from C-w; C-y then yanks that text, or
|
|
||||||
# the top paste buffer if nothing has been killed. Establish our own kill here
|
|
||||||
# so the result is deterministic.)
|
|
||||||
$IN send-keys C-u || exit 1
|
|
||||||
$IN send-keys -l "one two" || exit 1
|
|
||||||
$IN send-keys C-w || exit 1 # kill "two", buffer "one "
|
|
||||||
$IN send-keys C-y || exit 1 # yank it back -> "one two"
|
|
||||||
settle
|
|
||||||
search_is "one two" "C-y did not yank the killed text"
|
|
||||||
$IN send-keys C-y || exit 1 # yank again at cursor -> "one twotwo"
|
|
||||||
settle
|
|
||||||
search_is "one twotwo" "second C-y did not yank again"
|
|
||||||
|
|
||||||
# --- 7. History: accept a string, reopen, Up recalls it. ---
|
|
||||||
$IN send-keys C-u || exit 1
|
|
||||||
$IN send-keys -l "alpha" || exit 1
|
|
||||||
$IN send-keys Enter || exit 1
|
|
||||||
settle
|
|
||||||
$IN send-keys C-s || exit 1
|
|
||||||
settle
|
|
||||||
$IN send-keys Up || exit 1
|
|
||||||
settle
|
|
||||||
search_is "alpha" "history (Up) did not recall the previous entry"
|
|
||||||
|
|
||||||
# --- 8. Escape closes the prompt but leaves the mode open. ---
|
|
||||||
$IN send-keys Escape || exit 1
|
|
||||||
settle
|
|
||||||
search_row | grep -q '(search)' && fail "Escape left a dangling search prompt"
|
|
||||||
in_tree_mode || fail "Escape closed the mode as well as the prompt"
|
|
||||||
|
|
||||||
# Leave the mode.
|
|
||||||
$IN send-keys q || exit 1
|
|
||||||
settle
|
|
||||||
|
|
||||||
# ===========================================================================
|
|
||||||
# Status-line prompt (command-prompt): the same engine on the status line.
|
|
||||||
# Keys go through the inner client's terminal (outer send-keys); the accepted
|
|
||||||
# buffer is recovered exactly via %% -> @r.
|
|
||||||
# ===========================================================================
|
|
||||||
|
|
||||||
# --- 10. Prompt is drawn on the status line (the last row). ---
|
|
||||||
$IN set -g @r "" || exit 1
|
|
||||||
$OUT send-keys M-r || exit 1
|
|
||||||
settle
|
|
||||||
status_line | grep -q '>' || fail "status-line prompt not drawn on the status line"
|
|
||||||
|
|
||||||
# --- 11. emacs cursor-marker edit, accept recovers the exact buffer. ---
|
|
||||||
$OUT send-keys -l "abc" || exit 1
|
|
||||||
$OUT send-keys Home || exit 1
|
|
||||||
$OUT send-keys -l "X" || exit 1
|
|
||||||
settle
|
|
||||||
status_line | grep -qF "> Xabc" || \
|
|
||||||
fail "status-line edit wrong (got '$(status_line)')"
|
|
||||||
$OUT send-keys Enter || exit 1
|
|
||||||
settle
|
|
||||||
[ "$($IN show -gv @r)" = "Xabc" ] || \
|
|
||||||
fail "status-line accept recovered '$($IN show -gv @r)', wanted 'Xabc'"
|
|
||||||
|
|
||||||
# --- 12. Unicode on the status line: insert, move, delete wide char. ---
|
|
||||||
$IN set -g @r "" || exit 1
|
|
||||||
$OUT send-keys M-r || exit 1
|
|
||||||
settle
|
|
||||||
$OUT send-keys -l "a㋡b" || exit 1
|
|
||||||
settle
|
|
||||||
status_line | grep -qF "a㋡b" || \
|
|
||||||
fail "status-line wide character not shown (got '$(status_line)')"
|
|
||||||
# Home, insert Z (start); End, BSpace (delete b); BSpace (delete wide char).
|
|
||||||
$OUT send-keys Home || exit 1
|
|
||||||
$OUT send-keys -l "Z" || exit 1
|
|
||||||
$OUT send-keys End || exit 1
|
|
||||||
$OUT send-keys BSpace || exit 1
|
|
||||||
$OUT send-keys BSpace || exit 1
|
|
||||||
settle
|
|
||||||
$OUT send-keys Enter || exit 1
|
|
||||||
settle
|
|
||||||
[ "$($IN show -gv @r)" = "Za" ] || \
|
|
||||||
fail "status-line wide edit recovered '$($IN show -gv @r)', wanted 'Za'"
|
|
||||||
|
|
||||||
# --- 13. Overflow: more text than fits stays within the line and is kept. ---
|
|
||||||
big="0123456789012345678901234567890123456789012345678901234567890123456789ABCDEFGHIJ"
|
|
||||||
$IN set -g @r "" || exit 1
|
|
||||||
$OUT send-keys M-r || exit 1
|
|
||||||
settle
|
|
||||||
$OUT send-keys -l "$big" || exit 1
|
|
||||||
settle
|
|
||||||
# The drawn status line must not exceed the client width (80): no wrap, no crash.
|
|
||||||
width=$(status_line | awk '{print length($0)}')
|
|
||||||
[ "$width" -le 80 ] || fail "overflowing prompt drew $width columns, wider than 80"
|
|
||||||
$OUT send-keys Enter || exit 1
|
|
||||||
settle
|
|
||||||
# The whole buffer was kept despite only part being visible.
|
|
||||||
[ "$($IN show -gv @r)" = "$big" ] || fail "overflowing prompt lost buffer content"
|
|
||||||
|
|
||||||
# --- 14. Escape closes the status-line prompt cleanly. ---
|
|
||||||
$IN set -g @r "SENTINEL" || exit 1
|
|
||||||
$OUT send-keys M-r || exit 1
|
|
||||||
settle
|
|
||||||
$OUT send-keys -l "discard" || exit 1
|
|
||||||
$OUT send-keys Escape || exit 1
|
|
||||||
settle
|
|
||||||
status_line | grep -q '> discard' && fail "Escape left a dangling status-line prompt"
|
|
||||||
[ "$($IN show -gv @r)" = "SENTINEL" ] || fail "Escape ran the prompt's accept action"
|
|
||||||
|
|
||||||
# ===========================================================================
|
|
||||||
# Two clients attached to the same window: a mode prompt must render on both.
|
|
||||||
# ===========================================================================
|
|
||||||
|
|
||||||
$OUT new-window || exit 1
|
|
||||||
$OUT set -g status off || exit 1
|
|
||||||
$OUT send-keys -l "$IN attach" || exit 1
|
|
||||||
$OUT send-keys Enter || exit 1
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
$IN choose-tree || exit 1
|
|
||||||
settle
|
|
||||||
$IN send-keys C-s || exit 1
|
|
||||||
settle
|
|
||||||
$IN send-keys -l "dual" || exit 1
|
|
||||||
settle
|
|
||||||
for w in $($OUT list-windows -F '#{window_index}'); do
|
|
||||||
$OUT capture-pane -t ":$w" -p | grep -qF "(search) dual" || \
|
|
||||||
fail "mode prompt not shown on client in outer window $w"
|
|
||||||
done
|
|
||||||
$IN send-keys Escape || exit 1
|
|
||||||
settle
|
|
||||||
|
|
||||||
# --- Inner tmux is still alive and responsive. ---
|
|
||||||
$IN display-message -p '#{version}' >/dev/null 2>&1 || fail "inner tmux died"
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,336 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Exercise the prompt mechanics shared by all three host paths of the prompt
|
|
||||||
# engine in prompt.c:
|
|
||||||
#
|
|
||||||
# status.c status_prompt_set - the status-line command prompt.
|
|
||||||
# window.c window_pane_set_prompt - a prompt drawn over a pane (-P).
|
|
||||||
# mode-tree.c mode_tree_set_prompt - search/filter prompts in tree modes.
|
|
||||||
#
|
|
||||||
# prompt-keys.sh covers the editing keys; this test covers that each path OPENS
|
|
||||||
# and DRAWS in the right place and that the prompt flags select the right engine
|
|
||||||
# behaviour: -1 (single), -N (numeric), -i (incremental), -k (key), -e
|
|
||||||
# (backspace exit), -I (prefill), multi prompts, type-scoped history and command
|
|
||||||
# completion.
|
|
||||||
|
|
||||||
PATH=/bin:/usr/bin
|
|
||||||
TERM=screen
|
|
||||||
LC_ALL=C.UTF-8
|
|
||||||
LANG=C.UTF-8
|
|
||||||
export TERM LC_ALL LANG
|
|
||||||
|
|
||||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
||||||
OUT="$TEST_TMUX -Ltest -f/dev/null" # outer (host for the client)
|
|
||||||
IN="$TEST_TMUX -Ltest2 -f/dev/null" # inner (under test)
|
|
||||||
|
|
||||||
$OUT kill-server 2>/dev/null
|
|
||||||
$IN kill-server 2>/dev/null
|
|
||||||
trap "$OUT kill-server 2>/dev/null; $IN kill-server 2>/dev/null" EXIT
|
|
||||||
|
|
||||||
fail() {
|
|
||||||
echo "[FAIL] $1"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Capture the outer pane: what the inner client rendered. Pane-area prompts
|
|
||||||
# (over a pane or in a tree mode) and the status-line prompt all end up here.
|
|
||||||
capture() {
|
|
||||||
$OUT capture-pane -p
|
|
||||||
}
|
|
||||||
|
|
||||||
# The inner status line is the last row of the outer capture.
|
|
||||||
status_line() {
|
|
||||||
capture | tail -1
|
|
||||||
}
|
|
||||||
|
|
||||||
# The recovered buffer. Every prompt below accepts into the @r option so the
|
|
||||||
# exact final string can be checked; reset it to a sentinel first so we can tell
|
|
||||||
# "accept ran" from "prompt cancelled".
|
|
||||||
got() {
|
|
||||||
$IN show -gv @r
|
|
||||||
}
|
|
||||||
reset() {
|
|
||||||
$IN set -g @r "SENTINEL" || exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Settle for the key -> inner server -> inner client -> outer pane redraw round
|
|
||||||
# trip, as in prompt-keys.sh.
|
|
||||||
settle() {
|
|
||||||
sleep 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
# --- Inner session under test. ---------------------------------------------
|
|
||||||
#
|
|
||||||
# The window is created at -y23 so that, with a one-row bottom status, the pane
|
|
||||||
# area (23) exactly fills the 24-row client: a pane prompt drawn on the pane's
|
|
||||||
# bottom row lands on visible row 23, just above the status line on row 24. A
|
|
||||||
# second, distinctively named window gives the tree something to filter.
|
|
||||||
$IN new -d -x80 -y23 -n YAK "sh -c 'exec sleep 1000'" || exit 1
|
|
||||||
$IN set -g status on || exit 1
|
|
||||||
$IN set -g status-position bottom || exit 1
|
|
||||||
$IN set -g status-keys emacs || exit 1
|
|
||||||
$IN set -g window-size manual || exit 1
|
|
||||||
$IN new-window -d -n ZEBRA "sh -c 'exec sleep 1000'" || exit 1
|
|
||||||
|
|
||||||
# One root-table key per path/flag. The accept template records the final
|
|
||||||
# buffer in @r (or both buffers, for the multi-prompt case).
|
|
||||||
$IN bind -n M-s command-prompt -p '(stat)' "set -g @r '%%'" || exit 1
|
|
||||||
$IN bind -n M-p command-prompt -P -p '(pane)' "set -g @r '%%'" || exit 1
|
|
||||||
$IN bind -n M-o command-prompt -P -1 -p '(one)' "set -g @r '%%'" || exit 1
|
|
||||||
$IN bind -n M-n command-prompt -P -N -I 5 -p '(num)' "set -g @r '%%'" || exit 1
|
|
||||||
$IN bind -n M-i command-prompt -P -i -p '(inc)' "set -g @r '%%'" || exit 1
|
|
||||||
$IN bind -n M-k command-prompt -P -k -p '(key)' "set -g @r '%%'" || exit 1
|
|
||||||
$IN bind -n M-e command-prompt -P -e -p '(bs)' "set -g @r '%%'" || exit 1
|
|
||||||
$IN bind -n M-j command-prompt -P -I hello -p '(pre)' "set -g @r '%%'" || exit 1
|
|
||||||
$IN bind -n M-m command-prompt -p 'first,second' "set -g @r '%1/%2'" || exit 1
|
|
||||||
$IN bind -n M-c command-prompt -p '(cmd)' "set -g @r '%%'" || exit 1
|
|
||||||
$IN bind -n M-h command-prompt -T search -p '(srch)' "set -g @r '%%'" || exit 1
|
|
||||||
|
|
||||||
# --- Outer session: attach the inner one inside its pane. -------------------
|
|
||||||
$OUT new -d -x80 -y24 || exit 1
|
|
||||||
$OUT set -g status off || exit 1
|
|
||||||
$OUT set -g window-size manual || exit 1
|
|
||||||
$OUT send-keys -l "$IN attach" || exit 1
|
|
||||||
$OUT send-keys Enter || exit 1
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# ===========================================================================
|
|
||||||
# 1. Each path opens and draws in the right place.
|
|
||||||
# ===========================================================================
|
|
||||||
|
|
||||||
# --- 1a. status.c: drawn on the status line (the last row). ---
|
|
||||||
reset
|
|
||||||
$OUT send-keys M-s || exit 1
|
|
||||||
settle
|
|
||||||
status_line | grep -qF '(stat)' || \
|
|
||||||
fail "status-line prompt not on the status line (got '$(status_line)')"
|
|
||||||
$OUT send-keys -l "go" || exit 1
|
|
||||||
$OUT send-keys Enter || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "go" ] || fail "status-line accept recovered '$(got)', wanted 'go'"
|
|
||||||
|
|
||||||
# --- 1b. window.c: drawn over the pane, not on the status line. ---
|
|
||||||
reset
|
|
||||||
$OUT send-keys M-p || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -qF '(pane)' || fail "pane prompt not drawn in the pane"
|
|
||||||
status_line | grep -qF '(pane)' && \
|
|
||||||
fail "pane prompt drawn on the status line, not over the pane"
|
|
||||||
$OUT send-keys -l "deep" || exit 1
|
|
||||||
$OUT send-keys Enter || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "deep" ] || fail "pane prompt accept recovered '$(got)', wanted 'deep'"
|
|
||||||
|
|
||||||
# --- 1c. mode-tree.c: search prompt drawn in the pane. ---
|
|
||||||
$IN choose-tree || exit 1
|
|
||||||
settle
|
|
||||||
[ "$($IN display-message -p '#{pane_mode}')" = "tree-mode" ] || \
|
|
||||||
fail "choose-tree did not enter tree-mode"
|
|
||||||
$IN send-keys C-s || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -qF '(search)' || fail "mode-tree search prompt not drawn in the pane"
|
|
||||||
status_line | grep -qF '(search)' && \
|
|
||||||
fail "mode-tree search prompt drawn on the status line"
|
|
||||||
$IN send-keys Escape || exit 1
|
|
||||||
settle
|
|
||||||
|
|
||||||
# --- 1d. mode-tree.c: filter prompt opens, applies, prefills, and clears. ---
|
|
||||||
$IN send-keys f || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -qF '(filter)' || fail "mode-tree filter prompt not drawn"
|
|
||||||
$IN send-keys -l "ZEBRA" || exit 1
|
|
||||||
$IN send-keys Enter || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -q 'filter: active' || fail "accepting the filter did not apply it"
|
|
||||||
# Reopening the filter prompt prefills it with the current filter.
|
|
||||||
$IN send-keys f || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -qF '(filter) ZEBRA' || \
|
|
||||||
fail "filter prompt not prefilled with the current filter"
|
|
||||||
$IN send-keys Escape || exit 1
|
|
||||||
settle
|
|
||||||
# 'c' clears the filter.
|
|
||||||
$IN send-keys c || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -q 'filter: active' && fail "'c' did not clear the filter"
|
|
||||||
$IN send-keys q || exit 1
|
|
||||||
settle
|
|
||||||
|
|
||||||
# ===========================================================================
|
|
||||||
# 2. Flags select the right engine behaviour.
|
|
||||||
# ===========================================================================
|
|
||||||
|
|
||||||
# --- 2a. -1 (PROMPT_SINGLE): one keystroke closes and accepts that char. ---
|
|
||||||
reset
|
|
||||||
$OUT send-keys M-o || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -qF '(one)' || fail "single prompt did not open"
|
|
||||||
$OUT send-keys -l "q" || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "q" ] || fail "single prompt recovered '$(got)', wanted 'q'"
|
|
||||||
capture | grep -qF '(one)' && fail "single prompt stayed open after one key"
|
|
||||||
|
|
||||||
# --- 2b. -N (PROMPT_NUMERIC): prefilled, digits append, non-digit closes. ---
|
|
||||||
reset
|
|
||||||
$OUT send-keys M-n || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -qF '(num) 5' || fail "numeric prompt not prefilled with 5"
|
|
||||||
$OUT send-keys -l "7" || exit 1 # 57
|
|
||||||
$OUT send-keys Enter || exit 1 # Enter is a non-digit: close
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "57" ] || fail "numeric accept recovered '$(got)', wanted '57'"
|
|
||||||
# A non-digit key closes the prompt with the existing buffer, dropping the key.
|
|
||||||
reset
|
|
||||||
$OUT send-keys M-n || exit 1
|
|
||||||
settle
|
|
||||||
$OUT send-keys -l "x" || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "5" ] || fail "numeric non-digit close recovered '$(got)', wanted '5'"
|
|
||||||
capture | grep -qF '(num)' && fail "numeric prompt stayed open after a non-digit"
|
|
||||||
|
|
||||||
# --- 2c. -i (PROMPT_INCREMENTAL): callback fires on every edit, stays open. ---
|
|
||||||
# The incremental code path prefixes the buffer with '=' (or +/-), so the '='
|
|
||||||
# proves the value came through the incremental callback, not a plain accept.
|
|
||||||
reset
|
|
||||||
$OUT send-keys M-i || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "=" ] || fail "incremental prompt did not fire on open (got '$(got)')"
|
|
||||||
$OUT send-keys -l "a" || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "=a" ] || fail "incremental did not fire after 'a' (got '$(got)')"
|
|
||||||
$OUT send-keys -l "b" || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "=ab" ] || fail "incremental did not fire after 'b' (got '$(got)')"
|
|
||||||
capture | grep -qF '(inc)' || fail "incremental prompt closed during editing"
|
|
||||||
$OUT send-keys Escape || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -qF '(inc)' && fail "Escape did not close the incremental prompt"
|
|
||||||
|
|
||||||
# --- 2d. -k (PROMPT_KEY): the next key closes and delivers its name. ---
|
|
||||||
reset
|
|
||||||
$OUT send-keys M-k || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -qF '(key)' || fail "key prompt did not open"
|
|
||||||
$OUT send-keys -l "z" || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "z" ] || fail "key prompt recovered '$(got)', wanted 'z'"
|
|
||||||
capture | grep -qF '(key)' && fail "key prompt stayed open after a key"
|
|
||||||
|
|
||||||
# --- 2e. -e (PROMPT_BSPACE_EXIT): backspace on empty cancels (no accept). ---
|
|
||||||
reset
|
|
||||||
$OUT send-keys M-e || exit 1
|
|
||||||
settle
|
|
||||||
$OUT send-keys BSpace || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "SENTINEL" ] || fail "backspace-exit ran the accept action (got '$(got)')"
|
|
||||||
capture | grep -qF '(bs)' && fail "backspace on empty did not close the prompt"
|
|
||||||
|
|
||||||
# --- 2f. -I (prefill): prompt opens with the given buffer. ---
|
|
||||||
reset
|
|
||||||
$OUT send-keys M-j || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -qF '(pre) hello' || fail "prefill not shown (got '$(capture | grep -F '(pre)')')"
|
|
||||||
$OUT send-keys Enter || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "hello" ] || fail "prefill accept recovered '$(got)', wanted 'hello'"
|
|
||||||
|
|
||||||
# --- 2g. Multi prompt: accept advances to the next, both are delivered. ---
|
|
||||||
reset
|
|
||||||
$OUT send-keys M-m || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -qF 'first' || fail "first of multi prompt not shown"
|
|
||||||
$OUT send-keys -l "X" || exit 1
|
|
||||||
$OUT send-keys Enter || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -qF 'second' || fail "multi prompt did not advance to the second"
|
|
||||||
$OUT send-keys -l "Y" || exit 1
|
|
||||||
$OUT send-keys Enter || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "X/Y" ] || fail "multi prompt recovered '$(got)', wanted 'X/Y'"
|
|
||||||
|
|
||||||
# ===========================================================================
|
|
||||||
# 3. Type-scoped history and command completion.
|
|
||||||
# ===========================================================================
|
|
||||||
|
|
||||||
# --- 3a. Command history is recalled with Up; search history is separate. ---
|
|
||||||
reset
|
|
||||||
$OUT send-keys M-c || exit 1
|
|
||||||
settle
|
|
||||||
$OUT send-keys -l "alpha" || exit 1
|
|
||||||
$OUT send-keys Enter || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "alpha" ] || fail "command prompt accept recovered '$(got)'"
|
|
||||||
# Reopen the command prompt: Up recalls the command-type entry.
|
|
||||||
$OUT send-keys M-c || exit 1
|
|
||||||
settle
|
|
||||||
$OUT send-keys Up || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -qF '(cmd) alpha' || fail "Up did not recall command history"
|
|
||||||
$OUT send-keys Escape || exit 1
|
|
||||||
settle
|
|
||||||
# A search-type prompt must NOT recall the command-type entry (separate rings).
|
|
||||||
$OUT send-keys M-h || exit 1
|
|
||||||
settle
|
|
||||||
$OUT send-keys Up || exit 1
|
|
||||||
settle
|
|
||||||
capture | grep -qF 'alpha' && fail "search prompt recalled command-type history"
|
|
||||||
$OUT send-keys Escape || exit 1
|
|
||||||
settle
|
|
||||||
|
|
||||||
# --- 3b. Tab completion works in a command prompt (command type only). ---
|
|
||||||
$OUT send-keys M-c || exit 1
|
|
||||||
settle
|
|
||||||
$OUT send-keys -l "new-w" || exit 1
|
|
||||||
$OUT send-keys Tab || exit 1
|
|
||||||
settle
|
|
||||||
status_line | grep -qF 'new-window' || \
|
|
||||||
fail "Tab did not complete new-w to new-window (got '$(status_line)')"
|
|
||||||
$OUT send-keys Escape || exit 1
|
|
||||||
settle
|
|
||||||
# A search-type prompt does not complete commands: Tab is literal / inert.
|
|
||||||
$OUT send-keys M-h || exit 1
|
|
||||||
settle
|
|
||||||
$OUT send-keys -l "new-w" || exit 1
|
|
||||||
$OUT send-keys Tab || exit 1
|
|
||||||
settle
|
|
||||||
status_line | grep -qF 'new-window' && fail "search prompt completed a command"
|
|
||||||
$OUT send-keys Escape || exit 1
|
|
||||||
settle
|
|
||||||
|
|
||||||
# ===========================================================================
|
|
||||||
# 4. Robustness: re-entrancy guard and Escape, then liveness.
|
|
||||||
# ===========================================================================
|
|
||||||
|
|
||||||
# --- 4a. A second prompt while one is open is refused (status path). ---
|
|
||||||
client=$($IN list-clients -F '#{client_name}' | head -1)
|
|
||||||
reset
|
|
||||||
$OUT send-keys M-s || exit 1
|
|
||||||
settle
|
|
||||||
$OUT send-keys -l "AAA" || exit 1
|
|
||||||
settle
|
|
||||||
$IN command-prompt -t"$client" -p '(re)' "set -g @r 'REENTERED'" 2>/dev/null
|
|
||||||
settle
|
|
||||||
capture | grep -qF '(re)' && fail "a second status prompt opened over the first"
|
|
||||||
status_line | grep -qF '(stat) AAA' || fail "first status prompt was disturbed"
|
|
||||||
$OUT send-keys Escape || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "SENTINEL" ] || fail "Escape ran the status prompt accept action"
|
|
||||||
|
|
||||||
# --- 4b. A second pane prompt while one is open is refused (pane path). ---
|
|
||||||
reset
|
|
||||||
$OUT send-keys M-p || exit 1
|
|
||||||
settle
|
|
||||||
$OUT send-keys -l "BBB" || exit 1
|
|
||||||
settle
|
|
||||||
$IN command-prompt -P -t"$client" -p '(re)' "set -g @r 'REENTERED'" 2>/dev/null
|
|
||||||
settle
|
|
||||||
capture | grep -qF '(re)' && fail "a second pane prompt opened over the first"
|
|
||||||
capture | grep -qF '(pane) BBB' || fail "first pane prompt was disturbed"
|
|
||||||
$OUT send-keys Escape || exit 1
|
|
||||||
settle
|
|
||||||
[ "$(got)" = "SENTINEL" ] || fail "Escape ran the pane prompt accept action"
|
|
||||||
|
|
||||||
# --- 4c. Inner tmux survived every path and flag. ---
|
|
||||||
$IN display-message -p '#{version}' >/dev/null 2>&1 || fail "inner tmux died"
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Exercise screen-redraw.c bidirectional-isolate handling. When the client is
|
|
||||||
# UTF-8 and its terminal has the Bidi capability, each drawn span is wrapped in
|
|
||||||
# directional isolate characters (U+2066 .. U+2069) so a bidi terminal does not
|
|
||||||
# reorder pane contents across borders (the REDRAW_ISOLATES path).
|
|
||||||
#
|
|
||||||
# The Bidi capability is added with terminal-overrides before the client
|
|
||||||
# attaches, so the attached client picks it up. The isolate characters appear in
|
|
||||||
# the captured output around each span.
|
|
||||||
#
|
|
||||||
# Run with GENERATE=1 to (re)create the golden files.
|
|
||||||
|
|
||||||
PATH=/bin:/usr/bin
|
|
||||||
TERM=screen
|
|
||||||
LC_ALL=C.UTF-8
|
|
||||||
export TERM LC_ALL
|
|
||||||
|
|
||||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
||||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
|
||||||
TMUX2="$TEST_TMUX -Ltest2 -f/dev/null"
|
|
||||||
RESULTS=screen-redraw-results
|
|
||||||
|
|
||||||
TMP=$(mktemp)
|
|
||||||
trap "rm -f $TMP; $TMUX kill-server 2>/dev/null; $TMUX2 kill-server 2>/dev/null" \
|
|
||||||
0 1 15
|
|
||||||
|
|
||||||
fail() {
|
|
||||||
echo "$*" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
compare() {
|
|
||||||
sleep 1
|
|
||||||
$TMUX capturep -p >$TMP || exit 1
|
|
||||||
if [ -n "$GENERATE" ]; then
|
|
||||||
cp $TMP "$RESULTS/$1.result" || exit 1
|
|
||||||
echo "generated $1"
|
|
||||||
else
|
|
||||||
cmp -s $TMP "$RESULTS/$1.result" || \
|
|
||||||
fail "scene $1 differs from $RESULTS/$1.result"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
new_scene() {
|
|
||||||
$TMUX2 neww -d "sh -c 'printf \"BIDI-LEFT 12345\nBIDI-RIGHT 67890\"; exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 selectw -t:\$ || exit 1
|
|
||||||
$TMUX2 resizew -x40 -y12 || exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
C="sh -c 'printf \"BIDI-PANE 12345\nBIDI-PANE 67890\"; exec sleep 100'"
|
|
||||||
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
$TMUX2 kill-server 2>/dev/null
|
|
||||||
|
|
||||||
$TMUX2 new -d -x40 -y12 "sh -c 'printf \"BIDI-BASE 12345\nBIDI-BASE 67890\"; exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 set -g status off || exit 1
|
|
||||||
$TMUX2 set -g window-size manual || exit 1
|
|
||||||
# Add the Bidi capability before the client attaches.
|
|
||||||
$TMUX2 set -ag terminal-overrides ",*:Bidi=\\E[8h" || exit 1
|
|
||||||
|
|
||||||
$TMUX new -d -x40 -y12 || exit 1
|
|
||||||
$TMUX set -g status off || exit 1
|
|
||||||
$TMUX set -g window-size manual || exit 1
|
|
||||||
$TMUX set -g default-terminal "tmux-256color" || exit 1
|
|
||||||
$TMUX send -l "$TMUX2 attach" || exit 1
|
|
||||||
$TMUX send Enter || exit 1
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# Single pane: content is wrapped in isolates.
|
|
||||||
new_scene
|
|
||||||
compare bidi-single
|
|
||||||
|
|
||||||
# Two panes: borders and both panes are isolated.
|
|
||||||
new_scene
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
compare bidi-split
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Exercise the scene caching in screen-redraw.c. A scene is built once and reused
|
|
||||||
# until it is invalidated; redraw_get_scene rebuilds it when the window changes,
|
|
||||||
# the generation number is bumped (panes moved/resized/swapped), or the offset
|
|
||||||
# changes. These tests make such a change in place and capture afterwards: if the
|
|
||||||
# matching invalidation did not fire, the stale cached scene would be drawn and
|
|
||||||
# the capture would not match the golden.
|
|
||||||
#
|
|
||||||
# Each scene is rendered in an inner tmux attached inside an outer tmux pane. The
|
|
||||||
# outer pane is captured and compared with a golden in screen-redraw-results/.
|
|
||||||
#
|
|
||||||
# Run with GENERATE=1 to (re)create the golden files.
|
|
||||||
|
|
||||||
PATH=/bin:/usr/bin
|
|
||||||
TERM=screen
|
|
||||||
LC_ALL=C.UTF-8
|
|
||||||
export TERM LC_ALL
|
|
||||||
|
|
||||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
||||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
|
||||||
TMUX2="$TEST_TMUX -Ltest2 -f/dev/null"
|
|
||||||
RESULTS=screen-redraw-results
|
|
||||||
|
|
||||||
TMP=$(mktemp)
|
|
||||||
trap "rm -f $TMP; $TMUX kill-server 2>/dev/null; $TMUX2 kill-server 2>/dev/null" \
|
|
||||||
0 1 15
|
|
||||||
|
|
||||||
fail() {
|
|
||||||
echo "$*" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
compare() {
|
|
||||||
sleep 1
|
|
||||||
$TMUX capturep -p >$TMP || exit 1
|
|
||||||
if [ -n "$GENERATE" ]; then
|
|
||||||
cp $TMP "$RESULTS/$1.result" || exit 1
|
|
||||||
echo "generated $1"
|
|
||||||
else
|
|
||||||
cmp -s $TMP "$RESULTS/$1.result" || \
|
|
||||||
fail "scene $1 differs from $RESULTS/$1.result"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
new_scene() {
|
|
||||||
$TMUX2 neww -d "sh -c 'i=0; while [ \$i -lt 13 ]; do printf \"BASE%02d abcdefghij\n\" \$i; i=\$((i + 1)); done; exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 selectw -t:\$ || exit 1
|
|
||||||
$TMUX2 resizew -x40 -y14 || exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
C="sh -c 'i=0; while [ \$i -lt 5 ]; do printf \"PANE%02d abcdefghij\n\" \$i; i=\$((i + 1)); done; exec sleep 100'"
|
|
||||||
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
$TMUX2 kill-server 2>/dev/null
|
|
||||||
|
|
||||||
$TMUX2 new -d -x40 -y14 "sh -c 'exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 set -g status off || exit 1
|
|
||||||
$TMUX2 set -g window-size manual || exit 1
|
|
||||||
|
|
||||||
$TMUX new -d -x40 -y14 || exit 1
|
|
||||||
$TMUX set -g status off || exit 1
|
|
||||||
$TMUX set -g window-size manual || exit 1
|
|
||||||
$TMUX set -g default-terminal "tmux-256color" || exit 1
|
|
||||||
$TMUX send -l "$TMUX2 attach" || exit 1
|
|
||||||
$TMUX send Enter || exit 1
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# --- Generation change: a pane is resized in place. ---
|
|
||||||
|
|
||||||
# Two columns; first capture pins the initial divider position. The scene is
|
|
||||||
# built here and cached.
|
|
||||||
new_scene
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
compare cache-resize-before
|
|
||||||
|
|
||||||
# Move the divider left. resize-pane bumps the generation, so the cached scene
|
|
||||||
# must be rebuilt and the divider must appear in its new position.
|
|
||||||
$TMUX2 resize-pane -t0 -L 6 || exit 1
|
|
||||||
compare cache-resize-after
|
|
||||||
|
|
||||||
# --- Generation change: panes are swapped/rotated in place. ---
|
|
||||||
|
|
||||||
# Three columns, each pane titled so the order is visible. The pane status line
|
|
||||||
# makes a swap show up in the captured scene.
|
|
||||||
new_scene
|
|
||||||
$TMUX2 setw pane-border-format " #{pane_title} " || exit 1
|
|
||||||
$TMUX2 setw pane-border-status top || exit 1
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t:.0 -T AAA || exit 1
|
|
||||||
$TMUX2 selectp -t:.1 -T BBB || exit 1
|
|
||||||
$TMUX2 selectp -t:.2 -T CCC || exit 1
|
|
||||||
$TMUX2 selectp -t:.0 || exit 1
|
|
||||||
compare cache-rotate-before
|
|
||||||
|
|
||||||
# Rotate the panes; the titles must move with them in the rebuilt scene.
|
|
||||||
# rotate-window keeps the cell geometry, so only its scene invalidation makes
|
|
||||||
# this differ from cache-rotate-before.
|
|
||||||
$TMUX2 rotate-window || exit 1
|
|
||||||
$TMUX2 selectp -t:.0 || exit 1
|
|
||||||
compare cache-rotate-after
|
|
||||||
|
|
||||||
# --- Generation change: two panes swapped in place. ---
|
|
||||||
|
|
||||||
# swap-pane likewise moves panes between cells without changing geometry; the
|
|
||||||
# swapped titles must appear in the rebuilt scene.
|
|
||||||
new_scene
|
|
||||||
$TMUX2 setw pane-border-format " #{pane_title} " || exit 1
|
|
||||||
$TMUX2 setw pane-border-status top || exit 1
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t:.0 -T LEFT || exit 1
|
|
||||||
$TMUX2 selectp -t:.1 -T RIGHT || exit 1
|
|
||||||
$TMUX2 selectp -t:.0 || exit 1
|
|
||||||
compare cache-swap-before
|
|
||||||
|
|
||||||
$TMUX2 swap-pane -d -s:.0 -t:.1 || exit 1
|
|
||||||
$TMUX2 selectp -t:.0 || exit 1
|
|
||||||
compare cache-swap-after
|
|
||||||
|
|
||||||
# --- Window change: the client switches between two differently laid out
|
|
||||||
# windows and back. The scene is keyed on the window, so each must show its own
|
|
||||||
# layout and switching back must not show the other window's cached scene. ---
|
|
||||||
|
|
||||||
# Window A: a single pane (no internal border).
|
|
||||||
$TMUX2 neww -d "sh -c 'i=0; while [ \$i -lt 13 ]; do printf \"WINA%02d abcdefghij\n\" \$i; i=\$((i + 1)); done; exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 selectw -t:\$ || exit 1
|
|
||||||
$TMUX2 resizew -x40 -y14 || exit 1
|
|
||||||
A=$($TMUX2 display -p '#{window_id}') || exit 1
|
|
||||||
|
|
||||||
# Window B: a top/bottom split (a horizontal border).
|
|
||||||
$TMUX2 neww -d "sh -c 'i=0; while [ \$i -lt 13 ]; do printf \"WINB%02d abcdefghij\n\" \$i; i=\$((i + 1)); done; exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 selectw -t:\$ || exit 1
|
|
||||||
$TMUX2 resizew -x40 -y14 || exit 1
|
|
||||||
$TMUX2 splitw -v "$C" || exit 1
|
|
||||||
B=$($TMUX2 display -p '#{window_id}') || exit 1
|
|
||||||
|
|
||||||
$TMUX2 selectw -t$A || exit 1
|
|
||||||
compare cache-window-a
|
|
||||||
$TMUX2 selectw -t$B || exit 1
|
|
||||||
compare cache-window-b
|
|
||||||
$TMUX2 selectw -t$A || exit 1
|
|
||||||
compare cache-window-a-again
|
|
||||||
|
|
||||||
# --- Size change: the client (and so the scene) is resized. ---
|
|
||||||
|
|
||||||
# With window-size latest the inner window tracks the client size, so resizing
|
|
||||||
# the outer window resizes the inner client and the scene. The cached scene must
|
|
||||||
# be rebuilt at the new size (the scene->sx/sy mismatch path in
|
|
||||||
# redraw_get_scene), not drawn at the old size.
|
|
||||||
$TMUX2 set -g window-size latest || exit 1
|
|
||||||
$TMUX2 neww -d "sh -c 'i=0; while [ \$i -lt 13 ]; do printf \"SIZE%02d abcdefghij\n\" \$i; i=\$((i + 1)); done; exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 selectw -t:\$ || exit 1
|
|
||||||
$TMUX2 splitw -v "$C" || exit 1
|
|
||||||
compare cache-resizeclient-before
|
|
||||||
|
|
||||||
$TMUX resizew -x30 -y10 || exit 1
|
|
||||||
compare cache-resizeclient-after
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,221 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Exercise screen-redraw.c drawing of floating panes: their borders and titles,
|
|
||||||
# clipping at the window edge, and the interaction with the area outside the
|
|
||||||
# window (when the window is smaller than the attached client).
|
|
||||||
#
|
|
||||||
# Each scene is rendered in an inner tmux attached inside an outer tmux pane.
|
|
||||||
# The outer pane is captured (the full client scene drawn by screen-redraw.c)
|
|
||||||
# and compared with a golden file in screen_redraw_results/.
|
|
||||||
#
|
|
||||||
# Run with GENERATE=1 to (re)create the golden files.
|
|
||||||
|
|
||||||
PATH=/bin:/usr/bin
|
|
||||||
TERM=screen
|
|
||||||
LC_ALL=C.UTF-8
|
|
||||||
export TERM LC_ALL
|
|
||||||
|
|
||||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
||||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
|
||||||
TMUX2="$TEST_TMUX -Ltest2 -f/dev/null"
|
|
||||||
RESULTS=screen-redraw-results
|
|
||||||
|
|
||||||
TMP=$(mktemp)
|
|
||||||
trap "rm -f $TMP; $TMUX kill-server 2>/dev/null; $TMUX2 kill-server 2>/dev/null" \
|
|
||||||
0 1 15
|
|
||||||
|
|
||||||
fail() {
|
|
||||||
echo "$*" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
compare() {
|
|
||||||
sleep 1
|
|
||||||
$TMUX capturep -p $2 >$TMP || exit 1
|
|
||||||
if [ -n "$GENERATE" ]; then
|
|
||||||
cp $TMP "$RESULTS/$1.result" || exit 1
|
|
||||||
echo "generated $1"
|
|
||||||
else
|
|
||||||
cmp -s $TMP "$RESULTS/$1.result" || \
|
|
||||||
fail "scene $1 differs from $RESULTS/$1.result"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# new_scene <width> <height>: fresh inner window of the given window size.
|
|
||||||
new_scene() {
|
|
||||||
$TMUX2 neww -d "sh -c 'printf base; exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 selectw -t:\$ || exit 1
|
|
||||||
$TMUX2 resizew -x$1 -y$2 || exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# tile_2x2: split the current window into a 2x2 grid of tiled panes.
|
|
||||||
tile_2x2() {
|
|
||||||
C="sh -c 'exec sleep 100'"
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 splitw -v "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 splitw -v "$C" || exit 1
|
|
||||||
$TMUX2 select-layout tiled || exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# fill_base_pattern: make clipped floating panes visibly cover every column.
|
|
||||||
fill_base_pattern() {
|
|
||||||
$TMUX2 respawnp -k "sh -c 'i=0; while [ \$i -lt 12 ]; do printf \"%02d:abcdefghijklmnopqrstuvwxyz0123456789\n\" \$i; i=\$((i + 1)); done; exec sleep 100'" || exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# fill_all_panes: make each pane visibly nonblank.
|
|
||||||
fill_all_panes() {
|
|
||||||
for pane in $($TMUX2 list-panes -F '#{pane_id}'); do
|
|
||||||
$TMUX2 respawnp -k -t "$pane" "sh -c 'i=0; while [ \$i -lt 5 ]; do printf \"TILE%02d abcdefghij\n\" \$i; i=\$((i + 1)); done; exec sleep 100'" || exit 1
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
$TMUX2 kill-server 2>/dev/null
|
|
||||||
|
|
||||||
$TMUX2 new -d -x40 -y12 "sh -c 'printf base; exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 set -g status off || exit 1
|
|
||||||
$TMUX2 set -g window-size manual || exit 1
|
|
||||||
$TMUX2 set -g pane-border-format " #{pane_title} " || exit 1
|
|
||||||
|
|
||||||
$TMUX new -d -x40 -y12 || exit 1
|
|
||||||
$TMUX set -g status off || exit 1
|
|
||||||
$TMUX set -g window-size manual || exit 1
|
|
||||||
$TMUX set -g default-terminal "tmux-256color" || exit 1
|
|
||||||
$TMUX send -l "$TMUX2 attach" || exit 1
|
|
||||||
$TMUX send Enter || exit 1
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# Basic floating pane, well inside the window.
|
|
||||||
new_scene 40 12
|
|
||||||
$TMUX2 new-pane -x20 -y6 -X8 -Y3 "sh -c 'printf FLOAT; exec sleep 100'" || exit 1
|
|
||||||
compare floating-basic
|
|
||||||
|
|
||||||
# Floating pane with a title on its border. pane-border-status also draws the
|
|
||||||
# base pane's title, so set it explicitly (the default is the hostname, which is
|
|
||||||
# not stable).
|
|
||||||
new_scene 40 12
|
|
||||||
$TMUX2 setw pane-border-status top || exit 1
|
|
||||||
$TMUX2 selectp -t:.0 -T base || exit 1
|
|
||||||
$TMUX2 new-pane -x20 -y6 -X8 -Y2 -T title \
|
|
||||||
"sh -c 'printf FLOAT; exec sleep 100'" || exit 1
|
|
||||||
compare floating-title
|
|
||||||
|
|
||||||
# Larger floating pane with double border lines.
|
|
||||||
new_scene 40 12
|
|
||||||
$TMUX2 new-pane -x28 -y8 -X4 -Y1 -B double \
|
|
||||||
"sh -c 'printf FLOAT; exec sleep 100'" || exit 1
|
|
||||||
compare floating-border-double
|
|
||||||
|
|
||||||
# Floating pane with no border lines: redraw_mark_pane_borders returns early so
|
|
||||||
# the float has no border at all, only its (clipped) content over the base pane.
|
|
||||||
new_scene 40 12
|
|
||||||
$TMUX2 new-pane -x20 -y6 -X10 -Y3 -B none \
|
|
||||||
"sh -c 'printf NOBORDER; exec sleep 100'" || exit 1
|
|
||||||
compare floating-noborder
|
|
||||||
|
|
||||||
# Floating pane positioned past the right and bottom edges: must clip.
|
|
||||||
new_scene 40 12
|
|
||||||
$TMUX2 new-pane -x20 -y6 -X30 -Y8 "sh -c 'printf CLIP; exec sleep 100'" || exit 1
|
|
||||||
compare floating-clip-edge
|
|
||||||
|
|
||||||
# Window smaller than the client (outside area filled), with a floating pane
|
|
||||||
# that overlaps the boundary into the outside region.
|
|
||||||
new_scene 28 8
|
|
||||||
$TMUX2 new-pane -x16 -y5 -X18 -Y4 "sh -c 'printf OUT; exec sleep 100'" || exit 1
|
|
||||||
compare floating-outside
|
|
||||||
|
|
||||||
# Floating pane clipped at the top-left corner (negative offsets).
|
|
||||||
new_scene 40 12
|
|
||||||
$TMUX2 new-pane -x18 -y6 -X-4 -Y-2 "sh -c 'printf TL; exec sleep 100'" || exit 1
|
|
||||||
compare floating-clip-topleft
|
|
||||||
|
|
||||||
# Floating panes clipped at each edge. The patterned base pane makes sure the
|
|
||||||
# clipped edge still obscures both content and borders underneath.
|
|
||||||
new_scene 40 12
|
|
||||||
fill_base_pattern
|
|
||||||
$TMUX2 new-pane -x20 -y6 -X-10 -Y3 "sh -c 'printf LEFT; exec sleep 100'" || exit 1
|
|
||||||
compare floating-clip-left
|
|
||||||
|
|
||||||
new_scene 40 12
|
|
||||||
fill_base_pattern
|
|
||||||
$TMUX2 new-pane -x20 -y6 -X30 -Y3 "sh -c 'printf RIGHT; exec sleep 100'" || exit 1
|
|
||||||
compare floating-clip-right
|
|
||||||
|
|
||||||
new_scene 40 12
|
|
||||||
fill_base_pattern
|
|
||||||
$TMUX2 new-pane -x20 -y6 -X10 -Y-3 "sh -c 'printf TOP; exec sleep 100'" || exit 1
|
|
||||||
compare floating-clip-top
|
|
||||||
|
|
||||||
new_scene 40 12
|
|
||||||
fill_base_pattern
|
|
||||||
$TMUX2 new-pane -x20 -y6 -X10 -Y9 "sh -c 'printf BOTTOM; exec sleep 100'" || exit 1
|
|
||||||
compare floating-clip-bottom
|
|
||||||
|
|
||||||
# Floating pane over a tiled 2x2 grid: the float draws a complete box and must
|
|
||||||
# NOT merge its borders with the tiled pane borders underneath.
|
|
||||||
new_scene 40 12
|
|
||||||
tile_2x2
|
|
||||||
fill_all_panes
|
|
||||||
$TMUX2 new-pane -x16 -y6 -X11 -Y3 "sh -c 'printf FLT; exec sleep 100'" || exit 1
|
|
||||||
compare floating-over-tiled
|
|
||||||
|
|
||||||
# Same, but the float uses double border lines while the tiled panes use single:
|
|
||||||
# the two border styles must coexist without merging.
|
|
||||||
new_scene 40 12
|
|
||||||
tile_2x2
|
|
||||||
fill_all_panes
|
|
||||||
$TMUX2 new-pane -x16 -y6 -X11 -Y3 -B double \
|
|
||||||
"sh -c 'printf FLT; exec sleep 100'" || exit 1
|
|
||||||
compare floating-over-tiled-double
|
|
||||||
|
|
||||||
# Two overlapping floating panes: the later (top) float draws over the earlier.
|
|
||||||
new_scene 40 12
|
|
||||||
$TMUX2 new-pane -x16 -y6 -X4 -Y2 "sh -c 'printf AAA; exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 new-pane -x16 -y6 -X14 -Y6 "sh -c 'printf BBB; exec sleep 100'" || exit 1
|
|
||||||
compare floating-overlap
|
|
||||||
|
|
||||||
# Two floating panes with different per-pane configuration: one has its status on
|
|
||||||
# top with single borders, the other has its status on the bottom with heavy
|
|
||||||
# borders (pane-border-status and pane-border-lines are per-pane options).
|
|
||||||
new_scene 40 12
|
|
||||||
$TMUX2 setw pane-border-format " #{pane_title} " || exit 1
|
|
||||||
$TMUX2 new-pane -x16 -y4 -X3 -Y1 -T one \
|
|
||||||
"sh -c 'printf ONE; exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 set -p pane-border-status top || exit 1
|
|
||||||
$TMUX2 set -p pane-border-lines single || exit 1
|
|
||||||
$TMUX2 new-pane -x16 -y4 -X18 -Y6 -T two \
|
|
||||||
"sh -c 'printf TWO; exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 set -p pane-border-status bottom || exit 1
|
|
||||||
$TMUX2 set -p pane-border-lines heavy || exit 1
|
|
||||||
compare floating-mixed-config
|
|
||||||
|
|
||||||
# Floating pane over a pane that has a scrollbar: the float must draw over the
|
|
||||||
# scrollbar. Captured with -e since the scrollbar is drawn with styles.
|
|
||||||
new_scene 40 12
|
|
||||||
$TMUX2 setw pane-scrollbars on || exit 1
|
|
||||||
$TMUX2 setw pane-scrollbars-style "bg=black,fg=white,width=1,pad=0" || exit 1
|
|
||||||
$TMUX2 new-pane -x16 -y6 -X22 -Y3 "sh -c 'printf OVERSB; exec sleep 100'" || exit 1
|
|
||||||
compare floating-over-scrollbar -e
|
|
||||||
|
|
||||||
# Floating pane overlapping the client status line: the status line is not part
|
|
||||||
# of the window scene, so the float is clipped at the window's bottom edge.
|
|
||||||
new_scene 40 11
|
|
||||||
$TMUX2 set status on || exit 1
|
|
||||||
$TMUX2 set status-position bottom || exit 1
|
|
||||||
$TMUX2 set status-format[0] "" || exit 1
|
|
||||||
$TMUX2 new-pane -x20 -y6 -X8 -Y7 "sh -c 'printf OVERST; exec sleep 100'" || exit 1
|
|
||||||
compare floating-over-status
|
|
||||||
|
|
||||||
# A window left with only a floating pane: killing the single tiled pane removes
|
|
||||||
# it from the layout, so the area it occupied is no longer owned by any pane and
|
|
||||||
# is drawn as EMPTY cells (middle dots) around the float. This is the only way to
|
|
||||||
# produce a REDRAW_SPAN_EMPTY span.
|
|
||||||
new_scene 40 12
|
|
||||||
$TMUX2 new-pane -x20 -y6 -X8 -Y3 "sh -c 'printf FLOAT; exec sleep 100'" || exit 1
|
|
||||||
tiled=$($TMUX2 list-panes -F '#{pane_floating_flag} #{pane_id}' | \
|
|
||||||
awk '$1==0{print $2; exit}') || exit 1
|
|
||||||
$TMUX2 kill-pane -t "$tiled" || exit 1
|
|
||||||
compare floating-empty
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,212 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Exercise screen-redraw.c pane-border-indicators: the arrow indicators that
|
|
||||||
# point at the active pane, and the two-pane border colour split.
|
|
||||||
#
|
|
||||||
# Arrows are drawn as glyphs (captured plain). The two-pane colour split is
|
|
||||||
# drawn with styles, so that scene is captured with escapes (-e) and uses
|
|
||||||
# distinct active/inactive border styles so the split is visible.
|
|
||||||
#
|
|
||||||
# Each scene is rendered in an inner tmux attached inside an outer tmux pane.
|
|
||||||
# The outer pane is captured and compared with a golden in screen-redraw-results/.
|
|
||||||
#
|
|
||||||
# Run with GENERATE=1 to (re)create the golden files.
|
|
||||||
|
|
||||||
PATH=/bin:/usr/bin
|
|
||||||
TERM=screen
|
|
||||||
LC_ALL=C.UTF-8
|
|
||||||
export TERM LC_ALL
|
|
||||||
|
|
||||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
||||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
|
||||||
TMUX2="$TEST_TMUX -Ltest2 -f/dev/null"
|
|
||||||
RESULTS=screen-redraw-results
|
|
||||||
|
|
||||||
TMP=$(mktemp)
|
|
||||||
trap "rm -f $TMP; $TMUX kill-server 2>/dev/null; $TMUX2 kill-server 2>/dev/null" \
|
|
||||||
0 1 15
|
|
||||||
|
|
||||||
fail() {
|
|
||||||
echo "$*" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# compare <name> [-e]: capture the outer pane and compare (or generate).
|
|
||||||
compare() {
|
|
||||||
sleep 1
|
|
||||||
$TMUX capturep -p $2 >$TMP || exit 1
|
|
||||||
if [ -n "$GENERATE" ]; then
|
|
||||||
cp $TMP "$RESULTS/$1.result" || exit 1
|
|
||||||
echo "generated $1"
|
|
||||||
else
|
|
||||||
cmp -s $TMP "$RESULTS/$1.result" || \
|
|
||||||
fail "scene $1 differs from $RESULTS/$1.result"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
new_scene() {
|
|
||||||
$TMUX2 neww -d "sh -c 'exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 selectw -t:\$ || exit 1
|
|
||||||
$TMUX2 resizew -x40 -y12 || exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
C="sh -c 'exec sleep 100'"
|
|
||||||
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
$TMUX2 kill-server 2>/dev/null
|
|
||||||
|
|
||||||
$TMUX2 new -d -x40 -y12 "sh -c 'exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 set -g status off || exit 1
|
|
||||||
$TMUX2 set -g window-size manual || exit 1
|
|
||||||
|
|
||||||
$TMUX new -d -x40 -y12 || exit 1
|
|
||||||
$TMUX set -g status off || exit 1
|
|
||||||
$TMUX set -g window-size manual || exit 1
|
|
||||||
$TMUX set -g default-terminal "tmux-256color" || exit 1
|
|
||||||
$TMUX send -l "$TMUX2 attach" || exit 1
|
|
||||||
$TMUX send Enter || exit 1
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# --- Arrows: must appear for whichever pane is active (GitHub #4780). ---
|
|
||||||
|
|
||||||
$TMUX2 set -g pane-border-indicators arrows || exit 1
|
|
||||||
|
|
||||||
# Two panes, left active: arrow points left.
|
|
||||||
new_scene
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
compare arrows-2pane-left
|
|
||||||
|
|
||||||
# Two panes, right active: arrow points right (the case that regressed).
|
|
||||||
new_scene
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t1 || exit 1
|
|
||||||
compare arrows-2pane-right
|
|
||||||
|
|
||||||
# Three columns, middle active.
|
|
||||||
new_scene
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t1 || exit 1
|
|
||||||
compare arrows-3pane
|
|
||||||
|
|
||||||
# Four panes (2x2), one active.
|
|
||||||
new_scene
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 splitw -v "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 splitw -v "$C" || exit 1
|
|
||||||
$TMUX2 select-layout tiled || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
compare arrows-4pane
|
|
||||||
|
|
||||||
# --- Two-pane border colour split. ---
|
|
||||||
|
|
||||||
# Distinct active/inactive styles so the coloured halves are visible; captured
|
|
||||||
# with -e to record the SGR.
|
|
||||||
$TMUX2 set -g pane-border-indicators colour || exit 1
|
|
||||||
|
|
||||||
# Left/right split: the border is vertical and is split into a top half (active
|
|
||||||
# pane colour) and a bottom half (the LAYOUT_LEFTRIGHT case).
|
|
||||||
new_scene
|
|
||||||
$TMUX2 setw pane-active-border-style fg=red || exit 1
|
|
||||||
$TMUX2 setw pane-border-style fg=green || exit 1
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
compare two-pane-colour-vertical -e
|
|
||||||
|
|
||||||
# Top/bottom split: the border is horizontal and is split into a left half and a
|
|
||||||
# right half instead (the LAYOUT_TOPBOTTOM case).
|
|
||||||
new_scene
|
|
||||||
$TMUX2 setw pane-active-border-style fg=red || exit 1
|
|
||||||
$TMUX2 setw pane-border-style fg=green || exit 1
|
|
||||||
$TMUX2 splitw -v "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
compare two-pane-colour-horizontal -e
|
|
||||||
|
|
||||||
# The colour split only applies with exactly two tiled panes. With three panes
|
|
||||||
# the split is suppressed: the whole border uses the active pane's colour and
|
|
||||||
# there is no coloured half (redraw_check_two_pane_colours returns 0).
|
|
||||||
new_scene
|
|
||||||
$TMUX2 setw pane-active-border-style fg=red || exit 1
|
|
||||||
$TMUX2 setw pane-border-style fg=green || exit 1
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
compare colour-three-suppressed -e
|
|
||||||
|
|
||||||
# A floating pane is ignored by the two-pane count, so two tiled panes plus a
|
|
||||||
# float still split. The float itself is never coloured by the indicator.
|
|
||||||
new_scene
|
|
||||||
$TMUX2 setw pane-active-border-style fg=red || exit 1
|
|
||||||
$TMUX2 setw pane-border-style fg=green || exit 1
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 new-pane -x16 -y6 -X10 -Y2 "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
compare colour-two-plus-float -e
|
|
||||||
|
|
||||||
# --- Both indicators together. ---
|
|
||||||
|
|
||||||
# pane-border-indicators both enables the arrow and the colour split at once
|
|
||||||
# (it satisfies both the arrow and the colour branches). Two panes so the colour
|
|
||||||
# split also applies.
|
|
||||||
$TMUX2 set -g pane-border-indicators both || exit 1
|
|
||||||
new_scene
|
|
||||||
$TMUX2 setw pane-active-border-style fg=red || exit 1
|
|
||||||
$TMUX2 setw pane-border-style fg=green || exit 1
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
compare indicators-both -e
|
|
||||||
|
|
||||||
# --- Marked pane. ---
|
|
||||||
|
|
||||||
# A marked pane (select-pane -m) has its border drawn reversed. Captured with -e
|
|
||||||
# to record the reverse attribute. The marked pane is made non-active so its
|
|
||||||
# reversed border is distinct from the active pane.
|
|
||||||
$TMUX2 set -g pane-border-indicators off || exit 1
|
|
||||||
|
|
||||||
# Left/right split, right pane marked.
|
|
||||||
new_scene
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 selectp -t1 -m || exit 1
|
|
||||||
compare marked-pane-lr -e
|
|
||||||
|
|
||||||
# Top/bottom split, bottom pane marked.
|
|
||||||
new_scene
|
|
||||||
$TMUX2 splitw -v "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 selectp -t1 -m || exit 1
|
|
||||||
compare marked-pane-tb -e
|
|
||||||
|
|
||||||
# Three columns, middle pane marked (reversed border on both sides).
|
|
||||||
new_scene
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 selectp -t1 -m || exit 1
|
|
||||||
compare marked-pane-three -e
|
|
||||||
|
|
||||||
# Floating pane marked: the whole floating box border is reversed.
|
|
||||||
new_scene
|
|
||||||
$TMUX2 new-pane -x20 -y6 -X8 -Y3 "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 selectp -t1 -m || exit 1
|
|
||||||
compare marked-pane-float -e
|
|
||||||
|
|
||||||
# Marked pane together with a pane status line: the title border is reversed too.
|
|
||||||
new_scene
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 setw pane-border-format " #{pane_index}:#{pane_title} " || exit 1
|
|
||||||
$TMUX2 setw pane-border-status top || exit 1
|
|
||||||
$TMUX2 selectp -t:.0 -T left || exit 1
|
|
||||||
$TMUX2 selectp -t:.1 -T right || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 selectp -t1 -m || exit 1
|
|
||||||
compare marked-pane-status -e
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Exercise screen-redraw.c when the window is smaller than the attached client,
|
|
||||||
# so part of the client is outside the window. screen-redraw.c fills the outside
|
|
||||||
# area and draws a real border along the window's right and/or bottom edge (not
|
|
||||||
# just where panes meet). This checks redraw_get_window_offset and the OUTSIDE
|
|
||||||
# span handling, including how the window-edge border joins the pane borders.
|
|
||||||
#
|
|
||||||
# Each scene is rendered in an inner tmux attached inside an outer tmux pane.
|
|
||||||
# The outer client is 40x14; the inner window is made smaller with resizew. The
|
|
||||||
# outer pane is captured and compared with a golden in screen-redraw-results/.
|
|
||||||
#
|
|
||||||
# Run with GENERATE=1 to (re)create the golden files.
|
|
||||||
|
|
||||||
PATH=/bin:/usr/bin
|
|
||||||
TERM=screen
|
|
||||||
LC_ALL=C.UTF-8
|
|
||||||
export TERM LC_ALL
|
|
||||||
|
|
||||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
||||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
|
||||||
TMUX2="$TEST_TMUX -Ltest2 -f/dev/null"
|
|
||||||
RESULTS=screen-redraw-results
|
|
||||||
|
|
||||||
TMP=$(mktemp)
|
|
||||||
trap "rm -f $TMP; $TMUX kill-server 2>/dev/null; $TMUX2 kill-server 2>/dev/null" \
|
|
||||||
0 1 15
|
|
||||||
|
|
||||||
fail() {
|
|
||||||
echo "$*" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
compare() {
|
|
||||||
sleep 1
|
|
||||||
$TMUX capturep -p >$TMP || exit 1
|
|
||||||
if [ -n "$GENERATE" ]; then
|
|
||||||
cp $TMP "$RESULTS/$1.result" || exit 1
|
|
||||||
echo "generated $1"
|
|
||||||
else
|
|
||||||
cmp -s $TMP "$RESULTS/$1.result" || \
|
|
||||||
fail "scene $1 differs from $RESULTS/$1.result"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# new_scene <width> <height>: fresh inner window smaller than the 40x14 client.
|
|
||||||
new_scene() {
|
|
||||||
$TMUX2 neww -d "sh -c 'i=0; while [ \$i -lt $(($2 - 1)) ]; do printf \"OUT%02d abcdefghij\n\" \$i; i=\$((i + 1)); done; exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 selectw -t:\$ || exit 1
|
|
||||||
$TMUX2 resizew -x$1 -y$2 || exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
C="sh -c 'i=0; while [ \$i -lt 8 ]; do printf \"PAN%02d abcdefghij\n\" \$i; i=\$((i + 1)); done; exec sleep 100'"
|
|
||||||
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
$TMUX2 kill-server 2>/dev/null
|
|
||||||
|
|
||||||
$TMUX2 new -d -x40 -y14 "sh -c 'i=0; while [ \$i -lt 13 ]; do printf \"OUT%02d abcdefghij\n\" \$i; i=\$((i + 1)); done; exec sleep 100'" || exit 1
|
|
||||||
$TMUX2 set -g status off || exit 1
|
|
||||||
$TMUX2 set -g window-size manual || exit 1
|
|
||||||
|
|
||||||
$TMUX new -d -x40 -y14 || exit 1
|
|
||||||
$TMUX set -g status off || exit 1
|
|
||||||
$TMUX set -g window-size manual || exit 1
|
|
||||||
$TMUX set -g default-terminal "tmux-256color" || exit 1
|
|
||||||
$TMUX send -l "$TMUX2 attach" || exit 1
|
|
||||||
$TMUX send Enter || exit 1
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# Single pane, narrower than the client: a border along the right edge.
|
|
||||||
new_scene 28 14
|
|
||||||
compare outside-right-single
|
|
||||||
|
|
||||||
# Narrower than the client with a left/right split: the inter-pane border plus a
|
|
||||||
# real border on the window's right edge, then the outside area.
|
|
||||||
new_scene 28 14
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
compare outside-right-split
|
|
||||||
|
|
||||||
# Shorter than the client with a top/bottom split: a real border on the window's
|
|
||||||
# bottom edge.
|
|
||||||
new_scene 40 9
|
|
||||||
$TMUX2 splitw -v "$C" || exit 1
|
|
||||||
compare outside-bottom-split
|
|
||||||
|
|
||||||
# Smaller in both dimensions with a 2x2 grid: borders on the right and bottom
|
|
||||||
# edges meeting the internal pane borders at the corner.
|
|
||||||
new_scene 28 9
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 splitw -v "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 splitw -v "$C" || exit 1
|
|
||||||
$TMUX2 select-layout tiled || exit 1
|
|
||||||
compare outside-both-2x2
|
|
||||||
|
|
||||||
# Window BIGGER than the client: only part of the window is viewed and the view
|
|
||||||
# can be panned (refresh-client). This exercises a non-zero scene offset.
|
|
||||||
# A 2x2 grid in a 60x20 window viewed through the 40x14 client.
|
|
||||||
new_scene 60 20
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
$TMUX2 splitw -v "$C" || exit 1
|
|
||||||
$TMUX2 selectp -t0 || exit 1
|
|
||||||
$TMUX2 splitw -v "$C" || exit 1
|
|
||||||
$TMUX2 select-layout tiled || exit 1
|
|
||||||
|
|
||||||
# Default view: the top-left of the window.
|
|
||||||
$TMUX2 refresh-client -U 100 || exit 1
|
|
||||||
$TMUX2 refresh-client -L 100 || exit 1
|
|
||||||
compare bigger-topleft
|
|
||||||
|
|
||||||
# Panned to the bottom-right of the window (down and right to the limit).
|
|
||||||
$TMUX2 refresh-client -D 100 || exit 1
|
|
||||||
$TMUX2 refresh-client -R 100 || exit 1
|
|
||||||
compare bigger-bottomright
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Exercise drawing of popups (display-popup) over the window scene. A popup is an
|
|
||||||
# overlay drawn on top of the redraw scene (the overlay_draw path in
|
|
||||||
# screen-redraw.c), so this guards against regressions in how popups appear.
|
|
||||||
#
|
|
||||||
# A popup is modal and stays open until its command exits, so each scene fully
|
|
||||||
# re-creates the servers and re-attaches; the popup is opened in the background
|
|
||||||
# (display-popup blocks the client that runs it) and the outer pane is captured
|
|
||||||
# while it is open.
|
|
||||||
#
|
|
||||||
# Run with GENERATE=1 to (re)create the golden files.
|
|
||||||
|
|
||||||
PATH=/bin:/usr/bin
|
|
||||||
TERM=screen
|
|
||||||
LC_ALL=C.UTF-8
|
|
||||||
export TERM LC_ALL
|
|
||||||
|
|
||||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
||||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
|
||||||
TMUX2="$TEST_TMUX -Ltest2 -f/dev/null"
|
|
||||||
RESULTS=screen-redraw-results
|
|
||||||
|
|
||||||
TMP=$(mktemp)
|
|
||||||
trap "rm -f $TMP; $TMUX kill-server 2>/dev/null; $TMUX2 kill-server 2>/dev/null" \
|
|
||||||
0 1 15
|
|
||||||
|
|
||||||
fail() {
|
|
||||||
echo "$*" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
compare() {
|
|
||||||
sleep 1
|
|
||||||
$TMUX capturep -p >$TMP || exit 1
|
|
||||||
if [ -n "$GENERATE" ]; then
|
|
||||||
cp $TMP "$RESULTS/$1.result" || exit 1
|
|
||||||
echo "generated $1"
|
|
||||||
else
|
|
||||||
cmp -s $TMP "$RESULTS/$1.result" || \
|
|
||||||
fail "scene $1 differs from $RESULTS/$1.result"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
C="sh -c 'i=0; while [ \$i -lt 13 ]; do printf \"POP%02d abcdefghij\n\" \$i; i=\$((i + 1)); done; exec sleep 100'"
|
|
||||||
|
|
||||||
# setup: fresh inner window attached inside a fresh outer pane, 40x14.
|
|
||||||
setup() {
|
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
$TMUX2 kill-server 2>/dev/null
|
|
||||||
$TMUX2 new -d -x40 -y14 "$C" || exit 1
|
|
||||||
$TMUX2 set -g status off || exit 1
|
|
||||||
$TMUX2 set -g window-size manual || exit 1
|
|
||||||
$TMUX2 resizew -x40 -y14 || exit 1
|
|
||||||
$TMUX new -d -x40 -y14 || exit 1
|
|
||||||
$TMUX set -g status off || exit 1
|
|
||||||
$TMUX set -g window-size manual || exit 1
|
|
||||||
$TMUX set -g default-terminal "tmux-256color" || exit 1
|
|
||||||
$TMUX send -l "$TMUX2 attach" || exit 1
|
|
||||||
$TMUX send Enter || exit 1
|
|
||||||
sleep 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# popup <args>: open a popup running a fixed command, in the background (it stays
|
|
||||||
# open because the command sleeps; the servers are killed at the next setup).
|
|
||||||
popup() {
|
|
||||||
$TMUX2 display-popup "$@" -E "sh -c 'printf POPUP; exec sleep 100'" &
|
|
||||||
sleep 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Basic popup over a single pane.
|
|
||||||
setup
|
|
||||||
popup -w20 -h6 -x6 -y3
|
|
||||||
compare popup-basic
|
|
||||||
|
|
||||||
# Popup over a split: drawn on top of the pane border.
|
|
||||||
setup
|
|
||||||
$TMUX2 splitw -h "$C" || exit 1
|
|
||||||
popup -w24 -h8 -x8 -y3
|
|
||||||
compare popup-over-split
|
|
||||||
|
|
||||||
# Popup with no border lines (-B).
|
|
||||||
setup
|
|
||||||
popup -B -w20 -h6 -x6 -y3
|
|
||||||
compare popup-noborder
|
|
||||||
|
|
||||||
# Popup with double border lines.
|
|
||||||
setup
|
|
||||||
popup -b double -w20 -h6 -x6 -y3
|
|
||||||
compare popup-double
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
│
|
|
||||||
←
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
│
|
|
||||||
→
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
│ │
|
|
||||||
→ ←
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
│
|
|
||||||
←
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
─↑─────────────────┼────────────────────
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
BIDI-LEFT 12345
|
|
||||||
BIDI-RIGHT 67890
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
BIDI-LEFT 12345 │BIDI-PANE 12345
|
|
||||||
BIDI-RIGHT 67890 │BIDI-PANE 67890
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
│PAN06 abcdefghij
|
|
||||||
│PAN07 abcdefghij
|
|
||||||
│
|
|
||||||
─────────┼──────────────────────────────
|
|
||||||
│PAN00 abcdefghij
|
|
||||||
│PAN01 abcdefghij
|
|
||||||
│PAN02 abcdefghij
|
|
||||||
│PAN03 abcdefghij
|
|
||||||
│PAN04 abcdefghij
|
|
||||||
│PAN05 abcdefghij
|
|
||||||
│PAN06 abcdefghij
|
|
||||||
│PAN07 abcdefghij
|
|
||||||
│
|
|
||||||
│
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
OUT11 abcdefghij │PAN00 abcd
|
|
||||||
OUT12 abcdefghij │PAN01 abcd
|
|
||||||
OUT13 abcdefghij │PAN02 abcd
|
|
||||||
OUT14 abcdefghij │PAN03 abcd
|
|
||||||
OUT15 abcdefghij │PAN04 abcd
|
|
||||||
OUT16 abcdefghij │PAN05 abcd
|
|
||||||
OUT17 abcdefghij │PAN06 abcd
|
|
||||||
OUT18 abcdefghij │PAN07 abcd
|
|
||||||
│
|
|
||||||
─────────────────────────────┼──────────
|
|
||||||
PAN00 abcdefghij │PAN00 abcd
|
|
||||||
PAN01 abcdefghij │PAN01 abcd
|
|
||||||
PAN02 abcdefghij │PAN02 abcd
|
|
||||||
PAN03 abcdefghij │PAN03 abcd
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
hij │PANE00 abcdefghij
|
|
||||||
BASE07 abcdefg│PANE01 abcdefghij
|
|
||||||
hij │PANE02 abcdefghij
|
|
||||||
BASE08 abcdefg│PANE03 abcdefghij
|
|
||||||
hij │PANE04 abcdefghij
|
|
||||||
BASE09 abcdefg│
|
|
||||||
hij │
|
|
||||||
BASE10 abcdefg│
|
|
||||||
hij │
|
|
||||||
BASE11 abcdefg│
|
|
||||||
hij │
|
|
||||||
BASE12 abcdefg│
|
|
||||||
hij │
|
|
||||||
│
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
BASE00 abcdefghij │PANE00 abcdefghij
|
|
||||||
BASE01 abcdefghij │PANE01 abcdefghij
|
|
||||||
BASE02 abcdefghij │PANE02 abcdefghij
|
|
||||||
BASE03 abcdefghij │PANE03 abcdefghij
|
|
||||||
BASE04 abcdefghij │PANE04 abcdefghij
|
|
||||||
BASE05 abcdefghij │
|
|
||||||
BASE06 abcdefghij │
|
|
||||||
BASE07 abcdefghij │
|
|
||||||
BASE08 abcdefghij │
|
|
||||||
BASE09 abcdefghij │
|
|
||||||
BASE10 abcdefghij │
|
|
||||||
BASE11 abcdefghij │
|
|
||||||
BASE12 abcdefghij │
|
|
||||||
│
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
SIZE09 abcdefghij
|
|
||||||
SIZE10 abcdefghij
|
|
||||||
SIZE11 abcdefghij
|
|
||||||
SIZE12 abcdefghij
|
|
||||||
|
|
||||||
──────────────────────────────
|
|
||||||
PANE02 abcdefghij
|
|
||||||
PANE03 abcdefghij
|
|
||||||
PANE04 abcdefghij
|
|
||||||
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
SIZE07 abcdefghij
|
|
||||||
SIZE08 abcdefghij
|
|
||||||
SIZE09 abcdefghij
|
|
||||||
SIZE10 abcdefghij
|
|
||||||
SIZE11 abcdefghij
|
|
||||||
SIZE12 abcdefghij
|
|
||||||
|
|
||||||
────────────────────────────────────────
|
|
||||||
PANE00 abcdefghij
|
|
||||||
PANE01 abcdefghij
|
|
||||||
PANE02 abcdefghij
|
|
||||||
PANE03 abcdefghij
|
|
||||||
PANE04 abcdefghij
|
|
||||||
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
── BBB ───┬── CCC ──┬── AAA ────────────
|
|
||||||
PANE00 abc│cdefghij │BASE01 abcdefghij
|
|
||||||
defghij │PANE03 ab│BASE02 abcdefghij
|
|
||||||
PANE01 abc│cdefghij │BASE03 abcdefghij
|
|
||||||
defghij │PANE04 ab│BASE04 abcdefghij
|
|
||||||
PANE02 abc│cdefghij │BASE05 abcdefghij
|
|
||||||
defghij │ │BASE06 abcdefghij
|
|
||||||
PANE03 abc│ │BASE07 abcdefghij
|
|
||||||
defghij │ │BASE08 abcdefghij
|
|
||||||
PANE04 abc│ │BASE09 abcdefghij
|
|
||||||
defghij │ │BASE10 abcdefghij
|
|
||||||
│ │BASE11 abcdefghij
|
|
||||||
│ │BASE12 abcdefghij
|
|
||||||
│ │
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
── AAA ───┬── BBB ──┬── CCC ────────────
|
|
||||||
BASE07 abc│PANE00 ab│PANE00 abcdefghij
|
|
||||||
defghij │cdefghij │PANE01 abcdefghij
|
|
||||||
BASE08 abc│PANE01 ab│PANE02 abcdefghij
|
|
||||||
defghij │cdefghij │PANE03 abcdefghij
|
|
||||||
BASE09 abc│PANE02 ab│PANE04 abcdefghij
|
|
||||||
defghij │cdefghij │
|
|
||||||
BASE10 abc│PANE03 ab│
|
|
||||||
defghij │cdefghij │
|
|
||||||
BASE11 abc│PANE04 ab│
|
|
||||||
defghij │cdefghij │
|
|
||||||
BASE12 abc│ │
|
|
||||||
defghij │ │
|
|
||||||
│ │
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
── RIGHT ───────────┬── LEFT ───────────
|
|
||||||
PANE00 abcdefghij │BASE01 abcdefghij
|
|
||||||
PANE01 abcdefghij │BASE02 abcdefghij
|
|
||||||
PANE02 abcdefghij │BASE03 abcdefghij
|
|
||||||
PANE03 abcdefghij │BASE04 abcdefghij
|
|
||||||
PANE04 abcdefghij │BASE05 abcdefghij
|
|
||||||
│BASE06 abcdefghij
|
|
||||||
│BASE07 abcdefghij
|
|
||||||
│BASE08 abcdefghij
|
|
||||||
│BASE09 abcdefghij
|
|
||||||
│BASE10 abcdefghij
|
|
||||||
│BASE11 abcdefghij
|
|
||||||
│BASE12 abcdefghij
|
|
||||||
│
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
── LEFT ────────────┬── RIGHT ──────────
|
|
||||||
BASE01 abcdefghij │PANE00 abcdefghij
|
|
||||||
BASE02 abcdefghij │PANE01 abcdefghij
|
|
||||||
BASE03 abcdefghij │PANE02 abcdefghij
|
|
||||||
BASE04 abcdefghij │PANE03 abcdefghij
|
|
||||||
BASE05 abcdefghij │PANE04 abcdefghij
|
|
||||||
BASE06 abcdefghij │
|
|
||||||
BASE07 abcdefghij │
|
|
||||||
BASE08 abcdefghij │
|
|
||||||
BASE09 abcdefghij │
|
|
||||||
BASE10 abcdefghij │
|
|
||||||
BASE11 abcdefghij │
|
|
||||||
BASE12 abcdefghij │
|
|
||||||
│
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
WINA00 abcdefghij
|
|
||||||
WINA01 abcdefghij
|
|
||||||
WINA02 abcdefghij
|
|
||||||
WINA03 abcdefghij
|
|
||||||
WINA04 abcdefghij
|
|
||||||
WINA05 abcdefghij
|
|
||||||
WINA06 abcdefghij
|
|
||||||
WINA07 abcdefghij
|
|
||||||
WINA08 abcdefghij
|
|
||||||
WINA09 abcdefghij
|
|
||||||
WINA10 abcdefghij
|
|
||||||
WINA11 abcdefghij
|
|
||||||
WINA12 abcdefghij
|
|
||||||
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
WINA00 abcdefghij
|
|
||||||
WINA01 abcdefghij
|
|
||||||
WINA02 abcdefghij
|
|
||||||
WINA03 abcdefghij
|
|
||||||
WINA04 abcdefghij
|
|
||||||
WINA05 abcdefghij
|
|
||||||
WINA06 abcdefghij
|
|
||||||
WINA07 abcdefghij
|
|
||||||
WINA08 abcdefghij
|
|
||||||
WINA09 abcdefghij
|
|
||||||
WINA10 abcdefghij
|
|
||||||
WINA11 abcdefghij
|
|
||||||
WINA12 abcdefghij
|
|
||||||
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
WINB07 abcdefghij
|
|
||||||
WINB08 abcdefghij
|
|
||||||
WINB09 abcdefghij
|
|
||||||
WINB10 abcdefghij
|
|
||||||
WINB11 abcdefghij
|
|
||||||
WINB12 abcdefghij
|
|
||||||
|
|
||||||
────────────────────────────────────────
|
|
||||||
PANE00 abcdefghij
|
|
||||||
PANE01 abcdefghij
|
|
||||||
PANE02 abcdefghij
|
|
||||||
PANE03 abcdefghij
|
|
||||||
PANE04 abcdefghij
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
[31m│[39m [32m│[39m
|
|
||||||
[31m│[39m [32m│[39m
|
|
||||||
[31m│[39m [32m│[39m
|
|
||||||
[31m│[39m [32m│[39m
|
|
||||||
[31m│[39m [32m│[39m
|
|
||||||
[31m│[39m [32m│[39m
|
|
||||||
[31m│[39m [32m│[39m
|
|
||||||
[31m│[39m [32m│[39m
|
|
||||||
[31m│[39m [32m│[39m
|
|
||||||
[31m│[39m [32m│[39m
|
|
||||||
[31m│[39m [32m│[39m
|
|
||||||
[31m│[39m [32m│[39m
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
[31m│[39m
|
|
||||||
[32m┌────────────────┐[39m
|
|
||||||
[32m│[39m [32m│[39m
|
|
||||||
[32m│[39m [32m│[39m
|
|
||||||
[32m│[39m [32m│[39m
|
|
||||||
[32m│[39m [32m│[39m
|
|
||||||
[32m│[39m [32m│[39m
|
|
||||||
[32m│[39m [32m│[39m
|
|
||||||
[32m└────────────────┘[39m
|
|
||||||
[32m│[39m
|
|
||||||
[32m│[39m
|
|
||||||
[32m│[39m
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
║
|
|
||||||
║
|
|
||||||
║
|
|
||||||
║
|
|
||||||
║
|
|
||||||
║
|
|
||||||
═══════════════════╬════════════════════
|
|
||||||
║
|
|
||||||
║
|
|
||||||
║
|
|
||||||
║
|
|
||||||
║
|
|
||||||
║
|
|
||||||
║
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
┃
|
|
||||||
┃
|
|
||||||
┃
|
|
||||||
┃
|
|
||||||
┃
|
|
||||||
┃
|
|
||||||
━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━
|
|
||||||
┃
|
|
||||||
┃
|
|
||||||
┃
|
|
||||||
┃
|
|
||||||
┃
|
|
||||||
┃
|
|
||||||
┃
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
0000000000000000000011111111111111111111
|
|
||||||
2
|
|
||||||
2
|
|
||||||
2
|
|
||||||
2
|
|
||||||
2
|
|
||||||
2
|
|
||||||
2
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
-------------------+--------------------
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
───────────────────┼────────────────────
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
base
|
|
||||||
|
|
||||||
┌────────────────────┐
|
|
||||||
│FLOAT │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
└────────────────────┘
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
bas╔════════════════════════════╗
|
|
||||||
║FLOAT ║
|
|
||||||
║ ║
|
|
||||||
║ ║
|
|
||||||
║ ║
|
|
||||||
║ ║
|
|
||||||
║ ║
|
|
||||||
║ ║
|
|
||||||
║ ║
|
|
||||||
╚════════════════════════════╝
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
01:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
02:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
03:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
04:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
05:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
06:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
07:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
08:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
09:abcdef┌────────────────────┐23456789
|
|
||||||
10:abcdef│BOTTOM │23456789
|
|
||||||
11:abcdef│ │23456789
|
|
||||||
│ │
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
base
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
┌──────────
|
|
||||||
│CLIP
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
01:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
02:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
──────────┐ijklmnopqrstuvwxyz0123456789
|
|
||||||
│ijklmnopqrstuvwxyz0123456789
|
|
||||||
│ijklmnopqrstuvwxyz0123456789
|
|
||||||
│ijklmnopqrstuvwxyz0123456789
|
|
||||||
│ijklmnopqrstuvwxyz0123456789
|
|
||||||
│ijklmnopqrstuvwxyz0123456789
|
|
||||||
│ijklmnopqrstuvwxyz0123456789
|
|
||||||
──────────┘ijklmnopqrstuvwxyz0123456789
|
|
||||||
11:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
01:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
02:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
03:abcdefghijklmnopqrstuvwxyz┌──────────
|
|
||||||
04:abcdefghijklmnopqrstuvwxyz│RIGHT
|
|
||||||
05:abcdefghijklmnopqrstuvwxyz│
|
|
||||||
06:abcdefghijklmnopqrstuvwxyz│
|
|
||||||
07:abcdefghijklmnopqrstuvwxyz│
|
|
||||||
08:abcdefghijklmnopqrstuvwxyz│
|
|
||||||
09:abcdefghijklmnopqrstuvwxyz│
|
|
||||||
10:abcdefghijklmnopqrstuvwxyz└──────────
|
|
||||||
11:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
01:abcdef│ │23456789
|
|
||||||
02:abcdef│ │23456789
|
|
||||||
03:abcdef│ │23456789
|
|
||||||
04:abcdef└────────────────────┘23456789
|
|
||||||
05:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
06:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
07:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
08:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
09:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
10:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
11:abcdefghijklmnopqrstuvwxyz0123456789
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
──────────────┘
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
········································
|
|
||||||
········································
|
|
||||||
·······┌────────────────────┐···········
|
|
||||||
·······│FLOAT │···········
|
|
||||||
·······│ │···········
|
|
||||||
·······│ │···········
|
|
||||||
·······│ │···········
|
|
||||||
·······│ │···········
|
|
||||||
·······│ │···········
|
|
||||||
·······└────────────────────┘···········
|
|
||||||
········································
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
ba┌── one ─────────┐
|
|
||||||
│ONE │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
└──────────────┏━━━━━━━━━━━━━━━━┓
|
|
||||||
┃TWO ┃
|
|
||||||
┃ ┃
|
|
||||||
┃ ┃
|
|
||||||
┃ ┃
|
|
||||||
┗━━ two ━━━━━━━━━┛
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
base
|
|
||||||
|
|
||||||
|
|
||||||
NOBORDER
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
base │···········
|
|
||||||
│···········
|
|
||||||
│···········
|
|
||||||
┌──────────│···········
|
|
||||||
│OUT │···········
|
|
||||||
│ │···········
|
|
||||||
│ │···········
|
|
||||||
│ │···········
|
|
||||||
────────────────────────────┘···········
|
|
||||||
········································
|
|
||||||
········································
|
|
||||||
········································
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user