Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: expand-or-complete-prefix



Steve Talley wrote:
> With expand-or-complete-prefix:
> 
> % cd /etc/[TAB]
> 
> produces no matches.

I didn't locate this, but looking at the code
expand-or-complete-prefix is a bit of a hack --- or rather the whole
completion code is a hack but this is hacked in on top of it, which is
not a recipe for success.  I've rewritten it as part of the standard
repertoire of hacks.  For once, the new code is considerably shorter
than the old.

This part of zsh is somewhere near the end of my `All Time Top
1,000,000,000 Easily Understandable Pieces of Code', but there's quite
a reasonable chance this is OK.  The most likely problem I can think
of is that I've made the completion code get the word beginning index
(wb) right from the start, so there could be somewhere innocently
subtracting 1 from it which shouldn't.

It would now be trivial to make this behaviour into an option.

(There are some useless hunks because somehow some whitespace got
trimmed.  It seemed silly to put it back in specially.)

*** Src/Zle/zle_tricky.c.ecp	Tue Jan 20 10:04:14 1998
--- Src/Zle/zle_tricky.c	Fri Feb 20 14:52:15 1998
***************
*** 173,179 ****
  static int ab, ae, fab, fae;
  
  /* This variable says what we are currently adding to the list of matches. */
!    
  static int addwhat;
  
  /* firstm hold the first match we found, shortest contains the shortest *
--- 173,179 ----
  static int ab, ae, fab, fae;
  
  /* This variable says what we are currently adding to the list of matches. */
! 
  static int addwhat;
  
  /* firstm hold the first match we found, shortest contains the shortest *
***************
*** 196,206 ****
  
  static int amenu;
  
- /* This is used by expandorcompleteprefix to save the position of the *
-  * inserted space (so that we can remove it later).                   */
- 
- static int remove_at = -1;
- 
  /* Find out if we have to insert a tab (instead of trying to complete). */
  
  /**/
--- 196,201 ----
***************
*** 524,530 ****
  	do_menucmp(lst);
  	return;
      }
!     
      /* Check if we have to start a menu-completion (via automenu). */
  
      if ((amenu = (isset(AUTOMENU) && lastambig)))
--- 519,525 ----
  	do_menucmp(lst);
  	return;
      }
! 
      /* Check if we have to start a menu-completion (via automenu). */
  
      if ((amenu = (isset(AUTOMENU) && lastambig)))
***************
*** 777,782 ****
--- 772,780 ----
  /* 1 if we are completing in a string */
  static int instring;
  
+ /* 1 if we are completing the prefix */
+ static int comppref;
+ 
  /* This function inserts an `x' in the command line at the cursor position. *
   *                                                                          *
   * Oh, you want to know why?  Well, if completion is tried somewhere on an  *
***************
*** 786,807 ****
   * command we are completing and such things).  So we temporarily add a `x' *
   * (any character without special meaning would do the job) at the cursor   *
   * position, than the lexer gives us the word `x' and its beginning and end *
!  * positions and we can remove the `x'.                                     */
  
  /**/
  static void
  addx(char **ptmp)
  {
      if (!line[cs] || line[cs] == '\n' ||
  	(iblank(line[cs]) && (!cs || line[cs-1] != '\\')) ||
  	line[cs] == ')' || line[cs] == '`' ||
! 	(instring && (line[cs] == '"' || line[cs] == '\''))) {
  	*ptmp = (char *)line;
! 	line = (unsigned char *)halloc(strlen((char *)line) + 3);
  	memcpy(line, *ptmp, cs);
  	line[cs] = 'x';
! 	strcpy((char *)line + cs + 1, (*ptmp) + cs);
! 	addedx = 1;
      } else {
  	addedx = 0;
  	*ptmp = NULL;
--- 784,817 ----
   * command we are completing and such things).  So we temporarily add a `x' *
   * (any character without special meaning would do the job) at the cursor   *
   * position, than the lexer gives us the word `x' and its beginning and end *
!  * positions and we can remove the `x'.                                     *
!  *									    *
!  * If we are just completing the prefix (comppref set), we also insert a    *
!  * space after the x to end the word.  We never need to remove the space:   *
!  * anywhere we are able to retrieve a word for completion it will be	    *
!  * discarded as whitespace.  It has the effect of making any suffix	    *
!  * referrable to as the next word on the command line when indexing	    *
!  * from a completion function.                                              */
  
  /**/
  static void
  addx(char **ptmp)
  {
+     int addspace = 0;
+ 
      if (!line[cs] || line[cs] == '\n' ||
  	(iblank(line[cs]) && (!cs || line[cs-1] != '\\')) ||
  	line[cs] == ')' || line[cs] == '`' ||
