From e70e9513a82a817edf35c86cb8b7f5ff2736c771 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sat, 21 Jun 2008 14:11:39 +0000 Subject: [PATCH] Simple tab completion of option names in command prompt. --- CHANGES | 6 +++++- NOTES | 3 +-- TODO | 2 ++ cmd.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- status.c | 17 ++++++++++++++++- tmux.h | 3 ++- 6 files changed, 71 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index dbd9347e..afa53fe0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,8 @@ 21 June 2008 +* Naive tab completion in the command prompt. This only completes command + names if a) they are at the start of the text b) the cursor is at + the end of the text c) the text contains no spaces. * Only attempt to set the title where TERM looks like an xterm (contains "xterm", "rxvt" or is "screen"). I hate this but I don't see a better way: setting the title actually kills some other terminals pretty much dead. @@ -19,6 +22,7 @@ paste-buffer [-d] [-b index] [-t target-window] delete-buffer [-b index] [-t target-session] show-buffers [-t target-session] + show-buffer [-b index] [-t target-session] -d to paste-buffer deletes the buffer after pasting it. * New option, display-time, sets the time status line messages stay on screen @@ -538,4 +542,4 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.134 2008-06-21 13:11:28 nicm Exp $ +$Id: CHANGES,v 1.135 2008-06-21 14:11:39 nicm Exp $ diff --git a/NOTES b/NOTES index 6a4234e2..9bd6b34d 100644 --- a/NOTES +++ b/NOTES @@ -54,7 +54,6 @@ tmux does not: use xterm-color or rxvt for colour. There are the following known issues: -- tmux on the console on OpenBSD (usually TERM=wsvt25) is broken beyond use. - cons25 on the FreeBSD console lies about its support for scroll regions, reports are that using TERM=screen pretty much works okay. - Darwin/OS X's poll(2) is broken and doesn't support polling pty(4)s; as tmux @@ -71,4 +70,4 @@ welcome. Please email: -- Nicholas Marriott -$Id: NOTES,v 1.33 2008-06-16 16:42:33 nicm Exp $ +$Id: NOTES,v 1.34 2008-06-21 14:11:39 nicm Exp $ diff --git a/TODO b/TODO index e9fe5837..7f579bf3 100644 --- a/TODO +++ b/TODO @@ -77,6 +77,8 @@ - document buffer stuff - copy-mode enhancements: next word etc etc - problems with force-width when wrapping line in emacs? +- options parsing could be much more generic, opening the way for abbreviation + and tab completion of option names --- save-buffer -b number filename load-buffer -b number filename diff --git a/cmd.c b/cmd.c index 7bae8033..b119698c 100644 --- a/cmd.c +++ b/cmd.c @@ -1,4 +1,4 @@ -/* $Id: cmd.c,v 1.52 2008-06-20 17:31:48 nicm Exp $ */ +/* $Id: cmd.c,v 1.53 2008-06-21 14:11:39 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -70,6 +70,50 @@ const struct cmd_entry *cmd_table[] = { NULL }; +char * +cmd_complete(const char *s) +{ + const struct cmd_entry **entryp; + ARRAY_DECL(, const char *) list; + char *prefix; + u_int i; + size_t j; + + if (*s == '\0') + return (xstrdup(s)); + + /* First, build a list of all the possible matches. */ + ARRAY_INIT(&list); + for (entryp = cmd_table; *entryp != NULL; entryp++) { + if (strncmp((*entryp)->name, s, strlen(s)) != 0) + continue; + ARRAY_ADD(&list, (*entryp)->name); + } + + /* If none, bail now with the original string. */ + if (ARRAY_LENGTH(&list) == 0) { + ARRAY_FREE(&list); + return (xstrdup(s)); + } + + /* Now loop through the list and find the longest common prefix. */ + prefix = xstrdup(ARRAY_FIRST(&list)); + for (i = 1; i < ARRAY_LENGTH(&list); i++) { + s = ARRAY_ITEM(&list, i); + + j = strlen(s); + if (j > strlen(prefix)) + j = strlen(prefix); + for (; j > 0; j--) { + if (prefix[j - 1] != s[j - 1]) + prefix[j - 1] = '\0'; + } + } + + ARRAY_FREE(&list); + return (prefix); +} + struct cmd * cmd_parse(int argc, char **argv, char **cause) { diff --git a/status.c b/status.c index d4ba281d..72f6060a 100644 --- a/status.c +++ b/status.c @@ -1,4 +1,4 @@ -/* $Id: status.c,v 1.36 2008-06-19 22:51:27 nicm Exp $ */ +/* $Id: status.c,v 1.37 2008-06-21 14:11:39 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -372,6 +372,7 @@ status_prompt_redraw(struct client *c) void status_prompt_key(struct client *c, int key) { + char *s; size_t size; size = strlen(c->prompt_buffer); @@ -400,6 +401,20 @@ status_prompt_key(struct client *c, int key) c->flags |= CLIENT_STATUS; } break; + case '\011': + if (strchr(c->prompt_buffer, ' ') != NULL) + break; + if (c->prompt_index != strlen(c->prompt_buffer)) + break; + + s = cmd_complete(c->prompt_buffer); + xfree(c->prompt_buffer); + + c->prompt_buffer = s; + c->prompt_index = strlen(c->prompt_buffer); + + c->flags |= CLIENT_STATUS; + break; case '\010': case '\177': if (c->prompt_index != 0) { diff --git a/tmux.h b/tmux.h index f7f7a479..b7a6febc 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.160 2008-06-21 10:19:36 nicm Exp $ */ +/* $Id: tmux.h,v 1.161 2008-06-21 14:11:39 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -881,6 +881,7 @@ struct session *arg_parse_session(const char *); int arg_parse_window(const char *, struct session **, int *); /* cmd.c */ +char *cmd_complete(const char *); struct cmd *cmd_parse(int, char **, char **); void cmd_exec(struct cmd *, struct cmd_ctx *); void cmd_send(struct cmd *, struct buffer *);