summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/ksh/edit.c83
-rw-r--r--bin/ksh/ksh.123
2 files changed, 100 insertions, 6 deletions
diff --git a/bin/ksh/edit.c b/bin/ksh/edit.c
index e66fd0ea356..1f5b69e8095 100644
--- a/bin/ksh/edit.c
+++ b/bin/ksh/edit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: edit.c,v 1.54 2016/08/16 15:32:07 tb Exp $ */
+/* $OpenBSD: edit.c,v 1.55 2016/09/04 17:21:44 nicm Exp $ */
/*
* Command line editing - common code
@@ -15,6 +15,7 @@
#include <errno.h>
#include <libgen.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <unistd.h>
@@ -578,13 +579,85 @@ x_locate_word(const char *buf, int buflen, int pos, int *startp,
return end - start;
}
+static int
+x_try_array(const char *buf, int buflen, const char *want, int wantlen,
+ int *nwords, char ***words)
+{
+ const char *cmd, *cp, *last;
+ int cmdlen, n;
+ char *name, *s;
+ size_t slen;
+ struct tbl *v, *vp;
+
+ *nwords = 0;
+ *words = NULL;
+
+ /* Walk back to find start of command. */
+ if (want == buf)
+ return 0;
+ for (cmd = want; cmd > buf; cmd--) {
+ if (strchr(";|&()`", cmd[-1]) != NULL)
+ break;
+ }
+ while (cmd < want && isspace((u_char)*cmd))
+ cmd++;
+ cmdlen = 0;
+ while (cmd + cmdlen < want && !isspace((u_char)cmd[cmdlen]))
+ cmdlen++;
+
+ /* Take a stab at argument count from here. */
+ n = 1;
+ for (cp = cmd + cmdlen + 1; cp < want; cp++) {
+ if (!isspace((u_char)cp[-1]) && isspace((u_char)*cp))
+ n++;
+ }
+
+ /* Try to find the array. */
+ if (asprintf(&name, "complete_%.*s_%d", cmdlen, cmd, n) < 0)
+ internal_errorf(1, "unable to allocate memory");
+ v = global(name);
+ free(name);
+ if (~v->flag & (ISSET|ARRAY)) {
+ if (asprintf(&name, "complete_%.*s", cmdlen, cmd) < 0)
+ internal_errorf(1, "unable to allocate memory");
+ v = global(name);
+ free(name);
+ if (~v->flag & (ISSET|ARRAY))
+ return 0;
+ }
+
+ /* Walk the array and build words list. */
+ for (vp = v; vp; vp = vp->u.array) {
+ if (~vp->flag & ISSET)
+ continue;
+
+ s = str_val(vp);
+ slen = strlen(s);
+
+ if (slen < wantlen)
+ continue;
+ if (slen > wantlen)
+ slen = wantlen;
+ if (slen != 0 && strncmp(s, want, slen) != 0)
+ continue;
+
+ *words = areallocarray(*words, (*nwords) + 2, sizeof **words,
+ ATEMP);
+ (*words)[(*nwords)++] = str_save(s, ATEMP);
+ }
+ if (*nwords != 0)
+ (*words)[*nwords] = NULL;
+
+ return *nwords != 0;
+}
+
int
x_cf_glob(int flags, const char *buf, int buflen, int pos, int *startp,
int *endp, char ***wordsp, int *is_commandp)
{
int len;
int nwords;
- char **words;
+ char **words = NULL;
int is_command;
len = x_locate_word(buf, buflen, pos, startp, &is_command);
@@ -597,8 +670,10 @@ x_cf_glob(int flags, const char *buf, int buflen, int pos, int *startp,
if (len == 0 && is_command)
return 0;
- nwords = (is_command ? x_command_glob : x_file_glob)(flags,
- buf + *startp, len, &words);
+ if (is_command)
+ nwords = x_command_glob(flags, buf + *startp, len, &words);
+ else if (!x_try_array(buf, buflen, buf + *startp, len, &nwords, &words))
+ nwords = x_file_glob(flags, buf + *startp, len, &words);
if (nwords == 0) {
*wordsp = NULL;
return 0;
diff --git a/bin/ksh/ksh.1 b/bin/ksh/ksh.1
index 557b4a0eb0b..a2bdea1843a 100644
--- a/bin/ksh/ksh.1
+++ b/bin/ksh/ksh.1
@@ -1,8 +1,8 @@
-.\" $OpenBSD: ksh.1,v 1.179 2016/04/27 12:46:23 naddy Exp $
+.\" $OpenBSD: ksh.1,v 1.180 2016/09/04 17:21:44 nicm Exp $
.\"
.\" Public Domain
.\"
-.Dd $Mdocdate: April 27 2016 $
+.Dd $Mdocdate: September 4 2016 $
.Dt KSH 1
.Os
.Sh NAME
@@ -4705,6 +4705,25 @@ is appended.
If there is no command or file name with the current partial word
as its prefix, a bell character is output (usually causing a beep to be
sounded).
+.Pp
+Custom completions may be configured by creating an array named
+.Ql complete_command ,
+optionally suffixed with an argument number to complete only for a single
+argument.
+So defining an array named
+.Ql complete_kill
+provides possible completions for any argument to the
+.Xr kill 1
+command, but
+.Ql complete_kill_1
+only completes the first argument.
+For example, the following command makes
+.Nm
+offer a selection of signal names for the first argument to
+.Xr kill 1 :
+.Pp
+.Dl set -A complete_kill_1 -- -9 -HUP -INFO -KILL -TERM
+.Pp
.It complete-command: ^X^[
Automatically completes as much as is unique of the command name having the
partial word up to the cursor as its prefix, as in the