swap-pane command.

This commit is contained in:
Nicholas Marriott 2009-04-02 23:28:16 +00:00
parent 089f090c0a
commit 8216f7b3d9
8 changed files with 300 additions and 13 deletions

View File

@ -1,4 +1,4 @@
# $Id: GNUmakefile,v 1.79 2009-04-01 18:21:22 nicm Exp $
# $Id: GNUmakefile,v 1.80 2009-04-02 23:28:15 nicm Exp $
.PHONY: clean
@ -37,7 +37,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
cmd-resize-pane-up.c cmd-resize-pane-down.c cmd-kill-pane.c \
cmd-up-pane.c cmd-down-pane.c cmd-choose-window.c cmd-choose-session.c \
cmd-suspend-client.c cmd-find-window.c cmd-load-buffer.c \
cmd-copy-buffer.c cmd-break-pane.c cmd-next-layout.c \
cmd-copy-buffer.c cmd-break-pane.c cmd-swap-pane.c cmd-next-layout.c \
window-clock.c window-scroll.c window-more.c window-copy.c \
window-choose.c \
options.c options-cmd.c paste.c colour.c utf8.c clock.c \

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.118 2009-04-02 22:12:28 nicm Exp $
# $Id: Makefile,v 1.119 2009-04-02 23:28:16 nicm Exp $
.SUFFIXES: .c .o .y .h
.PHONY: clean update-index.html upload-index.html
@ -40,7 +40,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
cmd-resize-pane-up.c cmd-resize-pane-down.c cmd-kill-pane.c \
cmd-up-pane.c cmd-down-pane.c cmd-choose-window.c cmd-choose-session.c \
cmd-suspend-client.c cmd-find-window.c cmd-load-buffer.c \
cmd-copy-buffer.c cmd-break-pane.c cmd-next-layout.c \
cmd-copy-buffer.c cmd-break-pane.c cmd-swap-pane.c cmd-next-layout.c \
window-clock.c window-scroll.c window-more.c window-copy.c \
window-choose.c \
options.c options-cmd.c paste.c colour.c utf8.c clock.c \

3
TODO
View File

@ -85,7 +85,7 @@
- test bug sshing from freebsd console
- layout/split stuff:
horiz split command, and similar resizing commands as for vert split
swap-pane command
rotate-window (-pane?) to rotate panes so first becomes last
display the layout in a readable format somewhere
previous-layout command
select-layout command
@ -97,6 +97,7 @@
speed improvements?
hardcoded 81 for left-vertical is nasty
- document new layout stuff: next-layout
- document swap-pane
- document repeat behaviour and -r on bind-key
- document status-keys
- document break-pane

View File

