mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-06-17 09:08:04 +02:00
zsh-3.1.5-pws-7
This commit is contained in:
parent
7a40d6c258
commit
850fb2e7f9
35 changed files with 1137 additions and 507 deletions
Config
Doc/Zsh
Etc
Functions
Misc
Src
patchlist.txt
|
@ -27,5 +27,5 @@
|
|||
# This must also serve as a shell script, so do not add spaces around the
|
||||
# `=' signs.
|
||||
|
||||
VERSION=3.1.5-pws-6
|
||||
VERSION_DATE='January 28, 1998'
|
||||
VERSION=3.1.5-pws-7
|
||||
VERSION_DATE='February 5, 1999'
|
||||
|
|
|
@ -913,7 +913,9 @@ is unset, the other will automatically be unset too. There is no way
|
|||
of untying the variables without unsetting them, or converting the
|
||||
type of one them with another tt(typeset) command; tt(+T) does not work,
|
||||
assigning an array to var(SCALAR) is an error, and assigning a scalar
|
||||
to var(array) sets it to be a single-element array.
|
||||
to var(array) sets it to be a single-element array. Note that
|
||||
both tt(typeset -xT ...) and tt(export -T ...) work, but only the
|
||||
scalar will be marked for export.
|
||||
|
||||
If no var(name) is present, the names and values of all parameters are
|
||||
printed. In this case the attribute flags restrict the the display to
|
||||
|
@ -1072,10 +1074,16 @@ Each named parameter is unset.
|
|||
Local parameters remain local even if unset; they appear unset within scope,
|
||||
but the previous value will still reappear when the scope ends.
|
||||
|
||||
If the tt(-m) flag is specified the
|
||||
arguments are taken as patterns (should be quoted) and all parameters
|
||||
with matching names are unset. tt(unset -f) is equivalent to
|
||||
tt(unfunction).
|
||||
Individual elements of associative array parameters may be unset by using
|
||||
subscript syntax on var(name), which should be quoted (or the entire command
|
||||
prefixed with tt(noglob)) to protect the subscript from filename generation.
|
||||
|
||||
If the tt(-m) flag is specified the arguments are taken as patterns (should
|
||||
be quoted) and all parameters with matching names are unset. Note that this
|
||||
cannot be used when unsetting associative array elements, as the subscript
|
||||
will be treated as part of the pattern.
|
||||
|
||||
tt(unset -f) is equivalent to tt(unfunction).
|
||||
)
|
||||
findex(unsetopt)
|
||||
cindex(options, unsetting)
|
||||
|
|
|
@ -32,6 +32,7 @@ menu(Extended Completion)
|
|||
menu(Matching Control)
|
||||
menu(Example)
|
||||
endmenu()
|
||||
|
||||
texinode(Command Flags)(Option Flags)()(Programmable Completion)
|
||||
sect(Command Flags)
|
||||
Completion of the arguments of a command may be different for each
|
||||
|
@ -49,18 +50,20 @@ pathname containing slashes and no completion definition is found, the
|
|||
search is retried with the last pathname component. If the command starts
|
||||
with a tt(=), completion is tried with the pathname of the command.
|
||||
|
||||
The strings may also be patterns (i.e. they may contain an unquoted
|
||||
occurrence of characters used to form patterns in the shell). When
|
||||
completion is attempted, the shell first tries all such pattern compctls.
|
||||
If one matches the command name on the line or if the pathname of the
|
||||
command on the line matches a pattern, it is used. The patterns are tested
|
||||
in reverse order, i.e. the pattern compctl defined last overrides all
|
||||
previously defined pattern compctls. Unless the option list of that compctl
|
||||
contains an tt(-t) flag with a \tt(c) character, no more compctls are tried.
|
||||
Any of the var(command) strings may be patterns of the form normally
|
||||
used for filename generation. These should be be quoted to protect them
|
||||
from immediate expansion; for example the command string tt('foo*')
|
||||
arranges for completion of the words of any command beginning with
|
||||
tt(foo). When completion is attempted, all pattern completions are
|
||||
tried in the reverse order of their definition until one matches. By
|
||||
default, completion then procedes as normal, i.e. the shell will try to
|
||||
generate more matches for the specific command on the command line; this
|
||||
can be overridden by including tt(-tn) in the flags for the pattern
|
||||
completion.
|
||||
|
||||
Note that aliases
|
||||
are expanded before the command name is determined unless the
|
||||
tt(COMPLETE_ALIASES) option is set. Commands should not be combined
|
||||
tt(COMPLETE_ALIASES) option is set. Commands may not be combined
|
||||
with the tt(-C), tt(-D) or tt(-T) flags.
|
||||
)
|
||||
item(tt(-C))(
|
||||
|
@ -76,8 +79,8 @@ been issued, filenames are completed.
|
|||
)
|
||||
item(tt(-T))(
|
||||
supplies completion flags to be used before any other processing is
|
||||
done, even those given to specific commands with other compctl
|
||||
definitions. This is especially useful when combined with extended
|
||||
done, even before processing for tt(compctl)s defined for specific
|
||||
commands. This is especially useful when combined with extended
|
||||
completion (the tt(-x) flag, see noderef(Extended Completion) below).
|
||||
Using this flag you can define default behavior
|
||||
which will apply to all commands without exception, or you can alter
|
||||
|
@ -85,10 +88,12 @@ the standard behavior for all commands. For example, if your access
|
|||
to the user database is too slow and/or it contains too many users (so
|
||||
that completion after `tt(~)' is too slow to be usable), you can use
|
||||
|
||||
nofill(tt(compctl -Tx 'C[0,*/*]' -f - 's[~]' -k friends -S/ -tn))
|
||||
indent(
|
||||
tt(compctl -T -x 'C[0,*/*]' -f - 's[~]' -k friends -S/ -tn)
|
||||
)
|
||||
|
||||
to complete the strings in the array tt(friends) after a `tt(~)'.
|
||||
The first argument is necessary so that this form of ~-completion is
|
||||
The tt(C[...]) argument is necessary so that this form of ~-completion is
|
||||
not tried after the directory name is finished.
|
||||
)
|
||||
item(tt(-L))(
|
||||
|
@ -111,7 +116,8 @@ the default. In other words, completion will subsequently use the
|
|||
options specified by the tt(-D) flag.
|
||||
|
||||
The form with tt(-M) as the first and only option defines global
|
||||
matching specifications described below in noderef(Matching Control).
|
||||
matching specifications, as described below in noderef(Matching Control).
|
||||
|
||||
texinode(Option Flags)(Alternative Completion)(Command Flags)(Programmable Completion)
|
||||
sect(Option Flags)
|
||||
startlist()
|
||||
|
@ -136,6 +142,7 @@ menu(Simple Flags)
|
|||
menu(Flags with Arguments)
|
||||
menu(Control Flags)
|
||||
endmenu()
|
||||
|
||||
texinode(Simple Flags)(Flags with Arguments)()(Option Flags)
|
||||
subsect(Simple Flags)
|
||||
These produce completion lists made up by the shell itself:
|
||||
|
@ -234,6 +241,7 @@ item(tt(-u))(
|
|||
User names.
|
||||
)
|
||||
enditem()
|
||||
|
||||
texinode(Flags with Arguments)(Control Flags)(Simple Flags)(Option Flags)
|
||||
subsect(Flags with Arguments)
|
||||
These have user supplied arguments to determine how the list of
|
||||
|
@ -248,8 +256,10 @@ of space- or comma-separated values in parentheses, in which any
|
|||
delimiter may be escaped with a backslash; in this case the argument
|
||||
should be quoted. For example,
|
||||
|
||||
indent(
|
||||
nofill(tt(compctl -k "(cputime filesize datasize stacksize
|
||||
coredumpsize resident descriptors)" limit))
|
||||
coredumpsize resident descriptors)" limit))
|
||||
)
|
||||
)
|
||||
item(tt(-g) var(globstring))(
|
||||
The var(globstring) is expanded using filename globbing; it should be
|
||||
|
@ -282,8 +292,10 @@ should not be made local to the function. From such a function the
|
|||
command line can be accessed with the tt(-c) and tt(-l) flags to
|
||||
the tt(read) builtin. For example,
|
||||
|
||||
indent(
|
||||
nofill(tt(function whoson { reply=(`users`); }
|
||||
compctl -K whoson talk))
|
||||
)
|
||||
|
||||
completes only logged-on users after `tt(talk)'. Note that `tt(whoson)' must
|
||||
return an array, so `tt(reply=`users`)' would be incorrect.
|
||||
|
@ -295,12 +307,15 @@ zero or negative the whole history is searched and if var(pattern) is
|
|||
the empty string all words are taken (as with `tt(*)'). A typical
|
||||
use is
|
||||
|
||||
nofill(tt(compctl -D -f PLUS() -H 0 ''))
|
||||
indent(
|
||||
tt(compctl -D -f PLUS() -H 0 '')
|
||||
)
|
||||
|
||||
which forces completion to look back in the history list for a word if
|
||||
no filename matches.
|
||||
)
|
||||
enditem()
|
||||
|
||||
texinode(Control Flags)()(Flags with Arguments)(Option Flags)
|
||||
subsect(Control Flags)
|
||||
These do not directly specify types of name to be completed, but
|
||||
|
@ -322,7 +337,9 @@ The var(prefix) is inserted just before the completed string; any
|
|||
initial part already typed will be completed and the whole var(prefix)
|
||||
ignored for completion purposes. For example,
|
||||
|
||||
nofill(tt(compctl -j -P "%" kill))
|
||||
indent(
|
||||
tt(compctl -j -P "%" kill)
|
||||
)
|
||||
|
||||
inserts a `%' after the kill command and then completes job names.
|
||||
)
|
||||
|
@ -337,20 +354,23 @@ With directory var(file-prefix): for command, file, directory and
|
|||
globbing completion (options tt(-c), tt(-f), tt(-/), tt(-g)), the file
|
||||
prefix is implicitly added in front of the completion. For example,
|
||||
|
||||
nofill(tt(compctl -/ -W ~/Mail maildirs))
|
||||
indent(
|
||||
tt(compctl -/ -W ~/Mail maildirs)
|
||||
)
|
||||
|
||||
completes any subdirectories to any depth beneath the directory
|
||||
tt(~/Mail), although that prefix does not appear on the command line.
|
||||
The var(suffix) may also be of the form accepted by the tt(-k) flag, i.e.
|
||||
the name of an array or a literal list in parenthesis. In this cases all
|
||||
words are used as prefixes.
|
||||
The var(file-prefix) may also be of the form accepted by the tt(-k)
|
||||
flag, i.e. the name of an array or a literal list in parenthesis. In
|
||||
this case all the directories in the list will be searched for
|
||||
possible completions.
|
||||
)
|
||||
item(tt(-q))(
|
||||
If used with a suffix as specified by the tt(-S) option, this
|
||||
causes the suffix to be removed if the next character typed is a blank
|
||||
or does not insert anything or if the suffix consists of only one character
|
||||
and the next character typed is the same character (the same rule as used
|
||||
for the tt(AUTO_REMOVE_SLASH) option). The option is most useful for list
|
||||
and the next character typed is the same character; this the same rule used
|
||||
for the tt(AUTO_REMOVE_SLASH) option. The option is most useful for list
|
||||
separators (comma, colon, etc.).
|
||||
)
|
||||
item(tt(-l) var(cmd))(
|
||||
|
@ -365,7 +385,9 @@ option. If the var(cmd) string is empty the first word in the range
|
|||
is instead taken as the command name, and command name completion
|
||||
performed on the first word in the range. For example,
|
||||
|
||||
nofill(tt(compctl -x 'r[-exec,;]' -l '' -- find))
|
||||
indent(
|
||||
tt(compctl -x 'r[-exec,;]' -l '' -- find)
|
||||
)
|
||||
|
||||
completes arguments between `tt(-exec)' and the following `tt(;)' (or the end
|
||||
of the command line if there is no such string) as if they were
|
||||
|
@ -417,33 +439,52 @@ expansion following the usual rules for strings in double quotes.
|
|||
The expansion will be carried out after any functions are called for
|
||||
the tt(-K) or tt(-y) options, allowing them to set variables.
|
||||
)
|
||||
item(tt(-J))(
|
||||
This gives the name of the group the matches should be placed in. Groups
|
||||
are listed and sorted separately. Also, menucompletion will offer the matches
|
||||
in the groups in the order, in which the groups were defined. If no group
|
||||
name is explicitly given, the matches are stored in a group named var(default).
|
||||
The first time a group name is encountered, a group with that name is created.
|
||||
After that all matches with the same group name are stored in that group.
|
||||
)
|
||||
item(tt(-V))(
|
||||
Like tt(-J), but the matches in the group will not be sorted in the listing and
|
||||
with menucompletion. These unsorted groups are in a different name space than
|
||||
the sorted ones. I.e. it is possible to have a sorted and a unsorted group
|
||||
with the same name and the matches in those groups will not be mixed.
|
||||
)
|
||||
item(tt(-t) var(continue))(
|
||||
The var(continue)-string contains a character that specifies which set
|
||||
of completion flags should be used next. Normally those of the next
|
||||
matching compctl are used, i.e. pattern compctls and normal compctls
|
||||
after tt(-T) and after a pattern compctl. If var(continue) is the
|
||||
character tt(PLUS()) the flags for the next alternative completion
|
||||
(see below) are used. The characters tt(-) and tt(x) can be used in
|
||||
sub-lists for extended completion (see below). They will make the
|
||||
completion code use the flag list after the next tt(-) (if the
|
||||
corresponding pattern matches) and the default flag list (those before
|
||||
the tt(-x)), respectively. if var(continue) is the character tt(n) no
|
||||
other flag lists are used, i.e. the generation of matches stops
|
||||
immediately.
|
||||
The var(continue)-string contains a character that specifies which set
|
||||
of completion flags should be used next. It is useful:
|
||||
|
||||
(i) With tt(-T), or when trying a list of pattern completions, when
|
||||
tt(compctl) would usually continue with ordinary processing after
|
||||
finding matches; this can be suppressed with `tt(-tn)'.
|
||||
|
||||
(ii) With a list of alternatives separated by tt(+), when tt(compctl)
|
||||
would normally stop when one of the alternatives generates matches. It
|
||||
can be forced to consider the next set of completions by adding `tt(-t+)'
|
||||
to the flags of the alternative before the `tt(+)'.
|
||||
|
||||
(iii) In an extended completion list (see below), when tt(compctl) would
|
||||
normally continue until a set of conditions succeeded, then use only
|
||||
the immediately following flags. With `tt(-t-)', tt(compctl) will
|
||||
continue trying extended completions after the next `tt(-)'; with
|
||||
`tt(-tx)' it will attempt completion with the default flags, in other
|
||||
words those before the `tt(-x)'.
|
||||
)
|
||||
item(tt(-J) var(name))(
|
||||
This gives the name of the group the matches should be placed in. Groups
|
||||
are listed and sorted separately; likewise, menucompletion will offer
|
||||
the matches in the groups in the order in which the groups were
|
||||
defined. If no group name is explicitly given, the matches are stored in
|
||||
a group named var(default). The first time a group name is encountered,
|
||||
a group with that name is created. After that all matches with the same
|
||||
group name are stored in that group.
|
||||
|
||||
This can be useful with non-exclusive alternative completions. For
|
||||
example, in
|
||||
|
||||
indent(
|
||||
tt(compctl -f -J files -t+ + -v -J variables foo)
|
||||
)
|
||||
|
||||
both files and variables are possible completions, as the tt(-t+) forces
|
||||
both sets of alternatives before and after the tt(+) to be considered at
|
||||
once. Because of the tt(-J) options, however, all files are listed
|
||||
before all variables.
|
||||
)
|
||||
item(tt(-V) var(name))(
|
||||
Like tt(-J), but matches within the group will not be sorted in listings
|
||||
nor in menucompletion. These unsorted groups are in a different name
|
||||
space than the sorted ones, so groups defined as tt(-J files) and tt(-V
|
||||
files) are distinct.
|
||||
)
|
||||
item(tt(-M) var(match-spec))(
|
||||
This defines additional matching control specifications that should be used
|
||||
|
@ -451,6 +492,7 @@ only when testing words for the list of flags this flag appears in. The format
|
|||
of the var(match-spec) string is described below in noderef(Matching Control).
|
||||
)
|
||||
enditem()
|
||||
|
||||
texinode(Alternative Completion)(Extended Completion)(Option Flags)(Programmable Completion)
|
||||
sect(Alternative Completion)
|
||||
startlist()
|
||||
|
@ -465,16 +507,17 @@ there are no flags after the last `tt(PLUS())' and a match has not been found
|
|||
up to that point, default completion is tried.
|
||||
If the list of flags contains a tt(-t) with a tt(PLUS()) character, the next
|
||||
list of flags is used even if the current list produced matches.
|
||||
|
||||
texinode(Extended Completion)(Matching Control)(Alternative Completion)(Programmable Completion)
|
||||
sect(Extended Completion)
|
||||
startlist()
|
||||
list(tt(compctl) [ tt(-CDT) ] var(options) \
|
||||
tt(-x) var(pattern) var(options) tt(-) ... tt(--) \
|
||||
[ var(command) ... ])
|
||||
list(tt(compctl) [ tt(-CDT) ] var(options) \
|
||||
[ tt(-x) var(pattern) var(options) tt(-) ... tt(--) ] \
|
||||
[ tt(PLUS()) var(options) [ tt(-x) ... tt(--) ] ... [tt(PLUS())] ] \
|
||||
[ var(command) ... ])
|
||||
list(nofill(tt(compctl) [ tt(-CDT) ] var(options) \
|
||||
tt(-x) var(pattern) var(options) tt(-) ... tt(--)
|
||||
[ var(command) ... ]))
|
||||
list(nofill(tt(compctl) [ tt(-CDT) ] var(options) \
|
||||
[ tt(-x) var(pattern) var(options) tt(-) ... tt(--) ]
|
||||
[ tt(PLUS()) var(options) [ tt(-x) ... tt(--) ] ... [tt(PLUS())] ] \
|
||||
[ var(command) ... ]))
|
||||
endlist()
|
||||
|
||||
The form with `tt(-x)' specifies extended completion for the
|
||||
|
@ -541,7 +584,9 @@ considered part of the completion, but the rest will. var(index) may
|
|||
be negative to count from the end: in most cases, var(index) will be
|
||||
1 or -1. For example,
|
||||
|
||||
nofill(tt(compctl -s '`users`' -x 'n[1,@]' -k hosts -- talk))
|
||||
indent(
|
||||
tt(compctl -s '`users`' -x 'n[1,@]' -k hosts -- talk)
|
||||
)
|
||||
|
||||
will usually complete usernames, but if you insert an tt(@) after the
|
||||
name, names from the array var(hosts) (assumed to contain hostnames,
|
||||
|
@ -568,184 +613,192 @@ item(tt(R[)var(str1)tt(,)var(str2)tt(])...)(
|
|||
Like tt(r) but using pattern matching instead.
|
||||
)
|
||||
enditem()
|
||||
|
||||
texinode(Matching Control)(Example)(Extended Completion)(Programmable Completion)
|
||||
sect(Matching Control)
|
||||
|
||||
Matching specifications are used to describe that certain strings
|
||||
on the command line match possibly different strings in the words produced
|
||||
by the completion code.
|
||||
It is possible by use of the tt(-M) var(spec) flag to specify how the
|
||||
characters in the string to be completed (referred to here as the
|
||||
command line) map onto the characters in the list of matches produced by
|
||||
the completion code (referred to here as the trial completions).
|
||||
|
||||
Matching specification strings consist of one or more matching
|
||||
descriptions separated by whitespace. Each description consists of
|
||||
a letter followed by a colon and the patterns describing which character
|
||||
sequences on the line match which character sequences in the words.
|
||||
The var(spec) consists of one or more matching descriptions separated by
|
||||
whitespace. Each description consists of a letter followed by a colon,
|
||||
then the patterns describing which character sequences on the line match
|
||||
which character sequences in the trial completion. Any sequence of characters not
|
||||
handled in this fashion must match exactly, as usual.
|
||||
|
||||
The forms of var(spec) understood are as follows. In each case, the
|
||||
form with an uppercase initial character retains the string already
|
||||
typed on the command line as the final result of completion, while with
|
||||
a lowercase initial character the string on the command line is changed
|
||||
into the corresponding part of the trial completion.
|
||||
|
||||
The letters understood are: tt(l), tt(r), tt(m), tt(L), tt(R), and tt(M).
|
||||
startitem()
|
||||
item(tt(m) and tt(M))(
|
||||
These describe patterns that match anywhere in the words. The colon should
|
||||
be followed by two patterns separated by an equal sign. The pattern on the
|
||||
left side describes the substrings that are to be matched on the command line,
|
||||
the pattern on the right side describes the substrings matched in the word.
|
||||
xitem(tt(m:)var(lpat)tt(=)var(tpat))
|
||||
item(tt(M:)var(lpat)tt(=)var(tpat))(
|
||||
Here, var(lpat) is a pattern that matches on the command line,
|
||||
corresponding to var(tpat) which matches in the trial completion.
|
||||
)
|
||||
item(tt(l) and tt(L))(
|
||||
xitem(tt(l:)var(anchor)tt(|)var(lpat)tt(=)var(tpat))
|
||||
item(tt(L:)var(anchor)tt(|)var(lpat)tt(=)var(tpat))(
|
||||
These letters are for patterns that are anchored by another pattern on
|
||||
the left side. In this case the colon has to be followed by the pattern
|
||||
for the anchor, a pipe symbol, the pattern for the command line, an equal
|
||||
sign, and the pattern for the word. Patterns anchored on the left side match
|
||||
only if the anchor-pattern matches directly before the line pattern and if
|
||||
the string in the word before the word pattern matches the string before
|
||||
the line pattern in the line string.
|
||||
the left side. Matching for var(lpat) and var(tpat) is as for tt(m) and
|
||||
tt(M), but the pattern var(lpat) matched on the command line must be
|
||||
preceeded by the pattern var(anchor). The var(anchor) can be blank to
|
||||
anchor the match to the start of the command line string; otherwise the
|
||||
anchor can occur anywhere, but must match in both the command line and
|
||||
trial completion strings.
|
||||
)
|
||||
item(tt(r) and tt(R))(
|
||||
Like tt(l) and tt(L) with the difference that the line and word patterns
|
||||
are anchored on the right side. Also, here the pattern for the anchor has
|
||||
to come after the pattern for the line, again separated by a pipe symbol.
|
||||
xitem(tt(r:)var(lpat)tt(|)var(anchor)tt(=)var(tpat))
|
||||
item(tt(R:)var(lpat)tt(|)var(anchor)tt(=)var(tpat))(
|
||||
As tt(l) and tt(L) with the difference that the command line and trial
|
||||
completion patterns are anchored on the right side. Here an empty
|
||||
var(anchor) forces the match to the end of the command line string.
|
||||
)
|
||||
enditem()
|
||||
|
||||
Each pattern is either an empty string or consists of a sequence of
|
||||
character (possibly quoted), question marks, character classes, and
|
||||
correspondence classes. Normal characters match only themselves, question
|
||||
marks match any character, and character classes are formed as for
|
||||
globbing and match the same characters as there.
|
||||
Correspondence classes are formed like character classes with two
|
||||
differences: they are delimited by a pair of braces and negated
|
||||
classes are not allowed (i.e. the characters tt(!) and tt(^) have no
|
||||
special meaning directly after the opening brace).
|
||||
Each var(lpat), var(tpat) or var(anchor) is either an empty string or
|
||||
consists of a sequence of literal characters (which may be quoted with a
|
||||
backslash), question marks, character classes, and correspondence
|
||||
classes; ordinary shell patterns are not used. Literal characters match
|
||||
only themselves, question marks match any character, and character
|
||||
classes are formed as for globbing and match any character in the given
|
||||
set.
|
||||
|
||||
Correspondence classes are used to conveniently describe that several
|
||||
characters on the line match several other characters in the word. For
|
||||
example, if you want to define the any lowercase letter on the line
|
||||
matches the corresponding uppercase letter in the word all you need to
|
||||
write down is: `tt(m:{a-z}={A-Z})'. More than one correspondence class
|
||||
may be given on either side of the equal sign, in this case the first
|
||||
class on the left says which character matches for the first class on
|
||||
the right, the second class on either side work together, and so on.
|
||||
If one side has more such classes than the other side, the superfluous
|
||||
classes behave like normal character classes. In anchor patterns
|
||||
correspondence classes always behave like normal character classes.
|
||||
Correspondence classes are defined like character classes, but with two
|
||||
differences: they are delimited by a pair of braces, and negated classes
|
||||
are not allowed, so the characters tt(!) and tt(^) have no special
|
||||
meaning directly after the opening brace. They indicate that a range of
|
||||
characters on the line match a range of characters in the trial
|
||||
completion, but (unlike ordinary character classes) paired according to
|
||||
the corresponding position in the sequence. For example, to make any
|
||||
lowercase letter on the line match the corresponding uppercase letter in
|
||||
the trial completion, you can use `tt(m:{a-z}={A-Z})'. More than one
|
||||
pair of classes can occur, in which case the first class before the
|
||||
tt(=) corresponds to the first after it, and so on. If one side has
|
||||
more such classes than the other side, the superfluous classes behave
|
||||
like normal character classes. In anchor patterns correspondence classes
|
||||
also behave like normal character classes.
|
||||
|
||||
The word pattern may also be a single star (tt(*)). This means that
|
||||
the line pattern matches any number of characters in the word. In this
|
||||
case the pattern has to be anchored (on any side) and the line pattern
|
||||
matches all characters in the word up to a character sequence that
|
||||
matches the anchor.
|
||||
|
||||
For anchors the empty string as a pattern has a special meaning. Such
|
||||
empty anchors match only the beginning (in the case of an left side
|
||||
anchor) or end (for right side anchors) of the command line string or
|
||||
word.
|
||||
|
||||
The distinction between the lowercase and the uppercase forms of the
|
||||
specification characters is used to define which matched substring
|
||||
should be put in the match and the generated command line. The
|
||||
lowercase forms use the substring from the word, so this should be
|
||||
used if the exact words produced by the completion code need to be
|
||||
used. The uppercase forms use the substring from the command line and
|
||||
should be used if the typed string need to be retained.
|
||||
The pattern var(tpat) may also be a single star, `tt(*)'. This means
|
||||
that the pattern on the command line can match any number of characters
|
||||
in the trial completion. In this case the pattern must be anchored (on
|
||||
either side); the var(anchor) then determines how much of the trial
|
||||
completion is to be included.
|
||||
|
||||
Examples:
|
||||
|
||||
startitem()
|
||||
The option tt(-o) produces option names in all-lowercase form, without
|
||||
The option tt(-o) produces option names in all-lowercase form, without
|
||||
underscores, and without the optional tt(no) at the beginning even
|
||||
though the buitlins tt(setopt) and tt(unsetopt) understand opotion
|
||||
names with uppercase letters, underscores, and the optional tt(no).
|
||||
So we want to be able to say, that in this case an prefix tt(no) and
|
||||
any underscore may be ignored when trying to match the produced words,
|
||||
and that uppercase letters on the line match the corresponding
|
||||
lowercase letters in the words. This can be done with:
|
||||
|
||||
though the builtins tt(setopt) and tt(unsetopt) understand option names
|
||||
with uppercase letters, underscores, and the optional tt(no). The
|
||||
following alters the matching rules so that the prefix tt(no) and any
|
||||
underscore are ignored when trying to match the trial completions
|
||||
generated and uppercase letters on the line match the corresponding
|
||||
lowercase letters in the words:
|
||||
indent(
|
||||
tt(compctl -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o setopt unsetopt)
|
||||
nofill(tt(compctl -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
|
||||
-o setopt unsetopt))
|
||||
)
|
||||
|
||||
The first part says that the pattern `tt([nN][oO])' at the beginning
|
||||
(note the empty anchor before the pipe symbol) of the string on the
|
||||
line matches the the empty string in the produced words, i.e. it need
|
||||
not be there. The second part says that an underscore anywhere on the
|
||||
line need not be present in the word, and the third part uses
|
||||
correspondence classes as in the example above to say that any
|
||||
(the empty anchor before the pipe symbol) of the string on the
|
||||
line matches the empty string in the list of words generated by
|
||||
completion, so it will be ignored if present. The second part does the
|
||||
same for an underscore anywhere in the command line string, and the
|
||||
third part uses correspondence classes so that any
|
||||
uppercase letter on the line matches the corresponding lowercase
|
||||
letter in the word. The use of the uppercase forms of the
|
||||
specification characters (tt(L) and tt(M)) guarantees that the special
|
||||
wrinting on the command line (and especially the option tt(no)) will
|
||||
not be erased.
|
||||
|
||||
As a second example we will make completion case insensitive. For this
|
||||
we use the form of tt(compctl) that defines matching specification that
|
||||
are to be used everywhere, i.e. a tt(compctl) with tt(-M) as the only
|
||||
option given.
|
||||
|
||||
The pattern needed was already explained above, this gives us:
|
||||
specification characters (tt(L) and tt(M)) guarantees that what has
|
||||
already been typed on the command line (in particular the prefix
|
||||
tt(no)) will not be deleted.
|
||||
|
||||
The second example makes completion case insensitive. By using
|
||||
tt(compctl) with the tt(-M) option alone this applies to every
|
||||
completion. This is just the same as in the tt(setopt) example, except
|
||||
here we wish to retain the characters in the list of completions:
|
||||
indent(
|
||||
tt(compctl -M 'm:{a-z}={A-Z}')
|
||||
)
|
||||
|
||||
This makes lowercase letters match their uppercase counterparts. If we
|
||||
want to make uppercase letters match the lowercase forms, we would
|
||||
have to use:
|
||||
|
||||
This makes lowercase letters match their uppercase counterparts.
|
||||
To make uppercase letters match the lowercase forms as well:
|
||||
indent(
|
||||
tt(compctl -M 'm:{a-z}={A-Z} m:{A-Z}={a-z}')
|
||||
tt(compctl -M 'm:{a-zA-Z}={A-Za-z}')
|
||||
)
|
||||
|
||||
A nice example for the use of tt(*) patterns is partial word
|
||||
completion. Sometimes you would like to make strings like tt(c.s.u)
|
||||
complete to strings like tt(comp.source.unix), i.e. you consider the
|
||||
word to consist of multiple parts (separated by the dot in the
|
||||
example) and each part should be completed separately. Defining such
|
||||
forms of matching is simple, for example if we want to separately
|
||||
complete word parts separated by dots, commas, underscores, and
|
||||
hyphens, we can do this by saying:
|
||||
complete to strings like tt(comp.source.unix), i.e. the word on the
|
||||
command line consists of multiple parts, separated by a dot in this
|
||||
example, where each part should be completed separately --- note,
|
||||
however, that the case where each part of the word, i.e. tt(comp),
|
||||
tt(source) and tt(unix) in this example, is to be completed separately
|
||||
is a different problem to be solved by extended completion. The
|
||||
example can be handled by:
|
||||
indent(
|
||||
nofill(tt(compctl -M 'r:|.=* r:|=*' \
|
||||
-k '(comp.sources.unix comp.sources.misc ...)' ngroups))
|
||||
)
|
||||
The first specification says that tt(lpat) is the empty string, while
|
||||
tt(anchor) is a dot; tt(tpat) is tt(*), so this can match anything in
|
||||
the trial completion word. So in tt(c.s.u), the matcher sees tt(c),
|
||||
followed by the empty string, followed by the anchor `tt(.)', and
|
||||
likewise for the second dot, and replaces the empty strings before the
|
||||
anchors, giving tt(c)[tt(omp)]tt(.s)[tt(ources)]tt(.u)[tt(nix)], where
|
||||
the last part of the completion is just as normal.
|
||||
|
||||
The second specification is needed to make this work when the cursor is
|
||||
in the middle of the string on the command line and the option
|
||||
tt(COMPLETE_IN_WORD) is set. In this case the completion code would
|
||||
normally try to match trial completions that end with the string as
|
||||
typed so far, i.e. it will only insert new characters at the cursor
|
||||
position rather then at the end. However in our example we would like
|
||||
the code to recognise matches which contain extra characters after the
|
||||
string on the line (the tt(nix) in the example). Hence we say that the
|
||||
empty string at the end of the string on the line matches any characters
|
||||
at the end of the trial completion.
|
||||
|
||||
More generally, the specification
|
||||
indent(
|
||||
tt(compctl -M 'r:|[.,_-]=* r:|=*')
|
||||
)
|
||||
allows one to complete words with abbreviations before any of the
|
||||
characters in the square brackets in any completion. For example, to
|
||||
complete tt(veryverylongfile.c) rather than tt(veryverylongheader.h)
|
||||
with the above in effect, you can just type tt(very.c) before attempting
|
||||
completion.
|
||||
|
||||
The first specification says that an empty string on the line before
|
||||
one of our special characters matches any number of characters in the
|
||||
word which has the effect we wanted. The second specification is
|
||||
needed to make this work when the cursor is in the middle of the word
|
||||
and the option tt(COMPLETE_IN_WORD) is set. In this case the
|
||||
completion code would normally try to match word that end with the
|
||||
string that is already on the command line, but in our example we
|
||||
would like the code to match words even if they contain extra
|
||||
characters after the string on the line. Hence we say that the empty
|
||||
string at the end of the string on the line matches any characters at
|
||||
the end of the word.
|
||||
|
||||
The form of tt(compctl) that defines the global matching
|
||||
specifications is a bit more powerful than described until now. It
|
||||
accepts not only one specification strin, but any number of them. When
|
||||
completion is attempted, the code first uses the definitions from the
|
||||
first string. If no words could be matched with these specifications,
|
||||
it tries the whole thing again with the specifications from the second
|
||||
string, and so on. This allows one to define simple and fast matches
|
||||
to be used first, more powerful matchers as a second choice, and so on.
|
||||
|
||||
As an example we would like to make the code match words that contain
|
||||
the string on the line as a substring (anywhere, not just at the
|
||||
beginning). But since this could produce more matches than we want,
|
||||
this should be tried only if the matchers described above don't
|
||||
produce any matches. E.g.:
|
||||
The form tt(compctl -M) that defines global matching actually accepts
|
||||
any number of specification strings, unlike the case where the tt(-M)
|
||||
option applies only to a particular command. In this case, when
|
||||
completion is attempted for any command, the code will try the
|
||||
specifications in order until one matches. This allows one to define
|
||||
simple and fast matches to be used first, more powerful matchers as a
|
||||
second choice, and so on.
|
||||
|
||||
For example, one can make the code match trial completions that contain
|
||||
the string on the command line as a substring, not just at the
|
||||
beginning. Since this might produce more matches than we want,
|
||||
we arrange for it to be tried only if the matchers described above don't
|
||||
produce any matches:
|
||||
indent(
|
||||
tt(compctl -M 'r:|[.,_-]=* r:|=*' 'l:|=* r:|=*')
|
||||
)
|
||||
Here, if the string on the command line is tt(foo.bar), tt(compctl)
|
||||
first tries matching tt(foo)var(anything)tt(.bar)var(anything), as
|
||||
with the previous example. If that fails, the two descriptions in the
|
||||
second string after the tt(-M) say that the blanks at the beginning
|
||||
and end of the string on the command line can match any set of
|
||||
characters at the beginning or end of the trial completion, so it will
|
||||
look for var(anything)tt(foo.bar)var(anything).
|
||||
|
||||
If using the first specification string does not produce matches, the
|
||||
second one is tried. The two descriptions it this string say that the
|
||||
empty string at the beginning and end of the string on the line
|
||||
matches any characters at the beginning or end of the word.
|
||||
enditem()
|
||||
texinode(Example)()(Matching Control)(Programmable Completion)
|
||||
sect(Example)
|
||||
nofill(tt(compctl -u -x 's[tt(PLUS())] c[-1,-f],s[-f+PLUS()]' -g '~/Mail/*(:t)' \
|
||||
- 's[-f],c[-1,-f]' -f -- mail))
|
||||
|
||||
indent(
|
||||
nofill(
|
||||
tt(compctl -u -x 's[tt(PLUS())] c[-1,-f],s[-f+PLUS()]' \
|
||||
-g '~/Mail/*(:t)' - 's[-f],c[-1,-f]' -f -- mail))
|
||||
)
|
||||
This is to be interpreted as follows:
|
||||
|
||||
If the current command is tt(mail), then
|
||||
|
|
|
@ -161,8 +161,10 @@ Print the new command but do not execute it. Only works with history
|
|||
expansion.
|
||||
)
|
||||
item(tt(q))(
|
||||
Quote the substituted words, escaping further substitutions. Only
|
||||
works with history expansion.
|
||||
Quote the substituted words, escaping further substitutions. Works
|
||||
with history expansion and parameter expansion, though in the second
|
||||
case it is only useful if the resulting text is to be re-evaluated
|
||||
such as by tt(eval).
|
||||
)
|
||||
item(tt(x))(
|
||||
Like tt(q), but break into words at each blank.
|
||||
|
@ -477,9 +479,10 @@ item(tt(${~)var(spec)tt(}))(
|
|||
pindex(GLOB_SUBST)
|
||||
Turn on the tt(GLOB_SUBST) option for the evaluation of
|
||||
var(spec); if the `tt(~)' is doubled, turn it off. When this option is
|
||||
set, any pattern characters resulting
|
||||
from parameter expansion are eligible for filename expansion and filename
|
||||
generation.
|
||||
set, the string resulting from the expansion will be interpreted as a
|
||||
pattern anywhere that is possible, such as in filename expansion and
|
||||
filename generation and pattern-matching contexts like the right
|
||||
hand side of the `tt(=)' and `tt(!=)' operators in conditions.
|
||||
)
|
||||
enditem()
|
||||
|
||||
|
@ -523,6 +526,15 @@ Perform em(parameter expansion), em(command substitution) and
|
|||
em(arithmetic expansion) on the result. Such expansions can be
|
||||
nested but too deep recursion may have unpredictable effects.
|
||||
)
|
||||
item(tt(P))(
|
||||
This makes the value of the parameter var(name) be taken as a
|
||||
parameter name on which to work. If it is used with a tt(${)...tt(})
|
||||
type parameter expression or a tt($LPAR())...tt(RPAR()) type command
|
||||
substitution in place of the parameter name this flag makes the result
|
||||
of the expansion be taken as a parameter name which is then
|
||||
used. E.g. if you have `tt(foo=bar)' and `tt(bar=baz)', the strings
|
||||
`tt(${(P)foo})' and `tt(${(P)${foo}})' will be expanded to `tt(baz)'.
|
||||
)
|
||||
item(tt(o))(
|
||||
Sort the resulting words in ascending order.
|
||||
)
|
||||
|
@ -788,7 +800,8 @@ directory as its prefix. If so, then the prefix portion
|
|||
is replaced with a `tt(~)' followed by the name of the directory.
|
||||
The shortest way of referring to the directory is used,
|
||||
with ties broken in favour of using a named directory,
|
||||
except when the directory is tt(/) itself.
|
||||
except when the directory is tt(/) itself. The variables tt($PWD) and
|
||||
tt($OLDPWD) are never abbreviated in this fashion.
|
||||
|
||||
If a word begins with an unquoted `tt(=)'
|
||||
and the tt(EQUALS) option is set,
|
||||
|
@ -1088,7 +1101,7 @@ setgid files (02000)
|
|||
item(tt(t))(
|
||||
files with the sticky bit (01000)
|
||||
)
|
||||
item(tt(o)var(spec))(
|
||||
item(tt(f)var(spec))(
|
||||
files with access rights matching var(spec). This var(spec) may be a
|
||||
octal number optionally preceded by a `tt(=)', a `tt(PLUS())', or a
|
||||
`tt(-)'. If none of these characters is given, the behavior is the
|
||||
|
@ -1101,7 +1114,7 @@ octal digit anywhere in the number ensures that the corresponding bits
|
|||
inthe file-modes are not checked, this is only useful in combination
|
||||
with `tt(=)'.
|
||||
|
||||
If the qualifier `tt(o)' is followed by any other character anything
|
||||
If the qualifier `tt(f)' is followed by any other character anything
|
||||
up to the next matching character (`tt([)', `tt({)', and `tt(<)' match
|
||||
`tt(])', `tt(})', and `tt(>)' respectively, any other character
|
||||
matches itself) is taken as a list of comma-separated
|
||||
|
@ -1122,11 +1135,11 @@ are to be expected: `tt(r)' for read access, `tt(w)' for write access,
|
|||
`tt(s)' for the setuid and setgid bits, and `tt(t)' for the sticky
|
||||
bit.
|
||||
|
||||
Thus, `tt(*(o70?))' gives the files for which the owner has read,
|
||||
Thus, `tt(*(f70?))' gives the files for which the owner has read,
|
||||
write, and execute permission, and for which other group members have
|
||||
no rights, independent of the permissions for other user. The pattern
|
||||
`tt(*(o-100))' gives all files for which the owner does not have
|
||||
execute permission, and `tt(*(o:gu+w,o-rx))' gives the files for which
|
||||
`tt(*(f-100))' gives all files for which the owner does not have
|
||||
execute permission, and `tt(*(f:gu+w,o-rx))' gives the files for which
|
||||
the owner and the other members of the group have at least write
|
||||
permission, and fo which other users don't have read or execute
|
||||
permission.
|
||||
|
@ -1205,7 +1218,7 @@ item(tt(D))(
|
|||
sets the tt(GLOB_DOTS) option for the current pattern
|
||||
pindex(GLOB_DOTS, setting in pattern)
|
||||
)
|
||||
item(tt(O)var(c))(
|
||||
item(tt(o)var(c))(
|
||||
specifies how the names of the files should be sorted. If var(c) is
|
||||
tt(n) they are sorted by name (the default), if var(c) is tt(L) they
|
||||
are sorted depending on the size (length) of the files, tt(l) makes
|
||||
|
@ -1214,16 +1227,20 @@ make them be sorted by the time of the last access, modification, and
|
|||
inode change respectively. Note that tt(a), tt(m), and tt(c) compare
|
||||
the age to the current time, so the first name in the list is the
|
||||
one of the youngest file. Also note that the modifiers tt(^) and tt(-) are
|
||||
used, so `tt(*(^-OL))' gives a list of all files sorted by file size in
|
||||
used, so `tt(*(^-oL))' gives a list of all files sorted by file size in
|
||||
descending order working not on symbolic links but on the files they
|
||||
point to.
|
||||
)
|
||||
item(tt(O)var(c))(
|
||||
like `tt(o)', but sorts in descending order; i.e. `tt(*(^oc))' is the
|
||||
same as `tt(*(Oc))' and `tt(*(^Oc))' is the same as `tt(*(oc))'
|
||||
)
|
||||
item(tt([)var(beg)[tt(,)var(end)]tt(]))(
|
||||
specifies which of the matched filenames should be included in the
|
||||
returned list. The syntax is the same as for array
|
||||
subscripts. var(beg) and the optional var(end) may be mathematical
|
||||
expressions. As in parameter subscripting they may be negative to make
|
||||
them count from the last match backward. E.g.: `tt(*(^-OL[1,3]))'
|
||||
them count from the last match backward. E.g.: `tt(*(-OL[1,3]))'
|
||||
gives a list of the names of three biggest files.
|
||||
)
|
||||
enditem()
|
||||
|
|
|
@ -20,6 +20,12 @@ commands are read from tt(/etc/zshrc) and then tt($ZDOTDIR/.zshrc).
|
|||
Finally, if the shell is a login shell, tt(/etc/zlogin) and
|
||||
tt($ZDOTDIR/.zlogin) are read.
|
||||
|
||||
When a login shell exits, the files tt($ZDOTDIR/.zlogout) and then
|
||||
tt(/etc/zlogout) are read. This happens with either an explicit exit
|
||||
via the tt(exit) or tt(logout) commands, or an implict exit by reading
|
||||
end-of-file from the terminal. However, if the shell terminates due
|
||||
to tt(exec)'ing another process, the logout files are not read.
|
||||
|
||||
If tt(ZDOTDIR) is unset, tt(HOME) is used instead.
|
||||
Those files listed above as being in tt(/etc) may be in another
|
||||
directory, depending on the installation.
|
||||
|
|
|
@ -91,28 +91,30 @@ cindex(mailing lists)
|
|||
Zsh has 3 mailing lists:
|
||||
|
||||
startitem()
|
||||
item(tt(<zsh-announce@math.gatech.edu>))(
|
||||
item(tt(<zsh-announce@sunsite.auc.dk>))(
|
||||
Announcements about releases, major changes in the shell and the
|
||||
monthly posting of the Zsh FAQ. (moderated)
|
||||
)
|
||||
item(tt(<zsh-users@math.gatech.edu>))(
|
||||
item(tt(<zsh-users@sunsite.auc.dk>))(
|
||||
User discussions.
|
||||
)
|
||||
item(tt(<zsh-workers@math.gatech.edu>))(
|
||||
item(tt(<zsh-workers@sunsite.auc.dk>))(
|
||||
Hacking, development, bug reports and patches.
|
||||
)
|
||||
enditem()
|
||||
|
||||
To subscribe, send mail with the SUBJECT `tt(subscribe) var(<e-mail-address>)'
|
||||
To subscribe or unsubscribe, send mail
|
||||
to the associated administrative address for the mailing list.
|
||||
|
||||
startlist()
|
||||
list(tt(<zsh-announce-request@math.gatech.edu>))
|
||||
list(tt(<zsh-users-request@math.gatech.edu>))
|
||||
list(tt(<zsh-workers-request@math.gatech.edu>))
|
||||
endlist()
|
||||
list(tt(<zsh-announce-subscribe@sunsite.auc.dk>))
|
||||
list(tt(<zsh-users-subscribe@sunsite.auc.dk>))
|
||||
list(tt(<zsh-workers-subscribe@sunsite.auc.dk>))
|
||||
|
||||
Unsubscribing is done similarly.
|
||||
list(tt(<zsh-announce-unsubscribe@sunsite.auc.dk>))
|
||||
list(tt(<zsh-users-unsubscribe@sunsite.auc.dk>))
|
||||
list(tt(<zsh-workers-unsubscribe@sunsite.auc.dk>))
|
||||
endlist()
|
||||
|
||||
YOU ONLY NEED TO JOIN ONE OF THE MAILING LISTS AS THEY ARE NESTED.
|
||||
All submissions to bf(zsh-announce) are automatically forwarded to
|
||||
|
@ -121,7 +123,7 @@ forwarded to bf(zsh-workers).
|
|||
|
||||
If you have problems subscribing/unsubscribing to any of the mailing
|
||||
lists, send mail to tt(<listmaster@zsh.org>). The mailing lists are
|
||||
maintained by Richard Coleman tt(<coleman@zsh.org>).
|
||||
maintained by Karsten Thygesen tt(<karthy@kom.auc.dk>).
|
||||
|
||||
The mailing lists are archived; the archives can be accessed via the
|
||||
administrative addresses listed above. There is also a hypertext
|
||||
|
|
|
@ -131,12 +131,20 @@ written as `tt(^?)'. Note that `tt(\M^?)' and `tt(^\M?)' are not the same.
|
|||
findex(vared)
|
||||
cindex(parameters, editing)
|
||||
cindex(editing parameters)
|
||||
item(tt(vared) [ tt(-ch) ] [ tt(-p) var(prompt) ] [ tt(-r) var(rprompt) ] var(name))(
|
||||
item(tt(vared) [ tt(-Aach) ] [ tt(-p) var(prompt) ] [ tt(-r) var(rprompt) ] var(name))(
|
||||
The value of the parameter var(name) is loaded into the edit
|
||||
buffer, and the line editor is invoked. When the editor exits,
|
||||
var(name) is set to the string value returned by the editor.
|
||||
If the tt(-c) flag is given, the parameter is created if it doesn't
|
||||
already exist.
|
||||
When the tt(-c) flag is given, the parameter is created if it doesn't
|
||||
already exist. The tt(-a) flag may be given with tt(-c) to create
|
||||
an array parameter, or the tt(-A) flag to create an associative array.
|
||||
If the type of an existing parameter does not match the type to be
|
||||
created, the parameter is unset and recreated.
|
||||
|
||||
Individual elements of existing array or associative array parameters
|
||||
may be edited by using subscript syntax on var(name). New elements are
|
||||
created automatically, even without tt(-c).
|
||||
|
||||
If the tt(-p) flag is given, the following string will be taken as
|
||||
the prompt to display at the left. If the tt(-r) flag is given,
|
||||
the following string gives the prompt to display at the right. If the
|
||||
|
|
|
@ -150,6 +150,17 @@ In a glob pattern, treat a trailing set of parentheses as a qualifier
|
|||
list, if it contains no `tt(|)', `tt(LPAR())' or (if special) `tt(~)'
|
||||
characters. See noderef(Filename Generation).
|
||||
)
|
||||
pindex(BASH_AUTO_LIST)
|
||||
cindex(completion, listing choices, bash style)
|
||||
item(tt(BASH_AUTO_LIST))(
|
||||
On an ambiguous completion, automatically list choices when the
|
||||
completion function is called twice in succession. This takes
|
||||
precedence over tt(AUTO_LIST). The setting of tt(LIST_AMBIGUOUS) is
|
||||
respected. If tt(AUTO_MENU) is set, the menu behaviour will then start
|
||||
with the third press. Note that this will not work with
|
||||
tt(MENU_COMPLETE), since repeated completion calls immediately cycle
|
||||
through the list in that case.
|
||||
)
|
||||
pindex(BEEP)
|
||||
cindex(beep, enabling)
|
||||
cindex(enabling the beep)
|
||||
|
@ -331,11 +342,12 @@ will be an array or a scalar.
|
|||
pindex(GLOB_COMPLETE)
|
||||
item(tt(GLOB_COMPLETE))(
|
||||
When the current word has a glob pattern, do not insert all the words
|
||||
resulting from the expansion but cycle through them like
|
||||
tt(MENU_COMPLETE). If no matches are found, a `tt(*)' is added to the end of the
|
||||
word or inserted at the cursor if tt(COMPLETE_IN_WORD) is set, and expansion
|
||||
is attempted again. Using patterns works not only for files but for all
|
||||
completions, such as options, user names, etc.
|
||||
resulting from the expansion but generate matches as for completion and
|
||||
cycle through them like tt(MENU_COMPLETE). If no matches are found, a
|
||||
`tt(*)' is added to the end of the word or inserted at the cursor if
|
||||
tt(COMPLETE_IN_WORD) is set, and completion is attempted again using
|
||||
pattern matching. Since this doesn't use globbing, it works not only for
|
||||
files but for all completions, such as options, user names, etc.
|
||||
)
|
||||
pindex(GLOB_DOTS)
|
||||
cindex(globbing, of . files)
|
||||
|
@ -488,9 +500,12 @@ pindex(LIST_AMBIGUOUS)
|
|||
cindex(ambiguous completion)
|
||||
cindex(completion, ambiguous)
|
||||
item(tt(LIST_AMBIGUOUS))(
|
||||
If this option is set, completions are shown only if the completions
|
||||
don't have a unambiguous prefix or suffix that could be inserted in
|
||||
the command line.
|
||||
This option works when tt(AUTO_LIST) or tt(BASH_AUTO_LIST) is also
|
||||
set. If there is an unambiguous prefix to insert on the command line,
|
||||
that is done without a completion list being displayed; in other
|
||||
words, auto-listing behaviour only takes place when nothing would be
|
||||
inserted. In the case of tt(BASH_AUTO_LIST), this means that the list
|
||||
will be delayed to the third call of the function.
|
||||
)
|
||||
pindex(LIST_BEEP)
|
||||
cindex(beep, ambiguous completion)
|
||||
|
|
|
@ -40,7 +40,8 @@ Shell function executions delimit scopes for shell parameters.
|
|||
(Parameters are dynamically scoped.) The tt(typeset) builtin, and its
|
||||
alternative forms tt(declare), tt(integer), tt(local) and tt(readonly)
|
||||
(but not tt(export)), can be used to declare a parameter as being local
|
||||
to the innermost scope.
|
||||
to the innermost scope. Note that em(special) parameters cannot be made
|
||||
local.
|
||||
|
||||
When a parameter is read or assigned to, the
|
||||
innermost existing parameter of that name is used. (That is, the
|
||||
|
@ -49,9 +50,8 @@ to a non-existent parameter, or declaring a new parameter with tt(export),
|
|||
causes it to be created in the em(outer)most scope.
|
||||
|
||||
Local parameters disappear when their scope ends.
|
||||
tt(unset) can be used to delete a parameter while it is still in scope; this
|
||||
will reveal the next outer parameter of the same name. However, em(special)
|
||||
parameters are still special when unset.
|
||||
tt(unset) can be used to delete a parameter while it is still in scope;
|
||||
any outer parameter of the same name remains hidden.
|
||||
texinode(Array Parameters)(Positional Parameters)(Local Parameters)(Parameters)
|
||||
sect(Array Parameters)
|
||||
The value of an array parameter may be assigned by writing:
|
||||
|
|
|
@ -55,6 +55,11 @@ Linux: Linux (i386) [3.1.4]
|
|||
process reports that there is no lstat, edit config.h and change
|
||||
HAVE_LSTAT to 1. libc-5.2.18 or later does not have this problem.
|
||||
|
||||
Various problems have been reported when using optimisation
|
||||
with the experimental GNU compiler, egcs. In particular,
|
||||
on Linux Alpha with egcs 1.0.3a and 1.1.1 using -O1 or greater,
|
||||
the completion code is not correctly compiled.
|
||||
|
||||
NetBSD: NetBSD 1.*
|
||||
Should build `out-of-the-box'.
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ local time=mtime tmod=m
|
|||
|
||||
if ((! ARGC)) then
|
||||
if [[ $opts = *t* ]]; then
|
||||
set *(O$tmod)
|
||||
set *(o$tmod)
|
||||
else
|
||||
set *
|
||||
fi
|
||||
|
@ -44,7 +44,7 @@ elif [[ $opts = *t* && $ARGC -gt 1 ]]; then
|
|||
for (( f = 2; f <= $ARGC; f++ )); do
|
||||
n="$n|\$$f"
|
||||
done
|
||||
eval "argv=(($n)(O$tmod))"
|
||||
eval "argv=(($n)(o$tmod))"
|
||||
fi
|
||||
|
||||
for f in $*
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Define a new widget behaving like `expand-or-complete' but calling the
|
||||
# function `main-complete' to generate matches.
|
||||
|
||||
zle -c my-comp expand-or-complete main-complete
|
||||
zle -C my-comp expand-or-complete main-complete
|
||||
|
||||
bindkey '\C-i' my-comp
|
||||
|
||||
|
@ -75,11 +75,8 @@ compalso() {
|
|||
# the arguments from the command line as its arguments.
|
||||
|
||||
call-complete() {
|
||||
local var
|
||||
|
||||
eval var\=\$\{\+$1\}
|
||||
if (( var )); then
|
||||
eval complist \$\{${1}\[\@\]\}
|
||||
if [[ ${(P)+${1}} -eq 1 ]] then
|
||||
complist ${(@P)${1}}
|
||||
else
|
||||
"$@"
|
||||
fi
|
||||
|
@ -96,15 +93,6 @@ main-complete() {
|
|||
setopt localoptions nullglob rcexpandparam globdots
|
||||
unsetopt markdirs globsubst shwordsplit nounset
|
||||
|
||||
# We first try the `compctl's. This is without first (-T) and default (-D)
|
||||
# completion. If you want them add `-T' and/or `-D' to this command.
|
||||
# If this produces any matches, we don't try new style completion. If you
|
||||
# want to have that tried anyway, remove the `[[ -nmatches ... ]] ...'
|
||||
# below.
|
||||
|
||||
compcall
|
||||
[[ -nmatches 0 ]] || return
|
||||
|
||||
# An entry for `--first--' is the replacement for `compctl -T'
|
||||
# The `|| return 1' is used throughout: if a function producing matches
|
||||
# returns non-zero this is interpreted as `do not try to produce more matches'
|
||||
|
@ -117,6 +105,15 @@ main-complete() {
|
|||
# convenience alias `compsub'.
|
||||
|
||||
if [[ $CONTEXT == argument || $CONTEXT == command ]] then
|
||||
# We first try the `compctl's. This is without first (-T) and default (-D)
|
||||
# completion. If you want them add `-T' and/or `-D' to this command.
|
||||
# If this produces any matches, we don't try new style completion. If you
|
||||
# want to have that tried anyway, remove the `[[ -nmatches ... ]] ...'
|
||||
# below.
|
||||
|
||||
compcall
|
||||
[[ -nmatches 0 ]] || return
|
||||
|
||||
compsub
|
||||
else
|
||||
# Let's see if we have a special completion definition for the other
|
||||
|
@ -191,7 +188,8 @@ do-complete() {
|
|||
# This is intended as a replacement for `complist -f', `complist -/', and
|
||||
# `complist -g ...' (but don't use it with other options).
|
||||
# This function behaves as if you have a matcher definition like:
|
||||
# compctl -M 'r:|[-.,_/]=* r:|=* m:{a-z}={A-Z} m:-=_ m:.=,'
|
||||
# compctl -M 'r:|[-.,_/]=* r:|=* m:{a-z}={A-Z} m:-=_ m:.=,' \
|
||||
# 'm:{a-z}={A-Z} l:|=* r:|=*'
|
||||
# so you may want to modify this.
|
||||
|
||||
pfiles() {
|
||||
|
@ -205,7 +203,7 @@ pfiles() {
|
|||
if [[ "$a[1]" = '(' ]] then
|
||||
ppres=( $a[2,-2]/ )
|
||||
else
|
||||
eval ppres\=\( \$$a/ \)
|
||||
ppres=( ${(P)${a}} )
|
||||
[[ $#ppres -eq 0 ]] && ppres=( $a/ )
|
||||
fi
|
||||
[[ $#ppres -eq 0 ]] && ppres=( '' )
|
||||
|
@ -214,7 +212,7 @@ pfiles() {
|
|||
ppres=( '' )
|
||||
fi
|
||||
|
||||
str="$PREFIX*$SUFFIX"
|
||||
str="${PREFIX:q}*${SUFFIX:q}"
|
||||
|
||||
if [[ -z "$a[1]" || "$str[1]" = [~/] || "$str" = (.|..)/* ]] then
|
||||
a=()
|
||||
|
@ -259,7 +257,12 @@ pfiles() {
|
|||
str="${str#*/}"
|
||||
done
|
||||
|
||||
ostr="$str:gs/,/*,/:gs/_/*_/:gs./.*/.:gs/-/*[-_]/:gs/./*[.,]/:gs-*[.,]*[.,]*/-../-:gs.**.*."
|
||||
if [[ -matcher 1 ]] then
|
||||
ostr="$str:gs/,/*,/:gs/_/*_/:gs./.*/.:gs/-/*[-_]/:gs/./*[.,]/:gs-*[.,]*[.,]*/-../-:gs.**.*."
|
||||
else
|
||||
ostr="${str%/*}/*${str##*/}*"
|
||||
ostr="$ostr:gs./.*/.:gs.**.*."
|
||||
fi
|
||||
|
||||
for ppre in "$ppres[@]"; do
|
||||
str="$ostr"
|
||||
|
@ -276,7 +279,6 @@ pfiles() {
|
|||
s=( "${(@)s:gs.**.*.}" )
|
||||
for i in $a; do
|
||||
b=( $~i/(#l)$~s )
|
||||
eval b\=\( \$\{b:/\*\(${(j:|:)fignore}\)\} \)
|
||||
[[ $#b -ne 0 ]] && c=( $c $i )
|
||||
done
|
||||
if [[ $#c -eq 0 ]] then
|
||||
|
@ -284,10 +286,9 @@ pfiles() {
|
|||
elif [[ $#c -ne 1 ]] then
|
||||
a="$ppre$epre$pa"
|
||||
c=( $~c/(#l)$~s )
|
||||
eval c\=\( \$\{c:/\*\(${(j:|:)fignore}\)\} \)
|
||||
c=( ${c#$a} )
|
||||
for i in $c; do
|
||||
compadd -p "$pre$pa" -W "$a" -s "/${i#*/}" -f "${i%%/*}"
|
||||
compadd -p "$pre$pa" -W "$a" -s "/${i#*/}" -fF -- "${i%%/*}"
|
||||
done
|
||||
continue 2
|
||||
fi
|
||||
|
@ -301,8 +302,7 @@ pfiles() {
|
|||
s=( $str$@ )
|
||||
s=( "${(@)s:gs.**.*.}" )
|
||||
b=( $~a(#l)$~s )
|
||||
eval b\=\( \$\{b:/\*\(${(j:|:)fignore}\)\} \)
|
||||
compadd -p "$pre$pa" -W "$ppre$epre$pa" -f ${b#$a}
|
||||
compadd -p "$pre$pa" -W "$ppre$epre$pa" -fF -- ${b#$a}
|
||||
done
|
||||
}
|
||||
|
||||
|
@ -332,11 +332,20 @@ __vars=( -v )
|
|||
|
||||
defcomp __subscr --subscr--
|
||||
__subscr() {
|
||||
local t
|
||||
|
||||
eval t\=\$\{\(t\)$COMMAND\}
|
||||
compalso --math-- "$@"
|
||||
[[ $t = assoc* ]] && eval complist -k \"\(\$\{\(k\)$COMMAND\}\)\"
|
||||
[[ ${(Pt)${COMMAND}} = assoc* ]] && complist -k "( ${(kP)${COMMAND}} )"
|
||||
}
|
||||
|
||||
defcomp __cond --cond--
|
||||
__cond() {
|
||||
if [[ -current -1 -o ]] then
|
||||
complist -o -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}'
|
||||
elif [[ -current -1 -nt || -current -1 -ot || -current -1 -ef ]] then
|
||||
files
|
||||
else
|
||||
files
|
||||
complist -v
|
||||
fi
|
||||
}
|
||||
|
||||
# Do sub-completion for pre-command modifiers.
|
||||
|
|
|
@ -210,6 +210,7 @@ struct cmatch {
|
|||
int flags; /* see CMF_* below */
|
||||
int brpl; /* the place where to put the brace prefix */
|
||||
int brsl; /* ...and the suffix */
|
||||
char *rems; /* when to remove the suffix */
|
||||
};
|
||||
|
||||
#define CMF_FILE 1 /* this is a file */
|
||||
|
@ -272,3 +273,12 @@ struct cline {
|
|||
|
||||
#define CFN_FIRST 1
|
||||
#define CFN_DEFAULT 2
|
||||
|
||||
/* Flags for compadd and addmatches(). */
|
||||
|
||||
#define CAF_QUOTE 1
|
||||
#define CAF_MENU 2
|
||||
#define CAF_NOSORT 4
|
||||
#define CAF_ALT 8
|
||||
#define CAF_FIGNORE 16
|
||||
#define CAF_MATCH 32
|
||||
|
|
|
@ -49,7 +49,7 @@ void (*makecompparamsptr) _((void));
|
|||
/* pointers to functions required by compctl and defined by zle */
|
||||
|
||||
/**/
|
||||
void (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, int, int, int, int, int, char **));
|
||||
void (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char **));
|
||||
|
||||
/**/
|
||||
char *(*comp_strptr) _((int*,int*));
|
||||
|
@ -95,7 +95,8 @@ int incompfunc;
|
|||
|
||||
/**/
|
||||
long compcurrent,
|
||||
compnmatches;
|
||||
compnmatches,
|
||||
compmatcher;
|
||||
|
||||
/**/
|
||||
char *compcontext,
|
||||
|
@ -104,14 +105,8 @@ char *compcontext,
|
|||
*compsuffix,
|
||||
*compiprefix;
|
||||
|
||||
/* This variable and the functions rembslash() and quotename() came from *
|
||||
* zle_tricky.c, but are now used in compctl.c, too. */
|
||||
|
||||
/* 1 if we are completing in a string */
|
||||
|
||||
/**/
|
||||
int instring;
|
||||
|
||||
/* The function rembslash() came from zle_tricky.c, but is now used *
|
||||
* in compctl.c, too. */
|
||||
|
||||
/**/
|
||||
static void
|
||||
|
@ -395,70 +390,6 @@ rembslash(char *s)
|
|||
return t;
|
||||
}
|
||||
|
||||
/* Quote the string s and return the result. If e is non-zero, the *
|
||||
* pointer it points to may point to a position in s and in e the position *
|
||||
* of the corresponding character in the quoted string is returned. Like *
|
||||
* e, te may point to a position in the string and pl is used to return *
|
||||
* the position of the character pointed to by te in the quoted string. *
|
||||
* The string is metafied and may contain tokens. */
|
||||
|
||||
/**/
|
||||
char *
|
||||
quotename(const char *s, char **e, char *te, int *pl)
|
||||
{
|
||||
const char *u, *tt;
|
||||
char *v, buf[PATH_MAX * 2];
|
||||
int sf = 0;
|
||||
|
||||
tt = v = buf;
|
||||
u = s;
|
||||
for (; *u; u++) {
|
||||
if (e && *e == u)
|
||||
*e = v, sf |= 1;
|
||||
if (te == u)
|
||||
*pl = v - tt, sf |= 2;
|
||||
if (ispecial(*u) &&
|
||||
(!instring || (isset(BANGHIST) &&
|
||||
*u == (char)bangchar) ||
|
||||
(instring == 2 &&
|
||||
(*u == '$' || *u == '`' || *u == '\"')) ||
|
||||
(instring == 1 && *u == '\''))) {
|
||||
if (*u == '\n' || (instring == 1 && *u == '\'')) {
|
||||
if (unset(RCQUOTES)) {
|
||||
*v++ = '\'';
|
||||
if (*u == '\'')
|
||||
*v++ = '\\';
|
||||
*v++ = *u;
|
||||
*v++ = '\'';
|
||||
} else if (*u == '\n')
|
||||
*v++ = '"', *v++ = '\n', *v++ = '"';
|
||||
else
|
||||
*v++ = '\'', *v++ = '\'';
|
||||
continue;
|
||||
} else
|
||||
*v++ = '\\';
|
||||
}
|
||||
if(*u == Meta)
|
||||
*v++ = *u++;
|
||||
*v++ = *u;
|
||||
}
|
||||
*v = '\0';
|
||||
if (strcmp(buf, s))
|
||||
tt = dupstring(buf);
|
||||
else
|
||||
tt = s;
|
||||
v += tt - buf;
|
||||
if (e && (sf & 1))
|
||||
*e += tt - buf;
|
||||
|
||||
if (e && *e == u)
|
||||
*e = v;
|
||||
if (te == u)
|
||||
*pl = v - tt;
|
||||
|
||||
return (char *) tt;
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
setup_comp1(Module m)
|
||||
|
|
|
@ -14,6 +14,7 @@ compcontext
|
|||
compctltab
|
||||
compcurrent
|
||||
compiprefix
|
||||
compmatcher
|
||||
compnmatches
|
||||
compprefix
|
||||
comp_strptr
|
||||
|
@ -30,5 +31,4 @@ makecomplistcallptr
|
|||
makecomplistctlptr
|
||||
makecompparamsptr
|
||||
patcomps
|
||||
quotename
|
||||
rembslash
|
||||
|
|
|
@ -1385,7 +1385,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat)
|
|||
untokenize(p);
|
||||
quotedzputs(p, stdout);
|
||||
} else
|
||||
quotedzputs(quotename(s, NULL, NULL, NULL), stdout);
|
||||
quotedzputs(bslashquote(s, NULL, NULL, NULL, 0), stdout);
|
||||
}
|
||||
|
||||
/* loop through flags w/o args that are set, printing them if so */
|
||||
|
@ -1515,7 +1515,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat)
|
|||
char *p = dupstring(s);
|
||||
|
||||
untokenize(p);
|
||||
quotedzputs(quotename(p, NULL, NULL, NULL), stdout);
|
||||
quotedzputs(bslashquote(p, NULL, NULL, NULL, 0), stdout);
|
||||
}
|
||||
}
|
||||
putchar('\n');
|
||||
|
@ -1547,8 +1547,6 @@ bin_compctl(char *name, char **argv, char *ops, int func)
|
|||
cclist = 0;
|
||||
showmask = 0;
|
||||
|
||||
instring = 0;
|
||||
|
||||
/* Parse all the arguments */
|
||||
if (*argv) {
|
||||
/* Let's see if this is a global matcher definition. */
|
||||
|
@ -1671,8 +1669,9 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
|||
{
|
||||
char *p, **sp, *e;
|
||||
char *ipre = NULL, *ppre = NULL, *psuf = NULL, *prpre = NULL;
|
||||
char *pre = NULL, *suf = NULL, *group = NULL;
|
||||
int f = 0, q = 0, m = 0, ns = 0, a = 0;
|
||||
char *pre = NULL, *suf = NULL, *group = NULL, *m = NULL, *rs = NULL;
|
||||
int f = 0, a = 0, dm;
|
||||
Cmatcher match = NULL;
|
||||
|
||||
if (incompfunc != 1) {
|
||||
zerrnam(name, "can only be called from completion function", NULL, 0);
|
||||
|
@ -1681,21 +1680,25 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
|||
for (; *argv && **argv == '-'; argv++) {
|
||||
for (p = *argv + 1; *p; p++) {
|
||||
sp = NULL;
|
||||
dm = 0;
|
||||
switch (*p) {
|
||||
case 'q':
|
||||
f |= CMF_REMOVE;
|
||||
break;
|
||||
case 'Q':
|
||||
q = 1;
|
||||
a |= CAF_QUOTE;
|
||||
break;
|
||||
case 'f':
|
||||
f |= CMF_FILE;
|
||||
break;
|
||||
case 'F':
|
||||
a |= CAF_FIGNORE;
|
||||
break;
|
||||
case 'n':
|
||||
f |= CMF_NOLIST;
|
||||
break;
|
||||
case 'U':
|
||||
m = 1;
|
||||
a |= CAF_MENU;
|
||||
break;
|
||||
case 'P':
|
||||
sp = ⪯
|
||||
|
@ -1711,7 +1714,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
|||
break;
|
||||
case 'V':
|
||||
if (!group)
|
||||
ns = 1;
|
||||
a |= CAF_NOSORT;
|
||||
sp = &group;
|
||||
e = "group name expected after -%c";
|
||||
break;
|
||||
|
@ -1732,7 +1735,19 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
|||
e = "string expected after -%c";
|
||||
break;
|
||||
case 'a':
|
||||
a = 1;
|
||||
a |= CAF_ALT;
|
||||
break;
|
||||
case 'm':
|
||||
a |= CAF_MATCH;
|
||||
break;
|
||||
case 'M':
|
||||
sp = &m;
|
||||
e = "matching specification expected after -%c";
|
||||
dm = 1;
|
||||
break;
|
||||
case 'r':
|
||||
sp = &rs;
|
||||
e = "string expected after -%c";
|
||||
break;
|
||||
case '-':
|
||||
argv++;
|
||||
|
@ -1756,6 +1771,10 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
|||
zerrnam(name, e, NULL, *p);
|
||||
return 1;
|
||||
}
|
||||
if (dm && (match = parse_cmatcher(name, m)) == pcm_err) {
|
||||
match = NULL;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1764,7 +1783,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
|||
return 1;
|
||||
|
||||
addmatchesptr(ipre, ppre, psuf, prpre, pre, suf, group,
|
||||
f, q, m, ns, a, argv);
|
||||
rs, f, a, match, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1794,6 +1813,7 @@ static struct compparam {
|
|||
{ "SUFFIX", PM_SCALAR, VAR(compsuffix) },
|
||||
{ "IPREFIX", PM_SCALAR, VAR(compiprefix) },
|
||||
{ "NMATCHES", PM_INTEGER, VAR(compnmatches) },
|
||||
{ "MATCHER", PM_INTEGER, VAR(compmatcher) },
|
||||
{ NULL, 0, NULL }
|
||||
};
|
||||
|
||||
|
@ -2096,6 +2116,15 @@ cond_nmatches(char **a, int id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
cond_matcher(char **a, int id)
|
||||
{
|
||||
if (comp_check())
|
||||
return compmatcher == cond_val(a, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct builtin bintab[] = {
|
||||
BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("complist", 0, bin_complist, 1, -1, 0, NULL, NULL),
|
||||
|
@ -2119,6 +2148,7 @@ static struct conddef cotab[] = {
|
|||
CONDDEF("after", 0, cond_range, 1, 1, 0),
|
||||
CONDDEF("mafter", 0, cond_range, 1, 1, 1),
|
||||
CONDDEF("nmatches", 0, cond_nmatches, 1, 1, 0),
|
||||
CONDDEF("matcher", 0, cond_matcher, 1, 1, 0),
|
||||
};
|
||||
|
||||
static struct funcwrap wrapper[] = {
|
||||
|
|
|
@ -663,6 +663,11 @@ doisearch(int dir)
|
|||
static char *previous_search = NULL;
|
||||
static int previous_search_len = 0;
|
||||
|
||||
invalidatelist();
|
||||
moveto(0, 0);
|
||||
clearflag = 0;
|
||||
resetneeded = 1;
|
||||
|
||||
strcpy(ibuf, ISEARCH_PROMPT);
|
||||
memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
|
||||
remember_edits();
|
||||
|
@ -943,6 +948,10 @@ getvisrchstr(void)
|
|||
zsfree(visrchstr);
|
||||
visrchstr = NULL;
|
||||
}
|
||||
invalidatelist();
|
||||
moveto(0, 0);
|
||||
clearflag = 0;
|
||||
resetneeded = 1;
|
||||
statusline = sbuf;
|
||||
sbuf[0] = (visrchsense == -1) ? '?' : '/';
|
||||
selectkeymap("main", 1);
|
||||
|
|
|
@ -661,10 +661,17 @@ bin_vared(char *name, char **args, char *ops, int func)
|
|||
{
|
||||
char *s;
|
||||
char *t;
|
||||
Param pm;
|
||||
Value v;
|
||||
Param pm = 0;
|
||||
int create = 0;
|
||||
int type = PM_SCALAR;
|
||||
char *p1 = NULL, *p2 = NULL;
|
||||
|
||||
if (zleactive) {
|
||||
zwarnnam(name, "ZLE cannot be used recursively (yet)", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* all options are handled as arguments */
|
||||
while (*args && **args == '-') {
|
||||
while (*++(*args))
|
||||
|
@ -674,6 +681,12 @@ bin_vared(char *name, char **args, char *ops, int func)
|
|||
yet exist */
|
||||
create = 1;
|
||||
break;
|
||||
case 'a':
|
||||
type = PM_ARRAY;
|
||||
break;
|
||||
case 'A':
|
||||
type = PM_HASHED;
|
||||
break;
|
||||
case 'p':
|
||||
/* -p option -- set main prompt string */
|
||||
if ((*args)[1])
|
||||
|
@ -709,6 +722,9 @@ bin_vared(char *name, char **args, char *ops, int func)
|
|||
}
|
||||
args++;
|
||||
}
|
||||
if (type && !create) {
|
||||
zwarnnam(name, "-%s ignored", type == PM_ARRAY ? "a" : "A", 0);
|
||||
}
|
||||
|
||||
/* check we have a parameter name */
|
||||
if (!*args) {
|
||||
|
@ -716,17 +732,17 @@ bin_vared(char *name, char **args, char *ops, int func)
|
|||
return 1;
|
||||
}
|
||||
/* handle non-existent parameter */
|
||||
if (!(s = getsparam(args[0]))) {
|
||||
if (create)
|
||||
createparam(args[0], PM_SCALAR);
|
||||
else {
|
||||
zwarnnam(name, "no such variable: %s", args[0], 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(zleactive) {
|
||||
zwarnnam(name, "ZLE cannot be used recursively (yet)", NULL, 0);
|
||||
s = args[0];
|
||||
v = fetchvalue(&s, (!create || type == PM_SCALAR),
|
||||
SCANPM_WANTKEYS|SCANPM_WANTVALS|SCANPM_MATCHMANY);
|
||||
if (!v && !create) {
|
||||
zwarnnam(name, "no such variable: %s", args[0], 0);
|
||||
return 1;
|
||||
} else if (v) {
|
||||
s = getstrvalue(v);
|
||||
pm = v->pm;
|
||||
} else if (*s) {
|
||||
zwarnnam(name, "invalid parameter name: %s", args[0], 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -744,14 +760,24 @@ bin_vared(char *name, char **args, char *ops, int func)
|
|||
if (t[strlen(t) - 1] == '\n')
|
||||
t[strlen(t) - 1] = '\0';
|
||||
/* final assignment of parameter value */
|
||||
pm = (Param) paramtab->getnode(paramtab, args[0]);
|
||||
if (pm && PM_TYPE(pm->flags) == PM_ARRAY) {
|
||||
if (create && (!pm || (type && PM_TYPE(pm->flags) != type))) {
|
||||
if (pm)
|
||||
unsetparam(args[0]);
|
||||
createparam(args[0], type);
|
||||
pm = 0;
|
||||
}
|
||||
if (!pm)
|
||||
pm = (Param) paramtab->getnode(paramtab, args[0]);
|
||||
if (pm && (PM_TYPE(pm->flags) & (PM_ARRAY|PM_HASHED))) {
|
||||
char **a;
|
||||
|
||||
PERMALLOC {
|
||||
a = spacesplit(t, 1);
|
||||
} LASTALLOC;
|
||||
setaparam(args[0], a);
|
||||
if (PM_TYPE(pm->flags) == PM_ARRAY)
|
||||
setaparam(args[0], a);
|
||||
else
|
||||
sethparam(args[0], a);
|
||||
} else
|
||||
setsparam(args[0], t);
|
||||
return 0;
|
||||
|
@ -766,6 +792,10 @@ describekeybriefly(void)
|
|||
|
||||
if (statusline)
|
||||
return;
|
||||
invalidatelist();
|
||||
moveto(0, 0);
|
||||
clearflag = 0;
|
||||
resetneeded = 1;
|
||||
statusline = "Describe key briefly: _";
|
||||
statusll = strlen(statusline);
|
||||
zrefresh();
|
||||
|
|
|
@ -612,6 +612,10 @@ executenamedcommand(char *prmt)
|
|||
char *ptr;
|
||||
char *okeymap = curkeymapname;
|
||||
|
||||
invalidatelist();
|
||||
moveto(0, 0);
|
||||
clearflag = 0;
|
||||
resetneeded = 1;
|
||||
cmdbuf = halloc(l + NAMLEN + 2);
|
||||
strcpy(cmdbuf, prmt);
|
||||
statusline = cmdbuf;
|
||||
|
@ -792,6 +796,49 @@ makeparamsuffix(int br, int n)
|
|||
}
|
||||
}
|
||||
|
||||
/* Set up suffix given a string containing the characters on which to *
|
||||
* remove the suffix. */
|
||||
|
||||
/**/
|
||||
void
|
||||
makesuffixstr(char *s, int n)
|
||||
{
|
||||
if (s) {
|
||||
int inv, i, v, z = 0;
|
||||
|
||||
if (*s == '^' || *s == '!') {
|
||||
inv = 1;
|
||||
s++;
|
||||
} else
|
||||
inv = 0;
|
||||
s = getkeystring(s, &i, 5, &z);
|
||||
s = metafy(s, i, META_USEHEAP);
|
||||
|
||||
if (inv) {
|
||||
v = 0;
|
||||
for (i = 0; i < 257; i++)
|
||||
suffixlen[i] = n;
|
||||
} else
|
||||
v = n;
|
||||
|
||||
if (z)
|
||||
suffixlen[256] = v;
|
||||
|
||||
while (*s) {
|
||||
if (s[1] == '-' && s[2]) {
|
||||
int b = (int) *s, e = (int) s[2];
|
||||
|
||||
while (b <= e)
|
||||
suffixlen[b++] = v;
|
||||
s += 2;
|
||||
} else
|
||||
suffixlen[STOUC(*s)] = v;
|
||||
s++;
|
||||
}
|
||||
} else
|
||||
makesuffix(n);
|
||||
}
|
||||
|
||||
/* Remove suffix, if there is one, when inserting character c. */
|
||||
|
||||
/**/
|
||||
|
|
|
@ -390,7 +390,7 @@ scanlistwidgets(HashNode hn, int list)
|
|||
if(w->flags & WIDGET_INT)
|
||||
return;
|
||||
if(list) {
|
||||
fputs("zle -N ", stdout);
|
||||
printf("zle -%c ", (w->flags & WIDGET_NCOMP) ? 'C' : 'N');
|
||||
if(t->nam[0] == '-')
|
||||
fputs("-- ", stdout);
|
||||
quotedzputs(t->nam, stdout);
|
||||
|
@ -406,7 +406,7 @@ scanlistwidgets(HashNode hn, int list)
|
|||
} else {
|
||||
nicezputs(t->nam, stdout);
|
||||
if (w->flags & WIDGET_NCOMP) {
|
||||
fputs(" -c ", stdout);
|
||||
fputs(" -C ", stdout);
|
||||
nicezputs(w->u.comp.wid, stdout);
|
||||
fputc(' ', stdout);
|
||||
nicezputs(w->u.comp.func, stdout);
|
||||
|
|
|
@ -223,7 +223,7 @@ typedef struct aminfo *Aminfo;
|
|||
|
||||
struct aminfo {
|
||||
int cpl, csl, icpl, icsl; /* common prefix/suffix lengths */
|
||||
int prerest; /* minimum prefix rest */
|
||||
int minlen; /* minimum match length */
|
||||
int suflen; /* minimum suffix length */
|
||||
Cmatch firstm; /* the first match */
|
||||
char *pprefix; /* common part of the -P prefixes */
|
||||
|
@ -270,6 +270,19 @@ enum { COMP_COMPLETE,
|
|||
COMP_LIST_EXPAND };
|
||||
#define COMP_ISEXPAND(X) ((X) >= COMP_EXPAND)
|
||||
|
||||
/* Non-zero if the last completion done was ambiguous (used to find *
|
||||
* out if AUTOMENU should start). More precisely, it's nonzero after *
|
||||
* successfully doing any completion, unless the completion was *
|
||||
* unambiguous and did not cause the display of a completion list. *
|
||||
* From the other point of view, it's nonzero iff AUTOMENU (if set) *
|
||||
* should kick in on another completion. *
|
||||
* *
|
||||
* If both AUTOMENU and BASHAUTOLIST are set, then we get a listing *
|
||||
* on the second tab, a` la bash, and then automenu kicks in when *
|
||||
* lastambig == 2. */
|
||||
|
||||
static int lastambig;
|
||||
|
||||
/**/
|
||||
void
|
||||
completecall(void)
|
||||
|
@ -287,8 +300,13 @@ completeword(void)
|
|||
useglob = isset(GLOBCOMPLETE);
|
||||
if (c == '\t' && usetab())
|
||||
selfinsert();
|
||||
else
|
||||
docomplete(COMP_COMPLETE);
|
||||
else {
|
||||
if (lastambig == 1 && isset(BASHAUTOLIST) && !usemenu && !menucmp) {
|
||||
docomplete(COMP_LIST_COMPLETE);
|
||||
lastambig = 2;
|
||||
} else
|
||||
docomplete(COMP_COMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
|
@ -358,8 +376,13 @@ expandorcomplete(void)
|
|||
useglob = isset(GLOBCOMPLETE);
|
||||
if (c == '\t' && usetab())
|
||||
selfinsert();
|
||||
else
|
||||
docomplete(COMP_EXPAND_COMPLETE);
|
||||
else {
|
||||
if (lastambig == 1 && isset(BASHAUTOLIST) && !usemenu && !menucmp) {
|
||||
docomplete(COMP_LIST_COMPLETE);
|
||||
lastambig = 2;
|
||||
} else
|
||||
docomplete(COMP_EXPAND_COMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
|
@ -451,15 +474,6 @@ static int lincmd, linredir;
|
|||
|
||||
static char *rdstr;
|
||||
|
||||
/* Non-zero if the last completion done was ambiguous (used to find *
|
||||
* out if AUTOMENU should start). More precisely, it's nonzero after *
|
||||
* successfully doing any completion, unless the completion was *
|
||||
* unambiguous and did not cause the display of a completion list. *
|
||||
* From the other point of view, it's nonzero iff AUTOMENU (if set) *
|
||||
* should kick in on another completion. */
|
||||
|
||||
static int lastambig;
|
||||
|
||||
/* This holds the name of the current command (used to find the right *
|
||||
* compctl). */
|
||||
|
||||
|
@ -473,6 +487,16 @@ static char *varname;
|
|||
|
||||
static int insubscr;
|
||||
|
||||
/* 1 if we are completing in a string */
|
||||
|
||||
/**/
|
||||
int instring;
|
||||
|
||||
/* Convenience macro for calling bslashquote() (formerly quotename()). *
|
||||
* This uses the instring variable above. */
|
||||
|
||||
#define quotename(s, e, te, pl) bslashquote(s, e, te, pl, instring)
|
||||
|
||||
/* Check if the given string is the name of a parameter and if this *
|
||||
* parameter is one worth expanding. */
|
||||
|
||||
|
@ -569,7 +593,8 @@ docomplete(int lst)
|
|||
|
||||
/* Check if we have to start a menu-completion (via automenu). */
|
||||
|
||||
if ((amenu = (isset(AUTOMENU) && lastambig)))
|
||||
if ((amenu = (isset(AUTOMENU) && lastambig &&
|
||||
(!isset(BASHAUTOLIST) || lastambig == 2))))
|
||||
usemenu = 1;
|
||||
|
||||
/* Expand history references before starting completion. If anything *
|
||||
|
@ -919,7 +944,7 @@ unmetafy_line(void)
|
|||
static char *
|
||||
get_comp_string(void)
|
||||
{
|
||||
int t0, tt0, i, j, k, cp, rd, sl, ocs, ins, oins;
|
||||
int t0, tt0, i, j, k, cp, rd, sl, ocs, ins, oins, inarr, ia, parct;
|
||||
char *s = NULL, *linptr, *tmp, *p, *tt = NULL;
|
||||
|
||||
zsfree(brbeg);
|
||||
|
@ -982,7 +1007,7 @@ get_comp_string(void)
|
|||
inpush(dupstrspace((char *) linptr), 0, NULL);
|
||||
strinbeg();
|
||||
stophist = 2;
|
||||
i = tt0 = cp = rd = ins = oins = 0;
|
||||
i = tt0 = cp = rd = ins = oins = inarr = parct = ia = 0;
|
||||
|
||||
/* This loop is possibly the wrong way to do this. It goes through *
|
||||
* the previously massaged command line using the lexer. It stores *
|
||||
|
@ -1001,7 +1026,21 @@ get_comp_string(void)
|
|||
linredir = (inredir && !ins);
|
||||
oins = ins;
|
||||
/* Get the next token. */
|
||||
if (inarr)
|
||||
incmdpos = 0;
|
||||
ctxtlex();
|
||||
if (tok == ENVARRAY) {
|
||||
inarr = 1;
|
||||
zsfree(varname);
|
||||
varname = ztrdup(tokstr);
|
||||
} else if (tok == INPAR)
|
||||
parct++;
|
||||
else if (tok == OUTPAR) {
|
||||
if (parct)
|
||||
parct--;
|
||||
else
|
||||
inarr = 0;
|
||||
}
|
||||
if (inredir)
|
||||
rdstr = tokstrings[tok];
|
||||
if (tok == DINPAR)
|
||||
|
@ -1043,6 +1082,7 @@ get_comp_string(void)
|
|||
clwpos = i;
|
||||
cp = lincmd;
|
||||
rd = linredir;
|
||||
ia = inarr;
|
||||
if (inwhat == IN_NOTHING && incond)
|
||||
inwhat = IN_COND;
|
||||
} else if (linredir)
|
||||
|
@ -1084,8 +1124,13 @@ get_comp_string(void)
|
|||
zsfree(clwords[clwnum]);
|
||||
clwords[clwnum] = NULL;
|
||||
t0 = tt0;
|
||||
lincmd = cp;
|
||||
linredir = rd;
|
||||
if (ia) {
|
||||
lincmd = linredir = 0;
|
||||
inwhat = IN_ENV;
|
||||
} else {
|
||||
lincmd = cp;
|
||||
linredir = rd;
|
||||
}
|
||||
strinend();
|
||||
inpop();
|
||||
errflag = zleparse = 0;
|
||||
|
@ -1789,9 +1834,17 @@ inst_cline(Cline l, int pl, int sl)
|
|||
pl += brpl;
|
||||
|
||||
i = cs - wb;
|
||||
if (pl >= 0 && i >= pl && brbeg && *brbeg) {
|
||||
inststrlen(brbeg, 1, -1);
|
||||
pl = -1;
|
||||
hb = 1;
|
||||
}
|
||||
if (sl >= 0 && i >= sl && brend && *brend) {
|
||||
inststrlen(brend, 1, -1);
|
||||
sl = -1;
|
||||
hb = 1;
|
||||
}
|
||||
while (l) {
|
||||
if (d < 0 && (l->flags & CLF_DIFF))
|
||||
d = cs;
|
||||
if (m < 0 && (l->flags & (CLF_MISS | CLF_SUF)) == (CLF_MISS | CLF_SUF))
|
||||
m = cs;
|
||||
if (l->flags & CLF_MID) {
|
||||
|
@ -1805,6 +1858,8 @@ inst_cline(Cline l, int pl, int sl)
|
|||
} else {
|
||||
inststrlen(l->line, 1, l->llen);
|
||||
}
|
||||
if (d < 0 && (l->flags & CLF_DIFF))
|
||||
d = cs;
|
||||
if (m < 0 && (l->flags & CLF_MISS))
|
||||
m = cs;
|
||||
i += l->llen;
|
||||
|
@ -1893,8 +1948,10 @@ match_pfx(char *l, char *w, Cline *nlp, int *lp, Cline *rlp, int *bplp,
|
|||
while (ll && lw) {
|
||||
for (ms = mstack; ms; ms = ms->next) {
|
||||
for (mp = ms->matcher; mp; mp = mp->next) {
|
||||
if (nm == mp || lm == mp)
|
||||
if (nm == mp || lm == mp) {
|
||||
nm = NULL;
|
||||
continue;
|
||||
}
|
||||
t = 1;
|
||||
/* Try to match the prefix, if any. */
|
||||
if (mp->flags & CMF_LEFT) {
|
||||
|
@ -1930,7 +1987,7 @@ match_pfx(char *l, char *w, Cline *nlp, int *lp, Cline *rlp, int *bplp,
|
|||
NULL, NULL, mp))
|
||||
break;
|
||||
}
|
||||
if (k) {
|
||||
if (k && i) {
|
||||
if (nlp) {
|
||||
nw = addtoword(&rw, &rwlen, nw, mp,
|
||||
l, w, i, 0);
|
||||
|
@ -2106,8 +2163,10 @@ match_sfx(char *l, char *w, Cline *nlp, int *lp, int *bslp, Cmatcher nm)
|
|||
while (ll && lw) {
|
||||
for (ms = mstack; ms; ms = ms->next) {
|
||||
for (mp = ms->matcher; mp; mp = mp->next) {
|
||||
if (nm == mp || lm == mp)
|
||||
if (nm == mp || lm == mp) {
|
||||
nm = NULL;
|
||||
continue;
|
||||
}
|
||||
t = 1;
|
||||
if (mp->flags & CMF_RIGHT) {
|
||||
if (il < mp->ralen || iw < mp->ralen)
|
||||
|
@ -2135,13 +2194,13 @@ match_sfx(char *l, char *w, Cline *nlp, int *lp, int *bslp, Cmatcher nm)
|
|||
if (t) {
|
||||
int i = 0, j = iw, k = lw;
|
||||
int jj = il + mp->llen, kk = ll - mp->llen;
|
||||
char *p = l - mp->llen, *q = w;
|
||||
char *p = l - mp->llen - 1, *q = w - 1;
|
||||
|
||||
for (; k; i++, j++, k--, q--)
|
||||
if (match_sfx(p, q, NULL, NULL,
|
||||
NULL, mp))
|
||||
if (match_pfx(p, q, NULL, NULL,
|
||||
NULL, NULL, mp))
|
||||
break;
|
||||
if (k) {
|
||||
if (k && i) {
|
||||
if (nlp) {
|
||||
nw = addtoword(&rw, &rwlen, nw, mp,
|
||||
l - mp->llen, w - i,
|
||||
|
@ -2151,10 +2210,10 @@ match_sfx(char *l, char *w, Cline *nlp, int *lp, int *bslp, Cmatcher nm)
|
|||
((mp->flags & CMF_LEFT) ?
|
||||
CLF_SUF : 0));
|
||||
}
|
||||
w = q;
|
||||
w = q + 1;
|
||||
iw = j;
|
||||
lw = k;
|
||||
l = p;
|
||||
l = p + 1;
|
||||
il = jj;
|
||||
ll = kk;
|
||||
bc -= i;
|
||||
|
@ -2395,20 +2454,45 @@ instmatch(Cmatch m)
|
|||
/**/
|
||||
void
|
||||
addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
|
||||
char *suf, char *group,
|
||||
int flags, int quote, int menu, int nosort, int alt, char **argv)
|
||||
char *suf, char *group, char *rems,
|
||||
int flags, int aflags, Cmatcher match, char **argv)
|
||||
{
|
||||
char *s, *t;
|
||||
int lpl, lsl, i;
|
||||
Aminfo ai = (alt ? fainfo : ainfo);
|
||||
char *s, *t, *e, *te, *ms, *lipre = NULL, *lpre, *lsuf;
|
||||
int lpl, lsl, i, pl, sl, test, bpl, bsl, lsm, llpl;
|
||||
Aminfo ai;
|
||||
Cline lc = NULL;
|
||||
LinkList l;
|
||||
Cmatch cm;
|
||||
struct cmlist mst;
|
||||
Cmlist oms = mstack;
|
||||
|
||||
if (menu && isset(AUTOMENU))
|
||||
if (aflags & CAF_ALT) {
|
||||
l = fmatches;
|
||||
ai = fainfo;
|
||||
} else {
|
||||
l = matches;
|
||||
ai = ainfo;
|
||||
}
|
||||
if (match) {
|
||||
mst.next = mstack;
|
||||
mst.matcher = match;
|
||||
mstack = &mst;
|
||||
}
|
||||
if ((aflags & CAF_MENU) && isset(AUTOMENU))
|
||||
usemenu = 1;
|
||||
SWITCHHEAPS(compheap) {
|
||||
HEAPALLOC {
|
||||
if (aflags & CAF_MATCH) {
|
||||
ctokenize(lipre = dupstring(compiprefix));
|
||||
remnulargs(lipre);
|
||||
ctokenize(lpre = dupstring(compprefix));
|
||||
remnulargs(lpre);
|
||||
llpl = strlen(lpre);
|
||||
ctokenize(lsuf = dupstring(compsuffix));
|
||||
remnulargs(lsuf);
|
||||
}
|
||||
if (ipre)
|
||||
ipre = dupstring(ipre);
|
||||
ipre = (lipre ? dyncat(lipre, ipre) : dupstring(ipre));
|
||||
if (ppre) {
|
||||
ppre = dupstring(ppre);
|
||||
lpl = strlen(ppre);
|
||||
|
@ -2419,6 +2503,8 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
|
|||
lsl = strlen(psuf);
|
||||
} else
|
||||
lsl = 0;
|
||||
if (aflags & CAF_MATCH)
|
||||
lsm = (psuf ? !strcmp(psuf, lsuf) : (!lsuf || !*lsuf));
|
||||
if (pre)
|
||||
pre = dupstring(pre);
|
||||
if (suf)
|
||||
|
@ -2430,10 +2516,12 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
|
|||
prpre = dupstring(prpre);
|
||||
if (group) {
|
||||
endcmgroup(NULL);
|
||||
begcmgroup(group, nosort);
|
||||
if (nosort)
|
||||
begcmgroup(group, (aflags & CAF_NOSORT));
|
||||
if (aflags & CAF_NOSORT)
|
||||
mgroup->flags |= CGF_NOSORT;
|
||||
}
|
||||
if (rems)
|
||||
rems = dupstring(rems);
|
||||
if (ai->pprefix) {
|
||||
if (pre)
|
||||
ai->pprefix[pfxlen(ai->pprefix, pre)] = '\0';
|
||||
|
@ -2442,10 +2530,54 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
|
|||
} else
|
||||
ai->pprefix = dupstring(pre ? pre : "");
|
||||
|
||||
for (; (s = *argv); argv++) {
|
||||
if (ai->firstm) {
|
||||
if ((i = pfxlen(ai->firstm->str, s)) < ai->prerest)
|
||||
ai->prerest = i;
|
||||
for (; (s = dupstring(*argv)); argv++) {
|
||||
sl = strlen(s);
|
||||
ms = NULL;
|
||||
bpl = brpl;
|
||||
bsl = brsl;
|
||||
if ((!psuf || !*psuf) && (aflags & CAF_FIGNORE)) {
|
||||
char **pt = fignore;
|
||||
int filell;
|
||||
|
||||
for (test = 1; test && *pt; pt++)
|
||||
if ((filell = strlen(*pt)) < sl
|
||||
&& !strcmp(*pt, s + sl - filell))
|
||||
test = 0;
|
||||
|
||||
if (!test) {
|
||||
l = fmatches;
|
||||
ai = fainfo;
|
||||
} else {
|
||||
l = matches;
|
||||
ai = ainfo;
|
||||
}
|
||||
}
|
||||
if (aflags & CAF_MATCH) {
|
||||
t = (ppre ? dyncat(ppre, s) : s);
|
||||
pl = sl + lpl;
|
||||
if ((test = (llpl <= pl && !strncmp(t, lpre, pl))))
|
||||
test = lsm;
|
||||
if (!test && mstack &&
|
||||
(ms = comp_match(lpre, lsuf,
|
||||
(psuf ? dyncat(t, psuf) : t),
|
||||
&lc, (aflags & CAF_QUOTE),
|
||||
&bpl, &bsl)))
|
||||
test = 1;
|
||||
if (!test)
|
||||
continue;
|
||||
e = s + sl;
|
||||
} else {
|
||||
e = s;
|
||||
pl = lpl;
|
||||
}
|
||||
if (!(aflags & CAF_QUOTE)) {
|
||||
te = s + pl;
|
||||
s = quotename(s, &e, te, &pl);
|
||||
sl = strlen(s);
|
||||
}
|
||||
if (!ms && ai->firstm) {
|
||||
if (sl < ai->minlen)
|
||||
ai->minlen = sl;
|
||||
if ((i = sfxlen(ai->firstm->str, s)) < ai->suflen)
|
||||
ai->suflen = i;
|
||||
}
|
||||
|
@ -2453,15 +2585,20 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
|
|||
if (ppre)
|
||||
t = dyncat(ppre, t);
|
||||
if (ipre && *ipre) {
|
||||
Cline tlc = prepend_cline(ipre, lc);
|
||||
|
||||
ai->noipre = 0;
|
||||
if (ai->icpl > lpl)
|
||||
ai->icpl = lpl;
|
||||
if (ai->icsl > lsl)
|
||||
ai->icsl = lsl;
|
||||
if (ai->iaprefix)
|
||||
ai->iaprefix[pfxlen(ai->iaprefix, t)] = '\0';
|
||||
else
|
||||
ai->iaprefix = dupstring(t);
|
||||
if (!ms) {
|
||||
if ((aflags & CAF_MATCH) || ai->icpl > pl)
|
||||
ai->icpl = pl;
|
||||
if ((aflags & CAF_MATCH) || ai->icsl > lsl)
|
||||
ai->icsl = lsl;
|
||||
if (ai->iaprefix)
|
||||
ai->iaprefix[pfxlen(ai->iaprefix, t)] = '\0';
|
||||
else
|
||||
ai->iaprefix = dupstring(t);
|
||||
} else
|
||||
ai->ilinecl = join_clines(ai->ilinecl, lc);
|
||||
if (ai->iprefix) {
|
||||
if (strcmp(ipre, ai->iprefix))
|
||||
ai->iprefix = "";
|
||||
|
@ -2469,16 +2606,21 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
|
|||
ai->iprefix = dupstring(ipre);
|
||||
|
||||
t = dyncat(ipre, t);
|
||||
lc = tlc;
|
||||
} else
|
||||
ai->iprefix = "";
|
||||
if (ai->cpl > lpl)
|
||||
ai->cpl = lpl;
|
||||
if (ai->csl > lsl)
|
||||
ai->csl = lsl;
|
||||
if (ai->aprefix)
|
||||
ai->aprefix[pfxlen(ai->aprefix, t)] = '\0';
|
||||
else
|
||||
ai->aprefix = dupstring(t);
|
||||
if (!ms) {
|
||||
if ((aflags & CAF_MATCH) || ai->cpl > pl)
|
||||
ai->cpl = pl;
|
||||
if ((aflags & CAF_MATCH) || ai->csl > lsl)
|
||||
ai->csl = lsl;
|
||||
if (ai->aprefix)
|
||||
ai->aprefix[pfxlen(ai->aprefix, t)] = '\0';
|
||||
else
|
||||
ai->aprefix = dupstring(t);
|
||||
} else
|
||||
ai->linecl = join_clines(ai->linecl, lc);
|
||||
|
||||
mnum++;
|
||||
ai->count++;
|
||||
|
||||
|
@ -2486,25 +2628,41 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
|
|||
cm->ppre = ppre;
|
||||
cm->psuf = psuf;
|
||||
cm->prpre = prpre;
|
||||
if (!quote)
|
||||
s = quotename(s, NULL, NULL, NULL);
|
||||
cm->str = dupstring(s);
|
||||
cm->str = (ms ? ms : dupstring(s));
|
||||
cm->ipre = cm->ripre = ipre;
|
||||
cm->pre = pre;
|
||||
cm->suf = suf;
|
||||
cm->flags = flags;
|
||||
cm->brpl = brpl;
|
||||
cm->brsl = brsl;
|
||||
addlinknode((alt ? fmatches : matches), cm);
|
||||
cm->brpl = bpl;
|
||||
cm->brsl = bsl;
|
||||
cm->rems = rems;
|
||||
addlinknode(l, cm);
|
||||
|
||||
if (expl)
|
||||
expl->fcount++;
|
||||
if (!ai->firstm)
|
||||
ai->firstm = cm;
|
||||
if (expl) {
|
||||
if (l == matches)
|
||||
expl->count++;
|
||||
else
|
||||
expl->fcount++;
|
||||
}
|
||||
if (!ms) {
|
||||
if (!ai->firstm)
|
||||
ai->firstm = cm;
|
||||
if ((aflags & CAF_MATCH) && !(e - (s + pl))) {
|
||||
if (!ai->exact)
|
||||
ai->exact = 1;
|
||||
else {
|
||||
ai->exact = 2;
|
||||
cm = NULL;
|
||||
}
|
||||
ai->exactm = cm;
|
||||
}
|
||||
}
|
||||
}
|
||||
compnmatches = mnum;
|
||||
} LASTALLOC;
|
||||
} SWITCHBACKHEAPS;
|
||||
|
||||
mstack = oms;
|
||||
}
|
||||
|
||||
/* This adds a match to the list of matches. The string to add is given *
|
||||
|
@ -2685,8 +2843,8 @@ addmatch(char *s, char *t)
|
|||
if (!test)
|
||||
return;
|
||||
if (!ms && !ispattern && ai->firstm) {
|
||||
if ((test = sl - pfxlen(ai->firstm->str, s)) < ai->prerest)
|
||||
ai->prerest = test;
|
||||
if (sl < ai->minlen)
|
||||
ai->minlen = sl;
|
||||
if ((test = sfxlen(ai->firstm->str, s)) < ai->suflen)
|
||||
ai->suflen = test;
|
||||
}
|
||||
|
@ -2716,8 +2874,7 @@ addmatch(char *s, char *t)
|
|||
ai->iaprefix[pfxlen(ai->iaprefix, t)] = '\0';
|
||||
else
|
||||
ai->iaprefix = dupstring(t);
|
||||
}
|
||||
else
|
||||
} else
|
||||
ai->ilinecl = join_clines(ai->ilinecl, lc);
|
||||
if (ai->iprefix) {
|
||||
if (strcmp(ipre, ai->iprefix))
|
||||
|
@ -2737,8 +2894,7 @@ addmatch(char *s, char *t)
|
|||
ai->aprefix[pfxlen(ai->aprefix, t)] = '\0';
|
||||
else
|
||||
ai->aprefix = dupstring(t);
|
||||
}
|
||||
else
|
||||
} else
|
||||
ai->linecl = join_clines(ai->linecl, lc);
|
||||
|
||||
mnum++;
|
||||
|
@ -2780,6 +2936,7 @@ addmatch(char *s, char *t)
|
|||
cm->flags = mflags | isf;
|
||||
cm->brpl = bpl;
|
||||
cm->brsl = bsl;
|
||||
cm->rems = NULL;
|
||||
addlinknode(l, cm);
|
||||
|
||||
/* One more match for this explanation. */
|
||||
|
@ -3211,7 +3368,12 @@ callcompfunc(char *s, char *fn)
|
|||
case IN_ENV:
|
||||
compcontext = "value";
|
||||
compcommand = varname;
|
||||
usea = 0;
|
||||
if (!clwpos) {
|
||||
clwpos = 1;
|
||||
zsfree(clwords[1]);
|
||||
clwords[1] = ztrdup(s);
|
||||
}
|
||||
aadd = 1;
|
||||
break;
|
||||
case IN_COND:
|
||||
compcontext = "condition";
|
||||
|
@ -3305,17 +3467,19 @@ makecomplist(char *s, int incmd, int lst)
|
|||
if (validlist)
|
||||
return !nmatches;
|
||||
|
||||
compmatcher = 1;
|
||||
for (;;) {
|
||||
if (m) {
|
||||
ms.next = NULL;
|
||||
ms.matcher = m->matcher;
|
||||
mstack = &ms;
|
||||
}
|
||||
} else
|
||||
mstack = NULL;
|
||||
ainfo = (Aminfo) hcalloc(sizeof(struct aminfo));
|
||||
fainfo = (Aminfo) hcalloc(sizeof(struct aminfo));
|
||||
|
||||
ainfo->prerest = ainfo->suflen =
|
||||
fainfo->prerest = fainfo->suflen = 10000;
|
||||
ainfo->minlen = ainfo->suflen =
|
||||
fainfo->minlen = fainfo->suflen = 10000;
|
||||
ainfo->noipre = fainfo->noipre= 1;
|
||||
|
||||
freecl = NULL;
|
||||
|
@ -3358,12 +3522,14 @@ makecomplist(char *s, int incmd, int lst)
|
|||
break;
|
||||
|
||||
errflag = 0;
|
||||
compmatcher++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This should probably be moved into tokenize(). */
|
||||
|
||||
/**/
|
||||
static char *
|
||||
ctokenize(char *p)
|
||||
{
|
||||
|
@ -3564,10 +3730,11 @@ makecomplistcmd(char *os, int incmd, int flags)
|
|||
}
|
||||
/* Then search the pattern compctls, with the command name and the *
|
||||
* full pathname of the command. */
|
||||
makecomplistpc(os, incmd);
|
||||
if (!(ccont & CC_CCCONT))
|
||||
return;
|
||||
|
||||
if (cmdstr) {
|
||||
makecomplistpc(os, incmd);
|
||||
if (!(ccont & CC_CCCONT))
|
||||
return;
|
||||
}
|
||||
/* If the command string starts with `=', try the path name of the *
|
||||
* command. */
|
||||
if (cmdstr && cmdstr[0] == Equals) {
|
||||
|
@ -5057,6 +5224,7 @@ dupmatch(Cmatch m)
|
|||
r->flags = m->flags;
|
||||
r->brpl = m->brpl;
|
||||
r->brsl = m->brsl;
|
||||
r->rems = ztrdup(m->rems);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -5168,6 +5336,7 @@ freematch(Cmatch m)
|
|||
zsfree(m->ppre);
|
||||
zsfree(m->psuf);
|
||||
zsfree(m->prpre);
|
||||
zsfree(m->rems);
|
||||
|
||||
zfree(m, sizeof(m));
|
||||
}
|
||||
|
@ -5325,10 +5494,11 @@ do_ambiguous(void)
|
|||
* on the next call to completion the inserted string would be *
|
||||
* taken as a match and no menu completion would be started. */
|
||||
|
||||
if (isset(RECEXACT) && !lc && !ainfo->prerest)
|
||||
if (isset(RECEXACT) && !lc && ps && ainfo->minlen == strlen(ps))
|
||||
am = 1;
|
||||
|
||||
/* If the LIST_AMBIGUOUS option (meaning roughly `show a list only *
|
||||
/*
|
||||
* If the LIST_AMBIGUOUS option (meaning roughly `show a list only *
|
||||
* if the completion is completely ambiguous') is set, and some *
|
||||
* prefix was inserted, return now, bypassing the list-displaying *
|
||||
* code. On the way, invalidate the list and note that we don't *
|
||||
|
@ -5344,7 +5514,8 @@ do_ambiguous(void)
|
|||
* if it is needed. */
|
||||
if (isset(LISTBEEP))
|
||||
feep();
|
||||
if (isset(AUTOLIST) && !amenu && !showinglist && smatches >= 2)
|
||||
if (isset(AUTOLIST) && !isset(BASHAUTOLIST) && !amenu && !showinglist &&
|
||||
smatches >= 2)
|
||||
showinglist = -2;
|
||||
if (am)
|
||||
lastambig = 1;
|
||||
|
@ -5420,7 +5591,7 @@ do_single(Cmatch m)
|
|||
if (menuwe) {
|
||||
menuend += menuinsc;
|
||||
if (m->flags & CMF_REMOVE) {
|
||||
makesuffix(menuinsc);
|
||||
makesuffixstr(m->rems, menuinsc);
|
||||
if (menuinsc == 1)
|
||||
suffixlen[STOUC(m->suf[0])] = 1;
|
||||
}
|
||||
|
|
|
@ -816,6 +816,10 @@ viswapcase(void)
|
|||
void
|
||||
vicapslockpanic(void)
|
||||
{
|
||||
invalidatelist();
|
||||
moveto(0, 0);
|
||||
clearflag = 0;
|
||||
resetneeded = 1;
|
||||
zbeep();
|
||||
statusline = "press a lowercase key to continue";
|
||||
statusll = strlen(statusline);
|
||||
|
|
|
@ -1036,6 +1036,9 @@ fixdir(char *src)
|
|||
{
|
||||
char *dest = src;
|
||||
char *d0 = dest;
|
||||
#ifdef __CYGWIN__
|
||||
char *s0 = src;
|
||||
#endif
|
||||
|
||||
/*** if have RFS superroot directory ***/
|
||||
#ifdef HAVE_SUPERROOT
|
||||
|
@ -1052,6 +1055,11 @@ fixdir(char *src)
|
|||
for (;;) {
|
||||
/* compress multiple /es into single */
|
||||
if (*src == '/') {
|
||||
#ifdef __CYGWIN__
|
||||
/* allow leading // under cygwin */
|
||||
if (src == s0 && src[1] == '/')
|
||||
*dest++ = *src++;
|
||||
#endif
|
||||
*dest++ = *src++;
|
||||
while (*src == '/')
|
||||
src++;
|
||||
|
@ -1657,7 +1665,8 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
|
||||
if (on & PM_TIED) {
|
||||
Param apm;
|
||||
char *name1;
|
||||
struct asgment asg0;
|
||||
char *oldval = NULL;
|
||||
|
||||
if (ops['m']) {
|
||||
zwarnnam(name, "incompatible options for -T", NULL, 0);
|
||||
|
@ -1669,36 +1678,61 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!(asg = getasg(argv[0])))
|
||||
return 1;
|
||||
asg0 = *asg;
|
||||
if (!(asg = getasg(argv[1])))
|
||||
return 1;
|
||||
if (!strcmp(asg0.name, asg->name)) {
|
||||
zerrnam(name, "can't tie a variable to itself", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* Keep the old value of the scalar. We need to do this
|
||||
* here as if it is already tied to the same array it
|
||||
* will be unset when we retie the array. This is all
|
||||
* so that typeset -T is idempotent.
|
||||
*
|
||||
* We also need to remember here whether the damn thing is
|
||||
* exported and pass that along. Isn't the world complicated?
|
||||
*/
|
||||
if ((pm = (Param) paramtab->getnode(paramtab, asg0.name))
|
||||
&& !(pm->flags & PM_UNSET)
|
||||
&& (locallevel == pm->level || func == BIN_EXPORT)) {
|
||||
if (!asg0.value && !(PM_TYPE(pm->flags) & (PM_ARRAY|PM_HASHED)))
|
||||
oldval = ztrdup(getsparam(asg0.name));
|
||||
on |= (pm->flags & PM_EXPORTED);
|
||||
}
|
||||
/*
|
||||
* Create the tied array; this is normal except that
|
||||
* it has the PM_TIED flag set. Do it first because
|
||||
* we need the address.
|
||||
*/
|
||||
if (!(asg = getasg(argv[1])))
|
||||
return 1;
|
||||
name1 = ztrdup(asg->name);
|
||||
if (!(apm=typeset_single(name, asg->name,
|
||||
(Param)paramtab->getnode(paramtab,
|
||||
asg->name),
|
||||
func, on | PM_ARRAY, off, roff,
|
||||
asg->value, NULL)))
|
||||
func, (on | PM_ARRAY) & ~PM_EXPORTED,
|
||||
off, roff, asg->value, NULL)))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Create the tied colonarray. We make it as a normal scalar
|
||||
* and fix up the oddities later.
|
||||
*/
|
||||
if (!(asg = getasg(argv[0])) ||
|
||||
!(pm=typeset_single(name, asg->name,
|
||||
if (!(pm=typeset_single(name, asg0.name,
|
||||
(Param)paramtab->getnode(paramtab,
|
||||
asg->name),
|
||||
func, on, off, roff, asg->value, apm))) {
|
||||
asg0.name),
|
||||
func, on, off, roff, asg0.value, apm))) {
|
||||
if (oldval)
|
||||
zsfree(oldval);
|
||||
unsetparam_pm(apm, 1, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pm->ename = name1;
|
||||
apm->ename = ztrdup(asg->name);
|
||||
pm->ename = ztrdup(asg->name);
|
||||
apm->ename = ztrdup(asg0.name);
|
||||
if (oldval)
|
||||
setsparam(asg0.name, oldval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1928,14 +1962,39 @@ bin_unset(char *name, char **argv, char *ops, int func)
|
|||
|
||||
/* do not glob -- unset the given parameter */
|
||||
while ((s = *argv++)) {
|
||||
char *ss = strchr(s, '[');
|
||||
char *sse = ss;
|
||||
if (ss) {
|
||||
if (skipparens('[', ']', &sse) || *sse) {
|
||||
zerrnam(name, "%s: invalid parameter name", s, 0);
|
||||
returnval = 1;
|
||||
continue;
|
||||
}
|
||||
*ss = 0;
|
||||
}
|
||||
pm = (Param) paramtab->getnode(paramtab, s);
|
||||
if (!pm)
|
||||
returnval = 1;
|
||||
else if ((pm->flags & PM_RESTRICTED) && isset(RESTRICTED)) {
|
||||
zerrnam(name, "%s: restricted", pm->nam, 0);
|
||||
returnval = 1;
|
||||
} else if (ss) {
|
||||
if (PM_TYPE(pm->flags) == PM_HASHED) {
|
||||
HashTable tht = paramtab;
|
||||
if ((paramtab = pm->gets.hfn(pm))) {
|
||||
*--sse = 0;
|
||||
unsetparam(ss+1);
|
||||
*sse = ']';
|
||||
}
|
||||
paramtab = tht;
|
||||
} else {
|
||||
zerrnam(name, "%s: invalid element for unset", s, 0);
|
||||
returnval = 1;
|
||||
}
|
||||
} else
|
||||
unsetparam(s);
|
||||
unsetparam_pm(pm, 0, 1);
|
||||
if (ss)
|
||||
*ss = '[';
|
||||
}
|
||||
return returnval;
|
||||
}
|
||||
|
|
27
Src/compat.c
27
Src/compat.c
|
@ -111,12 +111,17 @@ zgetdir(struct dirsav *d)
|
|||
{
|
||||
char nbuf[PATH_MAX+3];
|
||||
char *buf;
|
||||
int bufsiz, pos, len;
|
||||
int bufsiz, pos;
|
||||
struct stat sbuf;
|
||||
ino_t pino;
|
||||
dev_t pdev;
|
||||
#ifndef __CYGWIN__
|
||||
struct dirent *de;
|
||||
DIR *dir;
|
||||
ino_t ino, pino;
|
||||
dev_t dev, pdev;
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
int len;
|
||||
#endif
|
||||
|
||||
buf = halloc(bufsiz = PATH_MAX);
|
||||
pos = bufsiz - 1;
|
||||
|
@ -137,6 +142,7 @@ zgetdir(struct dirsav *d)
|
|||
#ifdef HAVE_FCHDIR
|
||||
else
|
||||
#endif
|
||||
#ifndef __CYGWIN__
|
||||
holdintr();
|
||||
|
||||
for (;;) {
|
||||
|
@ -221,6 +227,21 @@ zgetdir(struct dirsav *d)
|
|||
if (*buf)
|
||||
zchdir(buf + pos + 1);
|
||||
noholdintr();
|
||||
|
||||
#else /* __CYGWIN__ case */
|
||||
|
||||
if (!getcwd(buf, bufsiz)) {
|
||||
if (d) {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (d) {
|
||||
return d->dirname = ztrdup(buf);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
buf[0] = '.';
|
||||
buf[1] = '\0';
|
||||
return buf;
|
||||
|
|
|
@ -148,6 +148,7 @@ parse_string(char *s)
|
|||
return l;
|
||||
}
|
||||
|
||||
/**/
|
||||
#ifdef HAVE_GETRLIMIT
|
||||
|
||||
/* the resource limits for the shell and its children */
|
||||
|
@ -184,6 +185,7 @@ setlimits(char *nam)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif /* HAVE_GETRLIMIT */
|
||||
|
||||
/* fork and set limits */
|
||||
|
|
|
@ -1432,7 +1432,7 @@ glob(LinkList list, LinkNode np)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
case 'f':
|
||||
/* Match modes with chmod-spec. */
|
||||
func = qualmodeflags;
|
||||
data = qgetmodespec(&s);
|
||||
|
@ -1501,6 +1501,7 @@ glob(LinkList list, LinkNode np)
|
|||
data = qgetnum(&s);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
case 'O':
|
||||
{
|
||||
int t;
|
||||
|
@ -1524,7 +1525,7 @@ glob(LinkList list, LinkNode np)
|
|||
}
|
||||
gf_sorts |= t;
|
||||
gf_sortlist[gf_nsorts++] = t |
|
||||
((sense & 1) ? GS_DESC : 0);
|
||||
(((sense & 1) ^ (s[-1] == 'O')) ? GS_DESC : 0);
|
||||
s++;
|
||||
break;
|
||||
}
|
||||
|
|
30
Src/init.c
30
Src/init.c
|
@ -28,11 +28,12 @@
|
|||
*/
|
||||
|
||||
#include "zsh.mdh"
|
||||
#include "init.pro"
|
||||
|
||||
#include "zshpaths.h"
|
||||
#include "zshxmods.h"
|
||||
|
||||
#include "init.pro"
|
||||
|
||||
/**/
|
||||
int noexitct = 0;
|
||||
|
||||
|
@ -300,22 +301,19 @@ init_io(void)
|
|||
|
||||
/* Make sure the tty is opened read/write. */
|
||||
if (isatty(0)) {
|
||||
#ifdef TIOCNXCL
|
||||
/*
|
||||
* See if the terminal claims to be busy. If so, and fd 0
|
||||
* is a terminal, try and set non-exclusive use for that.
|
||||
* This is something to do with Solaris over-cleverness.
|
||||
*/
|
||||
int tmpfd;
|
||||
if ((tmpfd = open("/dev/tty", O_RDWR | O_NOCTTY)) < 0) {
|
||||
if (errno == EBUSY)
|
||||
ioctl(0, TIOCNXCL, 0);
|
||||
} else
|
||||
close(tmpfd);
|
||||
#endif
|
||||
zsfree(ttystrname);
|
||||
if ((ttystrname = ztrdup(ttyname(0))))
|
||||
if ((ttystrname = ztrdup(ttyname(0)))) {
|
||||
SHTTY = movefd(open(ttystrname, O_RDWR | O_NOCTTY));
|
||||
#ifdef TIOCNXCL
|
||||
/*
|
||||
* See if the terminal claims to be busy. If so, and fd 0
|
||||
* is a terminal, try and set non-exclusive use for that.
|
||||
* This is something to do with Solaris over-cleverness.
|
||||
*/
|
||||
if (SHTTY == -1 && errno == EBUSY)
|
||||
ioctl(0, TIOCNXCL, 0);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* xterm, rxvt and probably all terminal emulators except
|
||||
* dtterm on Solaris 2.6 & 7 have a bug. Applications are
|
||||
|
@ -936,6 +934,7 @@ noop_function_int(int nothing)
|
|||
/* do nothing */
|
||||
}
|
||||
|
||||
/**/
|
||||
# ifdef UNLINKED_XMOD_zle
|
||||
|
||||
/**/
|
||||
|
@ -947,6 +946,7 @@ autoload_zleread(char *lp, char *rp, int ha)
|
|||
return zleread(lp, rp, ha);
|
||||
}
|
||||
|
||||
/**/
|
||||
# endif /* UNLINKED_XMOD_zle */
|
||||
|
||||
/**/
|
||||
|
|
|
@ -40,6 +40,13 @@ BEGIN {
|
|||
aborting = 1
|
||||
exit 1
|
||||
}
|
||||
if (line == "" && $0 ~ /^[ \t]*#/) {
|
||||
# Directly after the /**/ was a preprocessor line.
|
||||
# Spit it out and re-start the outer loop.
|
||||
printf "%s\n", $0
|
||||
locals = locals $0 "\n"
|
||||
next
|
||||
}
|
||||
gsub(/\t/, " ")
|
||||
line = line " " $0
|
||||
gsub(/\/\*([^*]|\*+[^*\/])*\*+\//, " ", line)
|
||||
|
|
|
@ -90,6 +90,7 @@ static struct optname optns[] = {
|
|||
{NULL, "badpattern", OPT_EMULATE|OPT_NONBOURNE, BADPATTERN},
|
||||
{NULL, "banghist", OPT_EMULATE|OPT_NONBOURNE, BANGHIST},
|
||||
{NULL, "bareglobqual", OPT_EMULATE|OPT_ZSH, BAREGLOBQUAL},
|
||||
{NULL, "bashautolist", 0, BASHAUTOLIST},
|
||||
{NULL, "beep", OPT_ALL, BEEP},
|
||||
{NULL, "bgnice", OPT_EMULATE|OPT_NONBOURNE, BGNICE},
|
||||
{NULL, "braceccl", 0, BRACECCL},
|
||||
|
|
|
@ -1500,7 +1500,7 @@ setsparam(char *s, char *val)
|
|||
} else {
|
||||
if (!(v = getvalue(&s, 1)))
|
||||
createparam(t, PM_SCALAR);
|
||||
else if (PM_TYPE(v->pm->flags) == PM_ARRAY &&
|
||||
else if ((PM_TYPE(v->pm->flags) & (PM_ARRAY|PM_HASHED)) &&
|
||||
!(v->pm->flags & (PM_SPECIAL|PM_TIED)) && unset(KSHARRAYS)) {
|
||||
unsetparam(t);
|
||||
createparam(t, PM_SCALAR);
|
||||
|
|
37
Src/subst.c
37
Src/subst.c
|
@ -718,10 +718,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
int copied = 0;
|
||||
int arrasg = 0;
|
||||
int eval = 0;
|
||||
int aspar = 0;
|
||||
int nojoin = 0;
|
||||
char inbrace = 0; /* != 0 means ${...}, otherwise $... */
|
||||
char hkeys = 0;
|
||||
char hvals = 0;
|
||||
int subexp;
|
||||
|
||||
*s++ = '\0';
|
||||
if (!ialnum(*s) && *s != '#' && *s != Pound && *s != '-' &&
|
||||
|
@ -813,6 +815,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
case 'e':
|
||||
eval = 1;
|
||||
break;
|
||||
case 'P':
|
||||
aspar = 1;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
whichlen = 1;
|
||||
|
@ -949,7 +954,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
} else
|
||||
globsubst = 1;
|
||||
} else if (*s == '+') {
|
||||
if (iident(s[1]))
|
||||
if (iident(s[1]) || (aspar && isstring(s[1]) &&
|
||||
(s[2] == Inbrace || s[2] == Inpar)))
|
||||
chkset = 1, s++;
|
||||
else if (!inbrace) {
|
||||
*aptr = '$';
|
||||
|
@ -965,7 +971,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
globsubst = globsubst && !qt;
|
||||
|
||||
idbeg = s;
|
||||
if (s[-1] && isstring(*s) && (s[1] == Inbrace || s[1] == Inpar)) {
|
||||
if ((subexp = (s[-1] && isstring(*s) &&
|
||||
(s[1] == Inbrace || s[1] == Inpar)))) {
|
||||
int sav;
|
||||
int quoted = *s == Qstring;
|
||||
|
||||
|
@ -973,17 +980,28 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
skipparens(*s, *s == Inpar ? Outpar : Outbrace, &s);
|
||||
sav = *s;
|
||||
*s = 0;
|
||||
if (multsub(&val, &aval, &isarr, NULL) && quoted) {
|
||||
if (multsub(&val, (aspar ? NULL : &aval), &isarr, NULL) && quoted) {
|
||||
isarr = -1;
|
||||
aval = alloc(sizeof(char *));
|
||||
}
|
||||
aspar = 0;
|
||||
} else if (aspar)
|
||||
idbeg = val;
|
||||
if (isarr)
|
||||
isarr = -1;
|
||||
copied = 1;
|
||||
*s = sav;
|
||||
v = (Value) NULL;
|
||||
} else {
|
||||
if (!(v = fetchvalue(&s, (wantt ? -1 :
|
||||
} else if (aspar) {
|
||||
if ((v = getvalue(&s, 1))) {
|
||||
val = idbeg = getstrvalue(v);
|
||||
subexp = 1;
|
||||
} else
|
||||
vunset = 1;
|
||||
}
|
||||
if (!subexp || aspar) {
|
||||
char *ov = val;
|
||||
|
||||
if (!(v = fetchvalue((subexp ? &ov : &s), (wantt ? -1 :
|
||||
((unset(KSHARRAYS) || inbrace) ? 1 : -1)),
|
||||
hkeys|hvals)))
|
||||
vunset = 1;
|
||||
|
@ -1690,6 +1708,7 @@ modify(char **str, char **ptr)
|
|||
case 't':
|
||||
case 'l':
|
||||
case 'u':
|
||||
case 'q':
|
||||
c = **ptr;
|
||||
break;
|
||||
|
||||
|
@ -1808,6 +1827,9 @@ modify(char **str, char **ptr)
|
|||
if (hsubl && hsubr)
|
||||
subst(©, hsubl, hsubr, gbal);
|
||||
break;
|
||||
case 'q':
|
||||
copy = bslashquote(copy, NULL, NULL, NULL, 0);
|
||||
break;
|
||||
}
|
||||
tc = *tt;
|
||||
*tt = '\0';
|
||||
|
@ -1859,6 +1881,9 @@ modify(char **str, char **ptr)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
*str = bslashquote(*str, NULL, NULL, NULL, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rec < 0) {
|
||||
|
|
108
Src/utils.c
108
Src/utils.c
|
@ -446,7 +446,8 @@ finddir_scan(HashNode hn, int flags)
|
|||
{
|
||||
Nameddir nd = (Nameddir) hn;
|
||||
|
||||
if(nd->diff > finddir_best && !dircmp(nd->dir, finddir_full)) {
|
||||
if(nd->diff > finddir_best && !dircmp(nd->dir, finddir_full)
|
||||
&& !(nd->flags & ND_NOABBREV)) {
|
||||
finddir_last=nd;
|
||||
finddir_best=nd->diff;
|
||||
}
|
||||
|
@ -514,9 +515,8 @@ adduserdir(char *s, char *t, int flags, int always)
|
|||
* with always==0. Unless the AUTO_NAME_DIRS option is set, we *
|
||||
* don't let such assignments actually create directory names. *
|
||||
* Instead, a reference to the parameter as a directory name can *
|
||||
* cause the actual creation of the hash table entry. Never hash *
|
||||
* PWD unless it was explicitly requested (or already hashed). */
|
||||
if (!always && (unset(AUTONAMEDIRS) || !strcmp(s, "PWD")) &&
|
||||
* cause the actual creation of the hash table entry. */
|
||||
if (!always && unset(AUTONAMEDIRS) &&
|
||||
!nameddirtab->getnode2(nameddirtab, s))
|
||||
return;
|
||||
|
||||
|
@ -534,6 +534,9 @@ adduserdir(char *s, char *t, int flags, int always)
|
|||
nd = (Nameddir) zcalloc(sizeof *nd);
|
||||
nd->flags = flags;
|
||||
nd->dir = ztrdup(t);
|
||||
/* The variables PWD and OLDPWD are not to be displayed as ~PWD etc. */
|
||||
if (!strcmp(s, "PWD") || !strcmp(s, "OLDPWD"))
|
||||
nd->flags |= ND_NOABBREV;
|
||||
nameddirtab->addnode(nameddirtab, ztrdup(s), nd);
|
||||
}
|
||||
|
||||
|
@ -1150,11 +1153,24 @@ checkrmall(char *s)
|
|||
return (getquery("ny", 1) == 'y');
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
read1char(void)
|
||||
{
|
||||
char c;
|
||||
|
||||
while (read(SHTTY, &c, 1) != 1) {
|
||||
if (errno != EINTR)
|
||||
return -1;
|
||||
}
|
||||
return STOUC(c);
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
getquery(char *valid_chars, int purge)
|
||||
{
|
||||
char c, d;
|
||||
int c, d;
|
||||
int isem = !strcmp(term, "emacs");
|
||||
|
||||
#ifdef FIONREAD
|
||||
|
@ -1177,7 +1193,7 @@ getquery(char *valid_chars, int purge)
|
|||
return 'n';
|
||||
}
|
||||
#endif
|
||||
while (read(SHTTY, &c, 1) == 1) {
|
||||
while ((c = read1char()) >= 0) {
|
||||
if (c == 'Y' || c == '\t')
|
||||
c = 'y';
|
||||
else if (c == 'N')
|
||||
|
@ -1199,13 +1215,13 @@ getquery(char *valid_chars, int purge)
|
|||
}
|
||||
if (isem) {
|
||||
if (c != '\n')
|
||||
while (read(SHTTY, &d, 1) == 1 && d != '\n');
|
||||
while ((d = read1char()) >= 0 && d != '\n');
|
||||
} else {
|
||||
settyinfo(&shttyinfo);
|
||||
if (c != '\n' && !valid_chars)
|
||||
write(SHTTY, "\n", 1);
|
||||
}
|
||||
return (int)c;
|
||||
return c;
|
||||
}
|
||||
|
||||
static int d;
|
||||
|
@ -3109,6 +3125,73 @@ hasspecial(char const *s)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Quote the string s and return the result. If e is non-zero, the *
|
||||
* pointer it points to may point to a position in s and in e the position *
|
||||
* of the corresponding character in the quoted string is returned. Like *
|
||||
* e, te may point to a position in the string and pl is used to return *
|
||||
* the position of the character pointed to by te in the quoted string. *
|
||||
* The last argument should be zero if this is to be used outside a string, *
|
||||
* one if it is to be quoted for the inside of a single quoted string, and *
|
||||
* two if it is for the inside of double quoted string. *
|
||||
* The string may be metafied and contain tokens. */
|
||||
|
||||
/**/
|
||||
char *
|
||||
bslashquote(const char *s, char **e, char *te, int *pl, int instring)
|
||||
{
|
||||
const char *u, *tt;
|
||||
char *v, buf[PATH_MAX * 2];
|
||||
int sf = 0;
|
||||
|
||||
tt = v = buf;
|
||||
u = s;
|
||||
for (; *u; u++) {
|
||||
if (e && *e == u)
|
||||
*e = v, sf |= 1;
|
||||
if (te == u)
|
||||
*pl = v - tt, sf |= 2;
|
||||
if (ispecial(*u) &&
|
||||
(!instring || (isset(BANGHIST) &&
|
||||
*u == (char)bangchar) ||
|
||||
(instring == 2 &&
|
||||
(*u == '$' || *u == '`' || *u == '\"')) ||
|
||||
(instring == 1 && *u == '\''))) {
|
||||
if (*u == '\n' || (instring == 1 && *u == '\'')) {
|
||||
if (unset(RCQUOTES)) {
|
||||
*v++ = '\'';
|
||||
if (*u == '\'')
|
||||
*v++ = '\\';
|
||||
*v++ = *u;
|
||||
*v++ = '\'';
|
||||
} else if (*u == '\n')
|
||||
*v++ = '"', *v++ = '\n', *v++ = '"';
|
||||
else
|
||||
*v++ = '\'', *v++ = '\'';
|
||||
continue;
|
||||
} else
|
||||
*v++ = '\\';
|
||||
}
|
||||
if(*u == Meta)
|
||||
*v++ = *u++;
|
||||
*v++ = *u;
|
||||
}
|
||||
*v = '\0';
|
||||
if (strcmp(buf, s))
|
||||
tt = dupstring(buf);
|
||||
else
|
||||
tt = s;
|
||||
v += tt - buf;
|
||||
if (e && (sf & 1))
|
||||
*e += tt - buf;
|
||||
|
||||
if (e && *e == u)
|
||||
*e = v;
|
||||
if (te == u)
|
||||
*pl = v - tt;
|
||||
|
||||
return (char *) tt;
|
||||
}
|
||||
|
||||
/* Unmetafy and output a string, quoted if it contains special characters. */
|
||||
|
||||
/**/
|
||||
|
@ -3349,12 +3432,19 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
|
|||
case Meta:
|
||||
*t++ = '\\', s--;
|
||||
break;
|
||||
case '-':
|
||||
if (fromwhere == 5) {
|
||||
*misc = 1;
|
||||
break;
|
||||
}
|
||||
goto def;
|
||||
case 'c':
|
||||
if (fromwhere < 2) {
|
||||
*misc = 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
def:
|
||||
if ((idigit(*s) && *s < '8') || *s == 'x') {
|
||||
if (!fromwhere) {
|
||||
if (*s == '0')
|
||||
|
@ -3386,7 +3476,7 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
|
|||
} else if (fromwhere == 4 && *s == Snull) {
|
||||
for (u = t; (*u++ = *s++););
|
||||
return t + 1;
|
||||
} else if (*s == '^' && fromwhere == 2) {
|
||||
} else if (*s == '^' && (fromwhere == 2 || fromwhere == 5)) {
|
||||
control = 1;
|
||||
continue;
|
||||
} else if (*s == Meta)
|
||||
|
|
|
@ -14,6 +14,7 @@ attachtty
|
|||
bangchar
|
||||
bin_notavail
|
||||
breaks
|
||||
bslashquote
|
||||
bufstack
|
||||
builtintab
|
||||
chline
|
||||
|
@ -55,6 +56,7 @@ exlast
|
|||
expanding
|
||||
fallback_compctlread
|
||||
fallback_zleread
|
||||
fetchvalue
|
||||
fignore
|
||||
file_type
|
||||
filesub
|
||||
|
@ -72,6 +74,7 @@ getkeystring
|
|||
getlinknode
|
||||
getshfunc
|
||||
getsparam
|
||||
getstrvalue
|
||||
gettempname
|
||||
glob_pre
|
||||
glob_suf
|
||||
|
@ -228,6 +231,7 @@ ugetnode
|
|||
uinsertlinknode
|
||||
unmeta
|
||||
unmetafy
|
||||
unsetparam
|
||||
unsetparam_pm
|
||||
untokenize
|
||||
uremnode
|
||||
|
|
|
@ -963,6 +963,7 @@ struct nameddir {
|
|||
/* flags for named directories */
|
||||
/* DISABLED is defined (1<<0) */
|
||||
#define ND_USERNAME (1<<1) /* nam is actually a username */
|
||||
#define ND_NOABBREV (1<<2) /* never print as abbrev (PWD or OLDPWD) */
|
||||
|
||||
|
||||
/* flags for controlling printing of hash table nodes */
|
||||
|
@ -1056,6 +1057,7 @@ enum {
|
|||
BADPATTERN,
|
||||
BANGHIST,
|
||||
BAREGLOBQUAL,
|
||||
BASHAUTOLIST,
|
||||
BEEP,
|
||||
BGNICE,
|
||||
BRACECCL,
|
||||
|
|
|
@ -328,3 +328,66 @@ Me: fix for unsetting special zle variables, 5111
|
|||
|
||||
Drazen Kacar, modified by me: unlock terminal device on Solaris, 5118
|
||||
(5117 was wrong)
|
||||
|
||||
pws-7
|
||||
|
||||
Me: patch for zls, 5054 (appeared in pws-6 but not in corresponding
|
||||
patchlist).
|
||||
|
||||
Bart: finally added missing hunk from 4965 which allowed unsetting an
|
||||
assoc array when it was assigned to as a scalar which should have been
|
||||
there all along
|
||||
|
||||
Bart: vared to edit associative arrays and array elements, 5129
|
||||
|
||||
Matt Armstrong: makepro.awk can spit out preprocessor lines, 5132
|
||||
(+ move init.pro inclusion, 5151)
|
||||
|
||||
Matt: cygwin needs to use native getcwd(), 5133
|
||||
|
||||
Sven: partial word completion fix, 5144
|
||||
|
||||
Sven: compadd -m, -F, -r, 5145, 5204
|
||||
|
||||
Bart: unset can unset assoc array elements, 5174
|
||||
|
||||
Sven: fix for command completion and pattern completions, 5178
|
||||
|
||||
Sven: ${(P)...} 5183, 5199, 5200
|
||||
|
||||
Me: compctl documentation tidy-up, 5185, 5198
|
||||
|
||||
Sven: zle commands which use the minibuffer erase completion listings,
|
||||
5201
|
||||
|
||||
Sven: glob qualifiers o -> f, O -> o, new O = ^o, 5203
|
||||
|
||||
Sven: completion in arrays, 5206
|
||||
|
||||
Sven: new completion in conditions, 5207
|
||||
|
||||
Sven: ${foo:q}, 5208, preliminary
|
||||
|
||||
Sven: use ${foo:q} for quoting prefix and suffix in new completion, 5120
|
||||
|
||||
Me: bashautolist option, 5229; Sven's addition, 5234, and doc 5235; 5269
|
||||
|
||||
Me: .zlogout doc, 5233
|
||||
|
||||
Me: added note on Linux Alpha with egcs to Etc/MACHINES, not posted
|
||||
|
||||
Me: typeset -T fix, 5247
|
||||
|
||||
Bart: parameter scoping docs, 5258
|
||||
|
||||
Bart: new mailing lists in Meta-FAQ, 5260
|
||||
|
||||
Sven: GLOB_COMPLETE docs, 5261, 5268
|
||||
|
||||
Sven: compctl -M and REC_EXACT fixes, 5262
|
||||
|
||||
Sven: rewrite of $foo:q, 5265
|
||||
|
||||
Sven: get matcher number in new completion function, 5266
|
||||
|
||||
Me: interrupts in getquery() weren't gracefully handled, 5281
|
||||
|
|
Loading…
Reference in a new issue