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

PATCH: 3.1.2-zefram3: history completion



Here's a patch to do completion from the history list as a special
command.  This is definitely useful when completing a long path name
if filename completion is also an option; you can choose whether to
complete chunk by chunk or to look for some long name which has
already been typed.  It's bound by default to M-/ in emacs mode, just
like in emacs itself.

I implemented it in a fairly simple way, just by forcing the
completion structure to an appropriate value, so the changes aren't
big.  Most of the rest of the patch is just book-keeping.  You could
generalise this, allowing a particular binding to specify completion
with an ad hoc compctl; probably Zefram could do this with widgets,
e.g. a new option to either zle or compctl would remember the
completion list as a widget; binding it would do completion with the
given compctl.  On the other hand, it's nice to have this particular
version bound by default which is messy the other way.

I had to invent a new flag ZLE_HISTCOMP for use with menu completion:
the point is that you may, for example, complete a path prefix with
ordinary completion then decide to switch to history completion to get
a long filename starting with that.  At this point, the history
completion needs to know the previous command was ordinary completion
so it doesn't just mindlessly cycle the same choices.  On the other
hand, I haven't done it the other way, so that after you type M-/, TAB
will still cycle the possibilities just produced (which is what it
usually does no matter how the list was produced).  I hope this is
rational.

I also moved the COMP_ flags to an enum; these are now widely used
elsewhere in the code.

*** Doc/Zsh/zle.yo.histcomp	Fri Jan 16 12:13:34 1998
--- Doc/Zsh/zle.yo	Fri Jan 16 12:13:49 1998
***************
*** 794,799 ****
--- 794,805 ----
  item(tt(complete-word))(
  Attempt completion on the current word.
  )
+ tindex(history-complete-word)
+ item(tt(history-complete-word) (ESC-/) (unbound) (unbound))(
+ Attempt completion on the current word using words on the history list
+ as possibilities.  This is useful, for example, when completing a long
+ path name which has already been used.
+ )
  tindex(delete-char-or-list)
  item(tt(delete-char-or-list) (^D) (unbound) (unbound))(
  Delete the character under the cursor.  If the cursor
***************
*** 919,924 ****
--- 925,931 ----
  tt(list-choices),
  tt(delete-char-or-list),
  tt(complete-word),
+ tt(history-complete-word),
  tt(accept-line),
  tt(expand-or-complete) and
  tt(expand-or-complete-prefix).
*** Src/Zle/iwidgets.list.histcomp	Fri Jan 16 10:33:02 1998
--- Src/Zle/iwidgets.list	Fri Jan 16 11:59:03 1998
***************
*** 59,64 ****
--- 59,65 ----
  "gosmacs-transpose-chars", gosmacstransposechars, 0
  "history-beginning-search-backward", historybeginningsearchbackward, 0
  "history-beginning-search-forward", historybeginningsearchforward, 0
+ "history-complete-word", historycompleteword, ZLE_MENUCMP | ZLE_KEEPSUFFIX  | ZLE_HISTCOMP
  "history-incremental-search-backward", historyincrementalsearchbackward, 0
  "history-incremental-search-forward", historyincrementalsearchforward, 0
  "history-search-backward", historysearchbackward, 0
*** Src/Zle/widgets.list.histcomp	Fri Jan 16 10:33:02 1998
--- Src/Zle/widgets.list	Fri Jan 16 11:59:13 1998
***************
*** 52,57 ****
--- 52,58 ----
  W(0, t_gosmacstransposechars, gosmacstransposechars)
  W(0, t_historybeginningsearchbackward, historybeginningsearchbackward)
  W(0, t_historybeginningsearchforward, historybeginningsearchforward)
+ W(ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_HISTCOMP, t_historycompleteword, historycompleteword)
  W(0, t_historyincrementalsearchbackward, historyincrementalsearchbackward)
  W(0, t_historyincrementalsearchforward, historyincrementalsearchforward)
  W(0, t_historysearchbackward, historysearchbackward)
*** Src/Zle/zle.h.histcomp	Fri Jan 16 11:50:23 1998
--- Src/Zle/zle.h	Fri Jan 16 11:58:53 1998
***************
*** 58,63 ****
--- 58,64 ----
  #define ZLE_LASTCOL     (1<<5)    /* command maintains lastcol correctly */
  #define ZLE_KILL	(1<<6)
  #define ZLE_KEEPSUFFIX	(1<<9)    /* DON'T remove added suffix */
+ #define ZLE_HISTCOMP    (1<<10)   /* Last completion was from history */
  
  /* thingies */
  
*** Src/Zle/zle_bindings.c.histcomp	Fri Jan 16 11:04:12 1998
--- Src/Zle/zle_bindings.c	Fri Jan 16 11:04:27 1998
***************
*** 171,177 ****
      /* M-, */ z_undefinedkey,
      /* M-- */ z_negargument,
      /* M-. */ z_insertlastword,
!     /* M-/ */ z_undefinedkey,
      /* M-0 */ z_digitargument,
      /* M-1 */ z_digitargument,
      /* M-2 */ z_digitargument,
--- 171,177 ----
      /* M-, */ z_undefinedkey,
      /* M-- */ z_negargument,
      /* M-. */ z_insertlastword,
!     /* M-/ */ z_historycompleteword,
      /* M-0 */ z_digitargument,
      /* M-1 */ z_digitargument,
      /* M-2 */ z_digitargument,
*** Src/Zle/zle_misc.c.histcomp	Fri Jan 16 11:01:22 1998
--- Src/Zle/zle_misc.c	Fri Jan 16 11:01:37 1998
***************
*** 658,663 ****
--- 658,664 ----
  	    if (cmd == Th(z_listchoices) || cmd == Th(z_deletecharorlist) ||
  		cmd == Th(z_expandorcomplete) || cmd == Th(z_completeword) ||
  		cmd == Th(z_expandorcompleteprefix) || cmd == Th(z_vicmdmode) ||
+ 		cmd == Th(z_historycompleteword) ||
  		cmd == Th(z_acceptline) || c == ' ' || c == '\t') {
  		cmdambig = 100;
  
*** Src/Zle/zle_tricky.c.histcomp	Fri Jan 16 10:33:01 1998
--- Src/Zle/zle_tricky.c	Fri Jan 16 11:59:01 1998
***************
*** 215,226 ****
      return 1;
  }
  
! #define COMP_COMPLETE 0
! #define COMP_LIST_COMPLETE 1
! #define COMP_SPELL 2
! #define COMP_EXPAND 3
! #define COMP_EXPAND_COMPLETE 4
! #define COMP_LIST_EXPAND 5
  #define COMP_ISEXPAND(X) ((X) >= COMP_EXPAND)
  
  /**/
--- 215,228 ----
      return 1;
  }
  
