mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-01-01 05:16:05 +01:00
Initial revision
This commit is contained in:
parent
adefa2757a
commit
b346c4796b
5 changed files with 1061 additions and 0 deletions
15
Completion/User/_chown
Normal file
15
Completion/User/_chown
Normal file
|
@ -0,0 +1,15 @@
|
|||
#compdef chown chgrp
|
||||
|
||||
if [[ CURRENT -eq 2 || CURRENT -eq 3 && $words[CURRENT-1] = -* ]]; then
|
||||
if [[ $words[1] = chgrp ]] || compset -P '*[:.]'; then
|
||||
_groups
|
||||
else
|
||||
if [[ $OSTYPE = (solaris*|hpux*) ]]; then
|
||||
compgen -u -S ':' -q
|
||||
else
|
||||
compgen -u -S '.' -q
|
||||
fi
|
||||
fi
|
||||
else
|
||||
_files
|
||||
fi
|
6
Completion/User/_groups
Normal file
6
Completion/User/_groups
Normal file
|
@ -0,0 +1,6 @@
|
|||
#compdef newgrp
|
||||
|
||||
: ${(A)groups:=${${(s: :)$(</etc/group)}%%:*}}
|
||||
# : ${(A)groups:=${${(s: :)$(ypcat group.byname)}%%:*}} # If you use NIS
|
||||
|
||||
compadd $groups
|
119
Doc/Zsh/mod_complist.yo
Normal file
119
Doc/Zsh/mod_complist.yo
Normal file
|
@ -0,0 +1,119 @@
|
|||
texinode(The complist Module)(The deltochar Module)(The compctl Module)(Zsh Modules)
|
||||
sect(The complist Module)
|
||||
cindex(completion, listing)
|
||||
The tt(complist) module offers two extensions to completion listings:
|
||||
the ability to highlight matches in such a list and a different
|
||||
style of menu-completion.
|
||||
|
||||
subsect(Parameters)
|
||||
For both extensions one of the parameters tt(ZLS_COLORS) or tt(ZLS_COLOURS)
|
||||
must be set, even if the value is empty (which uses all the default values
|
||||
given below). These describe how matches are highlighted. The format of the
|
||||
value of these parameters is the same as used by the GNU version of the
|
||||
tt(ls) command: a colon-separated list of specifications of the form
|
||||
`var(name)=var(value)'. The var(name) may be one of the following strings,
|
||||
most of which specify file-types for which the var(value) will be used. The
|
||||
strings and their default values are:
|
||||
|
||||
startitem()
|
||||
item(tt(no 0))(
|
||||
for normal text (not the string displayed for a match)
|
||||
)
|
||||
item(tt(fi 0))(
|
||||
for regular files
|
||||
)
|
||||
item(tt(di 32))(
|
||||
for directories
|
||||
)
|
||||
item(tt(ln 36))(
|
||||
for symbolic links
|
||||
)
|
||||
item(tt(pi 31))(
|
||||
for named pipes (FIFOs)
|
||||
)
|
||||
item(tt(so 33))(
|
||||
for sockets
|
||||
)
|
||||
item(tt(bd 44;37))(
|
||||
for block devices
|
||||
)
|
||||
item(tt(cd 44;37))(
|
||||
for character devices
|
||||
)
|
||||
item(tt(ex 35))(
|
||||
for executable files
|
||||
)
|
||||
item(tt(mi) var(none))(
|
||||
for names not naming a file (default is the value defined for tt(fi))
|
||||
)
|
||||
item(tt(lc \e[))(
|
||||
for the left code (see below)
|
||||
)
|
||||
item(tt(rc m))(
|
||||
for the right code
|
||||
)
|
||||
item(tt(ec) var(none))(
|
||||
for the end code
|
||||
)
|
||||
enditem()
|
||||
|
||||
Apart from these strings, the var(name) may also be an asterisk
|
||||
(`tt(*)') followed by any string. The var(value) given for such a
|
||||
string will be used for all files whose name ends with the string.
|
||||
|
||||
When printing a match, the code prints the value of tt(lc), the value
|
||||
for the file-type or the last matching specification with a `tt(*)',
|
||||
the value of tt(rc), the string to display for the match itself, and
|
||||
then the value of tt(ec) if that is defined or the values of tt(lc),
|
||||
tt(no), and tt(rc) if tt(ec) is not defined.
|
||||
|
||||
The default values are ISO 6429 (ANSI) compliant and can be used on
|
||||
vt100 compatible terminals such as tt(xterm)s. On monochrome terminals
|
||||
the default values will have no visual effect.
|
||||
|
||||
Whenever one of the parameters tt(ZLS_COLORS) or tt(ZLS_COLOURS) is set
|
||||
and the tt(complist) module is loaded or linked into the shell,
|
||||
completion lists will be colored.
|
||||
|
||||
subsect(Menu selection)
|
||||
The tt(complist) module also offers a different style of selecting
|
||||
matches from a list called menu-selection. It can be invoked directly by
|
||||
the widget tt(menu-select) defined by the module. Alternatively,
|
||||
the parameter tt(SELECTMIN) can be set to an integer giving the minimum
|
||||
number of matches which must be present before menu selection is
|
||||
automatically turned on. This second method requires that menu completion
|
||||
be started, either directly from a widget such as tt(menu-complete), or due
|
||||
to one of the options tt(MENU_COMPLETE) or tt(AUTO_MENU) being set. If
|
||||
tt(SELECTMIN) is set, but is 0, 1 or empty, menu selection will always be
|
||||
started during menu completion if the completion is ambiguous.
|
||||
|
||||
After menu-selection is started, the matches will be listed. The
|
||||
matches to insert into the command line can be selected from this
|
||||
list. In the list one match is highlighted using the value for tt(ma)
|
||||
from the tt(ZLS_COLORS) or tt(ZLS_COLOURS) parameter. The default
|
||||
value for this it `tt(7)' which forces the selected match to be
|
||||
highlighted using standout mode on a vt100 compatible terminal.
|
||||
|
||||
Selecting matches is done by moving the mark around using the zle movement
|
||||
functions. The zle functions tt(send-break) and tt(accept-line) can be used
|
||||
to leave menu-selection, leaving the match currently inserted into the line
|
||||
in place. The functions tt(accept-and-hold) and
|
||||
tt(accept-and-menu-complete) can be used to accept the match currently
|
||||
inserted and continue inserting matches after that. Matches inserted this
|
||||
way can be removed by invoking the tt(undo) function. Keys bound to one of
|
||||
the completion functions will cycle to the next (or, in case of
|
||||
tt(reverse-menu-complete), the previous) match, and the tt(redisplay) and
|
||||
tt(clear-screen) functions work as usual without leaving
|
||||
menu-selection. Any other zle function leaves menu-selection and executes
|
||||
that function.
|
||||
|
||||
During this selection the widget uses the keymap tt(menuselect). Any
|
||||
key that is not defined in this keymap or that is bound to
|
||||
tt(undefined-key) is looked up in the keymap currently selected. This
|
||||
is used to ensure that the most important keys used during selection
|
||||
have sensible default (namely the cursor keys, return, and TAB). However,
|
||||
keys in the the tt(menuselect) keymap can be modified directly using the
|
||||
tt(bindkey) builtin command (see
|
||||
ifzman(zmanref(zshmodules))\
|
||||
ifnzman(noderef(The zle Module))\
|
||||
).
|
918
Src/Zle/complist.c
Normal file
918
Src/Zle/complist.c
Normal file
|
@ -0,0 +1,918 @@
|
|||
/*
|
||||
* complist.c - completion listing enhancements
|
||||
*
|
||||
* This file is part of zsh, the Z shell.
|
||||
*
|
||||
* Copyright (c) 1999 Sven Wischnowsky
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and to distribute modified versions of this software for any
|
||||
* purpose, provided that the above copyright notice and the following
|
||||
* two paragraphs appear in all copies of this software.
|
||||
*
|
||||
* In no event shall Sven Wischnowsky or the Zsh Development Group be liable
|
||||
* to any party for direct, indirect, special, incidental, or consequential
|
||||
* damages arising out of the use of this software and its documentation,
|
||||
* even if Sven Wischnowsky and the Zsh Development Group have been advised of
|
||||
* the possibility of such damage.
|
||||
*
|
||||
* Sven Wischnowsky and the Zsh Development Group specifically disclaim any
|
||||
* warranties, including, but not limited to, the implied warranties of
|
||||
* merchantability and fitness for a particular purpose. The software
|
||||
* provided hereunder is on an "as is" basis, and Sven Wischnowsky and the
|
||||
* Zsh Development Group have no obligation to provide maintenance,
|
||||
* support, updates, enhancements, or modifications.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "complist.mdh"
|
||||
#include "complist.pro"
|
||||
|
||||
|
||||
/* We use the parameters ZLS_COLORS and ZLS_COLOURS in the same way as
|
||||
* the color ls does. It's just that we don't support the `or' file
|
||||
* type. */
|
||||
|
||||
|
||||
static Widget w_menuselect;
|
||||
static Keymap mskeymap;
|
||||
|
||||
/* Indixes into the terminal string arrays. */
|
||||
|
||||
#define COL_NO 0
|
||||
#define COL_FI 1
|
||||
#define COL_DI 2
|
||||
#define COL_LN 3
|
||||
#define COL_PI 4
|
||||
#define COL_SO 5
|
||||
#define COL_BD 6
|
||||
#define COL_CD 7
|
||||
#define COL_EX 8
|
||||
#define COL_MI 9
|
||||
#define COL_LC 10
|
||||
#define COL_RC 11
|
||||
#define COL_EC 12
|
||||
#define COL_MA 13
|
||||
|
||||
#define NUM_COLS 14
|
||||
|
||||
/* Names of the terminal strings. */
|
||||
|
||||
static char *colnames[] = {
|
||||
"no", "fi", "di", "ln", "pi", "so", "bd", "cd", "ex", "mi",
|
||||
"lc", "rc", "ec", "ma", NULL
|
||||
};
|
||||
|
||||
/* Default values. */
|
||||
|
||||
static char *defcols[] = {
|
||||
"0", "0", "1;34", "1;36", "33", "1;35", "1;33", "1;33", "1;32", NULL,
|
||||
"\033[", "m", NULL, "7"
|
||||
};
|
||||
|
||||
/* This describes a terminal string for a filename extension. */
|
||||
|
||||
typedef struct extcol *Extcol;
|
||||
|
||||
struct extcol {
|
||||
char *ext; /* the extension */
|
||||
char *col; /* the terminal color string */
|
||||
Extcol next; /* the next one in the list */
|
||||
};
|
||||
|
||||
/* This holds all terminal strings. */
|
||||
|
||||
typedef struct listcols *Listcols;
|
||||
|
||||
struct listcols {
|
||||
char *cols[NUM_COLS]; /* strings for file types */
|
||||
Extcol exts; /* strings for extensions */
|
||||
};
|
||||
|
||||
/* This parses the value of a definition (the part after the `=').
|
||||
* The return value is a pointer to the character after it. */
|
||||
|
||||
static char *
|
||||
getcolval(char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = s; *s && *s != ':'; p++, s++) {
|
||||
if (*s == '\\' && s[1]) {
|
||||
switch (*++s) {
|
||||
case 'a': *p = '\007'; break;
|
||||
case 'n': *p = '\n'; break;
|
||||
case 'b': *p = '\b'; break;
|
||||
case 't': *p = '\t'; break;
|
||||
case 'v': *p = '\v'; break;
|
||||
case 'f': *p = '\f'; break;
|
||||
case 'r': *p = '\r'; break;
|
||||
case 'e': *p = '\033'; break;
|
||||
case '_': *p = ' '; break;
|
||||
case '?': *p = '\177'; break;
|
||||
default:
|
||||
if (*s >= '0' && *s <= '7') {
|
||||
int i = STOUC(*s);
|
||||
|
||||
if (*++s >= '0' && *s <= '7') {
|
||||
i = (i * 8) + STOUC(*s);
|
||||
if (*++s >= '0' && *s <= '7')
|
||||
i = (i * 8) + STOUC(*s);
|
||||
}
|
||||
*p = (char) i;
|
||||
} else
|
||||
*p = *s;
|
||||
}
|
||||
} else if (*s == '^') {
|
||||
if ((s[1] >= '@' && s[1] <= '_') ||
|
||||
(s[1] >= 'a' && s[1] <= 'z'))
|
||||
*p = (char) (STOUC(*s) & ~0x60);
|
||||
else if (s[1] == '?')
|
||||
*p = '\177';
|
||||
else {
|
||||
*p++ = *s;
|
||||
*p = s[1];
|
||||
}
|
||||
s++;
|
||||
} else
|
||||
*p = *s;
|
||||
}
|
||||
if (p != s)
|
||||
*p = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
/* This parses one definition. Return value is a pointer to the
|
||||
* character after it. */
|
||||
|
||||
static char *
|
||||
getcoldef(Listcols c, char *s)
|
||||
{
|
||||
if (*s == '*') {
|
||||
Extcol ec;
|
||||
char *n, *p;
|
||||
|
||||
/* This is for an extension. */
|
||||
|
||||
n = ++s;
|
||||
while (*s && *s != '=')
|
||||
s++;
|
||||
if (!*s )
|
||||
return s;
|
||||
*s++ = '\0';
|
||||
p = getcolval(s);
|
||||
if (*n) {
|
||||
ec = (Extcol) zhalloc(sizeof(*ec));
|
||||
ec->ext = n;
|
||||
ec->col = s;
|
||||
ec->next = c->exts;
|
||||
c->exts = ec;
|
||||
}
|
||||
if (*p)
|
||||
*p++ = '\0';
|
||||
return p;
|
||||
} else {
|
||||
char *n = s, *p, **nn;
|
||||
int i;
|
||||
|
||||
/* This is for a file type. */
|
||||
|
||||
while (*s && *s != '=')
|
||||
s++;
|
||||
if (!*s)
|
||||
return s;
|
||||
*s++ = '\0';
|
||||
for (i = 0, nn = colnames; *nn; i++, nn++)
|
||||
if (!strcmp(n ,*nn))
|
||||
break;
|
||||
p = getcolval(s);
|
||||
if (*nn)
|
||||
c->cols[i] = s;
|
||||
if (*p)
|
||||
*p++ = '\0';
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
/* This initializes the given terminal color structure. */
|
||||
|
||||
static int
|
||||
getcols(Listcols c)
|
||||
{
|
||||
char *s;
|
||||
int i;
|
||||
|
||||
if (!(s = getsparam("ZLS_COLORS")) &&
|
||||
!(s = getsparam("ZLS_COLOURS"))) {
|
||||
if (!c)
|
||||
return 1;
|
||||
for (i = 0; i < NUM_COLS; i++)
|
||||
c->cols[i] = "";
|
||||
|
||||
c->exts = NULL;
|
||||
return 1;
|
||||
}
|
||||
if (!c)
|
||||
return 0;
|
||||
/* We have one of the parameters, use it. */
|
||||
memset(c, 0, sizeof(*c));
|
||||
s = dupstring(s);
|
||||
while (*s)
|
||||
s = getcoldef(c, s);
|
||||
|
||||
/* Use default values for those that aren't set explicitly. */
|
||||
for (i = 0; i < NUM_COLS; i++)
|
||||
if (!c->cols[i])
|
||||
c->cols[i] = defcols[i];
|
||||
/* Default for missing files. */
|
||||
if (!c->cols[COL_MI])
|
||||
c->cols[COL_MI] = c->cols[COL_FI];
|
||||
|
||||
if (!c->cols[COL_EC]) {
|
||||
char *e = (char *) zhalloc(strlen(c->cols[COL_LC]) +
|
||||
strlen(c->cols[COL_NO]) +
|
||||
strlen(c->cols[COL_RC]) + 1);
|
||||
|
||||
/* If no `ec' was given, we is `<lc><no><rc>' as the default. */
|
||||
strcpy(e, c->cols[COL_LC]);
|
||||
strcat(e, c->cols[COL_NO]);
|
||||
strcat(e, c->cols[COL_RC]);
|
||||
c->cols[COL_EC] = e;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the terminal color string for the file with the given name and
|
||||
* file modes. */
|
||||
|
||||
static char *
|
||||
getcolstr(Listcols c, char *n, mode_t m)
|
||||
{
|
||||
Extcol e;
|
||||
|
||||
for (e = c->exts; e; e = e->next)
|
||||
if (strsfx(e->ext, n))
|
||||
return e->col;
|
||||
|
||||
if (S_ISDIR(m))
|
||||
return c->cols[COL_DI];
|
||||
else if (S_ISLNK(m))
|
||||
return c->cols[COL_LN];
|
||||
else if (S_ISFIFO(m))
|
||||
return c->cols[COL_PI];
|
||||
else if (S_ISSOCK(m))
|
||||
return c->cols[COL_SO];
|
||||
else if (S_ISBLK(m))
|
||||
return c->cols[COL_BD];
|
||||
else if (S_ISCHR(m))
|
||||
return c->cols[COL_CD];
|
||||
else if (S_ISREG(m) && (m & S_IXUGO))
|
||||
return c->cols[COL_EX];
|
||||
|
||||
return c->cols[COL_FI];
|
||||
}
|
||||
|
||||
/* Information about the list shown. */
|
||||
|
||||
static int noselect, mselect, inselect, mcol, mline, mcols, mlines;
|
||||
static Cmatch *mmatch, **mtab;
|
||||
static Cmgroup mgroup, *mgtab;
|
||||
|
||||
/* List the matches. Most of this is just taken from ilistmatches(),
|
||||
* of course. */
|
||||
|
||||
static int
|
||||
complistmatches(Hookdef dummy, Chdata dat)
|
||||
{
|
||||
Cmgroup amatches = dat->matches, g;
|
||||
Cmatch *p, m;
|
||||
Cexpl *e;
|
||||
int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0, opl = 0;
|
||||
int of = isset(LISTTYPES);
|
||||
int mc, ml = 0, cc, hasm = 0;
|
||||
struct listcols col;
|
||||
|
||||
if (minfo.asked == 2) {
|
||||
showinglist = 0;
|
||||
return (noselect = 1);
|
||||
}
|
||||
getcols(&col);
|
||||
|
||||
/* Set the cursor below the prompt. */
|
||||
if (inselect)
|
||||
clearflag = 0;
|
||||
trashzle();
|
||||
showinglist = listshown = 0;
|
||||
|
||||
clearflag = (isset(USEZLE) && !termflags &&
|
||||
complastprompt && *complastprompt);
|
||||
|
||||
for (g = amatches; g; g = g->next) {
|
||||
char **pp = g->ylist;
|
||||
int nl = 0, l;
|
||||
|
||||
if (pp) {
|
||||
/* We have an ylist, lets see, if it contains newlines. */
|
||||
while (!nl && *pp)
|
||||
nl = !!strchr(*pp++, '\n');
|
||||
|
||||
pp = g->ylist;
|
||||
if (nl) {
|
||||
/* Yup, there are newlines, count lines. */
|
||||
char *nlptr, *sptr;
|
||||
|
||||
g->flags |= CGF_LINES;
|
||||
noselect = 1;
|
||||
while ((sptr = *pp)) {
|
||||
while (sptr && *sptr) {
|
||||
nlines += (nlptr = strchr(sptr, '\n'))
|
||||
? 1 + (nlptr-sptr)/columns
|
||||
: strlen(sptr)/columns;
|
||||
sptr = nlptr ? nlptr+1 : NULL;
|
||||
}
|
||||
nlines++;
|
||||
pp++;
|
||||
}
|
||||
nlines--;
|
||||
} else {
|
||||
while (*pp) {
|
||||
if ((l = strlen(*pp)) > longest)
|
||||
longest = l;
|
||||
nlist++;
|
||||
pp++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (p = g->matches; (m = *p); p++) {
|
||||
if (!(m->flags & CMF_NOLIST)) {
|
||||
if ((l = niceztrlen(m->str)) > longest)
|
||||
longest = l;
|
||||
nlist++;
|
||||
} else
|
||||
noselect = 1;
|
||||
}
|
||||
}
|
||||
if ((e = g->expls)) {
|
||||
while (*e) {
|
||||
if ((*e)->count)
|
||||
nlines += 1 + printfmt((*e)->str, (*e)->count, 0);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
longest += 2 + of;
|
||||
if ((ncols = (columns + 1) / longest)) {
|
||||
for (g = amatches; g; g = g->next)
|
||||
nlines += (g->lcount + ncols - 1) / ncols;
|
||||
} else {
|
||||
ncols = 1;
|
||||
opl = 1;
|
||||
for (g = amatches; g; g = g->next) {
|
||||
char **pp = g->ylist;
|
||||
|
||||
if (pp) {
|
||||
if (!(g->flags & CGF_LINES)) {
|
||||
while (*pp) {
|
||||
nlines += 1 + (strlen(*pp) / columns);
|
||||
pp++;
|
||||
}
|
||||
}
|
||||
} else
|
||||
for (p = g->matches; (m = *p); p++)
|
||||
if (!(m->flags & CMF_NOLIST))
|
||||
nlines += 1 + ((1 + niceztrlen(m->str)) / columns);
|
||||
}
|
||||
}
|
||||
|
||||
/* Maybe we have to ask if the user wants to see the list. */
|
||||
if ((!minfo.cur || !minfo.asked) &&
|
||||
((complistmax && nlist > complistmax) ||
|
||||
(!complistmax && nlines >= lines))) {
|
||||
int qup;
|
||||
zsetterm();
|
||||
qup = printfmt("zsh: do you wish to see all %n possibilities? ", nlist, 1);
|
||||
fflush(shout);
|
||||
if (getzlequery() != 'y') {
|
||||
if (clearflag) {
|
||||
putc('\r', shout);
|
||||
tcmultout(TCUP, TCMULTUP, qup);
|
||||
if (tccan(TCCLEAREOD))
|
||||
tcout(TCCLEAREOD);
|
||||
tcmultout(TCUP, TCMULTUP, nlnct);
|
||||
} else
|
||||
putc('\n', shout);
|
||||
noselect = 1;
|
||||
if (minfo.cur)
|
||||
minfo.asked = 2;
|
||||
return 1;
|
||||
}
|
||||
if (clearflag) {
|
||||
putc('\r', shout);
|
||||
tcmultout(TCUP, TCMULTUP, qup);
|
||||
if (tccan(TCCLEAREOD))
|
||||
tcout(TCCLEAREOD);
|
||||
} else
|
||||
putc('\n', shout);
|
||||
settyinfo(&shttyinfo);
|
||||
if (minfo.cur)
|
||||
minfo.asked = 1;
|
||||
}
|
||||
if (mselect >= 0) {
|
||||
int i;
|
||||
|
||||
i = ncols * nlines;
|
||||
free(mtab);
|
||||
mtab = (Cmatch **) zalloc(i * sizeof(Cmatch **));
|
||||
memset(mtab, 0, i * sizeof(Cmatch **));
|
||||
free(mgtab);
|
||||
mgtab = (Cmgroup *) zalloc(i * sizeof(Cmgroup));
|
||||
memset(mgtab, 0, i * sizeof(Cmgroup));
|
||||
mcols = ncols;
|
||||
mlines = nlines;
|
||||
}
|
||||
/* Now print the matches. */
|
||||
g = amatches;
|
||||
while (g) {
|
||||
char **pp = g->ylist;
|
||||
|
||||
if ((e = g->expls)) {
|
||||
while (*e) {
|
||||
if ((*e)->count) {
|
||||
if (pnl) {
|
||||
putc('\n', shout);
|
||||
pnl = 0;
|
||||
ml++;
|
||||
}
|
||||
ml += printfmt((*e)->str, (*e)->count, 1);
|
||||
pnl = 1;
|
||||
}
|
||||
e++;
|
||||
}
|
||||
}
|
||||
if (pp && *pp) {
|
||||
if (pnl) {
|
||||
putc('\n', shout);
|
||||
pnl = 0;
|
||||
ml++;
|
||||
}
|
||||
if (g->flags & CGF_LINES) {
|
||||
while (*pp) {
|
||||
zputs(*pp, shout);
|
||||
if (*++pp)
|
||||
putc('\n', shout);
|
||||
}
|
||||
} else {
|
||||
int n = g->lcount, nl = (n + ncols - 1) / ncols, nc = nl, i, a;
|
||||
char **pq;
|
||||
|
||||
while (n && nl--) {
|
||||
i = ncols;
|
||||
mc = 0;
|
||||
pq = pp;
|
||||
while (n && i--) {
|
||||
if (pq - g->ylist >= g->lcount)
|
||||
break;
|
||||
zputs(*pq, shout);
|
||||
if (i) {
|
||||
a = longest - strlen(*pq);
|
||||
while (a--)
|
||||
putc(' ', shout);
|
||||
}
|
||||
pq += nc;
|
||||
n--;
|
||||
}
|
||||
if (n) {
|
||||
putc('\n', shout);
|
||||
ml++;
|
||||
}
|
||||
pp++;
|
||||
}
|
||||
}
|
||||
} else if (g->lcount) {
|
||||
int n = g->lcount, nl = (n + ncols - 1) / ncols, nc = nl, i, j, a = 0;
|
||||
int zt;
|
||||
Cmatch *q;
|
||||
|
||||
if (n && pnl) {
|
||||
putc('\n', shout);
|
||||
pnl = 0;
|
||||
ml++;
|
||||
}
|
||||
for (p = skipnolist(g->matches); n && nl--;) {
|
||||
i = ncols;
|
||||
mc = 0;
|
||||
q = p;
|
||||
while (n && i--) {
|
||||
fputs(col.cols[COL_LC], shout);
|
||||
if (!(m = *q)) {
|
||||
fputs(col.cols[COL_MI], shout);
|
||||
fputs(col.cols[COL_RC], shout);
|
||||
a = longest - 2;
|
||||
while (a--)
|
||||
putc(' ', shout);
|
||||
fputs(col.cols[COL_EC], shout);
|
||||
break;
|
||||
}
|
||||
hasm = 1;
|
||||
if (mselect >= 0) {
|
||||
mtab[mc + (ncols * ml)] = q;
|
||||
mgtab[mc + (ncols * ml)] = g;
|
||||
}
|
||||
if (m->gnum == mselect) {
|
||||
mcol = mc;
|
||||
mline = ml;
|
||||
mmatch = q;
|
||||
mgroup = g;
|
||||
cc = COL_MA;
|
||||
} else
|
||||
cc = -1;
|
||||
if (m->flags & CMF_FILE) {
|
||||
struct stat buf;
|
||||
char *pb;
|
||||
|
||||
pb = (char *) zhalloc((m->prpre ? strlen(m->prpre) : 0) +
|
||||
3 + strlen(m->str));
|
||||
sprintf(pb, "%s%s", (m->prpre ? m->prpre : "./"),
|
||||
m->str);
|
||||
|
||||
zt = ztat(pb, &buf, 1);
|
||||
if (cc >= 0)
|
||||
fputs(col.cols[cc], shout);
|
||||
else if (zt)
|
||||
fputs(col.cols[COL_NO], shout);
|
||||
else
|
||||
fputs(getcolstr(&col, pb, buf.st_mode), shout);
|
||||
fputs(col.cols[COL_RC], shout);
|
||||
nicezputs(m->str, shout);
|
||||
if (zt)
|
||||
putc(' ', shout);
|
||||
else
|
||||
putc(file_type(buf.st_mode), shout);
|
||||
} else {
|
||||
fputs(col.cols[cc >= 0 ? cc : COL_NO], shout);
|
||||
fputs(col.cols[COL_RC], shout);
|
||||
nicezputs(m->str, shout);
|
||||
if (of)
|
||||
putc(' ', shout);
|
||||
}
|
||||
a = longest - niceztrlen(m->str) - 2 - of;
|
||||
while (a--)
|
||||
putc(' ', shout);
|
||||
fputs(col.cols[COL_EC], shout);
|
||||
if (i) {
|
||||
fputs(col.cols[COL_LC], shout);
|
||||
fputs(col.cols[COL_NO], shout);
|
||||
fputs(col.cols[COL_RC], shout);
|
||||
fputs(" ", shout);
|
||||
fputs(col.cols[COL_EC], shout);
|
||||
}
|
||||
if (--n)
|
||||
for (j = nc; j && *q; j--)
|
||||
q = skipnolist(q + 1);
|
||||
mc++;
|
||||
}
|
||||
if (i > 0) {
|
||||
fputs(col.cols[COL_LC], shout);
|
||||
fputs(col.cols[COL_MI], shout);
|
||||
fputs(col.cols[COL_RC], shout);
|
||||
a = longest - 2;
|
||||
while (a--)
|
||||
putc(' ', shout);
|
||||
fputs(col.cols[COL_EC], shout);
|
||||
}
|
||||
if (n) {
|
||||
putc('\n', shout);
|
||||
ml++;
|
||||
if (n && nl)
|
||||
p = skipnolist(p + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (g->lcount)
|
||||
pnl = 1;
|
||||
g = g->next;
|
||||
}
|
||||
|
||||
if (clearflag) {
|
||||
/* Move the cursor up to the prompt, if always_last_prompt *
|
||||
* is set and all that... */
|
||||
if ((nlines += nlnct - 1) < lines) {
|
||||
tcmultout(TCUP, TCMULTUP, nlines);
|
||||
showinglist = -1;
|
||||
listshown = 1;
|
||||
} else
|
||||
clearflag = 0, putc('\n', shout);
|
||||
} else
|
||||
putc('\n', shout);
|
||||
if (!hasm || nlines >= lines)
|
||||
noselect = 1;
|
||||
return noselect;
|
||||
}
|
||||
|
||||
typedef struct menustack *Menustack;
|
||||
|
||||
struct menustack {
|
||||
Menustack prev;
|
||||
char *line;
|
||||
int cs;
|
||||
struct menuinfo info;
|
||||
};
|
||||
|
||||
static int
|
||||
domenuselect(Hookdef dummy, Chdata dat)
|
||||
{
|
||||
Cmatch **p;
|
||||
Cmgroup *pg;
|
||||
Thingy cmd;
|
||||
Menustack u = NULL;
|
||||
int i = 0;
|
||||
char *s;
|
||||
|
||||
if (getcols(NULL) || (dummy && (!(s = getsparam("SELECTMIN")) ||
|
||||
(dat && dat->num < atoi(s)))))
|
||||
return 1;
|
||||
|
||||
selectlocalmap(mskeymap);
|
||||
noselect = 0;
|
||||
mselect = (*(minfo.cur))->gnum;
|
||||
for (;;) {
|
||||
showinglist = -2;
|
||||
zrefresh();
|
||||
inselect = 1;
|
||||
if (noselect)
|
||||
break;
|
||||
if (!i) {
|
||||
i = mcols * mlines;
|
||||
while (i--)
|
||||
if (mtab[i])
|
||||
break;
|
||||
if (!i)
|
||||
break;
|
||||
i = 1;
|
||||
}
|
||||
p = mtab + mcol + (mline * mcols);
|
||||
pg = mgtab + mcol + (mline * mcols);
|
||||
minfo.cur = *p;
|
||||
minfo.group = *pg;
|
||||
|
||||
getk:
|
||||
|
||||
if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak) ||
|
||||
cmd == Th(z_acceptline))
|
||||
break;
|
||||
else if (cmd == Th(z_acceptandhold) ||
|
||||
cmd == Th(z_acceptandmenucomplete)) {
|
||||
Menustack s = (Menustack) zhalloc(sizeof(*s));
|
||||
|
||||
s->prev = u;
|
||||
u = s;
|
||||
s->line = dupstring((char *) line);
|
||||
s->cs = cs;
|
||||
memcpy(&(s->info), &minfo, sizeof(struct menuinfo));
|
||||
acceptlast();
|
||||
do_menucmp(0);
|
||||
mselect = (*(minfo.cur))->gnum;
|
||||
continue;
|
||||
} else if (cmd == Th(z_undo)) {
|
||||
int l;
|
||||
|
||||
if (!u)
|
||||
goto getk;
|
||||
|
||||
cs = 0;
|
||||
foredel(ll);
|
||||
spaceinline(l = strlen(u->line));
|
||||
strncpy((char *) line, u->line, l);
|
||||
cs = u->cs;
|
||||
memcpy(&minfo, &(u->info), sizeof(struct menuinfo));
|
||||
p = &(minfo.cur);
|
||||
u = u->prev;
|
||||
} else if (cmd == Th(z_redisplay)) {
|
||||
redisplay(zlenoargs);
|
||||
continue;
|
||||
} else if (cmd == Th(z_clearscreen)) {
|
||||
clearscreen(zlenoargs);
|
||||
continue;
|
||||
} else if (cmd == Th(z_downhistory) ||
|
||||
cmd == Th(z_downlineorhistory) ||
|
||||
cmd == Th(z_downlineorsearch) ||
|
||||
cmd == Th(z_vidownlineorhistory)) {
|
||||
do {
|
||||
if (mline == mlines - 1) {
|
||||
p -= mline * mcols;
|
||||
mline = 0;
|
||||
} else {
|
||||
mline++;
|
||||
p += mcols;
|
||||
}
|
||||
} while (!*p);
|
||||
} else if (cmd == Th(z_uphistory) ||
|
||||
cmd == Th(z_uplineorhistory) ||
|
||||
cmd == Th(z_uplineorsearch) ||
|
||||
cmd == Th(z_viuplineorhistory)) {
|
||||
do {
|
||||
if (!mline) {
|
||||
mline = mlines - 1;
|
||||
p += mline * mcols;
|
||||
} else {
|
||||
mline--;
|
||||
p -= mcols;
|
||||
}
|
||||
} while (!*p);
|
||||
} else if (cmd == Th(z_forwardchar) || cmd == Th(z_viforwardchar)) {
|
||||
do {
|
||||
if (mcol == mcols - 1) {
|
||||
p -= mcol;
|
||||
mcol = 0;
|
||||
} else {
|
||||
mcol++;
|
||||
p++;
|
||||
}
|
||||
} while (!*p);
|
||||
} else if (cmd == Th(z_backwardchar) || cmd == Th(z_vibackwardchar)) {
|
||||
do {
|
||||
if (!mcol) {
|
||||
mcol = mcols - 1;
|
||||
p += mcol;
|
||||
} else {
|
||||
mcol--;
|
||||
p--;
|
||||
}
|
||||
} while (!*p);
|
||||
} else if (cmd == Th(z_beginningofbufferorhistory) ||
|
||||
cmd == Th(z_beginningofline) ||
|
||||
cmd == Th(z_beginningoflinehist) ||
|
||||
cmd == Th(z_vibeginningofline)) {
|
||||
p -= mcol;
|
||||
mcol = 0;
|
||||
while (!*p) {
|
||||
mcol++;
|
||||
p++;
|
||||
}
|
||||
} else if (cmd == Th(z_endofbufferorhistory) ||
|
||||
cmd == Th(z_endofline) ||
|
||||
cmd == Th(z_endoflinehist) ||
|
||||
cmd == Th(z_viendofline)) {
|
||||
p += mcols - mcol - 1;
|
||||
mcol = mcols - 1;
|
||||
while (!*p) {
|
||||
mcol--;
|
||||
p--;
|
||||
}
|
||||
} else if (cmd == Th(z_forwardword) ||
|
||||
cmd == Th(z_emacsforwardword) ||
|
||||
cmd == Th(z_viforwardword) ||
|
||||
cmd == Th(z_viforwardwordend)) {
|
||||
Cmgroup g = *pg;
|
||||
int ol = mline;
|
||||
|
||||
do {
|
||||
if (mline == mlines - 1) {
|
||||
p -= mline * mcols;
|
||||
pg -= mline * mcols;
|
||||
mline = 0;
|
||||
} else {
|
||||
mline++;
|
||||
p += mcols;
|
||||
pg += mcols;
|
||||
}
|
||||
} while (ol != mline && (*pg == g || !*pg));
|
||||
} else if (cmd == Th(z_backwardword) ||
|
||||
cmd == Th(z_emacsbackwardword) ||
|
||||
cmd == Th(z_vibackwardword)) {
|
||||
Cmgroup g = *pg;
|
||||
int ol = mline;
|
||||
|
||||
do {
|
||||
if (!mline) {
|
||||
mline = mlines - 1;
|
||||
p += mline * mcols;
|
||||
pg += mline * mcols;
|
||||
} else {
|
||||
mline--;
|
||||
p -= mcols;
|
||||
pg -= mcols;
|
||||
}
|
||||
} while (ol != mline && (*pg == g || !*pg));
|
||||
} else if (cmd == Th(z_completeword) ||
|
||||
cmd == Th(z_expandorcomplete) ||
|
||||
cmd == Th(z_expandorcompleteprefix) ||
|
||||
cmd == Th(z_menucomplete) ||
|
||||
cmd == Th(z_menuexpandorcomplete) ||
|
||||
!strcmp(cmd->nam, "menu-select") ||
|
||||
!strcmp(cmd->nam, "complete-word") ||
|
||||
!strcmp(cmd->nam, "expand-or-complete") ||
|
||||
!strcmp(cmd->nam, "expand-or-complete-prefix") ||
|
||||
!strcmp(cmd->nam, "menu-complete") ||
|
||||
!strcmp(cmd->nam, "menu-expand-or-complete")) {
|
||||
do_menucmp(0);
|
||||
mselect = (*(minfo.cur))->gnum;
|
||||
continue;
|
||||
} else if (cmd == Th(z_reversemenucomplete) ||
|
||||
!strcmp(cmd->nam, "reverse-menu-complete")) {
|
||||
reversemenucomplete(zlenoargs);
|
||||
mselect = (*(minfo.cur))->gnum;
|
||||
continue;
|
||||
} else {
|
||||
ungetkeycmd();
|
||||
break;
|
||||
}
|
||||
do_single(**p);
|
||||
mselect = (**p)->gnum;
|
||||
}
|
||||
selectlocalmap(NULL);
|
||||
mselect = -1;
|
||||
inselect = 0;
|
||||
if (!noselect) {
|
||||
showinglist = -2;
|
||||
zrefresh();
|
||||
}
|
||||
return noselect;
|
||||
}
|
||||
|
||||
/* The widget function. */
|
||||
|
||||
static int
|
||||
menuselect(char **args)
|
||||
{
|
||||
int d = 0;
|
||||
|
||||
if (!minfo.cur) {
|
||||
menucomplete(args);
|
||||
if ((minfo.cur && minfo.asked == 2) || getsparam("ZLS_SELECT"))
|
||||
return 0;
|
||||
d = 1;
|
||||
}
|
||||
if (minfo.cur && (minfo.asked == 2 || domenuselect(NULL, NULL)) && !d)
|
||||
menucomplete(args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
setup_complist(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
boot_complist(Module m)
|
||||
{
|
||||
mtab = NULL;
|
||||
mgtab = NULL;
|
||||
mselect = -1;
|
||||
inselect = 0;
|
||||
|
||||
w_menuselect = addzlefunction("menu-select", menuselect,
|
||||
ZLE_MENUCMP|ZLE_KEEPSUFFIX|ZLE_ISCOMP);
|
||||
if (!w_menuselect) {
|
||||
zwarnnam(m->nam, "name clash when adding ZLE function `menu-select'",
|
||||
NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
addhookfunc("list_matches", (Hookfn) complistmatches);
|
||||
addhookfunc("menu_start", (Hookfn) domenuselect);
|
||||
mskeymap = newkeymap(NULL, "menuselect");
|
||||
linkkeymap(mskeymap, "menuselect", 1);
|
||||
bindkey(mskeymap, "\t", refthingy(t_completeword), NULL);
|
||||
bindkey(mskeymap, "\n", refthingy(t_acceptline), NULL);
|
||||
bindkey(mskeymap, "\r", refthingy(t_acceptline), NULL);
|
||||
bindkey(mskeymap, "\33[A", refthingy(t_uplineorhistory), NULL);
|
||||
bindkey(mskeymap, "\33[B", refthingy(t_downlineorhistory), NULL);
|
||||
bindkey(mskeymap, "\33[C", refthingy(t_forwardchar), NULL);
|
||||
bindkey(mskeymap, "\33[D", refthingy(t_backwardchar), NULL);
|
||||
bindkey(mskeymap, "\33OA", refthingy(t_uplineorhistory), NULL);
|
||||
bindkey(mskeymap, "\33OB", refthingy(t_downlineorhistory), NULL);
|
||||
bindkey(mskeymap, "\33OC", refthingy(t_forwardchar), NULL);
|
||||
bindkey(mskeymap, "\33OD", refthingy(t_backwardchar), NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
/**/
|
||||
int
|
||||
cleanup_complist(Module m)
|
||||
{
|
||||
free(mtab);
|
||||
free(mgtab);
|
||||
|
||||
deletezlefunction(w_menuselect);
|
||||
deletehookfunc("list_matches", (Hookfn) complistmatches);
|
||||
deletehookfunc("menu_start", (Hookfn) domenuselect);
|
||||
unlinkkeymap("menuselect", 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
finish_complist(Module m)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
3
Src/Zle/complist.mdd
Normal file
3
Src/Zle/complist.mdd
Normal file
|
@ -0,0 +1,3 @@
|
|||
moddeps="comp1 zle"
|
||||
|
||||
objects="complist.o"
|
Loading…
Reference in a new issue