From 98c85cf989a951c28e536e10de147b3263d934ce Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 13 Jan 2009 01:08:40 +0000 Subject: [PATCH] command-prompt now accepts a single argument, a template string. Any occurrences of %% in this string are replaced by whatever is entered at the prompt and the result is executed as a command. This allows things like (now bound by default): bind , command-prompt "rename-window %%" Or my favourite: bind x command-prompt "split-window 'man %%'" --- CHANGES | 13 ++++++- TODO | 5 +-- cmd-command-prompt.c | 93 ++++++++++++++++++++++++++++++++++++++------ key-bindings.c | 3 +- 4 files changed, 96 insertions(+), 18 deletions(-) diff --git a/CHANGES b/CHANGES index 0e786101..69a86312 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,16 @@ 12 January 2009 +* command-prompt now accepts a single argument, a template string. Any + occurrences of %% in this string are replaced by whatever is entered at the + prompt and the result is executed as a command. This allows things like (now + bound by default): + + bind , command-prompt "rename-window %%" + + or my favourite: + + bind x command-prompt "split-window 'man %%'" + * Option to set prefix time, allowing multiple commands to be entered without pressing the prefix key again, so long as they each typed within this time of each other. @@ -887,7 +898,7 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.199 2009-01-12 23:37:02 nicm Exp $ +$Id: CHANGES,v 1.200 2009-01-13 01:08:40 nicm 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 diff --git a/TODO b/TODO index 28b0c523..e4fc4be0 100644 --- a/TODO +++ b/TODO @@ -93,9 +93,6 @@ move-pane (to window) >2 panes per window - would be nice if tmux could be the shell -- some sort of extension to command prompt so can do eg - bind m command-prompt 'split "man %%"' - bind r command-prompt 'renamew "%%"' - which then asks for a string, substitutes %% in command and executes it +- command-prompt should accept an argument to specify the prompt - fix rxvt cursor fg issue (text under cursor has non-white fg) - key handling sucks a bit and needs to be reworked diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c index 0bf3c084..f5a1d271 100644 --- a/cmd-command-prompt.c +++ b/cmd-command-prompt.c @@ -1,4 +1,4 @@ -/* $Id: cmd-command-prompt.c,v 1.7 2009-01-11 00:48:42 nicm Exp $ */ +/* $Id: cmd-command-prompt.c,v 1.8 2009-01-13 01:08:40 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -19,6 +19,7 @@ #include #include +#include #include "tmux.h" @@ -26,15 +27,16 @@ * Prompt for command in client. */ +void cmd_command_prompt_init(struct cmd *, int); void cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *); int cmd_command_prompt_callback(void *, const char *); const struct cmd_entry cmd_command_prompt_entry = { "command-prompt", NULL, - CMD_TARGET_CLIENT_USAGE, - 0, - cmd_target_init, + CMD_TARGET_CLIENT_USAGE " [template]", + CMD_ZEROONEARG, + cmd_command_prompt_init, cmd_target_parse, cmd_command_prompt_exec, cmd_target_send, @@ -43,11 +45,33 @@ const struct cmd_entry cmd_command_prompt_entry = { cmd_target_print }; +struct cmd_command_prompt_data { + struct client *c; + char *template; +}; + +void +cmd_command_prompt_init(struct cmd *self, int key) +{ + struct cmd_target_data *data; + + cmd_target_init(self, key); + data = self->data; + + switch (key) { + case ',': + data->arg = xstrdup("rename-window \"%%\""); + break; + } +} + void cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct client *c; + struct cmd_target_data *data = self->data; + struct cmd_command_prompt_data *cdata; + struct client *c; + char *hdr, *ptr; if ((c = cmd_find_client(ctx, data->target)) == NULL) return; @@ -55,7 +79,19 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) if (c->prompt_string != NULL) return; - server_set_client_prompt(c, ":", cmd_command_prompt_callback, c, 0); + cdata = xmalloc(sizeof *cdata); + cdata->c = c; + if (data->arg != NULL) { + cdata->template = xstrdup(data->arg); + if ((ptr = strchr(data->arg, ' ')) == NULL) + ptr = strchr(data->arg, '\0'); + xasprintf(&hdr, "(%.*s) ", (int) (ptr - data->arg), data->arg); + } else { + cdata->template = NULL; + hdr = xstrdup(":"); + } + server_set_client_prompt(c, hdr, cmd_command_prompt_callback, cdata, 0); + xfree(hdr); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); @@ -64,13 +100,44 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) int cmd_command_prompt_callback(void *data, const char *s) { - struct client *c = data; - struct cmd *cmd; - struct cmd_ctx ctx; - char *cause; + struct cmd_command_prompt_data *cdata = data; + struct client *c = cdata->c; + struct cmd *cmd; + struct cmd_ctx ctx; + char *cause, *ptr, *buf, ch; + size_t len, slen; if (s == NULL) return (0); + slen = strlen(s); + + len = 0; + buf = NULL; + if (cdata->template != NULL) { + ptr = cdata->template; + while (*ptr != '\0') { + switch (ch = *ptr++) { + case '%': + if (*ptr != '%') + break; + ptr++; + + buf = xrealloc(buf, 1, len + slen + 1); + memcpy(buf + len, s, slen); + len += slen; + break; + default: + buf = xrealloc(buf, 1, len + 2); + buf[len++] = ch; + break; + } + } + xfree(cdata->template); + + buf[len] = '\0'; + s = buf; + } + xfree(cdata); if (cmd_string_parse(s, &cmd, &cause) != 0) { if (cause == NULL) @@ -78,8 +145,10 @@ cmd_command_prompt_callback(void *data, const char *s) *cause = toupper((u_char) *cause); server_set_client_message(c, cause); xfree(cause); - return (0); + cmd = NULL; } + if (buf != NULL) + xfree(buf); if (cmd == NULL) return (0); diff --git a/key-bindings.c b/key-bindings.c index 60b223f4..f3ce1bb8 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -1,4 +1,4 @@ -/* $Id: key-bindings.c,v 1.44 2009-01-12 19:23:14 nicm Exp $ */ +/* $Id: key-bindings.c,v 1.45 2009-01-13 01:08:40 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -80,6 +80,7 @@ key_bindings_init(void) { '"', &cmd_split_window_entry }, { '#', &cmd_list_buffers_entry }, { '&', &cmd_kill_window_entry }, + { ',', &cmd_command_prompt_entry }, { '-', &cmd_delete_buffer_entry }, { '0', &cmd_select_window_entry }, { '1', &cmd_select_window_entry },