=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/cmd-command-prompt.c,v retrieving revision 1.7 retrieving revision 1.8 diff -c -r1.7 -r1.8 *** src/usr.bin/tmux/cmd-command-prompt.c 2009/08/13 23:44:18 1.7 --- src/usr.bin/tmux/cmd-command-prompt.c 2009/08/19 10:39:50 1.8 *************** *** 1,4 **** ! /* $OpenBSD: cmd-command-prompt.c,v 1.7 2009/08/13 23:44:18 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: cmd-command-prompt.c,v 1.8 2009/08/19 10:39:50 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott *************** *** 27,82 **** * Prompt for command in client. */ ! void cmd_command_prompt_init(struct cmd *, int); ! int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *); ! int cmd_command_prompt_callback(void *, const char *); ! void cmd_command_prompt_free(void *); const struct cmd_entry cmd_command_prompt_entry = { "command-prompt", NULL, ! CMD_TARGET_CLIENT_USAGE " [template]", ! CMD_ARG01, 0, cmd_command_prompt_init, ! cmd_target_parse, cmd_command_prompt_exec, ! cmd_target_free, ! 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; case '.': ! data->arg = xstrdup("move-window -t '%%'"); break; case 'f': ! data->arg = xstrdup("find-window '%%'"); break; } } int cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) { ! 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 (-1); --- 27,138 ---- * Prompt for command in client. */ ! void cmd_command_prompt_init(struct cmd *, int); ! int cmd_command_prompt_parse(struct cmd *, int, char **, char **); ! int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *); ! void cmd_command_prompt_free(struct cmd *); ! size_t cmd_command_prompt_print(struct cmd *, char *, size_t); ! int cmd_command_prompt_callback(void *, const char *); ! void cmd_command_prompt_cfree(void *); ! char *cmd_command_prompt_replace(char *, const char *, int); const struct cmd_entry cmd_command_prompt_entry = { "command-prompt", NULL, ! CMD_TARGET_CLIENT_USAGE " [-p prompts] [template]", ! 0, 0, cmd_command_prompt_init, ! cmd_command_prompt_parse, cmd_command_prompt_exec, ! cmd_command_prompt_free, ! cmd_command_prompt_print }; struct cmd_command_prompt_data { + char *prompts; + char *target; + char *template; + }; + + struct cmd_command_prompt_cdata { struct client *c; + char *next_prompt; + char *prompts; char *template; + int idx; }; void cmd_command_prompt_init(struct cmd *self, int key) { ! struct cmd_command_prompt_data *data; ! self->data = data = xmalloc(sizeof *data); ! data->prompts = NULL; ! data->target = NULL; ! data->template = NULL; switch (key) { case ',': ! data->template = xstrdup("rename-window '%%'"); break; case '.': ! data->template = xstrdup("move-window -t '%%'"); break; case 'f': ! data->template = xstrdup("find-window '%%'"); break; } } int + cmd_command_prompt_parse(struct cmd *self, int argc, char **argv, char **cause) + { + struct cmd_command_prompt_data *data; + int opt; + + self->entry->init(self, 0); + data = self->data; + + while ((opt = getopt(argc, argv, "p:t:")) != -1) { + switch (opt) { + case 'p': + if (data->prompts == NULL) + data->prompts = xstrdup(optarg); + break; + case 't': + if (data->target == NULL) + data->target = xstrdup(optarg); + break; + default: + goto usage; + } + } + argc -= optind; + argv += optind; + if (argc != 0 && argc != 1) + goto usage; + + if (argc == 1) + data->template = xstrdup(argv[0]); + + return (0); + + usage: + xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); + + self->entry->free(self); + return (-1); + } + + int cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) { ! struct cmd_command_prompt_data *data = self->data; ! struct cmd_command_prompt_cdata *cdata; struct client *c; ! char *prompt, *ptr; ! size_t n; if ((c = cmd_find_client(ctx, data->target)) == NULL) return (-1); *************** *** 86,161 **** 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(":"); ! } ! status_prompt_set(c, hdr, ! cmd_command_prompt_callback, cmd_command_prompt_free, cdata, 0); ! xfree(hdr); return (0); } int cmd_command_prompt_callback(void *data, const char *s) { ! struct cmd_command_prompt_data *cdata = data; struct client *c = cdata->c; struct cmd_list *cmdlist; ! struct cmd_ctx ctx; ! char *cause, *ptr, *buf, ch; ! size_t len, slen; ! if (s == NULL || *s == '\0') 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; ! } ! } ! ! if (buf == NULL) ! return (0); ! buf[len] = '\0'; ! s = buf; } ! if (cmd_string_parse(s, &cmdlist, &cause) != 0) { ! if (cause == NULL) ! return (0); ! *cause = toupper((u_char) *cause); ! status_message_set(c, "%s", cause); ! xfree(cause); ! cmdlist = NULL; ! } ! if (buf != NULL) ! xfree(buf); ! if (cmdlist == NULL) return (0); ctx.msgdata = NULL; ctx.cursession = c->session; --- 142,241 ---- cdata = xmalloc(sizeof *cdata); cdata->c = c; ! cdata->idx = 1; ! cdata->next_prompt = NULL; ! cdata->prompts = NULL; ! cdata->template = NULL; + if (data->template != NULL) + cdata->template = xstrdup(data->template); + else + cdata->template = xstrdup("%1"); + if (data->prompts != NULL) + cdata->prompts = xstrdup(data->prompts); + else if (data->template != NULL) { + n = strcspn(data->template, " ,"); + xasprintf(&cdata->prompts, "(%.*s) ", (int) n, data->template); + } else + cdata->prompts = xstrdup(":"); + + cdata->next_prompt = cdata->prompts; + ptr = strsep(&cdata->next_prompt, ","); + if (data->prompts == NULL) + prompt = xstrdup(ptr); + else + xasprintf(&prompt, "%s ", ptr); + status_prompt_set(c, prompt, cmd_command_prompt_callback, + cmd_command_prompt_cfree, cdata, 0); + xfree(prompt); + return (0); } + void + cmd_command_prompt_free(struct cmd *self) + { + struct cmd_command_prompt_data *data = self->data; + + if (data->prompts != NULL) + xfree(data->prompts); + if (data->target != NULL) + xfree(data->target); + if (data->template != NULL) + xfree(data->template); + xfree(data); + } + + size_t + cmd_command_prompt_print(struct cmd *self, char *buf, size_t len) + { + struct cmd_command_prompt_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->prompts != NULL) + off += cmd_prarg(buf + off, len - off, " -p ", data->prompts); + if (off < len && data->target != NULL) + off += cmd_prarg(buf + off, len - off, " -t ", data->target); + if (off < len && data->template != NULL) + off += cmd_prarg(buf + off, len - off, " ", data->template); + return (off); + } + int cmd_command_prompt_callback(void *data, const char *s) { ! struct cmd_command_prompt_cdata *cdata = data; struct client *c = cdata->c; struct cmd_list *cmdlist; ! struct cmd_ctx ctx; ! char *cause, *newtempl, *prompt, *ptr; ! if (s == NULL) return (0); ! newtempl = cmd_command_prompt_replace(cdata->template, s, cdata->idx); ! xfree(cdata->template); ! cdata->template = newtempl; ! if ((ptr = strsep(&cdata->next_prompt, ",")) != NULL) { ! xasprintf(&prompt, "%s ", ptr); ! status_prompt_update(c, prompt); ! xfree(prompt); ! cdata->idx++; ! return (1); } ! if (cmd_string_parse(newtempl, &cmdlist, &cause) != 0) { ! if (cause != NULL) { ! *cause = toupper((u_char) *cause); ! status_message_set(c, "%s", cause); ! xfree(cause); ! } return (0); + } ctx.msgdata = NULL; ctx.cursession = c->session; *************** *** 176,186 **** } void ! cmd_command_prompt_free(void *data) { ! struct cmd_command_prompt_data *cdata = data; if (cdata->template != NULL) xfree(cdata->template); xfree(cdata); } --- 256,308 ---- } void ! cmd_command_prompt_cfree(void *data) { ! struct cmd_command_prompt_cdata *cdata = data; + if (cdata->prompts != NULL) + xfree(cdata->prompts); if (cdata->template != NULL) xfree(cdata->template); xfree(cdata); + } + + char * + cmd_command_prompt_replace(char *template, const char *s, int idx) + { + char ch; + char *buf, *ptr; + int replaced; + size_t len; + + if (strstr(template, "%") == NULL) + return (xstrdup(template)); + + buf = xmalloc(1); + *buf = '\0'; + len = 0; + replaced = 0; + + ptr = template; + while (*ptr != '\0') { + switch (ch = *ptr++) { + case '%': + if (*ptr < '1' || *ptr > '9' || *ptr - '0' != idx) { + if (*ptr != '%' || replaced) + break; + replaced = 1; + } + ptr++; + + len += strlen(s); + buf = xrealloc(buf, 1, len + 1); + strlcat(buf, s, len + 1); + continue; + } + buf = xrealloc(buf, 1, len + 2); + buf[len++] = ch; + buf[len] = '\0'; + } + + return (buf); }