From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28224 invoked from network); 13 Feb 1998 18:44:20 -0000 Received: from math.gatech.edu (list@130.207.146.50) by ns1.primenet.com.au with SMTP; 13 Feb 1998 18:44:20 -0000 Received: (from list@localhost) by math.gatech.edu (8.8.5/8.8.5) id NAA26123; Fri, 13 Feb 1998 13:25:13 -0500 (EST) Resent-Date: Fri, 13 Feb 1998 13:25:13 -0500 (EST) Message-ID: <19980213182709.13077@thelonious.new.ox.ac.uk> Date: Fri, 13 Feb 1998 18:27:09 +0000 From: Adam Spiers To: zsh workers mailing list Subject: tcsh-like history-based dabbrev-expand patch Reply-To: Adam Spiers Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Mailer: Mutt 0.84 Resent-Message-ID: <"c-vuQ3.0.3O6.809vq"@math> Resent-From: zsh-workers@math.gatech.edu X-Mailing-List: archive/latest/3768 X-Loop: zsh-workers@math.gatech.edu Precedence: list Resent-Sender: zsh-workers-request@math.gatech.edu Hi all, Have to confess I'm a complete newbie at this game, but I've written a patch to implement similar functionality to tcsh's dabbrev-expand function and I think it might be good enough (maybe with a few tweaks here and there) to include in the distribution. Here's the relevant quote from the tcsh man page: dabbrev-expand (M-/) Expands the current word to the most recent pre- ceding one for which the current is a leading sub- string, wrapping around the history list (once) if necessary. Repeating dabbrev-expand without any intervening typing changes to the next previous word etc., skipping identical matches much like history-search-backward does. It applies cleanly over 3.0.5 and introduces two new key commands: history-dabbrev-expand (default binding M-/) reverse-history-dabbrev-expand (default binding M-,) I'm no expert C coder, but I think it should be a fairly clean patch. The only bit which slightly bothers me is the setting of showinglist to 0 -- I wanted to disable the message zsh: do you wish to see all %n possibilities? when completing via this command, and didn't know enough about the refresh() function to know for certain how I should do it. I guessed at showinglist = 0 and it seemed to work :-) All comments welcome. It doesn't patch the man/info pages yet; I'm short of time so I thought I'd only bother if you decided it was worth including in the distribution :-) If you think it is (I would be very keen to see it go in because I think dabbrev-expand is SO useful) then I will make it patch the documentation too. -------- 8< -------- 8< -------- *** zsh-3.0.5/Src/globals.h Fri Feb 13 17:59:56 1998 --- zsh-3.0.5-as.dabbrev-expand.patch/Src/globals.h Fri Feb 13 14:19:32 1998 *************** *** 290,296 **** /* default completion infos */ ! EXTERN struct compctl cc_compos, cc_default, cc_first, cc_dummy; /* the job table */ --- 290,296 ---- /* default completion infos */ ! EXTERN struct compctl cc_compos, cc_default, cc_first, cc_dummy, cc_histdummy; /* the job table */ *** zsh-3.0.5/Src/zle.h Fri Feb 13 17:59:56 1998 --- zsh-3.0.5-as.dabbrev-expand.patch/Src/zle.h Thu Jan 8 00:58:52 1998 *************** *** 323,328 **** --- 323,329 ---- z_gosmacstransposechars, z_historybeginningsearchbackward, z_historybeginningsearchforward, + z_historydabbrevexpand, z_historyincrementalsearchbackward, z_historyincrementalsearchforward, z_historysearchbackward, *************** *** 351,356 **** --- 352,358 ---- z_quoteregion, z_redisplay, z_reversemenucomplete, + z_reversehistorydabbrevexpand, z_runhelp, z_selfinsert, z_selfinsertunmeta, *** zsh-3.0.5/Src/zle_bindings.c Fri Feb 13 17:59:56 1998 --- zsh-3.0.5-as.dabbrev-expand.patch/Src/zle_bindings.c Thu Jan 8 00:59:22 1998 *************** *** 83,88 **** --- 83,89 ---- {"gosmacs-transpose-chars", gosmacstransposechars, 0}, {"history-beginning-search-backward", historybeginningsearchbackward, ZLE_HISTSEARCH}, {"history-beginning-search-forward", historybeginningsearchforward, ZLE_HISTSEARCH}, + {"history-dabbrev-expand", historydabbrevexpand, ZLE_MENUCMP}, {"history-incremental-search-backward", historyincrementalsearchbackward, 0}, {"history-incremental-search-forward", historyincrementalsearchforward, 0}, {"history-search-backward", historysearchbackward, ZLE_HISTSEARCH}, *************** *** 110,115 **** --- 111,117 ---- {"quote-line", quoteline, 0}, {"quote-region", quoteregion, 0}, {"redisplay", redisplay, ZLE_MENUCMP}, + {"reverse-history-dabbrev-expand", reversehistorydabbrevexpand, ZLE_MENUCMP}, {"reverse-menu-complete", reversemenucomplete, ZLE_MENUCMP}, {"run-help", processcmd, ZLE_MENUCMP}, {"self-insert", selfinsert, ZLE_INSERT}, *************** *** 373,382 **** /* M-) */ z_undefinedkey, /* M-* */ z_undefinedkey, /* M-+ */ z_undefinedkey, ! /* M-, */ z_undefinedkey, /* M-- */ z_negargument, /* M-. */ z_insertlastword, ! /* M-/ */ z_undefinedkey, /* M-0 */ z_digitargument, /* M-1 */ z_digitargument, /* M-2 */ z_digitargument, --- 375,384 ---- /* M-) */ z_undefinedkey, /* M-* */ z_undefinedkey, /* M-+ */ z_undefinedkey, ! /* M-, */ z_reversehistorydabbrevexpand, /* M-- */ z_negargument, /* M-. */ z_insertlastword, ! /* M-/ */ z_historydabbrevexpand, /* M-0 */ z_digitargument, /* M-1 */ z_digitargument, /* M-2 */ z_digitargument, *** zsh-3.0.5/Src/zle_misc.c Fri Feb 13 17:59:56 1998 --- zsh-3.0.5-as.dabbrev-expand.patch/Src/zle_misc.c Tue Jan 6 21:42:26 1998 *************** *** 631,638 **** } if (cmd == z_listchoices || cmd == z_deletecharorlist || cmd == z_expandorcomplete || cmd == z_expandorcompleteprefix || ! cmd == z_completeword || cmd == z_vicmdmode || ! cmd == z_acceptline || c == ' ' || c == '\t') { LinkList cmdll; int ambig = 100; --- 631,639 ---- } if (cmd == z_listchoices || cmd == z_deletecharorlist || cmd == z_expandorcomplete || cmd == z_expandorcompleteprefix || ! cmd == z_completeword || cmd == z_historydabbrevexpand || ! cmd == z_vicmdmode || cmd == z_acceptline || ! c == ' ' || c == '\t') { LinkList cmdll; int ambig = 100; *** zsh-3.0.5/Src/zle_tricky.c Fri Feb 13 17:59:56 1998 --- zsh-3.0.5-as.dabbrev-expand.patch/Src/zle_tricky.c Fri Feb 13 18:02:07 1998 *************** *** 80,86 **** /* These control the type of completion that will be done. They are * * affected by the choice of ZLE command and by relevant shell options. */ ! static int usemenu, useglob; /* A pointer to the current position in the menu-completion array (the one * * that was put in the command line last). */ --- 80,86 ---- /* These control the type of completion that will be done. They are * * affected by the choice of ZLE command and by relevant shell options. */ ! static int usemenu, useglob, usehistonly = 0; /* A pointer to the current position in the menu-completion array (the one * * that was put in the command line last). */ *************** *** 114,120 **** static int nmatches; ! /* !=0 if we have a valid completion list. */ static int validlist; --- 114,121 ---- static int nmatches; ! /* 1 if we have a valid completion list; ! 2 if we have a valid completion list from history only. */ static int validlist; *************** *** 230,235 **** --- 231,247 ---- /**/ void + historydabbrevexpand(void) + { + usehistonly = 1; + usemenu = 1; + useglob = 0; + docomplete(COMP_COMPLETE); + usehistonly = showinglist = 0; + } + + /**/ + void menucomplete(void) { usemenu = 1; *************** *** 337,342 **** --- 349,374 ---- } LASTALLOC; } + /**/ + void + reversehistorydabbrevexpand(void) + { + if (!menucmp) { + historydabbrevexpand(); + return; + } + HEAPALLOC { + if (menucur == amatches) + menucur = amatches + nmatches - 1; + else + menucur--; + complexpect = menuce; + metafy_line(); + do_single(*menucur); + unmetafy_line(); + } LASTALLOC; + } + /* Accepts the current completion and starts a new arg, * * with the next completions. This gives you a way to * * accept several selections from the list of matches. */ *************** *** 2168,2176 **** /* Create the completion list. This is called whenever some bit of * * completion code needs the list. If the list is already available * ! * (validlist!=0), this function doesn't do anything. Along with * ! * the list is maintained the prefixes/suffixes etc. When any of * ! * this becomes invalid -- e.g. if some text is changed on the * * command line -- invalidatelist() should be called, to set * * validlist to zero and free up the memory used. This function * * returns non-zero on error. delit and compadd return information * --- 2200,2208 ---- /* Create the completion list. This is called whenever some bit of * * completion code needs the list. If the list is already available * ! * and of the right type, this function doesn't do anything. Along * ! * with the list is maintained the prefixes/suffixes etc. When any * ! * of this becomes invalid -- e.g. if some text is changed on the * * command line -- invalidatelist() should be called, to set * * validlist to zero and free up the memory used. This function * * returns non-zero on error. delit and compadd return information * *************** *** 2188,2195 **** /* If we already have a list from a previous execution of this * * function, skip the list building code. */ ! if (validlist) ! return !nmatches; os = dupstring(s); ol = (unsigned char *)dupstring((char *)line); --- 2220,2235 ---- /* If we already have a list from a previous execution of this * * function, skip the list building code. */ ! ! if (((validlist == 1) && !usehistonly) || ! ((validlist == 2) && usehistonly)) ! return !nmatches; ! ! /* If we already have a list from a previous execution of this * ! * function, but it is of the wrong sort, invalidate the list. */ ! if (((validlist == 1) && usehistonly) || ! ((validlist == 2) && !usehistonly)) ! invalidatelist(); os = dupstring(s); ol = (unsigned char *)dupstring((char *)line); *************** *** 2219,2224 **** --- 2259,2278 ---- if (!cc || cc->ext) cc = get_ccompctl(cc, compadd, incmd); + /* If activated with history-dabbrev-expand, override user-specified * + * compctl settings with these. */ + if (usehistonly) { + cc = &cc_histdummy; + cc->next = NULL; + cc->mask = 0; + cc->keyvar = cc->glob = cc->str = cc->func = cc->explain = + cc->prefix = cc->suffix = cc->subcmd = NULL; + cc->hpat = "*"; + cc->hnum = 0; + cc->ext = cc->xor = NULL; + cc->cond = NULL; + } + /* *compadd is the number of characters we have to ignore at the * * beginning of the word. */ wb += *compadd; *************** *** 2856,2862 **** /* Now search the history. */ while (n-- && (he = quietgethist(i--))) { int iwords; ! for (iwords = 0; iwords < he->nwords; iwords++) { h = he->text + he->words[iwords*2]; e = he->text + he->words[iwords*2+1]; hpatsav = *e; --- 2910,2916 ---- /* Now search the history. */ while (n-- && (he = quietgethist(i--))) { int iwords; ! for (iwords = he->nwords-1; iwords >= 0; iwords--) { h = he->text + he->words[iwords*2]; e = he->text + he->words[iwords*2+1]; hpatsav = *e; *************** *** 2933,2939 **** remsuffix = (cc->mask & CC_REMOVE); ccsuffix = cc->suffix; ! validlist = 1; if ((nmatches || expl) && !errflag) return 0; --- 2987,2993 ---- remsuffix = (cc->mask & CC_REMOVE); ccsuffix = cc->suffix; ! validlist = usehistonly ? 2 : 1; if ((nmatches || expl) && !errflag) return 0; *************** *** 3095,3103 **** *ap++ = (char *)getdata(nod); *ap = NULL; ! /* Now sort the array. */ ! qsort((void *) amatches, nmatches, sizeof(char *), ! (int (*) _((const void *, const void *)))strbpcmp); /* And delete the ones that occur more than once. */ for (ap = cp = amatches; *ap; ap++) { --- 3149,3159 ---- *ap++ = (char *)getdata(nod); *ap = NULL; ! if (!usehistonly) { ! /* Now sort the array. */ ! qsort((void *) amatches, nmatches, sizeof(char *), ! (int (*) _((const void *, const void *)))strbpcmp); ! } /* And delete the ones that occur more than once. */ for (ap = cp = amatches; *ap; ap++) { *************** *** 3558,3564 **** } /* Maybe we have to ask if the user wants to see the list. */ ! if ((listmax && ct > listmax) || (!listmax && up >= lines)) { int qup; setterm(); qup = printfmt("zsh: do you wish to see all %n possibilities? ", ct, 1); --- 3614,3620 ---- } /* Maybe we have to ask if the user wants to see the list. */ ! if (!usehistonly && ((listmax && ct > listmax) || (!listmax && up >= lines))) { int qup; setterm(); qup = printfmt("zsh: do you wish to see all %n possibilities? ", ct, 1); -------- 8< -------- 8< -------- -- Adam Spiers, Computing Officer, New College, Oxford University, UK ** cello/modern jazz/juggling/cycling/Perl/Linux/Quake fanatic, M$ hater e-mail: adam.spiers@new.ox.ac.uk WWW: http://www.new.ox.ac.uk/~adam/