Subject: ksh: escape spaces when expanding
To: None <tech-userlevel@netbsd.org>
From: Jaromir Dolecek <dolecek@ics.muni.cz>
List: tech-userlevel
Date: 09/21/1999 16:37:57
Hi,
what always bothered me that pdksh's tab expanding doesn't really play well
with filenames containing spaces. While playing with CygWin, I
found out that bash uses nice hack - it just escapes the space with
a backslash. So I implemented the same for ksh.
Note that only spaces are currently supported. Adding e.g. tab would
not be hard, but I haven't came across any filename containing it yet.
If nobody would complain, I'll commit the changes shortly.
Please keep me on CC, I'm not subscribed on tech-userlevel@NetBSD.org.
Index: edit.c
===================================================================
RCS file: /cvsroot/basesrc/bin/ksh/edit.c,v
retrieving revision 1.4
diff -u -p -r1.4 edit.c
--- edit.c 1998/11/04 18:27:21 1.4
+++ edit.c 1999/09/21 14:29:10
@@ -537,7 +537,7 @@ x_file_glob(flags, str, slen, wordsp)
{
char *toglob;
char **words;
- int nwords;
+ int nwords, i, idx, escaping;
XPtrV w;
struct source *s, *sold;
@@ -546,6 +546,20 @@ x_file_glob(flags, str, slen, wordsp)
toglob = add_glob(str, slen);
+ /* remove all escaping backward slashes */
+ escaping = 0;
+ for(i = 0, idx = 0; toglob[i]; i++) {
+ if (toglob[i] == '\\' && !escaping) {
+ escaping = 1;
+ continue;
+ }
+
+ toglob[idx] = toglob[i];
+ idx++;
+ if (escaping) escaping = 0;
+ }
+ toglob[idx] = '\0';
+
/*
* Convert "foo*" (toglob) to an array of strings (words)
*/
@@ -740,11 +754,14 @@ x_locate_word(buf, buflen, pos, startp,
/* Keep going backwards to start of word (has effect of allowing
* one blank after the end of a word)
*/
- for (; start > 0 && IS_WORDC(buf[start - 1]); start--)
+ for (; (start > 0 && IS_WORDC(buf[start - 1]))
+ || (start > 1 && buf[start-2] == '\\'); start--)
;
/* Go forwards to end of word */
- for (end = start; end < buflen && IS_WORDC(buf[end]); end++)
- ;
+ for (end = start; end < buflen && IS_WORDC(buf[end]); end++) {
+ if (buf[end] == '\\' && (end+1) < buflen && buf[end+1] == ' ')
+ end++;
+ }
if (is_commandp) {
int iscmd;
Index: vi.c
===================================================================
RCS file: /cvsroot/basesrc/bin/ksh/vi.c,v
retrieving revision 1.3
diff -u -p -r1.3 vi.c
--- vi.c 1998/11/04 18:27:21 1.3
+++ vi.c 1999/09/21 14:29:11
@@ -1995,8 +1995,8 @@ complete_word(command, count)
int nwords;
int start, end;
char **words;
- char *match;
- int match_len;
+ char *match, *spp;
+ int match_len, len, add;
int is_unique;
int is_command;
@@ -2069,16 +2069,30 @@ complete_word(command, count)
buf = save_edstate(es);
del_range(start, end);
es->cursor = start;
- if (putbuf(match, match_len, 0) != 0)
- rval = -1;
- else if (is_unique) {
+ len = match_len;
+ do {
+ spp = memchr(match, ' ', len);
+ add = (spp) ? spp - match : len;
+ if (putbuf(match, add, 0) != 0) {
+ rval = -1;
+ break;
+ }
+ if (spp) {
+ add++;
+ putbuf("\\ ", 2, 0);
+ }
+ match += add;
+ len -= add;
+ } while(spp);
+
+ if (rval == 0 && is_unique) {
/* If exact match, don't undo. Allows directory completions
* to be used (ie, complete the next portion of the path).
*/
expanded = NONE;
/* If not a directory, add a space to the end... */
- if (match_len > 0 && !ISDIRSEP(match[match_len - 1]))
+ if (match_len > 0 && !ISDIRSEP(match[-1]))
rval = putbuf(space, 1, 0);
}
x_free_words(nwords, words);
--
Jaromir Dolecek <jdolecek@NetBSD.org> http://www.ics.muni.cz/~dolecek/
"The only way how to get rid temptation is to yield to it." -- Oscar Wilde