! enum { COMP_COMPLETE,
!        COMP_LIST_COMPLETE,
!        COMP_HIST_COMPLETE,
!        COMP_SPELL,
!        COMP_EXPAND,
!        COMP_EXPAND_COMPLETE,
!        COMP_LIST_EXPAND };
! 
  #define COMP_ISEXPAND(X) ((X) >= COMP_EXPAND)
  
  /**/
***************
*** 235,240 ****
--- 237,260 ----
  	docomplete(COMP_COMPLETE);
  }
  
+ extern int lastcmd;
+ 
+ /**/
+ void
+ historycompleteword(void)
+ {
+   usemenu = isset(MENUCOMPLETE);
+   useglob = isset(GLOBCOMPLETE);
+   if ((lastcmd & (ZLE_MENUCMP|ZLE_HISTCOMP)) == ZLE_MENUCMP) {
+     /* if we just did a completion but it wasn't from the history,
+      * act as if that completion was finished.
+      */
+     fixsuffix();
+     invalidatelist();
+   }
+   docomplete(COMP_HIST_COMPLETE);  
+ }
+ 
  /**/
  void
  menucomplete(void)
***************
*** 1764,1769 ****
--- 1784,1790 ----
          cc_dummy.mask = CC_PARAMS;
  	    ret = &cc_dummy;
  	    cc_dummy.refc = 10000;
+ 	    cc_dummy.hpat = NULL;
  	} else if (inwhat == IN_COND) {
  	    /* We try to be clever here: in conditions we complete option   *
  	     * names after a `-o', file names after `-nt', `-ot', and `-ef' *
***************
*** 1777,1782 ****
--- 1798,1804 ----
  		(CC_FILES | CC_PARAMS);
  	    ret = &cc_dummy;
  	    cc_dummy.refc = 10000;
+ 	    cc_dummy.hpat = NULL;
  	} else if (incmd)
  	    ret = &cc_compos;
  	/* And in redirections or if there is no command name (and we are *
***************
*** 2171,2177 ****
  	pushheap();
  
  	/* Make sure we have the completion list and compctl. */
! 	if(makecomplist(s, incmd, &delit, &compadd, untokenized)) {
  	    /* Error condition: feeeeeeeeeeeeep(). */
  	    feep();
  	    goto compend;
--- 2193,2199 ----
  	pushheap();
  
  	/* Make sure we have the completion list and compctl. */
! 	if(makecomplist(s, incmd, &delit, &compadd, untokenized, lst)) {
  	    /* Error condition: feeeeeeeeeeeeep(). */
  	    feep();
  	    goto compend;
***************
*** 2239,2245 ****
  
  /**/
  static int
! makecomplist(char *s, int incmd, int *delit, int *compadd, int untokenized)
  {
      Compctl cc = NULL;
      int oloffs = offs, owe = we, owb = wb, ocs = cs, oll = ll, isf = 1;
--- 2261,2268 ----
  
  /**/
  static int
! makecomplist(char *s, int incmd, int *delit, int *compadd,
! 	     int untokenized, int lst)
  {
      Compctl cc = NULL;
      int oloffs = offs, owe = we, owb = wb, ocs = cs, oll = ll, isf = 1;
***************
*** 2275,2280 ****
--- 2298,2310 ----
      matches = newlinklist();
      fmatches = newlinklist();
  
+     if (lst == COMP_HIST_COMPLETE) {
+       cc = ccmain = &cc_dummy;
+       cc->hpat = "";
+       cc->refc = 10000;
+       cc->mask = 0;
+     }
+ 
      /* If we don't have a compctl definition yet or we have a compctl *
       * with extended completion, get it (or the next one, resp.).     */
      if (!cc || cc->ext)
***************
*** 2402,2407 ****
--- 2432,2438 ----
  	    cc = ccmain = &cc_dummy;
  	    cc_dummy.refc = 10000;
  	    cc_dummy.mask = CC_PARAMS | CC_ENVVARS;
+ 	    cc_dummy.hpat = NULL;
  	}
      }
      ooffs = offs;

-- 
Peter Stephenson <pws@xxxxxxxxxxxxxxxxxxx>       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