1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-03 10:21:46 +02:00

zsh-workers/8932

This commit is contained in:
Tanaka Akira 1999-12-07 16:25:53 +00:00
parent 18e6f5f1ee
commit 36b2667e6f
10 changed files with 200 additions and 218 deletions

View file

@ -5,8 +5,7 @@
# shown in a list and one can cycle through them as in a menucompletion
# or get the corrected prefix.
local _comp_correct _correct_prompt comax
local cfgacc cfgorig cfgps cfgins
local _comp_correct _correct_expl comax cfgacc
local curcontext="${curcontext}" oldcontext
# Only if all global matchers have been tried.
@ -22,9 +21,6 @@ local curcontext="${curcontext}" oldcontext
oldcontext="$curcontext"
_style -s '' max-errors cfgacc
_style -s '' original cfgorig
_style -s '' prompt cfgps
_style -s '' insert cfgins
# Get the number of errors to accept.
@ -44,6 +40,8 @@ fi
[[ "$comax" -lt 1 ]] && return 1
_tags corrections original
# Otherwise temporarily define functions to use instead of
# the builtins that add matches. This is used to be able
# to stick the `(#a...)' into the right place (after an
@ -58,11 +56,7 @@ compadd() {
else
PREFIX="(#a${_comp_correct})$PREFIX"
fi
if [[ -n "$_correct_prompt" ]]; then
builtin compadd -X "$_correct_prompt" -J corrections "$@"
else
builtin compadd -J corrections "$@"
fi
builtin compadd "$_correct_expl[@]" "$@"
}
# Now initialise our counter. We also set `compstate[matcher]'
@ -76,39 +70,28 @@ compadd() {
_comp_correct=1
compstate[matcher]=-1
_correct_prompt="${cfgps//\\%e/1}"
_setup corrections
[[ "$cfgorig" != *last* ]] && builtin compadd -V original
builtin compadd -J corrections
[[ -z "$compstate[pattern_match]" ]] && compstate[pattern_match]='*'
while [[ _comp_correct -le comax ]]; do
curcontext="${oldcontext}:$_comp_correct"
if _complete; then
if [[ "$cfgins" = unambig* &&
"${#compstate[unambiguous]}" -ge "${#:-$PREFIX$SUFFIX}" ]]; then
compstate[pattern_insert]=unambiguous
elif [[ compstate[nmatches] -gt 1 || "$cfgorig" = *always* ]]; then
local expl format
_description corrections _correct_expl corrections \
"e:$_comp_correct" "o:$PREFIX$SUFFIX"
if [[ "$cfgorig" = *show* ]]; then
if _style -s descriptions format format; then
expl=(-X "${format//\\%d/original}")
else
expl=()
fi
else
expl=(-n)
fi
_setup original
builtin compadd "$expl[@]" -U -V original -Q - "$PREFIX$SUFFIX"
if _complete; then
if _style '' insert-unambiguous &&
[[ "${#compstate[unambiguous]}" -ge "${#:-$PREFIX$SUFFIX}" ]]; then
compstate[pattern_insert]=unambiguous
elif _requested original &&
( [[ compstate[nmatches] -gt 1 ]] || _style '' original ); then
local expl
_description -V original expl original
builtin compadd "$expl[@]" -U -Q - "$PREFIX$SUFFIX"
# If you always want to see the list of possible corrections,
# set `compstate[list]=list' here.
# set `compstate[list]=list force' here.
[[ "$compstate[list]" != list* ]] &&
compstate[list]="$compstate[list] force"
@ -121,8 +104,6 @@ while [[ _comp_correct -le comax ]]; do
[[ "${#:-$PREFIX$SUFFIX}" -le _comp_correct+1 ]] && break
(( _comp_correct++ ))
_correct_prompt="${cfgps//\\%e/$_comp_correct}"
done
compstate[matcher]="$compstate[total_matchers]"

View file

@ -1,8 +1,9 @@
#autoload
local gropt format gname
local name gropt format gname hidden hide
gropt=(-J)
hide=()
if [[ "$1" = -[VJ] ]]; then
gropt=("$1")
@ -16,20 +17,30 @@ _lastdescr=( "$_lastdescr[@]" "$3" )
_setup "$1"
_style -s descriptions format format
name="$2"
_style -s "$1" format format || _style -s descriptions format format
_style -s "$1" hidden hidden
if [[ "$hidden" = (all|yes|true|1|on) ]]; then
[[ "$hidden" = all ]] && format=''
hide=(-n)
fi
_style -s "$1" group-name gname && [[ -z "$gname" ]] && gname="$1"
shift 2
[[ -n "$format" ]] && compfmt format "$format" "d:$1" "${(@)argv[2,-1]}"
if [[ -n "$gname" ]]; then
if [[ -n "$format" ]]; then
eval "$2=($gropt ${(q)gname} -X ${(q)format//\\%d/$3})"
eval "${name}=($hide $gropt ${(q)gname} -X \"${format}\")"
else
eval "$2=($gropt ${(q)gname})"
eval "${name}=($hide $gropt ${(q)gname})"
fi
else
if [[ -n "$format" ]]; then
eval "$2=(-J -default- -X ${(q)format//\\%d/$3})"
eval "${name}=($hide -J -default- -X \"${format}\")"
else
eval "$2=(-J -default-)"
eval "${name}=($hide -J -default-)"
fi
fi

View file

@ -7,10 +7,9 @@
# the expansions done produce no result or do not change the original
# word from the line.
local exp word="$PREFIX$SUFFIX" group=-V expl expl2 disp orig menu prompt
local curcontext="${curcontext}" expr descr
local exp word="$PREFIX$SUFFIX" sort expr expl curcontext="${curcontext}"
[[ "$curcontext" != :correct* ]] && curcontext="${curcontext}:correct"
[[ "$curcontext" != :expand* ]] && curcontext="${curcontext}:expand"
# First, see if we should insert all *completions*.
@ -49,97 +48,34 @@ _style -s '' glob expr && [[ "${(e):-\$[$expr]}" -eq 1 ]] &&
[[ $#exp -eq 0 ||
( $#exp -eq 1 && "$exp[1]" = "$word"(|\(N\)) ) ]] && return 1
# Get the options for adding the original string and `all'-string.
# Now add as matches whatever the user requested.
_style -s '' original orig
_style -s '' menu menu
_style -s '' prompt prompt
_style -s descriptions format descr
_style -s '' sort sort
if [[ "$orig" = *show* ]]; then
if [[ -n "$descr" ]]; then
expl=(-X "${descr//\\%d/original}")
else
expl=()
fi
[[ "$sort" = (yes|true|1|on) ]] && exp=( "${(@o)exp}" )
if [[ -z "$compstate[insert]" ]] ;then
_description all-expansions expl 'all expansions' "o:$word"
compadd "$expl[@]" -UQ - "$exp"
else
expl=(-n)
fi
_tags all-expansions expansions original
if [[ -n "$menu" && "$menu" != *only* && "$menu" = *show-all* ]]; then
if [[ -n "$descr" ]]; then
expl2=(-ld disp -X "${descr//\\%d/all words}")
else
expl2=(-ld disp )
fi
disp=( "$exp" )
if [[ ${#disp[1]} -gt COLUMNS-5 ]]; then
disp=( "${disp[1][1,COLUMNS-5]}..." )
fi
else
expl2=(-n)
fi
# Quote the results and remove unnecessary quotes before `='s.
_requested all-expansions expl 'all expansions' "o:$word" &&
compadd "$expl[@]" -UQ "$exp"
exp=( "${(@)${(@)${(@q)exp}//\\\\=/=}/#=/\\=}" )
# We have expansions, should we menucomplete them?
if [[ -z "$menu" ]]; then
# No, so if the user only wants a list, we add the strings
# separately. Otherwise we add the whole array as one string,
# probably also adding the original string.
if [[ -z "$compstate[insert]" ]]; then
_setup all-expansions
compadd -U -V all-expansions -Q - "$exp[@]"
else
if [[ -n "$orig" && "$orig" != *last* ]]; then
_setup original
compadd "$expl[@]" -UQ -V original - "$word"
if _requested expansions; then
if [[ "$sort" = menu ]]; then
_description expansions expl expansions "o:$word"
else
_description -V expansions expl expansions "o:$word"
fi
_setup expansions
compadd -UQ -V expansions - "$exp"
compadd "$expl[@]" -UQ - "$exp[@]"
fi
if [[ -n "$orig" && "$orig" = *last* ]]; then
_setup original
compadd "$expl[@]" -UQ -V original - "$word"
fi
compstate[insert]=menu
fi
else
# Sorting? We just use a different group type then.
_requested original expl original && compadd "$expl[@]" -UQ - "$word"
[[ "$menu" = *sort* ]] && group=-J
# Now add the expansion string, probably also adding the original
# and/or the string containing all expanded string.
if [[ -n "$orig" && "$orig" != *last* ]]; then
_setup original
compadd "$expl[@]" -UQ -V original - "$word"
fi
if [[ $#exp -ne 1 && "$menu" = *last* && "$menu" != *only* ]]; then
_setup all-expansions
compadd "$expl2[@]" -UQ -V all-expansions - "$exp"
fi
_setup expansions
if [[ -z "$prompt" ]]; then
compadd -UQ $group expansions - "$exp[@]"
else
compadd -UQ -X "${prompt//\\%o/$word}" \
$group expansions - "$exp[@]"
fi
if [[ $#exp -ne 1 && "$menu" != *last* && "$menu" != *only* ]]; then
_setup all-expansions
compadd "$expl2[@]" -UQ -V all-expansions - "$exp"
fi
if [[ -n "$orig" && "$orig" = *last* ]]; then
_setup original
compadd "$expl[@]" -UQ -V original - "$word"
fi
compstate[insert]=menu
fi

View file

@ -7,11 +7,12 @@ _tags messages || return 1
_style -s messages format format || _style -s descriptions format format
if [[ -n "$format" ]]; then
compfmt format "$format" "d:$1" "${(@)argv[2,-1]}"
if [[ $compstate[nmatches] -eq 0 ]]; then
compstate[list]='list force'
compstate[insert]=''
compadd -UX "${format//\\%d/$1}" -n ''
compadd -UX "${format}" -n ''
else
compadd -X "${format//\\%d/$1}" -n '' && compstate[list]='list force'
compadd -X "${format}" -n '' && compstate[list]='list force'
fi
fi

View file

@ -18,7 +18,6 @@ if (( $# )); then
[[ "$1" = -(|-) ]] && shift
if _style -a '' group-order order; then
local name

View file

@ -844,6 +844,15 @@ string to display above matches in completion lists. The sequence
what these matches are. This string may also contain the sequences to
specify output attributes, such as `tt(%b)' and `tt(%s)'.
For the same purpose, this style is also tested with the tags used
when matches are generated em(before it is tested for the
tt(descriptions) tag). This gives the possibility to define different
format strings for different types of matches.
Not also that some completer functions define additional
`tt(%)'-sequences. These are described for the completer function that
make use of them.
For the tt(messages) tag, this defines a string used by some
completion functions to display messages. Here, the `tt(%d)' is
replaced with the message given by the completion function.
@ -907,6 +916,18 @@ A style holding the names of the groups that should be completed. If
this is not set by the user, the group names from the YP database or
the file `tt(/etc/group)' will be used.
)
item(tt(hidden))(
If this is set to one of the `true' values, the matches for the tags
for which this is set will not appear in the list, only the
description for the matches as set with the tt(format) style will be
shown. If this is set to tt(all), not even the description will be
displayed.
Note that the matches will still be completed, they are just not shown
in the list. To avoid having some matches to considered possible
completions one can modify the tt(_sort_tags) function as described
above.
)
item(tt(hosts))(
A style holding the names of hosts that should be completed. If this
is not set by the user the hostnames in `tt(/etc/hosts)' will be used.
@ -929,8 +950,8 @@ filenames to ignore. The matches ignored will only be completed when
there are no other matches.
)
item(tt(insert-unambiguous))(
This is used by the tt(_match) completer function. If it is set to
`true', the tt(_completer) will start menu
This is used by the tt(_match) and tt(_approximate) completer
functions. If it is set to `true', the completer will start menu
completion only if no unambiguous string could be generated that is at
least as long as the original string from the line.
)
@ -969,7 +990,7 @@ tt(_oldlist), it will instead show the list of corrections already
generated.
As another example consider the tt(_match) completer: with the
tt(insert) style set to tt(unambig) it inserts only an
tt(insert-unambiguous) style set to `true' it inserts only an
unambiguous prefix string if there is any. But since this may remove
parts of the original pattern, attempting completion again may result
in more matches than on the first attempt. But by using the
@ -1054,22 +1075,7 @@ correcting completion with two errors will usually be performed, but if a
numeric argument is given, correcting completion will not be performed.
)
item(tt(menu))(
This is used by the tt(_expand) completer. If it is unset or set to
an empty value, the words resulting from expansion (if any) will
simply be inserted in the command line, replacing the original
string. However, if this style is set to a non-empty value, the user
can cycle through the expansions as in menucompletion. Unless the value
contains the string `tt(only)', the user will still be offered all
expansions at once as one of the strings to insert in the command
line; normally, this possibility is offered first, but if the value
contains the string `tt(last)', it is offered last. Also, if the
value contains the string `tt(sort)', the expansions will be sorted
alphabetically, normally they are kept in the order the expansion
produced them in. And finally, if the value contains the string
`tt(show-all)', the string of all words will be shown in the list of
expansions.
The tt(_oldlist) completer uses this, too. Here it controls how menu
This is used by the tt(_oldlist) completer. It controls how menu
completion behaves when a completion has already been inserted and the
user types a standard completion key type such as tt(TAB). The default
behaviour of tt(_oldlist) is that menu completion always continues
@ -1085,32 +1091,13 @@ appears. With tt(_oldlist), it will instead continue to cycle through the
list of completions.
)
item(tt(original))(
In the tt(_approximate) completer this style is used to specify
whether the original string on which correcting completion was
attempted is to be included in the list of possible corrections. If it
is set to any non-empty value, the original string will be offered
when cycling through the completions. Normally it will appear as the
first string, so that the command line does not change immediately;
consecutive completion attempts will cycle through the corrected
strings. If the value for this style contains the string `tt(last)',
the original string will be the last one in the list, so that it
appears just before wrapping around to the first corrected string
again. Also, if the value contains the string `tt(always)', the
original string will always be included; normally it is included only
if more than one possible correction was generated. And finally, if
the value contains the string `tt(show)', the original string will
be shown in the list of corrections.
This is used by the tt(_approximate) and tt(_match) completers. The
first one uses it to decide if the original string should be added as
one possible completion. Normally, this is done only if there at least
two possible corrections, but if this style is set to `true', it will
always be added.
For the tt(_expand) completer function, if this is set to an non-empty
string, the original string from the line will be included in the list
of strings the user can cycle through as in a menucompletion. If the
value contains the string `tt(last)', the original string will
appear as the last string, with other values it is inserted as the
first one (so that the command line does not change
immediately). Also, if the value contains the string `tt(show)',
the original string will be shown in the list of expansions.
Finally, for the tt(_match) completer, if this style is set to
For the tt(_match) completer, if this style is set to
`tt(only)', it will try to generate matches without inserting a
`tt(*)' at the cursor position. If set to any other non-empty value,
it will first try to generate matches without inserting the `tt(*)'
@ -1149,18 +1136,7 @@ matches. E.g. for options this means that the `tt(-)', `tt(+)', or
all.
)
item(tt(prompt))(
The tt(approximate) completer uses the value of this style as a string
to be displayed on top of the corrected strings generated when cycling
through them. This string may contain the control sequences `tt(%n)',
`tt(%B)', etc. known from the `tt(-X)' option of tt(compadd). Also,
the sequence `tt(%e)' will be replaced by the number of errors
accepted to generate the corrected strings.
The tt(_expand) completer uses it for the same purpose, but here the
sequence `tt(%o)' will be replaced by the original string from the
line.
Also, the tt(incremental-complete-word) widget shows the value of this
The tt(incremental-complete-word) widget shows the value of this
style in the status line during incremental completion. The sequence
`tt(%u)' is replaced by the unambiguous part of all matches if there
is any and it is different from the word on the line. A `tt(%s)' is
@ -1189,6 +1165,12 @@ If set to `true', completion functions that generate words from the
history as possible matches sort these words alphabetically instead of
keeping them in the order in which they appear in the history (from
youngest to oldest).
This is also used by the tt(_expand) completer. Here, if it is set to
`true', the expansions generated will always be sorted. If it is set
to tt(menu), then the expansions are only sorted when they are offered
as single strings (not in the string containing all possible
expansions).
)
item(tt(stop))(
If set to a non-empty string, the tt(_history_complete_word) bindable
@ -1398,10 +1380,12 @@ normal completion doesn't yield any possible completions. When
corrected completions are found, the completer will normally start
menucompletion allowing you to cycle through these strings.
The exact behavior of this completer can be changed by using the
styles tt(max-errors), tt(original), tt(prompt), and tt(insert), see
ifzman(the section `Completion System Configuration' above)\
ifnzman(noderef(Completion System Configuration)).
This completer uses the tags tt(corrections) and tt(original) when
generating the possible coprrections and the original string. The
tt(format) style for the former may contain the additional seuqences
`tt(%e)' and `tt(%o)' which will be replaced by the number of errors
accepted to generate the corrections and the original string,
respectively.
Like all completers tt(_approximate) uses its name without the
undersccore as the top-level context name. Once it has started trying
@ -1450,7 +1434,7 @@ value, this completer will first try to generate matches without, then
with a `tt(*)' inserted at the cursor position.
The generated matches will be offered in a menucompletion unless the
tt(insert) style is set to a string starting with `tt(unambig)'. In
tt(insert-unambiguous) style is set to `true'. In
this case menucompletion will only be started if no unambiguous string
could be generated that is at least as long as the original string.
@ -1467,11 +1451,17 @@ will expand the string on the line before the completion widget is
called. Also, this completer should be called before the tt(_complete)
completer function.
Control over how the expanded string will be treated is possible with the
tt(substitute), tt(glob), tt(menu), tt(original), and tt(prompt)
styles, see
ifzman(the section `Completion System Configuration' above)\
ifnzman(noderef(Completion System Configuration)).
The tags used when generating expansions are tt(all-expansions) for
the string containing all possible expansions, tt(expansions) when
adding the possible expansions as single matches and tt(original) when
adding the original string from the line. In which order these strings
are generated and which of these strings are generated at all can be
controlled by using the tt(group-order) style and by modifying the
tt(_sort_tags) function, as usual.
The format string for tt(all-expansions) and for tt(expansions) may
contain the sequence `tt(%o)' which will be replaced by the original
string from the line.
In a different mode selected by the tt(completions) style, all
em(completions) generated for the string on the line are inserted.
@ -1639,27 +1629,35 @@ one can write a pattern completion function that keeps other functions
from being tried simply by setting this parameter to any value.
)
item(tt(_description))(
This function gets two or three arguments: a group name,
the name of an array and a
string. It tests if the style tt(format) for the tt(descriptions) tag is
set and if it is, it stores some options in the array that can then be
given to the tt(compadd) builtin command to make the
value of the tt(format) style for the tt(descriptions) tag (with the
sequence `tt(%d)' replaced by the string given as the last argument)
be displayed above the matches added. These options also will make
sure that the matches are placed in a separate group if the style
tt(group) for the tt(matches) tag is set to `true'. The first argument
will be used as the name of the group and should in most cases be the
name of a tag. Normally a sorted
group will be used for this (with the `tt(-J)' option), but if a
option starting with `tt(-V)' or `tt(-J)' is given, that option will
be included in the array, so that it is possible to make the group
unsorted by giving the option `tt(-V)', `tt(-V1)', or `tt(-V2)'.
The first three arguments to this function are: a group name,
the name of an array and a string. It tests if some styles for the tag
and stores options usable for tt(compadd) in the array which guarantee
that the matches are generated as requested by the user. The styles
tested are: tt(format) (which is first tested for the given tag and
then for the tt(descriptions) tag if that isn't defined), tt(hidden)
and tt(group-name) (the last two are tested only for the tag given as
the first argument). This function also calls the tt(_setup) function
which tests some more styles.
The format string from the style (if any) will be modified so that the
sequence `tt(%d)' is replaced by the string given as the third
argument. If tt(_description) is called with more than three
arguments, these extra arguments should be of the form
`var(char)tt(:)var(str)' and every appearance of `tt(%)var(char)' in
the format string will be replaced by var(string).
These options placed in the array will also make sure that the matches
are placed in a separate group, depending on the value of the
tt(group-name) style. Normally a sorted group will be used for this
(with the `tt(-J)' option), but if a option starting with `tt(-V)' or
`tt(-J)' is given, that option will be included in the array, so that
it is possible to make the group unsorted by giving the option
`tt(-V)', `tt(-V1)', or `tt(-V2)'.
In most cases, this function will be used like this:
example(local expl
_description expl file # same as `files expl file'
_description expl files file
compadd "$expl[@]" - "$files[@]")
)
item(tt(_message))(

View file

@ -24,6 +24,13 @@ innermost quoting level.
The return value is non-zero in case of an error and zero otherwise.
)
item(tt(compfmt) var(name) var(string) var(defs) ...)(
The var(defs) ar of the form `var(char)tt(;)var(string)' and
tt(compfmt) will replace every occurance of the sequence
`tt(%)var(char)' for each of the var(char)s with the corresponding
var(string). The resulting string will be placed in the parameter
var(name).
)
item(tt(compdisplay) var(name) var(string) var(defs) ...)(
The var(defs) are strings which should be of the form
`var(str)tt(:)var(descr)' (the intended use is that the var(descr)

View file

@ -16,7 +16,7 @@ incremental-complete-word() {
#emulate -L zsh
unsetopt autolist menucomplete automenu # doesn't work well
local key lbuf="$LBUFFER" rbuf="$RBUFFER" pmpt word
local key lbuf="$LBUFFER" rbuf="$RBUFFER" pmpt pstr word
local lastl lastr wid twid num alt post toolong
local curcontext="${curcontext}:incremental" stop brk
@ -51,7 +51,9 @@ incremental-complete-word() {
word="${_lastcomp[unambiguous]}"
state=''
fi
zle -R "${${${${${${pmpt//\\%u/$word}//\\%s/$state}//\\%c/${_lastcomp[completer][2,-1]}}//\\%n/$num}//\\%a/$alt}//\\%l/$toolong}"
compfmt pstr "$pmpt" "u:${word}" "s:$state" "n:$num" "a:$alt" \
"l:$toolong" "c:${_lastcomp[completer][2,-1]}"
zle -R "$pstr"
read -k key
while [[ '#key' -ne '#\\r' && '#key' -ne '#\\n' &&
@ -97,7 +99,9 @@ incremental-complete-word() {
word="${_lastcomp[unambiguous]}"
state=''
fi
zle -R "${${${${${${pmpt//\\%u/$word}//\\%s/$state}//\\%c/${_lastcomp[completer][2,-1]}}//\\%n/$num}//\\%a/$alt}//\\%l/$toolong}"
compfmt pstr "$pmpt" "u:${word}" "s:$state" "n:$num" "a:$alt" \
"l:$toolong" "c:${_lastcomp[completer][2,-1]}"
zle -R "$pstr"
read -k key
done

View file

@ -2810,6 +2810,50 @@ bin_comptry(char *nam, char **args, char *ops, int func)
return 0;
}
static char *
fmtstr(char *str, char c, char *repl)
{
int len, num, rlen;
char *s, *ret, *rp;
len = strlen(str);
rlen = strlen(repl);
for (num = 0, s = str; *s; s++)
if (*s == '%' && s[1] == c)
num++, s++;
ret = (char *) zhalloc((num * (rlen - 2)) + len + 1);
for (s = str, rp = ret; *s; s++) {
if (*s == '%' && s[1] == c) {
strcpy(rp, repl);
rp += rlen;
s++;
} else
*rp++ = *s;
}
*rp = '\0';
return ret;
}
static int
bin_compfmt(char *nam, char **args, char *ops, int func)
{
char *param = args[0], *str = args[1];
for (args += 2; *args; args++) {
if (args[0][1] != ':') {
zerrnam(nam, "invalid argument `%s'", args[0], 0);
return 1;
}
str = fmtstr(str, **args, *args + 2);
}
setsparam(param, ztrdup(str));
return 0;
}
static struct builtin bintab[] = {
BUILTIN("compdisplay", 0, bin_compdisplay, 2, -1, 0, NULL, NULL),
BUILTIN("compdescribe", 0, bin_compdescribe, 3, -1, 0, NULL, NULL),
@ -2819,6 +2863,7 @@ static struct builtin bintab[] = {
BUILTIN("compstyles", 0, bin_compstyles, 1, -1, 0, NULL, NULL),
BUILTIN("comptags", 0, bin_comptags, 1, -1, 0, NULL, NULL),
BUILTIN("comptry", 0, bin_comptry, 0, -1, 0, NULL, NULL),
BUILTIN("compfmt", 0, bin_compfmt, 2, -1, 0, NULL, NULL),
};

View file

@ -1815,7 +1815,7 @@ printfmt(char *fmt, int n, int dopr, int doesc)
tcout(TCUNDERLINEEND);
break;
case '{':
for (p++; *p && (*p != '%' || p[1] != '}'); p++, cc++)
for (p++; *p && (*p != '%' || p[1] != '}'); p++)
if (dopr)
putc(*p, shout);
if (*p)