! 	(instring && (line[cs] == '"' || line[cs] == '\'')) ||
! 	(addspace = (comppref && !iblank(line[cs])))) {
  	*ptmp = (char *)line;
! 	line = (unsigned char *)halloc(strlen((char *)line) + 3 + addspace);
  	memcpy(line, *ptmp, cs);
  	line[cs] = 'x';
! 	if (addspace)
! 	    line[cs+1] = ' ';
! 	strcpy((char *)line + cs + 1 + addspace, (*ptmp) + cs);
! 	addedx = 1 + addspace;
      } else {
  	addedx = 0;
  	*ptmp = NULL;
***************
*** 966,972 ****
  		tt = tokstr ? dupstring(tokstr) : NULL;
  		/* If we added a `x', remove it. */
  		if (addedx && tt)
! 		    chuck(tt + cs - wb - 1);
  		tt0 = tok;
  		/* Store the number of this word. */
  		clwpos = i;
--- 976,982 ----
  		tt = tokstr ? dupstring(tokstr) : NULL;
  		/* If we added a `x', remove it. */
  		if (addedx && tt)
! 		    chuck(tt + cs - wb);
  		tt0 = tok;
  		/* Store the number of this word. */
  		clwpos = i;
***************
*** 1000,1007 ****
  	    /* If this is the word the cursor is in and we added a `x', *
  	     * remove it.                                               */
  	    if (clwpos == i++ && addedx)
! 		chuck(&clwords[i - 1][((cs - wb - 1) >= sl) ?
! 				     (sl - 1) : (cs - wb - 1)]);
  	} while (tok != LEXERR && tok != ENDINPUT &&
  		 (tok != SEPER || (zleparse && !tt0)));
  	/* Calculate the number of words stored in the clwords array. */
--- 1010,1017 ----
  	    /* If this is the word the cursor is in and we added a `x', *
  	     * remove it.                                               */
  	    if (clwpos == i++ && addedx)
! 		chuck(&clwords[i - 1][((cs - wb) >= sl) ?
! 				     (sl - 1) : (cs - wb)]);
  	} while (tok != LEXERR && tok != ENDINPUT &&
  		 (tok != SEPER || (zleparse && !tt0)));
  	/* Calculate the number of words stored in the clwords array. */
***************
*** 1014,1021 ****
  	strinend();
  	inpop();
  	errflag = zleparse = 0;
- 	if (addedx)
- 	    wb++;
  	if (parbegin != -1) {
  	    /* We are in command or process substitution */
  	    if (parend >= 0 && !tmp)
--- 1024,1029 ----
***************
*** 1292,1300 ****
  void
  gotword(void)
  {
!     we = ll + 1 - inbufct;
      if (cs <= we) {
! 	wb = ll - wordbeg;
  	zleparse = 0;
      }
  }
--- 1300,1308 ----
  void
  gotword(void)
  {
!     we = ll + 1 - inbufct + (addedx == 2 ? 1 : 0);
      if (cs <= we) {
! 	wb = ll - wordbeg + addedx;
  	zleparse = 0;
      }
  }
***************
*** 1313,1320 ****
  	len = strlen(str);
      spaceinline(len);
      strncpy((char *)(line + cs), str, len);
-     if (remove_at >= cs)
-         remove_at += len;
      if (move)
  	cs += len;
  }
--- 1321,1326 ----
***************
*** 3607,3623 ****
  	}
      }
  
-     /* When called from expandorcompleteprefix, we probably have to
-        remove a space now. */
-     if (remove_at >= 0) {
- 	int ocs = cs;
- 
- 	cs = remove_at;
- 	deletechar();
- 	remove_at = -1;
- 	cs = ocs;
-     }
- 
      /* Set the cursor below the prompt. */
      trashzle();
      showinglist = 0;
--- 3613,3618 ----
***************
*** 3775,3781 ****
  
  		if (aylist) {
  		    zputs(*ap, shout);
! 		    t2 = strlen(*ap);		    
  		} else if (ispattern) {
  		    int cut = strlen(*ap) - boff;
  
--- 3770,3776 ----
  
  		if (aylist) {
  		    zputs(*ap, shout);
! 		    t2 = strlen(*ap);
  		} else if (ispattern) {
  		    int cut = strlen(*ap) - boff;
  
***************
*** 4036,4060 ****
  void
  expandorcompleteprefix(void)
  {
!     /* global c is the current character typed. */
!     int csafe = c;
!     int m = zmult;
! 
!     /* insert a space and backspace. */
!     zmult = 1;
!     c = ' ';
!     selfinsert();		/* insert the extra character */
!     backwardchar();		/* move towards beginning */
!     
!     remove_at = cs;
! 
!     /* do the expansion/completion. */
!     c = csafe;
!     expandorcomplete();		/* complete. */
! 
!     /* remove the inserted space. */
!     if (remove_at >= 0)
! 	deletechar();		/* delete the added space. */
!     zmult = m;
!     remove_at = -1;
  }
--- 4031,4037 ----
  void
  expandorcompleteprefix(void)
  {
!     comppref = 1;
!     expandorcomplete();
!     comppref = 0;
  }

-- 
Peter Stephenson <pws@xxxxxx>       Tel: +39 50 911239
WWW:  http://www.ifh.de/~pws/
Gruppo Teorico, Dipartimento di Fisica
Piazza Torricelli 2, 56100 Pisa, Italy



Messages sorted by: Reverse Date, Date, Thread, Author