@ -1,4 +1,4 @@
/* $Id: cmd-server-info.c,v 1.13 2009-04-01 18:21:28 nicm Exp $ */
/* $Id: cmd-server-info.c,v 1.14 2009-04-02 23:28:16 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -133,9 +133,9 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
sizeof (**gd->udata);
}
}
ctx->print(ctx, "%6u: %s %lu %d %u/%u, %zu "
"bytes; UTF-8 %u/%u, %zu bytes", j, wp->tty,
(u_long) wp->pid, wp->fd, lines,
ctx->print(ctx, "%6u: %p %s %lu %d %u/%u, %zu "
"bytes; UTF-8 %u/%u, %zu bytes", j, wp,
wp->tty, (u_long) wp->pid, wp->fd, lines,
gd->hsize + gd->sy, size, ulines,
gd->hsize + gd->sy, usize);
j++;

282
cmd-swap-pane.c Normal file
View File

@ -0,0 +1,282 @@
/* $Id: cmd-swap-pane.c,v 1.1 2009-04-02 23:28:16 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <stdlib.h>
#include "tmux.h"
/*
* Swap two panes.
*/
int cmd_swap_pane_parse(struct cmd *, int, char **, char **);
int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *);
void cmd_swap_pane_send(struct cmd *, struct buffer *);
void cmd_swap_pane_recv(struct cmd *, struct buffer *);
void cmd_swap_pane_free(struct cmd *);
void cmd_swap_pane_init(struct cmd *, int);
size_t cmd_swap_pane_print(struct cmd *, char *, size_t);
struct cmd_swap_pane_data {
char *target;
int src;
int dst;
int flag_detached;
int flag_next;
int flag_previous;
};
const struct cmd_entry cmd_swap_pane_entry = {
"swap-pane", "swapp",
"[-dn] [-t target-window] [-p src-index] [-q dst-index]",
0,
cmd_swap_pane_init,
cmd_swap_pane_parse,
cmd_swap_pane_exec,
cmd_swap_pane_send,
cmd_swap_pane_recv,
cmd_swap_pane_free,
cmd_swap_pane_print
};
void
cmd_swap_pane_init(struct cmd *self, int key)
{
struct cmd_swap_pane_data *data;
self->data = data = xmalloc(sizeof *data);
data->target = NULL;
data->src = -1;
data->dst = -1;
data->flag_detached = 0;
data->flag_next = 0;
data->flag_previous = 0;
switch (key) {
case '}':
data->flag_next = 1;
break;
case '{':
data->flag_previous = 1;
break;
}
}
int
cmd_swap_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_swap_pane_data *data;
int opt, n;
const char *errstr;
self->entry->init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, "dt:np:q:r")) != -1) {
switch (opt) {
case 'd':
data->flag_detached = 1;
break;
case 'n':
data->flag_next = 1;
data->flag_previous = 0;
data->dst = -1;
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
case 'p':
if (data->src == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "src %s", errstr);
goto error;
}
data->src = n;
}
break;
case 'q':
if (data->dst == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "dst %s", errstr);
goto error;
}
data->dst = n;
}
data->flag_next = 0;
data->flag_previous = 0;
break;
case 'r':
data->flag_next = 0;
data->flag_previous = 1;
data->dst = -1;
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
int
cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_swap_pane_data *data = self->data;
struct winlink *wl;
struct window *w;
struct window_pane *tmp_wp, *src_wp, *dst_wp;
u_int xx, yy;
if (data == NULL)
return (0);
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
w = wl->window;
if (data->src == -1)
src_wp = w->active;
else {
src_wp = window_pane_at_index(w, data->src);
if (src_wp == NULL) {
ctx->error(ctx, "no pane: %d", data->src);
return (-1);
}
}
if (data->dst == -1)
dst_wp = w->active;
else {
dst_wp = window_pane_at_index(w, data->dst);
if (dst_wp == NULL) {
ctx->error(ctx, "no pane: %d", data->dst);
return (-1);
}
}
if (data->dst == -1 && data->flag_next) {
if ((dst_wp = TAILQ_NEXT(src_wp, entry)) == NULL)
dst_wp = TAILQ_FIRST(&w->panes);
}
if (data->dst == -1 && data->flag_previous) {
if ((dst_wp = TAILQ_PREV(src_wp, window_panes, entry)) == NULL)
dst_wp = TAILQ_LAST(&w->panes, window_panes);
}
if (src_wp == dst_wp)
return (0);
tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry);
TAILQ_REMOVE(&w->panes, dst_wp, entry);
TAILQ_REPLACE(&w->panes, src_wp, dst_wp, entry);
if (tmp_wp == src_wp)
tmp_wp = dst_wp;
if (tmp_wp == NULL)
TAILQ_INSERT_HEAD(&w->panes, src_wp, entry);
else
TAILQ_INSERT_AFTER(&w->panes, tmp_wp, src_wp, entry);
xx = src_wp->xoff;
yy = src_wp->yoff;
src_wp->xoff = dst_wp->xoff;
src_wp->yoff = dst_wp->yoff;
dst_wp->xoff = xx;
dst_wp->yoff = yy;
xx = src_wp->sx;
yy = src_wp->sy;
window_pane_resize(src_wp, dst_wp->sx, dst_wp->sy);
window_pane_resize(dst_wp, xx, yy);
if (!data->flag_detached) {
window_set_active_pane(w, dst_wp);
layout_refresh(w, 0);
}
return (0);
}
void
cmd_swap_pane_send(struct cmd *self, struct buffer *b)
{
struct cmd_swap_pane_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
}
void
cmd_swap_pane_recv(struct cmd *self, struct buffer *b)
{
struct cmd_swap_pane_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
}
void
cmd_swap_pane_free(struct cmd *self)
{
struct cmd_swap_pane_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
xfree(data);
}
size_t
cmd_swap_pane_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_swap_pane_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && (data->flag_next || data->flag_detached)) {
off += xsnprintf(buf + off, len - off, " -");
if (off < len && data->flag_next)
off += xsnprintf(buf + off, len - off, "d");
if (off < len && data->flag_detached)
off += xsnprintf(buf + off, len - off, "n");
}
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->src != -1)
off += xsnprintf(buf + off, len - off, " -p %d", data->src);
if (off < len && data->dst != -1)
off += xsnprintf(buf + off, len - off, " -q %d", data->dst);
return (off);
}

