Hi,
Custom completions in ksh is currently limited to commands that does not
contain hyphens since such a character cannot be part of an identifier.
We could cheat and replace hyphens with underscores upon performing
completions.
The motivation behind this is that I want to add completions for
ssh-add(1). With the attached diff, I can achieve the following:

  $ set -A complete_ssh_add -- $(find ~/.ssh -name '*_rsa')

Comments? OK?

Index: edit.c
===================================================================
RCS file: /cvs/src/bin/ksh/edit.c,v
retrieving revision 1.57
diff -u -p -r1.57 edit.c
--- edit.c      8 Sep 2016 12:12:40 -0000       1.57
+++ edit.c      2 Jun 2017 15:00:02 -0000
@@ -585,7 +585,7 @@ x_try_array(const char *buf, int buflen,
 {
        const char *cmd, *cp;
        int cmdlen, n, i, slen;
-       char *name, *s;
+       char *ncmd, *name, *s;
        struct tbl *v, *vp;
 
        *nwords = 0;
@@ -604,10 +604,19 @@ x_try_array(const char *buf, int buflen,
        while (cmd + cmdlen < want && !isspace((u_char)cmd[cmdlen]))
                cmdlen++;
        for (i = 0; i < cmdlen; i++) {
-               if (!isalnum((u_char)cmd[i]) && cmd[i] != '_')
+               if (!isalnum((u_char)cmd[i]) && cmd[i] != '_' && cmd[i] != '-')
                        return 0;
        }
 
+       /* Normalize the command by replacing hyphens with underscores. */
+       if ((ncmd = malloc(cmdlen)) == NULL)
+               internal_errorf(1, "unable to allocate memory");
+       for (i = 0; i < cmdlen; i++)
+               if (cmd[i] == '-')
+                       ncmd[i] = '_';
+               else
+                       ncmd[i] = cmd[i];
+
        /* Take a stab at argument count from here. */
        n = 1;
        for (cp = cmd + cmdlen + 1; cp < want; cp++) {
@@ -616,18 +625,21 @@ x_try_array(const char *buf, int buflen,
        }
 
        /* Try to find the array. */
-       if (asprintf(&name, "complete_%.*s_%d", cmdlen, cmd, n) < 0)
+       if (asprintf(&name, "complete_%.*s_%d", cmdlen, ncmd, 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)
+               if (asprintf(&name, "complete_%.*s", cmdlen, ncmd) < 0)
                        internal_errorf(1, "unable to allocate memory");
                v = global(name);
                free(name);
-               if (~v->flag & (ISSET|ARRAY))
+               if (~v->flag & (ISSET|ARRAY)) {
+                       free(ncmd);
                        return 0;
+               }
        }
+       free(ncmd);
 
        /* Walk the array and build words list. */
        for (vp = v; vp; vp = vp->u.array) {
Index: ksh.1
===================================================================
RCS file: /cvs/src/bin/ksh/ksh.1,v
retrieving revision 1.187
diff -u -p -r1.187 ksh.1
--- ksh.1       19 Feb 2017 22:09:18 -0000      1.187
+++ ksh.1       2 Jun 2017 15:00:02 -0000
@@ -4719,6 +4719,14 @@ offer a selection of signal names for th
 .Xr kill 1 :
 .Pp
 .Dl set -A complete_kill_1 -- -9 -HUP -INFO -KILL -TERM
+.Pp
+If the command contain hyphens,
+replace them with underscores.
+For example,
+offer selection of arguments to
+.Xr ssh-add 1 :
+.Pp
+.Dl set -A complete_ssh_add -- $(find ~/.ssh -name '*_rsa')
 .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

Reply via email to