Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: expand existing $'...' in completion string
- X-seq: zsh-workers 23809
- From: Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxx (Zsh hackers list)
- Subject: PATCH: expand existing $'...' in completion string
- Date: Thu, 30 Aug 2007 22:41:12 +0100
- Mailing-list: contact zsh-workers-help@xxxxxxxxxx; run by ezmlm
This is supposed to help completion of strings with unprintable/invalid
characters by expanding existing $'...' strings that are already on the
command line when completion starts. You won't be surprised to hear
this is fairly hairy; there are lots of ill-documented offsets to get
right. I've actually tried it out with normal characters. For example,
h$'\x69'$'\x73' is treated as "his" and so completes to hist.c etc.
(The expression is unquoted and then requoted later; attempting to
preserve the original quoting would be highly complicated and didn't
seem worthwhile.)
I've tried to cover problem cases such as where the $' expression
isn't finished, or when the cursor is in the middle of it, by simply
leaving the expression alone.
It seemed to handle the following case:
% touch A\ B
% echo A$'\x20'<TAB>
% echo A\ B
at which point I decided it was time to leave well alone.
I'm sure you'll let me know if it doesn't work.
Index: Src/Zle/zle_tricky.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_tricky.c,v
retrieving revision 1.87
diff -u -r1.87 zle_tricky.c
--- Src/Zle/zle_tricky.c 29 May 2007 17:01:09 -0000 1.87
+++ Src/Zle/zle_tricky.c 30 Aug 2007 21:30:55 -0000
@@ -1611,7 +1611,90 @@
/* While building the quoted form, we also clean up the command line. */
for (p = s, i = wb, j = 0; *p; p++, i++) {
int skipchars;
- if ((*p == String || *p == Qstring) && p[1] == Snull)
+ if (*p == String && p[1] == Snull) {
+ char *pe;
+ for (pe = p + 2; *pe && *pe != Snull && i + (pe - p) < zlemetacs;
+ pe++)
+ ;
+ if (!*pe) {
+ /* no terminating Snull, can't substitute */
+ skipchars = 2;
+ } else {
+ /*
+ * Try and substitute the $'...' expression.
+ */
+ int len, tlen;
+ char *t = getkeystring(p + 2, &len, GETKEYS_DOLLARS_QUOTE,
+ NULL);
+ len += 2;
+ tlen = strlen(t);
+ skipchars = len - tlen;
+ /*
+ * If this makes the line longer, we don't attempt
+ * to substitute it. This is because "we" don't
+ * really understand what the heck is going on anyway
+ * and have blindly copied the code here from
+ * the sections below.
+ */
+ if (skipchars >= 0) {
+ /* Update the completion string */
+ memcpy(p, t, tlen);
+ /* Update the version of the line we are operating on */
+ ocs = zlemetacs;
+ zlemetacs = i;
+ if (skipchars > 0) {
+ /* Move the tail of the completion string up. */
+ char *dptr = p + tlen;
+ char *sptr = p + len;
+ while ((*dptr++ = *sptr++))
+ ;
+ /*
+ * If the character is before the cursor, we need to
+ * update the offset into the completion string to the
+ * cursor position, too. (Use ocs since we've hacked
+ * zlemetacs at this point.)
+ */
+ if (i < ocs)
+ offs -= skipchars;
+ /* Move the tail of the line up */
+ foredel(skipchars);
+ /*
+ * Update the offset into the command line to the
+ * cursor position if that's after the current position.
+ */
+ if ((zlemetacs = ocs) > i)
+ zlemetacs -= skipchars;
+ /* Always update the word end. */
+ we -= skipchars;
+ }
+ /*
+ * Copy the unquoted string into place, which
+ * now has the correct size.
+ */
+ memcpy(zlemetaline + i, t, tlen);
+
+ /*
+ * Move both the completion string pointer
+ * and the command line offset to the end of
+ * the chunk we've copied in (minus 1 for
+ * the end of loop increment). The line
+ * and completion string chunks are now the
+ * same length.
+ */
+ p += tlen - 1;
+ i += tlen - 1;
+ continue;
+ } else {
+ /*
+ * We give up if the expansion is longer the original
+ * string. That's because "we" don't really have the
+ * first clue how the completion system actually works.
+ */
+ skipchars = 2;
+ }
+ }
+ }
+ else if (*p == Qstring && p[1] == Snull)
skipchars = 2;
else if (inull(*p))
skipchars = 1;
--
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/
Messages sorted by:
Reverse Date,
Date,
Thread,
Author