3
cmd.c
View File

@ -1,4 +1,4 @@
/* $Id: cmd.c,v 1.87 2009-04-01 18:21:29 nicm Exp $ */
/* $Id: cmd.c,v 1.88 2009-04-02 23:28:16 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -86,6 +86,7 @@ const struct cmd_entry *cmd_table[] = {
&cmd_split_window_entry,
&cmd_start_server_entry,
&cmd_suspend_client_entry,
&cmd_swap_pane_entry,
&cmd_swap_window_entry,
&cmd_switch_client_entry,
&cmd_unbind_key_entry,

View File

@ -1,4 +1,4 @@
/* $Id: key-bindings.c,v 1.64 2009-04-01 18:21:30 nicm Exp $ */
/* $Id: key-bindings.c,v 1.65 2009-04-02 23:28:16 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -102,6 +102,7 @@ key_bindings_init(void)
{ '?', 0, &cmd_list_keys_entry },
{ '[', 0, &cmd_copy_mode_entry },
{ '\'', 0, &cmd_select_prompt_entry },
{ '\032', /* C-z */ 0, &cmd_suspend_client_entry },
{ ']', 0, &cmd_paste_buffer_entry },
{ 'c', 0, &cmd_new_window_entry },
{ 'd', 0, &cmd_detach_client_entry },
@ -115,7 +116,8 @@ key_bindings_init(void)
{ 't', 0, &cmd_clock_mode_entry },
{ 'w', 0, &cmd_choose_window_entry },
{ 'x', 0, &cmd_kill_pane_entry, },
{ '\032', 0, &cmd_suspend_client_entry },
{ '{', 0, &cmd_swap_pane_entry },
{ '}', 0, &cmd_swap_pane_entry },
{ META, 0, &cmd_send_prefix_entry },
{ KEYC_PPAGE, 0, &cmd_scroll_mode_entry },
{ KEYC_ADDESC('n'), 0, &cmd_next_window_entry },

3
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.297 2009-04-02 21:08:14 nicm Exp $ */
/* $Id: tmux.h,v 1.298 2009-04-02 23:28:16 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -1230,6 +1230,7 @@ extern const struct cmd_entry cmd_source_file_entry;
extern const struct cmd_entry cmd_split_window_entry;
extern const struct cmd_entry cmd_start_server_entry;
extern const struct cmd_entry cmd_suspend_client_entry;
extern const struct cmd_entry cmd_swap_pane_entry;
extern const struct cmd_entry cmd_swap_window_entry;
extern const struct cmd_entry cmd_switch_client_entry;
extern const struct cmd_entry cmd_unbind_key_entry;