Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
tcsh-like history-based dabbrev-expand patch
- X-seq: zsh-workers 3768
- From: Adam Spiers <adam@xxxxxxxxxxxxxxxxxxxxxxx>
- To: zsh workers mailing list <zsh-workers@xxxxxxxxxxxxxxx>
- Subject: tcsh-like history-based dabbrev-expand patch
- Date: Fri, 13 Feb 1998 18:27:09 +0000
- Reply-to: Adam Spiers <adam.spiers@xxxxxxxxxxxx>
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@xxxxxxxxxxxx WWW: http://www.new.ox.ac.uk/~adam/
Messages sorted by:
Reverse Date,
Date,
Thread,
Author