Download raw body.
bin/ksh: add keep-tilde completion option
tech@,
this is a new optional feature for ksh: keep ~ as unexpanded for completion.
Not sure does I only one who prefer to keep short path with ~ isntead expand
to /home/user/
Feedbacks? Ok?
diff --git bin/ksh/edit.c bin/ksh/edit.c
index 83bab8ffbad..ad74110c7a9 100644
--- bin/ksh/edit.c
+++ bin/ksh/edit.c
@@ -31,6 +31,7 @@ void (*x_resize_cb)(void); /* callback for resize during edit */
static int x_file_glob(int, const char *, int, char ***);
static int x_command_glob(int, const char *, int, char ***);
static int x_locate_word(const char *, int, int, int *, int *);
+static void x_keep_tilde(char **, int, const char *, const char *);
/* Called from main */
@@ -425,10 +426,24 @@ x_file_glob(int flags, const char *str, int slen, char ***wordsp)
int nwords;
XPtrV w;
struct source *s, *sold;
+ char *tilde = NULL;
+ char *tilde_expanded = NULL;
+ int keep_tilde = 0;
+ int tlen = 0;
if (slen < 0)
return 0;
+ if (Flag(FKEEPTILDE) && slen > 0 && str[0] == '~') {
+ for (tlen = 1; tlen < slen; tlen++)
+ if (str[tlen] == '/')
+ break;
+ tilde = str_nsave(str, tlen, ATEMP);
+ tilde_expanded = evalstr(tilde, DOTILDE);
+ if (tilde_expanded != null && tilde_expanded[0] != '~')
+ keep_tilde = 1;
+ }
+
toglob = add_glob(str, slen);
/*
@@ -441,7 +456,8 @@ x_file_glob(int flags, const char *str, int slen, char ***wordsp)
if (yylex(ONEWORD|UNESCAPE) != LWORD) {
source = sold;
internal_warningf("%s: substitute error", __func__);
- return 0;
+ nwords = 0;
+ goto done;
}
source = sold;
XPinit(w, 32);
@@ -469,15 +485,54 @@ x_file_glob(int flags, const char *str, int slen, char ***wordsp)
afree(toglob, ATEMP);
if (nwords) {
+ if (keep_tilde)
+ x_keep_tilde(words, nwords, tilde, tilde_expanded);
*wordsp = words;
} else if (words) {
x_free_words(nwords, words);
*wordsp = NULL;
}
+done:
+ if (tilde)
+ afree(tilde, ATEMP);
+ if (tilde_expanded && tilde_expanded != null)
+ afree(tilde_expanded, ATEMP);
return nwords;
}
+static void
+x_keep_tilde(char **words, int nwords, const char *tilde,
+ const char *tilde_expanded)
+{
+ size_t tilde_len, exp_len;
+ int i;
+
+ tilde_len = strlen(tilde);
+ exp_len = strlen(tilde_expanded);
+ if (exp_len == 0)
+ return;
+
+ for (i = 0; i < nwords; i++) {
+ char *w = words[i];
+ size_t rest_len;
+ char *nw;
+
+ if (strncmp(w, tilde_expanded, exp_len) != 0)
+ continue;
+ if (w[exp_len] != '\0' && w[exp_len] != '/')
+ continue;
+
+ rest_len = strlen(w + exp_len);
+ nw = areallocarray(NULL, tilde_len + rest_len + 1,
+ sizeof(char), ATEMP);
+ memcpy(nw, tilde, tilde_len);
+ memcpy(nw + tilde_len, w + exp_len, rest_len + 1);
+ afree(w, ATEMP);
+ words[i] = nw;
+ }
+}
+
/* Data structure used in x_command_glob() */
struct path_order_info {
char *word;
diff --git bin/ksh/ksh.1 bin/ksh/ksh.1
index 4b5176c6598..f7286b10e4f 100644
--- bin/ksh/ksh.1
+++ bin/ksh/ksh.1
@@ -3630,6 +3630,8 @@ is read 13 times in a row.
The shell is an interactive shell.
This option can only be used when the shell is invoked.
See above for a description of what this means.
+.It Ic keep-tilde
+Keep leading tilde expressions in file name completion results.
.It Ic login
The shell is a login shell.
This option can only be used when the shell is invoked.
diff --git bin/ksh/misc.c bin/ksh/misc.c
index 809fae38d94..30cf21e9ba2 100644
--- bin/ksh/misc.c
+++ bin/ksh/misc.c
@@ -135,6 +135,7 @@ const struct option sh_options[] = {
#endif
{ "ignoreeof", 0, OF_ANY },
{ "interactive",'i', OF_CMDLINE },
+ { "keep-tilde", 0, OF_ANY }, /* non-standard */
{ "keyword", 'k', OF_ANY },
{ "login", 'l', OF_CMDLINE },
{ "markdirs", 'X', OF_ANY },
diff --git bin/ksh/sh.h bin/ksh/sh.h
index bffb374e0d1..85c18567eda 100644
--- bin/ksh/sh.h
+++ bin/ksh/sh.h
@@ -146,6 +146,7 @@ enum sh_flag {
#endif
FIGNOREEOF, /* eof does not exit */
FTALKING, /* -i: interactive */
+ FKEEPTILDE, /* keep ~ in completion */
FKEYWORD, /* -k: name=value anywhere */
FLOGIN, /* -l: a login shell */
FMARKDIRS, /* mark dirs with / in file name completion */
bin/ksh: add keep-tilde completion option