From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from boing.lanl.gov ([128.165.114.197]) by hawkwind.utcs.utoronto.ca with SMTP id <24823>; Thu, 9 Dec 1999 16:22:26 -0500 Received: from boing.lanl.gov (mkg@localhost) by boing.lanl.gov (8.9.3/8.9.3) with ESMTP id JAA30396 for ; Thu, 9 Dec 1999 09:27:31 -0700 Message-Id: <199912091627.JAA30396@boing.lanl.gov> To: rc@hawkwind.utcs.toronto.edu Subject: Re: tilde featuritis alert In-Reply-To: Your message of "Thu, 09 Dec 1999 02:52:05 EST." <19991209025205.B305@debian> Date: Thu, 9 Dec 1999 11:27:30 -0500 From: "Mark K. Gardner" Hi Decklin, Welcome to rc. [clip...] > I really miss my '~' for home directory from bash. [clip...] > One other thing - is there a replacement for the '~user' idiom? > What's the rc way? grep through /etc/passwd? I have a patch to rc that adds tilde expansion for both these cases. I have also monkeyed with modifications to solve the "readline expands it but rc doesn't grok it" problem. And I have had discussions with Gert-Jan Vons, the author of vrl, about how to do tilde expansion in vrl. Based on this experience (some may say bull-headed stubborness), I make two observations. 1) Tilde expansion for rc is fundamentally hard. The primary reason is the conflict with pattern matching. Tilde is already spoken for as the pattern matching operator. Its use as a file path component will always be problematic. My implementation of tilde expansion correctly interprets "ls ~", "ls ~/foo", "ls ~mkg" or "ls ~mkg/foo" but it cannot handle "ls ~ " (note the space after the tilde). You would have to type "ls ~/" instead to disambiguate with the use of tilde as the pattern matching operator. I tried snarfing % as the expansion character for a while, as it appears to be unencumbered by prior use. Its use in the place of tilde seemed... well ugly. Especially considering that tilde is still used in emacs, which I use alot. It was confusing switching back and forth between % and ~. Perhaps I just didn't give it enough time. Maybe I could have changed emacs, I don't know. I abandoned the idea. 2) rc will never have tilde expansion as "standard equipment". The primary reason is cultural. Most of us were attracted to rc because of its simplicity. Nearly all changes are seen as creeping featuritis and soundly rejected (witness the "echo debate"). I have come to appreciate this view and even embrace it. That said, I must confess that I am still lazily using a patched version of rc with tilde expansion (along with "false", "true", "version", "test" and "C-d trapping" features). Next to the bloat caused by statically linking in GNU Readline, these features are nearly free! However, I should warn you that my New Year's resolution is to "go on a diet" by suffering through tilde withdrawals, eliminating "false" and "true", and adopting vrl. [PS: Since you are about to ask for it anyway, I am including my patch for tilde expansion. Add -DTILDEHOME to CFLAGS and recompile. I will answer simple questions, but I "...MAKE NO WARRANTY...EXPRESSED OR IMPLIED...", yada, yada, yada.] [PPS: I have been reluctant to waste bandwidth with its publication. However, the question of tilde expansion frequently keeps popping up. I hope by publishing it that requests can be answered by the archive.] Mark -- Mark K. Gardner RADIANT Team Network Engineering, CIC-5 Los Alamos National Laboratory P.O. Box 1663, M.S. K766 Los Alamos, NM 87545 Email: mkg@lanl.gov Phone: 1-505-665-4809 -- ================================ Cut here ====================================== --- rc-1.6/lex.c Fri Jul 24 09:48:27 1998 +++ rc-1.6-mkg/lex.c Mon Oct 18 13:33:34 1999 @@ -3,6 +3,12 @@ #include "rc.h" #include "parse.h" +#if defined(TILDEHOME) +# include +# include +# include +#endif /* TILDEHOME */ + /* Special characters (i.e., "non-word") in rc: \t \n # ; & | ^ $ = ~ ` ' { } @ ! ( ) < > \ @@ -33,6 +39,18 @@ int lineno; +#if defined(TILDEHOME) +const char nw[] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, /* ~ */ 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +#else /* TILDEHOME */ const char nw[] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, @@ -43,6 +61,7 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +#endif /* TILDEHOME */ const char dnw[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -97,9 +116,22 @@ checkfreecaret; w = RW; i = 0; +#if defined(TILDEHOME) + if (c == '~') { + c = gchar(); + ugchar(c); + if (c == ' ' || c == '\t') + return TWIDDLE; + c = '~'; + } +#endif /* TILDEHOME */ read: do { buf[i++] = c; +#if defined(TILDEHOME) + if (c == '?' || c == '[' || c == '*' || c == '~') +#else if (c == '?' || c == '[' || c == '*') +#endif /* TILDEHOME */ saw_meta = TRUE; if (i >= bufsize) buf = realbuf = erealloc(buf, bufsize *= 2); @@ -137,6 +169,46 @@ if (streq(buf, "while")) return WHILE; if (streq(buf, "case")) return CASE; w = RW; +#if defined(TILDEHOME) + if (buf[0] == '~') { + if (buf[1] == '\0' || buf[1] == '/') { + /* ~ or ~/... */ + char *home = varlookup("home")->w; + int hlen, blen; + hlen = strlen(home); + blen = strlen(buf) - 1; + if (i + hlen >= bufsize) { + buf = realbuf = erealloc(buf, bufsize *= 2); + } + memmove(buf + hlen, &buf[1], blen); + memmove(buf, home, hlen); + buf[blen + hlen] = '\0'; + } else if (buf[1] != '\0' && buf[1] != '/') { + /* ~username */ + char *n, name[256], *b; + struct passwd *pwentry; + n = name; + b = &buf[1]; + while (isalnum(*b)) { + *n++ = *b++; + } + *n = '\0'; + pwentry = getpwnam(name); + if (pwentry != NULL) { + char *path = pwentry->pw_dir; + int plen, blen; + plen = strlen(path); + blen = strlen(buf) - 1; + if (i + plen >= bufsize) { + buf = realbuf = erealloc(buf, bufsize *= 2); + } + memmove(buf + plen, &buf[strlen(name) + 1], blen); + memmove(buf, path, plen); + buf[blen + plen] = '\0'; + } + } + } +#endif /* TILDEHOME */ y->word.w = ncpy(buf); if (saw_meta) { char *r, *s; ================================= End Cut ======================================