From 4213ff8faa476a8b63b9c0351fbf95fc5f1a78be Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Tue, 3 Feb 2009 17:21:19 +0000 Subject: [PATCH] copy-buffer command. --- CHANGES | 7 +- GNUmakefile | 3 +- Makefile | 3 +- TODO | 2 - cmd-copy-buffer.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++ cmd.c | 3 +- examples/tmux.vim | 3 +- tmux.1 | 11 ++- tmux.h | 3 +- 9 files changed, 248 insertions(+), 9 deletions(-) create mode 100644 cmd-copy-buffer.c diff --git a/CHANGES b/CHANGES index b512af76..6b0cf4dd 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +03 February 2009 + +* New command, copy-buffer (alias copyb), to copy a session paste buffer to + another session. + 01 February 2009 * The character pair #(command) may now contain (escaped) right parenthesis. @@ -1074,7 +1079,7 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.246 2009-02-01 18:14:49 tcunha Exp $ +$Id: CHANGES,v 1.247 2009-02-03 17:21:19 tcunha Exp $ LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB ms diff --git a/GNUmakefile b/GNUmakefile index 4800482b..741bb529 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,4 +1,4 @@ -# $Id: GNUmakefile,v 1.68 2009-01-27 20:22:33 nicm Exp $ +# $Id: GNUmakefile,v 1.69 2009-02-03 17:21:19 tcunha Exp $ .PHONY: clean @@ -37,6 +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 \ 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 \ diff --git a/Makefile b/Makefile index be0478f3..8abd4879 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.108 2009-01-29 19:26:53 nicm Exp $ +# $Id: Makefile,v 1.109 2009-02-03 17:21:19 tcunha Exp $ .SUFFIXES: .c .o .y .h .PHONY: clean update-index.html upload-index.html @@ -40,6 +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 \ 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 \ diff --git a/TODO b/TODO index 6b78b6b1..bf81d0cf 100644 --- a/TODO +++ b/TODO @@ -77,8 +77,6 @@ and n of width 0, then translate cursor indexes on-the-fly would need to adjust all cursor movement and also handle different width lines properly. - support other mouse modes (highlight etc) and use it in copy mode -- command: copy-buffer -s src-session -t dst-session -a src-index -b dst-index - (copy from other session) - swap-pane-up, swap-pane-down (maybe move-pane-*) - move-pane (to window) (maybe break-pane?) - $TMUX should contain socket path diff --git a/cmd-copy-buffer.c b/cmd-copy-buffer.c new file mode 100644 index 00000000..c72cbb5b --- /dev/null +++ b/cmd-copy-buffer.c @@ -0,0 +1,222 @@ +/* $Id: cmd-copy-buffer.c,v 1.1 2009-02-03 17:21:19 tcunha Exp $ */ + +/* + * Copyright (c) 2009 Tiago Cunha + * + * 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 + +#include "tmux.h" + +/* + * Copies a session paste buffer to another session. + */ + +int cmd_copy_buffer_parse(struct cmd *, int, char **, char **); +int cmd_copy_buffer_exec(struct cmd *, struct cmd_ctx *); +void cmd_copy_buffer_send(struct cmd *, struct buffer *); +void cmd_copy_buffer_recv(struct cmd *, struct buffer *); +void cmd_copy_buffer_free(struct cmd *); +void cmd_copy_buffer_init(struct cmd *, int); +size_t cmd_copy_buffer_print(struct cmd *, char *, size_t); + +struct cmd_copy_buffer_data { + char *dst_session; + char *src_session; + int dst_idx; + int src_idx; +}; + +const struct cmd_entry cmd_copy_buffer_entry = { + "copy-buffer", "copyb", + "[-a src-index] [-b dst-index] [-s src-session] [-t dst-session]", + 0, + cmd_copy_buffer_init, + cmd_copy_buffer_parse, + cmd_copy_buffer_exec, + cmd_copy_buffer_send, + cmd_copy_buffer_recv, + cmd_copy_buffer_free, + cmd_copy_buffer_print +}; + +void +cmd_copy_buffer_init(struct cmd *self, unused int arg) +{ + struct cmd_copy_buffer_data *data; + + self->data = data = xmalloc(sizeof *data); + data->dst_session = NULL; + data->src_session = NULL; + data->dst_idx = -1; + data->src_idx = -1; +} + +int +cmd_copy_buffer_parse(struct cmd *self, int argc, char **argv, char **cause) +{ + struct cmd_copy_buffer_data *data; + const char *errstr; + int n, opt; + + self->entry->init(self, 0); + data = self->data; + + while ((opt = getopt(argc, argv, "a:b:s:t:")) != -1) { + switch (opt) { + case 'a': + if (data->src_idx == -1) { + n = strtonum(optarg, 0, INT_MAX, &errstr); + if (errstr != NULL) { + xasprintf(cause, "buffer %s", errstr); + goto error; + } + data->src_idx = n; + } + break; + case 'b': + if (data->dst_idx == -1) { + n = strtonum(optarg, 0, INT_MAX, &errstr); + if (errstr != NULL) { + xasprintf(cause, "buffer %s", errstr); + goto error; + } + data->dst_idx = n; + } + break; + case 's': + if (data->src_session == NULL) + data->src_session = xstrdup(optarg); + break; + case 't': + if (data->dst_session == NULL) + data->dst_session = xstrdup(optarg); + break; + default: + goto usage; + } + } + argc -= optind; + argv += optind; + + return (0); + +usage: + xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); + +error: + self->entry->free(self); + return (-1); +} + +int +cmd_copy_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) +{ + struct cmd_copy_buffer_data *data = self->data; + struct paste_buffer *pb; + struct session *dst_session, *src_session; + u_int limit; + + if ((dst_session = cmd_find_session(ctx, data->dst_session)) == NULL || + (src_session = cmd_find_session(ctx, data->src_session)) == NULL) + return (-1); + + if (data->src_idx == -1) { + if ((pb = paste_get_top(&src_session->buffers)) == NULL) { + ctx->error(ctx, "no buffers"); + return (-1); + } + } else { + if ((pb = paste_get_index(&src_session->buffers, + data->src_idx)) == NULL) { + ctx->error(ctx, "no buffer %d", data->src_idx); + return (-1); + } + } + + limit = options_get_number(&dst_session->options, "buffer-limit"); + if (data->dst_idx == -1) { + paste_add(&dst_session->buffers, xstrdup(pb->data), limit); + return (0); + } + if (paste_replace(&dst_session->buffers, data->dst_idx, + xstrdup(pb->data)) != 0) { + ctx->error(ctx, "no buffer %d", data->dst_idx); + return (-1); + } + + return (0); +} + +void +cmd_copy_buffer_send(struct cmd *self, struct buffer *b) +{ + struct cmd_copy_buffer_data *data = self->data; + + buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->dst_session); + cmd_send_string(b, data->src_session); +} + +void +cmd_copy_buffer_recv(struct cmd *self, struct buffer *b) +{ + struct cmd_copy_buffer_data *data; + + self->data = data = xmalloc(sizeof *data); + buffer_read(b, data, sizeof *data); + data->dst_session = cmd_recv_string(b); + data->src_session = cmd_recv_string(b); +} + +void +cmd_copy_buffer_free(struct cmd *self) +{ + struct cmd_copy_buffer_data *data = self->data; + + if (data->dst_session != NULL) + xfree(data->dst_session); + if (data->src_session != NULL) + xfree(data->src_session); + xfree(data); +} + +size_t +cmd_copy_buffer_print(struct cmd *self, char *buf, size_t len) +{ + struct cmd_copy_buffer_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->src_idx != -1) { + off += xsnprintf(buf + off, len - off, " -a %d", + data->src_idx); + } + if (off < len && data->dst_idx != -1) { + off += xsnprintf(buf + off, len - off, " -b %d", + data->dst_idx); + } + if (off < len && data->src_session != NULL) { + off += cmd_prarg(buf + off, len - off, " -s ", + data->src_session); + } + if (off < len && data->dst_session != NULL) { + off += cmd_prarg(buf + off, len - off, " -t ", + data->dst_session); + } + return (off); +} diff --git a/cmd.c b/cmd.c index 72a8e00b..dd25c358 100644 --- a/cmd.c +++ b/cmd.c @@ -1,4 +1,4 @@ -/* $Id: cmd.c,v 1.84 2009-01-25 19:00:10 tcunha Exp $ */ +/* $Id: cmd.c,v 1.85 2009-02-03 17:21:19 tcunha Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -32,6 +32,7 @@ const struct cmd_entry *cmd_table[] = { &cmd_choose_window_entry, &cmd_clock_mode_entry, &cmd_command_prompt_entry, + &cmd_copy_buffer_entry, &cmd_copy_mode_entry, &cmd_delete_buffer_entry, &cmd_detach_client_entry, diff --git a/examples/tmux.vim b/examples/tmux.vim index b11e267c..a6ee1eb6 100644 --- a/examples/tmux.vim +++ b/examples/tmux.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: tmux(1) configuration file " Maintainer: Tiago Cunha -" Last Change: $Date: 2009-02-01 18:16:39 $ +" Last Change: $Date: 2009-02-03 17:21:19 $ if version < 600 syntax clear @@ -34,6 +34,7 @@ syn keyword tmuxCmds pass set-password saveb save-buffer downp down-pane killp syn keyword tmuxCmds kill-pane resizep-down resize-pane-down resizep-up syn keyword tmuxCmds resize-pane-up selectp select-pane splitw split-window syn keyword tmuxCmds upp up-pane choose-session choose-window loadb load-buffer +syn keyword tmuxCmds copyb copy-buffer syn keyword tmuxOptsSet prefix status status-fg status-bg bell-action syn keyword tmuxOptsSet default-command history-limit status-left status-right diff --git a/tmux.1 b/tmux.1 index cccaa59e..416d4c84 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1,4 +1,4 @@ -.\" $Id: tmux.1,v 1.74 2009-02-01 18:24:25 tcunha Exp $ +.\" $Id: tmux.1,v 1.75 2009-02-03 17:21:19 tcunha Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -396,6 +396,15 @@ If .Ar template is specified, it is used as the command; any %% in the template will be replaced by what is entered at the prompt. +.It Xo Ic copy-buffer +.Op Fl a Ar src-index +.Op Fl b Ar dst-index +.Op Fl s Ar src-session +.Op Fl t Ar dst-session +.Xc +.D1 (alias: Ic copyb) +Copies a session paste buffer to another session. If no sessions are +specified, the current one is used instead. .It Xo Ic copy-mode .Op Fl t Ar target-window .Op Fl u diff --git a/tmux.h b/tmux.h index c0124311..8f53d599 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.258 2009-01-30 00:24:49 nicm Exp $ */ +/* $Id: tmux.h,v 1.259 2009-02-03 17:21:19 tcunha Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1110,6 +1110,7 @@ extern const struct cmd_entry cmd_choose_session_entry; extern const struct cmd_entry cmd_choose_window_entry; extern const struct cmd_entry cmd_clock_mode_entry; extern const struct cmd_entry cmd_command_prompt_entry; +extern const struct cmd_entry cmd_copy_buffer_entry; extern const struct cmd_entry cmd_copy_mode_entry; extern const struct cmd_entry cmd_delete_buffer_entry; extern const struct cmd_entry cmd_detach_client_entry;