Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: PATCH: Simplify resolve_nameref and setscope
The last prerequisite (
workers/54053) has been submitted. Here is an updated patch.
Philippe
The following patch simplifies namref code, mainly in the functions "resolve_nameref" and "setscope". It also adds some documentation and a few tests. As far as I can remember, it doesn't change any behavior.
The patch was built in multiple steps, which can be seen in the following GitHub diff (note that the first commit is the one above and isn't part of this patch).
It's certainly easier to assess that the patch doesn't change any behavior by reviewing the individual steps above than by reviewing the whole patch at once.
Philippe
diff --git a/ChangeLog b/ChangeLog
index 3f1503dbe..88ecc1d7b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,30 +1,3 @@
-2025-11-10 Oliver Kiddle <opk@xxxxxxx>
-
- * 53402, 54042: Src/Zle/termquery.c, Src/Zle/zle_main.c,
- Doc/Zsh/params.yo, Doc/Zsh/zle.yo: make timeout for terminal queries
- configurable via a .term.querywait variable, clarify documentation
- and include fewer of the new extensions by default
-
- * 53438: Doc/Zsh/params.yo, Doc/Zsh/zle.yo, Src/Zle/termquery.c,
- Src/Zle/zle.h, Src/Zle/zle_refresh.c, Src/Zle/zle_vi.c, Src/init.c,
- Src/zsh.h: support for changing terminal cursor shape and colour
-
- * 53404: Doc/Zsh/params.yo, Src/Zle/termquery.c, Src/Zle/zle_main.c,
- Src/builtin.c, Src/init.c, Src/input.c, Src/loop.c, Src/prompt.c,
- Src/subst.c, Src/utils.c, Src/zsh.h, Test/X04zlehighlight.ztst,
- Test/X06termquery.ztst: terminal integration with semantic markers
-
- * 53379, 53380: Doc/Zsh/params.yo, Test/X04zlehighlight.ztst,
- Src/prompt.c: autoload nearcolor based on truecolor detection
-
- * 53377: Doc/Zsh/zle.yo, Src/Zle/termquery.c, Src/Zle/zle_misc.c,
- Src/Zle/zle_utils.c, Test/X06termquery.ztst: support OSC52 paste
- sequence with the "* and "+ vi registers
-
- * 53372, 53375: Doc/Zsh/params.yo, Src/Zle/termquery.c,
- Src/Zle/zle.mdd, Src/Zle/zle_main.c, Test/X04zlehighlight.ztst,
- Test/X06termquery.ztst: query terminal properties on ZLE startup
-
2025-11-09 Bart Schaefer <schaefer@xxxxxxx>
* Philippe: 54057: Src/params.c, Src/zsh.h, Test/K01nameref.ztst:
diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index 34825deae..dd4519622 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -965,46 +965,6 @@ there is a block of reserved or unused signal numbers before the POSIX
real-time signals so the array index can't be used as an accurate indicator
of their signal number. Use, for example, tt(kill -l SIGRTMIN) instead.
)
-vindex(.term.cursor)
-item(tt(.term.cursor))(
-The default color of the cursor.
-
-See also the tt(.term.extensions) parameter.
-)
-vindex(.term.bg)
-item(tt(.term.bg))(
-The background color of the terminal if the terminal supports the
-necessary interface for retrieving this information.
-
-See also the tt(.term.extensions) parameter.
-)
-vindex(.term.fg)
-item(tt(.term.fg))(
-Like tt(.term.bg) but for the foreground color.
-)
-vindex(.term.id)
-item(tt(.term.id))(
-Like the tt(TERM) parameter, this identifies the terminal but is obtained by
-querying the terminal. Many terminals name a different common terminal in
-tt(TERM) that they then emulate, often imperfectly. This allows them to work
-without the need to distribute updates to terminal capability databases. The
-more accurate identification in this parameter may be useful when configuring
-aspects of the shell differently for specific terminals.
-
-See also the tt(.term.extensions) parameter.
-)
-vindex(.term.version)
-item(tt(.term.version))(
-The version number of the terminal application, set in conjunction with
-tt(.term.id).
-)
-vindex(.term.mode)
-item(tt(.term.mode))(
-Either tt(light) or tt(dark). In cases where the terminal background color is
-detected and set in tt(.term.bg), this is set to provide a basic indication of
-how light that color is. This may help with configuring readable color
-combinations.
-)
vindex(TRY_BLOCK_ERROR)
item(tt(TRY_BLOCK_ERROR) <S>)(
In an tt(always) block, indicates whether the preceding list of code
@@ -1735,18 +1695,6 @@ causes the shell to reinitialise the terminal, making the workaround
`tt(TERM=$TERM)' unnecessary. Note that unlike other colon-separated
arrays this is not tied to a zsh array.
)
-vindex(.term.extensions)
-item(tt(.term.extensions))(
-An array containing a list of extension features of the terminal.
-See sectref(Terminal Extensions)(zshzle).
-)
-vindex(.term.querywait)
-item(tt(.term.querywait))(
-The time the shell waits, in hundredths of seconds, for the response to
-terminal queries. A value of tt(`0') disables the timeout and the shell will
-wait indefinitely. If not set, a default of tt(`50') or half a second is
-used.
-)
vindex(TIMEFMT)
item(tt(TIMEFMT))(
The format of process time reports with the tt(time) keyword.
@@ -1844,20 +1792,18 @@ vindex(zle_bracketed_paste)
cindex(bracketed paste)
cindex(enabling bracketed paste)
item(tt(zle_bracketed_paste))(
-This two-element array contains the terminal escape sequences for enabling and
-disabling the bracketed paste feature which allows ZLE to discern text that is
-pasted into the terminal. These escape sequences are used to enable bracketed
-paste when ZLE is active and disable it at other times. Unsetting the
-parameter has the effect of ensuring that bracketed paste remains disabled.
-However, see also the tt(.term.extensions) parameter which provides a single
-place to enable or disable terminal features.
-)
-vindex(zle_cursorform)
-item(tt(zle_cursorform))(
-An array describing contexts in which ZLE should change the shape and color
-of the cursor.
-See ifzman(em(Cursor Shape and Color) in zmanref(zshzle))\
-ifnzman(noderef(Cursor Shape and Color)).
+Many terminal emulators have a feature that allows applications to
+identify when text is pasted into the terminal rather than being typed
+normally. For ZLE, this means that special characters such as tabs
+and newlines can be inserted instead of invoking editor commands.
+Furthermore, pasted text forms a single undo event and if the region is
+active, pasted text will replace the region.
+
+This two-element array contains the terminal escape sequences for
+enabling and disabling the feature. These escape sequences are used to
+enable bracketed paste when ZLE is active and disable it at other times.
+Unsetting the parameter has the effect of ensuring that bracketed paste
+remains disabled.
)
vindex(zle_highlight)
item(tt(zle_highlight))(
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index e20184121..91cc8ca14 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -54,7 +54,6 @@ menu(Zle Builtins)
menu(Zle Widgets)
menu(User-Defined Widgets)
menu(Standard Widgets)
-menu(Terminal Extensions)
menu(Character Highlighting)
endmenu()
@@ -1197,7 +1196,7 @@ This can be used for detecting switches between the vi command
)
enditem()
-texinode(Standard Widgets)(Terminal Extensions)(User-Defined Widgets)(Zsh Line Editor)
+texinode(Standard Widgets)(Character Highlighting)(User-Defined Widgets)(Zsh Line Editor)
sect(Standard Widgets)
cindex(widgets, standard)
The following is a list of all the standard widgets,
@@ -2465,8 +2464,9 @@ appended to the buffer instead of overwriting it. When using the tt("_)
buffer, nothing happens. This can be useful for deleting text without
affecting any buffers.
-Accessing and updating the system clipboard relies on specific support from
-the terminal.
+Updating the system clipboard relies on specific support from the terminal.
+Reading it is not possible so a paste command with tt("*) or tt("+) will do
+nothing.
If no buffer is specified for a cut or change command, tt("1) is used, and
the contents of tt("1) to tt("8) are each shifted along one buffer;
@@ -2613,102 +2613,7 @@ argument, multiple words will be selected.
)
enditem()
-texinode(Terminal Extensions)(Character Highlighting)(Standard Widgets)(Zsh Line Editor)
-sect(Terminal Extensions)
-
-vindex(.term.extensions, setting)
-Modern terminals often carry functionality that is not covered by the
-`terminfo' library. For these cases, the availability of a feature can be
-asserted by including it in the array parameter tt(.term.extensions).
-Similarly the absence of a feature can be indicated via it's inclusion with a
-`tt(-)' prefix. Where a feature isn't listed, the status of terminal support
-is unknown and defaults apply as to whether ZLE will use the feature. This
-is often harmless as terminals ignore extra instructions they don't recognise.
-Even if your terminal does support a particular extension, you may choose to
-list it with an initial `tt(-)' as a way to disable the associated feature.
-Many extensions are named with common prefixes to group related extensions.
-This allows a whole class of extensions to be disabled with a single entry such
-as by adding `tt(-cursor)' to disable cursor shape and color changing.
-
-When ZLE starts, it will add entries for features that were auto-detected. This
-auto-detection uses extensions itself, all named with a `tt(query)' prefix. As
-this happens when ZLE starts disabling them needs to be done early in the
-startup files. A value of `tt(-query)' will disable all terminal queries on
-startup, including those that query terminal properties such as colors rather
-than detecting features. Populating the array with the status of auto-detected
-features will mean that associated terminal queries are not needed and will be
-skipped.
-
-Extensions can be any of the following, where the marks `<D>' and `<E>'
-indicate whether each one is disabled or enabled by default:
-
-startitem()
-item(tt(bracketed-paste) <E>)(
-Many terminal emulators have a feature that allows applications to identify
-when text is pasted into the terminal rather than being typed normally. For
-ZLE, this means that special characters such as tabs and newlines can be
-inserted instead of invoking editor commands. Furthermore, pasted text forms a
-single undo event and if the region is active, pasted text will replace the
-region.
-)
-item(tt(cursor-color) <E>)(
-Support for changing the color of the cursor.
-)
-item(tt(cursor-shape) <E>)(
-Support for changing the shape of the cursor.
-)
-item(tt(integration-output) <E>)(
-This provides the terminal with semantic information regarding where the output
-from commands start and finish. Some terminals use this information to make it
-easy to select just the output from a single command.
-)
-item(tt(integration-prompt) <E>)(
-This informs the terminal when the shell displays a prompt. This enables a
-variety of terminal features such as displaying markers, allowing you to jump
-to previous commands in the scroll-back buffer and ensuring that right prompts
-are handled correctly when the window is resized. The end of the prompt also
-provides the terminal with a marker for the start of user input.
-)
-item(tt(integration-pwd) <E>)(
-This advises the terminal of the shell's current directory which allows it
-to create new windows with the same current working directory.
-)
-item(tt(query-bg) <E>)(
-Query the terminal background color which is used for tt(.term.bg) and
-tt(.term.mode).
-)
-item(tt(query-cursorcolor) <E>)(
-Query the cursor color. This facilitates restoring the cursor to its original
-color if it has been configured via tt(zle_cursorform). The color is also
-assigned to tt(.term.cursor).
-)
-item(tt(query-fg) <E>)(
-Query the terminal foreground color which is used for tt(.term.fg).
-)
-item(tt(query-id) <E>)(
-Query the terminal identification which is used for tt(.term.id) and
-tt(.term.version).
-)
-xitem(tt(modkeys-kitty) <D>)
-item(tt(query-modkeys-kitty) <D>)(
-Support for the kitty keyboard handling protocol which enables reporting of a
-wider range of key combinations and resolves problems with ambiguous key
-sequences. Currently there is only support for detecting whether the terminal
-supports this feature.
-)
-item(tt(modkeys-xterm) <D>)(
-Support for the keyboard handling sequences associated with xterm's
-tt(modifyOtherKeys) X resource. This enables reporting of a wider range of key
-combinations and resolves some problems with ambiguous key sequences.
-)
-xitem(tt(truecolor) <D>)
-item(tt(query-truecolor) <E>)(
-Support for 24-bit truecolor escape sequences. Auto-detection also tries
-termcap and the tt(COLORTERM) environment variable.
-)
-enditem()
-
-texinode(Character Highlighting)()(Terminal Extensions)(Zsh Line Editor)
+texinode(Character Highlighting)()(Standard Widgets)(Zsh Line Editor)
sect(Character Highlighting)
vindex(zle_highlight, setting)
@@ -2951,66 +2856,3 @@ special array parameter tt(region_highlight); see
ifnzman(noderef(Zle Widgets))\
ifzman(above).
-texinode(Cursor Shape and Color)()()(Character Highlighting)
-subsect(Cursor Shape and Color)
-cindex(cursor shape)
-cindex(cursor color)
-
-vindex(zle_cursorform, setting)
-Some terminals support the ability to change the shape and color of the cursor.
-On such terminals, the line editor will use cursor styles appropriate to
-different contexts. This is controlled via the array parameter
-tt(zle_cursorform). To disable all cursor changes, see the tt(.term.extensions)
-parameter.
-
-Each element of the array should consist of a word indicating a context
-followed by a colon, then a comma-separated list of properties describing the
-shape and color to apply to the cursor.
-
-The available contexts follow with the default value shown in
-parentheses. Where no default is given, the terminal's default is applied:
-
-startitem()
-item(tt(command))(
-Used for vi normal mode.
-)
-item(tt(edit))(
-The default form used in the line editor and for editing text in emacs
-mode.
-)
-item(tt(insert) (tt(bar)))(
-Used for vi editing mode.
-)
-item(tt(overwrite))(
-Used when editing text in overwrite mode or with the vi replace command.
-)
-item(tt(pending) (tt(underline)))(
-Used where the line editor is waiting for a single key press such as the vi
-operator pending mode widget.
-)
-item(tt(region))(
-Applied for both tt(regionstart) and tt(regionend) contexts.
-)
-item(tt(regionstart))(
-Used when the region is active and the cursor is positioned at the start of the
-region. The region includes the text under the cursor when it is positioned at
-the start so it is best to configure the cursor so that it does not obscure
-this fact.
-)
-item(tt(regionend))(
-Used when the region is active and the cursor is positioned at the end of the
-region. Note that when this is the case, the region does not include the cursor
-position.
-)
-item(tt(visual))(
-Used when vi visual mode is active. The visual selection always includes the
-cursor position so the same advice as for tt(regionstart) applies.
-)
-enditem()
-
-The available cursor shapes are tt(none), tt(bar), tt(block), tt(underline) and
-tt(hidden). Additionally, you can specify either tt(blink) or tt(steady) to
-indicate whether the cursor should flash and specify a color as an RGB triplet
-in hexadecimal format with tt(color=)var(#xxxxxx). The value tt(none)
-applies the terminal's defaults. Note that on many terminals, this may
-differ from the initial cursor state from when the shell started.
diff --git a/Src/Modules/param_private.c b/Src/Modules/param_private.c
index 044617190..95859ce36 100644
--- a/Src/Modules/param_private.c
+++ b/Src/Modules/param_private.c
@@ -606,7 +606,7 @@ getprivatenode(HashTable ht, const char *nam)
/* resolve nameref after skipping private parameters */
if (pm && (pm->node.flags & PM_NAMEREF) &&
(pm->u.str || (pm->node.flags & PM_UNSET)))
- pm = (Param) resolve_nameref(pm, NULL);
+ pm = resolve_nameref(pm);
return (HashNode)pm;
}
diff --git a/Src/Zle/termquery.c b/Src/Zle/termquery.c
deleted file mode 100644
index c6f83044d..000000000
--- a/Src/Zle/termquery.c
+++ /dev/null
@@ -1,949 +0,0 @@
-/*
- * termquery.c - terminal feature probes
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 2025 Oliver Kiddle
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Oliver Kiddle or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Oliver Kiddle and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Oliver Kiddle and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose. The software
- * provided hereunder is on an "as is" basis, and Oliver Kiddle and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
-#include "zle.mdh"
-#include "termquery.pro"
-
-/* On a 9600 serial link, 0.2 seconds is about the minimum to safely work.
- * 0.5s should be generous enough. We only incur this delay on a terminal
- * that doesn't respond to device attributes requests. */
-#define TIMEOUT -51L
-
-#define TAG (1 << 7)
-#define SEQ (TAG | (1 << 6))
-
-/* tags */
-#define T_BEGIN 0x80 /* group start */
-#define T_END 0x81 /* group end */
-#define T_OR 0x82 /* alternation (within group) */
-#define T_REPEAT 0x83 /* repeat preceding block */
-#define T_NUM 0x84 /* decimal number, defaults to 0 if absent */
-#define T_HEX 0x85 /* hexadecimal digit used as part of a number */
-#define T_HEXCH 0x86 /* hexadecimal digit that is thrown away */
-#define T_WILDCARD 0x87 /* match any character */
-#define T_RECORD 0x88 /* start text capture */
-#define T_CAPTURE 0x89 /* end text capture */
-#define T_DROP 0x91 /* drop input + restart without matching a sequence */
-#define T_CONTINUE 0x92 /* when matching don't go back to first state */
-#define T_NEXT 0x94 /* advance to next stored number */
-
-typedef const unsigned char seqstate_t;
-
-/* macros for entries in the parse state table */
-#define OR "\x82"
-#define NUM "\x84"
-#define HEX "\x85"
-#define HEXCH "\x86"
-#define WILDCARD "\x87"
-#define RECORD "\x88"
-#define CAPTURE "\x89"
-#define EITHER(group) "\x80" group "\x81"
-#define OPT(opt) EITHER( opt OR EITHER() )
-#define REPEAT(r) EITHER( r ) "\x83" /* would use OPT() but done in C code */
-/* Sequence completion tags and other actions need to precede the state
- * where the final character is matched. This macro just reverses the
- * order so that they come in a more logical order. */
-#define MATCH(ch, arg) arg ch
-#define DROP "\x91"
-#define CONTINUE "\x92"
-#define NEXT "\x94"
-#define DA "\xc0"
-#define COLOR "\xc1"
-#define KITTY "\xc2"
-#define TINFO "\xc3"
-#define XTID "\xc4"
-#define XTVER "\xc5"
-#define CLIP "\xc6"
-
-/* Deterministic finite state automata for parsing terminal response sequences.
- * - alternatives decided by the first character (no back-tracking)
- * - matching literal characters is 7-bit ASCII only
- */
-#define QUERY_STATES \
- "\033" \
- EITHER( /* default terminal colours */ \
- "]1" NUM ";" \
- EITHER( "rgb:" \
- HEX OPT( HEX ) OPT( HEXCH HEXCH ) "/" \
- HEX OPT( HEX ) OPT( HEXCH HEXCH ) "/" \
- HEX OPT( HEX ) OPT( HEXCH HEXCH ) \
- OR "#" \
- HEX HEX NEXT HEX HEX NEXT HEX HEX ) \
- EITHER( \
- MATCH("\033", COLOR CONTINUE ) \
- MATCH("\\", DROP) /* urxvt 9.31 has bug: it omits the backslash */ \
- OR MATCH("\007", COLOR ) ) \
- OR "P" /* DCS */ \
- EITHER( /* terminal name and version */ \
- ">|" RECORD \
- REPEAT( \
- CAPTURE EITHER( MATCH("(", XTID CONTINUE) \
- OR MATCH(" ", XTID CONTINUE) ) RECORD \
- OR \
- CAPTURE OPT( ")" ) "\033" MATCH( "\\", XTVER ) \
- OR \
- WILDCARD \
- ) \
- OR /* 24-bit colour support */ \
- EITHER( \
- "0+r" OPT( "524742" ) /* mlterm responds without numbers */ \
- "\033" MATCH("\\", DROP) /* kitty does 24-bit but 0 => no */ \
- OR "1+r524742=" REPEAT( HEXCH HEXCH ) /* hex encoded bytes */ \
- "\033" MATCH("\\", TINFO) )) /* any value => truecolor */ \
- OR /* keyboard protocol and device attributes */ \
- "[?" \
- REPEAT( NUM \
- EITHER( ";" \
- OR MATCH("u", KITTY ) \
- OR MATCH("c", DA) )))
-
-#define OSC52_STATES \
- "\033]52;" EITHER("p" OR "c") ";" RECORD \
- REPEAT( \
- CAPTURE EITHER( "\033" MATCH("\\", CLIP) OR MATCH("\007", CLIP) ) \
- OR WILDCARD )
-
-static char *EXTVAR = ".term.extensions";
-static char *IDVAR = ".term.id";
-static char *VERVAR = ".term.version";
-static char *COLORVAR[] = { ".term.fg", ".term.bg", ".term.cursor" };
-static char *MODEVAR = ".term.mode";
-static char *WAITVAR = ".term.querywait";
-
-/* Query sequences
- * using ESC\\ as ST instead of BEL because the bell was emitted on
- * old xterm. */
-
-/* Terminal default colors. Probably best that these are queried first
- * because tmux will need to pass these on. */
-#define TQ_BGCOLOR "\033]11;?\033\\"
-#define TQ_FGCOLOR "\033]10;?\033\\"
-#define TQ_CURSOR "\033]12;?\033\\"
-
-/* Kitty / fixterms keyboard protocol which allows wider support for keys
- * and modifiers. This clears the screen in terminology. */
-#define TQ_KITTYKB "\033[?u"
-
-/* Query for 24-bit color support, This is an XTTERMCAP sequence which with
- * some terminals allows terminfo entries to be retrieved. */
-#define TQ_RGB "\033P+q524742\033\\"
-
-/* Query terminal name and version which is useful with terminals that
- * lie in $TERM so that they work without terminfo entries. */
-#define TQ_XTVERSION "\033[>0q"
-
-/* Device attributes, Response isn't especially interesting but we get a
- * response from most terminals so by putting this last we can short-circuit
- * the time delay waiting for less well-supported responses that might never
- * come.
- * Following two spaces + CR works to clear fragments of sequences that
- * appeared. GNU screen is an example terminal that needs this. */
-#define TQ_DA "\033[c \r"
-
-static seqstate_t*
-find_branch(seqstate_t* pos)
-{
- int nested = 0;
- seqstate_t* cur = pos + 1;
-
- for (; *cur && (nested || (*cur != T_END && *cur != T_OR)); cur++) {
- if (*cur == T_BEGIN)
- nested++;
- else if (*cur == T_END)
- nested--;
- }
- return cur;
-}
-
-static seqstate_t*
-find_matching(seqstate_t* pos, int direction)
-{
- int nested = 1;
- seqstate_t* cur = pos + direction;
-
- for (; *cur && nested; cur += direction) {
- if (*cur == T_BEGIN && !(nested += direction)) {
- break; /* going backward, stop on begin */
- } else if (*cur == T_END)
- nested -= direction;
- }
- return cur;
-}
-
-static void
-probe_terminal(const char *tquery, seqstate_t *states,
- void (*handle_seq) (int seq, int *numbers, int len,
- char *capture, int clen, void *output), void *output)
-{
- size_t blen = 256, nlen = 16;
- char *buf = zhalloc(blen);
- char *start = buf, *current = buf, *illgotten = buf;
- size_t record = 0, capture = 0;
- int *numbers = hcalloc(nlen * sizeof(int));
- int *num = numbers;
- int finish = 0, number = 0;
- int ch;
- struct ttyinfo ti, torig;
- struct value vbuf;
- Value v = getvalue(&vbuf, &WAITVAR, 0);
- long timeout = v ? -1 - getintvalue(v) : TIMEOUT;
-
- if (timeout == -1)
- timeout = -((long)1 << (sizeof(int)*8-11))*100;
-
- seqstate_t *curstate = states;
-
- gettyinfo(&ti);
- memcpy(&torig, &ti, sizeof(torig));
-#ifdef HAS_TIO
- ti.tio.c_lflag &= (~ECHO & ~ICANON);
- ti.tio.c_iflag &= ~ICRNL;
-#else
- ti.sgttyb.sg_flags &= ~ECHO;
- ti.sgttyb.sg_flags |= CBREAK;
-#endif
- settyinfo(&ti);
-
- write_loop(SHTTY, tquery, strlen(tquery));
- notify_pwd(); /* unrelated to the function's main purpose */
-
- while (!finish && *curstate) {
- int consumed = 0; /* whether an input token has been matched */
- int branches = 1; /* count of untried paths encountered */
- int triedstart = curstate == states; /* current char tried at start */
- unsigned char action = 0, sequence = 0;
-
- if (illgotten < current) {
- ch = *illgotten++;
- } else {
- if (current == buf + blen) {
- current = hrealloc(buf, blen, blen * 2);
- illgotten = current + (illgotten - buf);
- start = current + (start - buf);
- buf = current;
- current = buf + blen;
- memset(current, 0, blen);
- blen *= 2;
- }
- ch = getbyte(timeout, 0, 1);
- if (errflag) {
- errflag = 0;
- break;
- }
- if (ch == EOF)
- break;
- *current++ = ch;
- illgotten = current;
- }
-
- while (!consumed && branches >= 1 && *curstate) {
- int increment = 0, base = 1, tryhere = 0;
-
- do {
- switch (*curstate) {
- case T_BEGIN:
- branches++;
- curstate++;
- break;
- case T_END:
- branches--;
- sequence = action = 0;
- curstate++;
- break;
- case T_OR:
- curstate = find_matching(curstate, 1);
- break;
- case T_REPEAT:
- sequence = action = 0;
- if (branches > 1) {
- branches--;
- curstate++;
- } else {
- branches++;
- curstate = find_matching(curstate - 1, -1);
- }
- break;
- case T_NUM:
- if (!(tryhere = (ch >= '0' && ch <= '9')))
- curstate++;
- break;
- case T_RECORD:
- record = current - buf - 1;
- curstate++;
- break;
- case T_CAPTURE:
- capture = current - buf - 1;
- curstate++;
- break;
- case T_DROP:
- case T_CONTINUE:
- case T_NEXT:
- action |= *curstate;
- curstate++;
- break;
- default:
- if ((*curstate & SEQ) == SEQ) {
- sequence = *curstate;
- curstate++;
- } else {
- tryhere = 1;
- }
- }
- } while (!tryhere);
-
- switch (*curstate) {
- case T_HEX:
- if (ch >= '0' && ch <= '9') {
- increment = ch - '0';
- } else if (ch >= 'a' && ch <= 'f') {
- increment = ch - 'a' + 10;
- } else if (ch >= 'A' && ch <= 'F') {
- increment = ch - 'A' + 10;
- } else
- break;
- consumed = number = 1;
- base = 16;
- if (action & 4) /* NEXT was used */
- ++num;
- break;
- case T_HEXCH:
- consumed = (ch >= '0' && ch <= '9') ||
- (ch >= 'a' && ch <= 'f') ||
- (ch >= 'A' && ch <= 'F');
- if (consumed && number) {
- ++num;
- number = 0;
- }
- break;
- case T_NUM:
- if (ch >= '0' && ch <= '9') {
- increment = ch - '0';
- base = 10;
- consumed = number = 1;
- curstate--; /* allow repetition */
- }
- break;
- case T_WILDCARD:
- consumed = 1;
- if (number) {
- ++num;
- number = 0;
- }
- break;
- default:
- if (!(*curstate & TAG) && (consumed = (*curstate == ch)) &&
- number)
- {
- ++num;
- number = 0;
- }
- break;
- }
- if (num == numbers + nlen) {
- numbers = hrealloc((char *) numbers, nlen * sizeof(int),
- sizeof(int) * nlen * 2);
- memset(numbers + nlen, 0, nlen * sizeof(int));
- num = numbers + nlen; /* restore relative position */;
- nlen *= 2;
- }
- if (number)
- *num = *num * base + increment;
-
- /* if it didn't match, move to the next OR */
- if (!consumed && branches > 1) {
- sequence = action = 0;
- for (; branches > 1; branches--) {
- curstate = find_branch(curstate);
- if (*curstate == T_OR) {
- curstate++;
- break;
- /* repeated group can match zero times */
- } else if (curstate[1] == T_REPEAT)
- break;
- }
- }
- /* Retry character at the start if it is the only buffered
- * character and was tried from a later state. */
- if (!consumed && branches <= 1) {
- if (triedstart || start + 1 != current)
- break;
- branches = 1;
- curstate = states;
- triedstart = 1;
- memset((num = numbers), 0, nlen * sizeof(int));
- sequence = action = number = 0;
- }
- }
-
- if (!consumed) {
- illgotten = ++start;
- curstate = states; /* return to first state */
- memset((num = numbers), 0, nlen * sizeof(int));
- number = 0;
- } else {
- if (sequence && !(finish = sequence == SEQ))
- handle_seq(sequence & ~SEQ, numbers, num - numbers,
- buf + record, capture - record, output);
-
- if ((sequence || (action & 1)) &&
- (current = start) && /* drop input from sequence */
- (!(action & 2)))
- {
- curstate = states;
- memset((num = numbers), 0, nlen * sizeof(int));
- number = 0;
- } else { /* CONTINUE */
- while (*++curstate == T_END)
- ;
- }
- }
- }
-
- /* put back any type-ahead text */
- if (current > buf)
- ungetbytes(buf, current - buf);
-
- settyinfo(&torig);
-}
-
-static unsigned memo_cursor;
-
-static void
-handle_color(int bg, int red, int green, int blue)
-{
- char *colour;
-
- if (bg == 1) { /* background color */
- /* scale by Rec.709 coefficients for lightness */
- setsparam(MODEVAR, ztrdup(
- 0.2126f * red + 0.7152f * green + 0.0722f * blue <= 127 ?
- "dark" : "light"));
- }
-
- if (bg == 2) /* cursor color */
- memo_cursor = (red << 24) | (green << 16) | (blue << 8);
-
- colour = zalloc(8);
- sprintf(colour, "#%02x%02x%02x", red, green, blue);
- setsparam(COLORVAR[bg], colour);
-}
-
-/* roughly corresponding feature names */
-static const char *features[] =
- { "bg", "fg", "cursorcolor", "modkeys-kitty", "truecolor", "id" };
-static const char *queries[] =
- { TQ_BGCOLOR, TQ_FGCOLOR, TQ_CURSOR, TQ_KITTYKB, TQ_RGB, TQ_XTVERSION, TQ_DA };
-
-static void
-handle_query(int sequence, int *numbers, int len, char *capture, int clen,
- UNUSED(void *output))
-{
- char **feat;
-
- switch (sequence) {
- case 1: /* default colour */
- if (len == 4)
- handle_color(numbers[0], numbers[1], numbers[2], numbers[3]);
- break;
- case 2: /* kitty keyboard */
- feat = zshcalloc(2 * sizeof(char *));
- *feat = ztrdup(features[3]);
- assignaparam(EXTVAR, feat, ASSPM_WARN|ASSPM_AUGMENT);
- break;
- case 3: /* truecolor */
- feat = zshcalloc(2 * sizeof(char *));
- *feat = ztrdup(features[4]);
- assignaparam(EXTVAR, feat, ASSPM_WARN|ASSPM_AUGMENT);
- break;
- case 4: /* id */
- setsparam(IDVAR, ztrduppfx(capture, clen));
- break;
- case 5: /* version */
- setsparam(VERVAR, ztrduppfx(capture, clen));
- break;
- }
-}
-
-/**/
-void
-query_terminal(void) {
- char tquery[sizeof(TQ_BGCOLOR TQ_FGCOLOR TQ_CURSOR TQ_KITTYKB TQ_RGB TQ_XTVERSION TQ_DA)];
- char *tqend = tquery;
- static seqstate_t states[] = QUERY_STATES;
- char **f, **flist = getaparam(EXTVAR);
- size_t i;
-
- for (f = flist; f && *f; f++)
- if (!strcmp(*f, "-query"))
- return; /* disable all queries */
-
- for (i=0; i < sizeof(queries)/sizeof(*queries); i++) {
- int last = i >= sizeof(features)/sizeof(*features);
- int found = (last && tqend == tquery);
- int enable = 0;
- char *cterm;
-
- /* skip if the query or corresponding feature is already in the list */
- for (f = flist; !last && !found && f && *f; f++) {
- /* just i=3(TQ_KITTYKB) is disabled by default */
- enable = i == 3 && strpfx("query-", *f) && !strcmp(*f + 6, features[i]);
- found = enable || !strcmp(*f + (**f == '-'), features[i]) ||
- (strpfx("-query-", *f) && !strcmp(*f + 7, features[i]));
- }
- if (found ? !enable : i == 3)
- continue;
- /* if termcap indicates 24-bit color, assume support - even
- * though this is only based on the initial $TERM
- * failing that, check $COLORTERM */
- if (i == 4 && (tccolours == 1 << 24 ||
- ((cterm = getsparam("COLORTERM")) &&
- (!strcmp(cterm, "truecolor") ||
- !strcmp(cterm, "24bit")))))
- handle_query(3, NULL, 0, NULL, 0, NULL);
- else
- struncpy(&tqend, (char *) queries[i], /* collate escape sequences */
- sizeof(tquery) - (tqend - tquery));
- }
-
- if (tqend != tquery) /* unless nothing left after filtering */
- probe_terminal(tquery, states, &handle_query, NULL);
-}
-
-static char*
-base64_encode(const char *src, size_t len) {
- static const char* base64_table =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- const unsigned char *end = (unsigned char *)src + len;
- const unsigned char *in = (unsigned char *)src;
- char *ret = zhalloc(1 + 4 * ((len + 2) / 3)); /* 4 bytes out for 3 in */
- char *cur = ret;
-
- for (; end - in > 0; in += 3, cur += 4) {
- unsigned int n = *in << 16;
- cur[3] = end - in > 2 ? base64_table[(n |= in[2]) & 0x3f] : '=';
- cur[2] = end - in > 1 ? base64_table[((n |= in[1]<<8) >> 6) & 0x3f] : '=';
- cur[1] = base64_table[(n >> 12) & 0x3f];
- cur[0] = base64_table[n >> 18];
- }
- *cur = '\0';
-
- return ret;
-}
-
-static char*
-base64_decode(const char *src, size_t len)
-{
- int i = 0;
- unsigned int n;
- char *buf = hcalloc((3 * len) / 4 + 1);
- char *b = buf;
- char c;
-
- while (len && (c = src[i]) != '=') {
- n = isdigit(c) ? c - '0' + 52 :
- islower(c) ? c - 'a' + 26 :
- isupper(c) ? c - 'A' :
- (c == '+') ? 62 :
- (c == '/') ? 63 : 0;
- if (i % 4)
- *b++ |= n >> (2 * (3 - (i % 4)));
- if (++i >= len)
- break;
- *b = n << (2 * (i % 4));
- }
- return buf;
-}
-
-static void
-handle_paste(UNUSED(int sequence), UNUSED(int *numbers), UNUSED(int len),
- char *capture, int clen, void *output)
-{
- *(char**) output = base64_decode(capture, clen);
-}
-
-static char*
-url_encode(const char* path, size_t *ulen)
-{
- char *url = zhalloc(strlen(path) * 3 + 1); /* worst case length triples */
- const char *in = path;
- char *out = url;
-
- for (; *in; in++) {
- /* In theory, space can be encoded as '+' but not all terminals
- * handled that and %20 works reliably.
- * ':' as a Windows drive letter should also not be encoded */
- if (isalnum(*in) || strchr("-._~/", *in))
- *out++ = *in; /* untouched in encoding */
- else
- out += sprintf(out, "%%%02X", *in); /* otherwise %HH */
- }
-
- *out = '\0';
- *ulen = out - url;
- return url;
-}
-
-/**/
-char *
-system_clipget(char clip)
-{
- static seqstate_t osc52[] = OSC52_STATES;
- char seq[] = "\033]52;.;?\033\\";
- char *contents;
- seq[5] = clip;
- probe_terminal(seq, osc52, &handle_paste, &contents);
- return contents;
-}
-
-/**/
-void
-system_clipput(char clip, char *content, size_t clen)
-{
- char *encoded = base64_encode(content, clen);
- fprintf(shout, "\033]52;%c;%s\033\\", clip, encoded);
-}
-
-/**/
-static int
-extension_enabled(const char *class, const char *ext, unsigned clen, int def)
-{
- char **e, **elist = getaparam(EXTVAR);
-
- for (e = elist; e && *e; e++) {
- int negate = (**e == '-');
- if (strncmp(*e + negate, class, clen))
- continue;
-
- if (!*(*e + negate + clen) || !strcmp(*e + negate + clen + 1, ext))
- return !negate;
- }
- return def;
-}
-
-
-struct extension {
- char *key, *seq[2];
- int class, enabled;
-};
-
-static const struct extension editext[] = {
- { "bracketed-paste", { NULL, NULL}, 0, 1 },
- { "integration-prompt", { "\033]133;B\033\\" }, 11, 1 },
-#if 0
- { "modkeys-kitty", { "\033[=5u", "\033[=0u" }, 7, 0 },
-#endif
- { "modkeys-xterm", { "\033[>4;1m", "\033[>4m" }, 7, 0 }
-};
-
-static void
-collate_seq(int sindex, int dir)
-{
- char seq[256];
- char *pos = seq;
- int max = sizeof(editext) / sizeof(*editext);
- int i;
- char **bracket;
- char **e, **elist = getaparam(EXTVAR);
-
- for (i = dir > 0 ? 0 : max - 1; i >= 0 && i < max; i += dir) {
- int enabled = editext[i].enabled;
- if (i && !editext[i].seq[sindex])
- continue;
- for (e = elist; e && *e; e++) {
- int negate = (**e == '-');
- if (negate != enabled)
- continue;
- if ((editext[i].class &&
- !strncmp(*e + negate, editext[i].key, editext[i].class) &&
- !*(*e + negate + editext[i].class)) ||
- !strcmp(*e + negate + editext[i].class,
- editext[i].key + editext[i].class))
- {
- enabled = !negate;
- break;
- }
-
- }
- if (enabled) {
- if (i)
- strucpy(&pos, editext[i].seq[sindex]);
- else if ((bracket = getaparam("zle_bracketed_paste")) &&
- arrlen(bracket) == 2)
- strucpy(&pos, bracket[sindex]);
- }
- }
- write_loop(SHTTY, seq, pos - seq);
-}
-
-/**/
-void
-start_edit(void)
-{
- collate_seq(0, 1);
-}
-
-/**/
-void
-end_edit(void)
-{
- collate_seq(1, -1);
-}
-
-/**/
-const char **
-prompt_markers(void)
-{
- static unsigned int aid = 0;
- static char pre[] = "\033]133;A;cl=m;aid=zZZZZZZ\033\\"; /* before the prompt */
- static const char PR[] = "\033]133;P;k=i\033\\"; /* primary (PS1) */
- static const char SE[] = "\033]133;P;k=s\033\\"; /* secondary (PS2) */
- static const char RI[] = "\033]133;P;k=r\033\\"; /* right (RPS1,2) */
- static const char *markers[] = { PR, SE, RI };
- static const char *nomark[] = { NULL, NULL, NULL, NULL };
-
- if (!extension_enabled("integration", "prompt", 11, 1))
- return nomark;
-
- if (!aid) {
- /* hostname and pid should uniquely identify a shell instance */
- char *h = getsparam("HOST");
- aid = (h ? hasher(h) : 0) ^ getpid();
- if (!aid) aid = 1; /* unlikely but just to be safe */
- /* base64 not required but it is safe, convenient and compact */
- h = base64_encode((const char *)&aid, sizeof(aid));
- memcpy(pre + 13, h, 6);
- }
-
- return markers;
-}
-
-/**/
-void
-mark_output(int start)
-{
- static const char START[] = "\033]133;C\033\\";
- static const char END[] = "\033]133;D\033\\";
- if (extension_enabled("integration", "output", 11, 1))
- write_loop(SHTTY, start ? START : END,
- (start ? sizeof(START) : sizeof(END)) - 1);
-}
-
-/**/
-void
-notify_pwd(void)
-{
- char *url;
- size_t ulen;
-
- if (!extension_enabled("integration", "pwd", 11, 1))
- return;
-
- url = url_encode(pwd, &ulen);
- /* only "localhost" seems to be much use here as the host */
- write_loop(SHTTY, "\033]7;file://localhost", 20);
- write_loop(SHTTY, url, ulen);
- write_loop(SHTTY, "\033\\", 2);
-}
-
-static unsigned int *cursor_forms;
-static unsigned int cursor_enabled_mask;
-
-static void
-match_cursorform(const char *teststr, unsigned int *cursor_form)
-{
- static const struct {
- const char *name;
- unsigned char value, mask;
- } shapes[] = {
- { "none", 0, 0xff },
- { "underline", CURF_UNDERLINE, CURF_SHAPE_MASK },
- { "bar", CURF_BAR, CURF_SHAPE_MASK },
- { "block", CURF_BLOCK, CURF_SHAPE_MASK },
- { "blink", CURF_BLINK, CURF_STEADY },
- { "steady", CURF_STEADY, CURF_BLINK },
- { "hidden", CURF_HIDDEN, 0 }
- };
-
- *cursor_form = 0;
- while (*teststr) {
- size_t s;
- int found = 0;
-
- if (strpfx("color=#", teststr)) {
- char *end;
- teststr += 7;
- zlong col = zstrtol(teststr, &end, 16);
- if (end - teststr == 4) {
- unsigned int red = col >> 8;
- unsigned int green = (col & 0xf0) >> 4;
- unsigned int blue = (col & 0xf);
- *cursor_form &= 0xff; /* clear color */
- *cursor_form |= CURF_COLOR |
- ((red << 4 | red) << CURF_RED_SHIFT) |
- ((green << 4 | green) << CURF_GREEN_SHIFT) |
- ((blue << 4 | blue) << CURF_BLUE_SHIFT);
- found = 1;
- } else if (end - teststr == 6) {
- *cursor_form |= (col << 8) | CURF_COLOR;
- found = 1;
- }
- teststr = end;
- }
- for (s = 0; !found && s < sizeof(shapes) / sizeof(*shapes); s++) {
- if (strpfx(shapes[s].name, teststr)) {
- teststr += strlen(shapes[s].name);
- *cursor_form &= ~shapes[s].mask;
- *cursor_form |= shapes[s].value;
- found = 1;
- }
- }
- if (!found) /* skip an unknown component */
- teststr = strchr(teststr, ',');
- if (!teststr || *teststr != ',')
- break;
- teststr++;
- }
-}
-
-/**/
-void
-zle_set_cursorform(void)
-{
- char **atrs = getaparam("zle_cursorform");
- static int setup = 0;
- size_t i;
- static const char *contexts[] = {
- "edit:",
- "command:",
- "insert:",
- "overwrite:",
- "pending:",
- "regionstart:",
- "regionend:",
- "visual:"
- };
-
- if (!cursor_forms)
- cursor_forms = zalloc(CURC_DEFAULT * sizeof(*cursor_forms));
- memset(cursor_forms, 0, CURC_DEFAULT * sizeof(*cursor_forms));
- cursor_forms[CURC_INSERT] = CURF_BAR;
- cursor_forms[CURC_PENDING] = CURF_UNDERLINE;
-
- for (; atrs && *atrs; atrs++) {
- if (strpfx("region:", *atrs)) {
- match_cursorform(*atrs + 7, &cursor_forms[CURC_REGION_END]);
- cursor_forms[CURC_REGION_START] = cursor_forms[CURC_REGION_END];
- continue;
- }
- for (i = 0; i < sizeof(contexts) / sizeof(*contexts); i++) {
- if (strpfx(contexts[i], *atrs)) {
- match_cursorform(*atrs + strlen(contexts[i]), &cursor_forms[i]);
- break;
- }
- }
- }
-
- if (!setup || trashedzle) {
- cursor_enabled_mask = 0;
- setup = 1;
- if (!extension_enabled("cursor", "shape", 6, 1))
- cursor_enabled_mask |= CURF_SHAPE_MASK | CURF_BLINK | CURF_STEADY;
- if (!extension_enabled("cursor", "color", 6, 1))
- cursor_enabled_mask |= CURF_COLOR_MASK;
- }
-}
-
-/**/
-void
-free_cursor_forms(void)
-{
- if (cursor_forms)
- zfree(cursor_forms, CURC_DEFAULT * sizeof(*cursor_forms));
- cursor_forms = 0;
-}
-
-/**/
-void
-cursor_form(void)
-{
- char seq[31];
- char *s = seq;
- unsigned int want, changed;
- static unsigned int state = CURF_DEFAULT;
- enum cursorcontext context = CURC_DEFAULT;
-
- if (!cursor_forms)
- return;
-
- if (trashedzle) {
- ;
- } else if (!insmode) {
- context = CURC_OVERWRITE;
- } else if (vichgflag == 2) {
- context = CURC_PENDING;
- } else if (region_active) {
- if (invicmdmode()) {
- context = CURC_VISUAL;
- } else {
- context = mark > zlecs ? CURC_REGION_START : CURC_REGION_END;
- }
- } else
- context = invicmdmode() ? CURC_COMMAND : (vichgflag ? CURC_INSERT : CURC_EDIT);
- want = (context == CURC_DEFAULT) ? CURF_DEFAULT : cursor_forms[context];
- if (!(changed = (want ^ state) & ~cursor_enabled_mask))
- return;
-
- if (changed & CURF_HIDDEN)
- tcout(want & CURF_HIDDEN ? TCCURINV : TCCURVIS);
- if (changed & CURF_SHAPE_MASK) {
- char c = '0';
- switch (want & CURF_SHAPE_MASK) {
- case CURF_BAR: c += 2;
- case CURF_UNDERLINE: c += 2;
- case CURF_BLOCK:
- c += 2 - !!(want & CURF_BLINK);
- changed &= ~(CURF_BLINK | CURF_STEADY);
- }
- s += sprintf(s, "\033[%c q", c);
- }
- if (changed & (CURF_BLINK | CURF_STEADY)) {
- s += sprintf(s, "\033[?12%c", (want & CURF_BLINK) ? 'h' : 'l');
- }
- if (changed & CURF_COLOR_MASK) {
- if (!(want & CURF_COLOR_MASK))
- want = memo_cursor | (want & 0xff);
- s += sprintf(s, "\033]12;rgb:%02x00/%02x00/%02x00\033\\",
- want >> CURF_RED_SHIFT, (want >> CURF_GREEN_SHIFT) & 0xff,
- (want >> CURF_BLUE_SHIFT) & 0xff);
- }
- if (s - seq)
- write_loop(SHTTY, seq, s - seq);
- state = want;
-}
diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h
index 91eefc9e5..5bb9e7a5e 100644
--- a/Src/Zle/zle.h
+++ b/Src/Zle/zle.h
@@ -470,32 +470,6 @@ struct region_highlight {
* interaction in Doc/Zsh/zle.yo. */
#define N_SPECIAL_HIGHLIGHTS (4)
-/* Terminal cursor contexts */
-enum cursorcontext {
- CURC_EDIT,
- CURC_COMMAND,
- CURC_INSERT,
- CURC_OVERWRITE,
- CURC_PENDING,
- CURC_REGION_START,
- CURC_REGION_END,
- CURC_VISUAL,
- CURC_DEFAULT
-};
-
-#define CURF_DEFAULT 0
-#define CURF_UNDERLINE 1
-#define CURF_BAR 2
-#define CURF_BLOCK 3
-#define CURF_SHAPE_MASK 3
-#define CURF_BLINK (1 << 2)
-#define CURF_STEADY (1 << 3)
-#define CURF_HIDDEN (1 << 4)
-#define CURF_COLOR (1 << 5)
-#define CURF_COLOR_MASK ((0xffffffu << 8) | CURF_COLOR)
-#define CURF_RED_SHIFT 24
-#define CURF_GREEN_SHIFT 16
-#define CURF_BLUE_SHIFT 8
#ifdef MULTIBYTE_SUPPORT
/*
diff --git a/Src/Zle/zle.mdd b/Src/Zle/zle.mdd
index c7c914712..dd69eff2c 100644
--- a/Src/Zle/zle.mdd
+++ b/Src/Zle/zle.mdd
@@ -8,7 +8,7 @@ autofeatures="b:bindkey b:vared b:zle"
objects="zle_bindings.o zle_hist.o zle_keymap.o zle_main.o \
zle_misc.o zle_move.o zle_params.o zle_refresh.o \
zle_thingy.o zle_tricky.o zle_utils.o zle_vi.o zle_word.o \
-termquery.o textobjects.o"
+textobjects.o"
headers="zle.h zle_things.h"
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index d7b2ca21c..ab0b51374 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -426,7 +426,7 @@ enum ztmouttp {
* there's no general way to fix up if that's wrong.
*/
ZTM_MAX
-#define ZMAXTIMEOUT ((time_t)1 << (sizeof(int)*8-11))
+#define ZMAXTIMEOUT ((time_t)1 << (sizeof(time_t)*8-11))
};
struct ztmout {
@@ -1215,10 +1215,9 @@ zlecore(void)
char *
zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
{
- char *s;
+ char *s, **bracket;
int old_errno = errno;
int tmout = getiparam("TMOUT");
- const char **markers = prompt_markers();
#if defined(HAVE_POLL) || defined(HAVE_SELECT)
/* may not be set, but that's OK since getiparam() returns 0 == off */
@@ -1233,7 +1232,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
char *pptbuf;
int pptlen;
- pptbuf = unmetafy(promptexpand(lp ? *lp : NULL, 0, NULL, NULL, NULL),
+ pptbuf = unmetafy(promptexpand(lp ? *lp : NULL, 0, NULL, NULL),
&pptlen);
pmpt_attr = txtcurrentattrs;
write_loop(2, pptbuf, pptlen);
@@ -1271,11 +1270,10 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
trashedzle = 0;
raw_lp = lp;
txtcurrentattrs = txtpendingattrs = txtunknownattrs = 0;
- lpromptbuf = promptexpand(lp ? *lp : NULL, 1,
- markers[flags == ZLCON_LINE_CONT ? 2 : 1], NULL, NULL);
+ lpromptbuf = promptexpand(lp ? *lp : NULL, 1, NULL, NULL);
pmpt_attr = txtcurrentattrs;
raw_rp = rp;
- rpromptbuf = promptexpand(rp ? *rp : NULL, 1, markers[2], NULL, NULL);
+ rpromptbuf = promptexpand(rp ? *rp : NULL, 1, NULL, NULL);
rpmpt_attr = txtcurrentattrs;
prompt_attr = mixattrs(pmpt_attr, rpmpt_attr);
free_prepostdisplay();
@@ -1346,10 +1344,6 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
prefixflag = 0;
region_active = 0;
- /* semantic prompt marker printed before first prompt */
- if (*markers)
- write_loop(2, *markers, strlen(*markers));
-
zrefresh();
unqueue_signals(); /* Should now be safe to acknowledge SIGWINCH */
@@ -1359,7 +1353,8 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
if (zleline && *zleline)
redrawhook();
- start_edit();
+ if ((bracket = getaparam("zle_bracketed_paste")) && arrlen(bracket) == 2)
+ fputs(*bracket, shout);
zrefresh();
@@ -1370,7 +1365,8 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
"ZLE_VARED_ABORTED" :
"ZLE_LINE_ABORTED", zlegetline(NULL, NULL));
- end_edit();
+ if ((bracket = getaparam("zle_bracketed_paste")) && arrlen(bracket) == 2)
+ fputs(bracket[1], shout);
if (done && !exit_pending && !errflag)
zlecallhook(finish, NULL);
@@ -1899,13 +1895,11 @@ describekeybriefly(UNUSED(char **args))
return 1;
clearlist = 1;
statusline = "Describe key briefly: _";
- start_edit();
zrefresh();
if (invicmdmode() && region_active && (km = openkeymap("visual")))
selectlocalmap(km);
seq = getkeymapcmd(curkeymap, &func, &str);
selectlocalmap(NULL);
- end_edit();
statusline = NULL;
if(!*seq)
return 1;
@@ -2003,7 +1997,6 @@ reexpandprompt(void)
static int looping;
if (!reexpanding++) {
- const char **markers = prompt_markers();
/*
* If we're displaying a status in the prompt, it
* needs to be the toplevel one, not the one from
@@ -2022,7 +2015,7 @@ reexpandprompt(void)
looping = reexpanding;
txtcurrentattrs = txtpendingattrs = txtunknownattrs = 0;
- new_lprompt = promptexpand(raw_lp ? *raw_lp : NULL, 1, markers[0], NULL, NULL);
+ new_lprompt = promptexpand(raw_lp ? *raw_lp : NULL, 1, NULL, NULL);
pmpt_attr = txtcurrentattrs;
free(lpromptbuf);
lpromptbuf = new_lprompt;
@@ -2030,7 +2023,7 @@ reexpandprompt(void)
if (looping != reexpanding)
continue;
- new_rprompt = promptexpand(raw_rp ? *raw_rp : NULL, 1, markers[2], NULL, NULL);
+ new_rprompt = promptexpand(raw_rp ? *raw_rp : NULL, 1, NULL, NULL);
rpmpt_attr = txtcurrentattrs;
prompt_attr = mixattrs(pmpt_attr, rpmpt_attr);
free(rpromptbuf);
@@ -2184,18 +2177,6 @@ zle_main_entry(int cmd, va_list ap)
break;
}
- case ZLE_CMD_PREEXEC:
- mark_output(1);
- break;
-
- case ZLE_CMD_POSTEXEC:
- mark_output(0);
- break;
-
- case ZLE_CMD_CHPWD:
- notify_pwd();
- break;
-
default:
#ifdef DEBUG
dputs("Bad command %d in zle_main_entry", cmd);
@@ -2258,10 +2239,6 @@ setup_(UNUSED(Module m))
comprecursive = 0;
rdstrs = NULL;
- /* detect terminal color and features */
- if (shout)
- query_terminal();
-
/* initialise the keymap system */
init_keymaps();
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 3e50d5d4b..60982d92e 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -554,8 +554,7 @@ yank(UNUSED(char **args))
}
/* position: 0 is before, 1 after, 2 split the line */
-static void
-pastebuf(Cutbuffer buf, int mult, int position)
+static void pastebuf(Cutbuffer buf, int mult, int position)
{
int cc;
if (buf->flags & CUTBUFFER_LINE) {
@@ -614,20 +613,7 @@ viputbefore(UNUSED(char **args))
return 1;
if (zmod.flags & MOD_NULL)
return 0;
- if (zmod.flags & MOD_OSSEL) {
- struct cutbuffer kbuf;
- int x;
- char *pbuf = system_clipget(zmod.flags & MOD_CLIP ? 'c' : 'p');
- if (!pbuf || !*pbuf)
- return 1;
- kbuf.buf = stringaszleline(pbuf, 0, &x, NULL, NULL);
- kbuf.len = x;
- kbuf.flags = 0;
- kct = -1;
- yankcs = zlecs;
- pastebuf(&kbuf, n, 0);
- return 0;
- } else if (zmod.flags & MOD_VIBUF)
+ if (zmod.flags & MOD_VIBUF)
kctbuf = &vibuf[zmod.vibuf];
else
kctbuf = &cutbuf;
@@ -650,20 +636,7 @@ viputafter(UNUSED(char **args))
return 1;
if (zmod.flags & MOD_NULL)
return 0;
- if (zmod.flags & MOD_OSSEL) {
- struct cutbuffer kbuf;
- int x;
- char *pbuf = system_clipget(zmod.flags & MOD_CLIP ? 'c' : 'p');
- if (!pbuf || !*pbuf)
- return 1;
- kbuf.buf = stringaszleline(pbuf, 0, &x, NULL, NULL);
- kbuf.len = x;
- kbuf.flags = 0;
- kct = -1;
- yankcs = zlecs;
- pastebuf(&kbuf, n, 1);
- return 0;
- } else if (zmod.flags & MOD_VIBUF)
+ if (zmod.flags & MOD_VIBUF)
kctbuf = &vibuf[zmod.vibuf];
else
kctbuf = &cutbuf;
@@ -688,25 +661,15 @@ putreplaceselection(UNUSED(char **args))
startvichange(-1);
if (n < 0 || zmod.flags & MOD_NULL)
return 1;
- if (zmod.flags & MOD_OSSEL) {
- int x;
- char *pbuf = system_clipget(zmod.flags & MOD_CLIP ? 'c' : 'p');
- if (!pbuf || !*pbuf)
- return 1;
- prevbuf.buf = stringaszleline(pbuf, 0, &x, NULL, NULL);
- prevbuf.len = x;
- prevbuf.flags = 0;
- } else {
- putbuf = (zmod.flags & MOD_VIBUF) ? &vibuf[zmod.vibuf] : &cutbuf;
- if (!putbuf->buf)
- return 1;
- memcpy(&prevbuf, putbuf, sizeof(prevbuf));
+ putbuf = (zmod.flags & MOD_VIBUF) ? &vibuf[zmod.vibuf] : &cutbuf;
+ if (!putbuf->buf)
+ return 1;
+ memcpy(&prevbuf, putbuf, sizeof(prevbuf));
- /* if "9 was specified, prevent killregion from freeing it */
- if (zmod.vibuf == 35) {
- putbuf->buf = 0;
- clear = 1;
- }
+ /* if "9 was specified, prevent killregion from freeing it */
+ if (zmod.vibuf == 35) {
+ putbuf->buf = 0;
+ clear = 1;
}
zmod.flags = 0; /* flags apply to paste not kill */
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index f27191114..f076bdd61 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -1024,8 +1024,6 @@ zrefresh(void)
tmpalloced = 0;
}
- zle_set_cursorform();
-
/* this will create region_highlights if it's still NULL */
zle_set_highlight();
@@ -1668,7 +1666,6 @@ individually */
/* move to the new cursor position */
moveto(rpms.nvln, rpms.nvcs);
- cursor_form();
/* swap old and new buffers - better than freeing/allocating every time */
bufswap();
@@ -2709,6 +2706,4 @@ zle_refresh_finish(void)
region_highlights = NULL;
n_region_highlights = 0;
}
-
- free_cursor_forms();
}
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index 6e2456b1f..e2b86e863 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -937,6 +937,28 @@ cut(int i, int ct, int flags)
cuttext(zleline + i, ct, flags);
}
+static char*
+base64_encode(const char *src, size_t len) {
+ static const char* base64_table =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ const unsigned char *end = (unsigned char *)src + len;
+ const unsigned char *in = (unsigned char *)src;
+ char *ret = zhalloc(1 + 4 * ((len + 2) / 3)); /* 4 bytes out for 3 in */
+ char *cur = ret;
+
+ for (; end - in > 0; in += 3, cur += 4) {
+ unsigned int n = *in << 16;
+ cur[3] = end - in > 2 ? base64_table[(n |= in[2]) & 0x3f] : '=';
+ cur[2] = end - in > 1 ? base64_table[((n |= in[1]<<8) >> 6) & 0x3f] : '=';
+ cur[1] = base64_table[(n >> 12) & 0x3f];
+ cur[0] = base64_table[n >> 18];
+ }
+ *cur = '\0';
+
+ return ret;
+}
+
/*
* As cut, but explicitly supply the text together with its length.
*/
@@ -953,7 +975,10 @@ cuttext(ZLE_STRING_T line, int ct, int flags)
int cutll;
char *mbcut = zlelineasstring(line, ct, 0, &cutll, NULL, 1);
unmetafy(mbcut, &cutll);
- system_clipput(zmod.flags & MOD_CLIP ? 'c' : 'p', mbcut, cutll);
+ mbcut = base64_encode(mbcut, cutll);
+
+ fprintf(shout, "\033]52;%c;%s\a", zmod.flags & MOD_CLIP ? 'c' : 'p',
+ mbcut);
} else if (zmod.flags & MOD_VIBUF) {
struct cutbuffer *b = &vibuf[zmod.vibuf];
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index 667063774..6692df830 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -186,7 +186,6 @@ getvirange(int wf)
virangeflag = 1;
wordflag = wf;
mark = -1;
- cursor_form();
/* use operator-pending keymap if one exists */
Keymap km = openkeymap("viopp");
if (km)
diff --git a/Src/builtin.c b/Src/builtin.c
index 9ddaad93e..950dd4b93 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -1258,11 +1258,8 @@ cd_new_pwd(int func, LinkNode dir, int quiet)
/* execute the chpwd function */
fflush(stdout);
fflush(stderr);
- if (!quiet) {
+ if (!quiet)
callhookfunc("chpwd", NULL, 1, NULL);
- if (zle_load_state == 1)
- zleentry(ZLE_CMD_CHPWD);
- }
dirstacksize = getiparam("DIRSTACKSIZE");
/* handle directory stack sizes out of range */
@@ -2035,7 +2032,7 @@ typeset_single(char *cname, char *pname, Param pm, int func,
if (pm && (pm->node.flags & PM_NAMEREF) && !((off|on) & PM_NAMEREF) &&
(pm->level == locallevel || !(on & PM_LOCAL))) {
- if ((pm = (Param)resolve_nameref(pm, NULL)))
+ if ((pm = resolve_nameref(pm)))
pname = pm->node.nam;
if (pm && (pm->node.flags & PM_NAMEREF) &&
(on & ~(PM_NAMEREF|PM_LOCAL|PM_READONLY))) {
@@ -3916,7 +3913,7 @@ bin_unset(char *name, char **argv, Options ops, int func)
returnval = 1;
} else if (ss) {
if ((pm->node.flags & PM_NAMEREF) &&
- (!(pm = (Param)resolve_nameref(pm, NULL)) || pm->width)) {
+ (!(pm = resolve_nameref(pm)) || pm->width)) {
/* warning? */
continue;
}
@@ -3960,7 +3957,7 @@ bin_unset(char *name, char **argv, Options ops, int func)
} else {
if (!OPT_ISSET(ops,'n')) {
int ref = (pm->node.flags & PM_NAMEREF);
- if (!(pm = (Param)resolve_nameref(pm, NULL)))
+ if (!(pm = resolve_nameref(pm)))
continue;
if (ref && pm->level < locallevel &&
!(pm->node.flags & PM_READONLY)) {
@@ -4801,7 +4798,7 @@ bin_print(char *name, char **args, Options ops, int func)
*/
char *str = unmetafy(
promptexpand(metafy(args[n], len[n], META_NOALLOC),
- 0, NULL, NULL, NULL),
+ 0, NULL, NULL),
&len[n]);
args[n] = dupstrpfx(str, len[n]);
free(str);
diff --git a/Src/init.c b/Src/init.c
index 20b8cc7fd..dfef860f7 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -213,17 +213,12 @@ loop(int toplevel, int justonce)
*/
errflag &= ~ERRFLAG_ERROR;
}
- if (toplevel && zle_load_state == 1)
- zleentry(ZLE_CMD_PREEXEC);
if (stopmsg) /* unset 'you have stopped jobs' flag */
stopmsg--;
execode(prog, 0, 0, toplevel ? "toplevel" : "file");
tok = toksav;
- if (toplevel) {
+ if (toplevel)
noexitct = 0;
- if (zle_load_state == 1)
- zleentry(ZLE_CMD_POSTEXEC);
- }
}
if (ferror(stderr)) {
zerr("write error");
@@ -754,7 +749,7 @@ static char *tccapnams[TC_COUNT] = {
"cl", "le", "LE", "nd", "RI", "up", "UP", "do",
"DO", "dc", "DC", "ic", "IC", "cd", "ce", "al", "dl", "ta",
"md", "mh", "so", "us", "ZH", "me", "se", "ue", "ZR", "ch",
- "ku", "kd", "kl", "kr", "sc", "rc", "bc", "AF", "AB", "vi", "ve"
+ "ku", "kd", "kl", "kr", "sc", "rc", "bc", "AF", "AB"
};
/**/
@@ -1808,7 +1803,7 @@ VA_DCL
lp = va_arg(ap, char **);
- pptbuf = unmetafy(promptexpand(lp ? *lp : NULL, 0, NULL, NULL, NULL),
+ pptbuf = unmetafy(promptexpand(lp ? *lp : NULL, 0, NULL, NULL),
&pptlen);
write_loop(2, pptbuf, pptlen);
free(pptbuf);
diff --git a/Src/input.c b/Src/input.c
index 9b8e57f6a..b78c91680 100644
--- a/Src/input.c
+++ b/Src/input.c
@@ -399,7 +399,7 @@ inputline(void)
char *pptbuf;
int pptlen;
pptbuf = unmetafy(promptexpand(ingetcpmptl ? *ingetcpmptl : NULL,
- 0, NULL, NULL, NULL), &pptlen);
+ 0, NULL, NULL), &pptlen);
write_loop(2, pptbuf, pptlen);
free(pptbuf);
}
diff --git a/Src/loop.c b/Src/loop.c
index db78f00c7..ba01b1da5 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -282,7 +282,7 @@ execselect(Estate state, UNUSED(int do_exec))
/* Keep any user interrupt error status */
errflag = oef | (errflag & ERRFLAG_INT);
} else {
- str = promptexpand(prompt3, 0, NULL, NULL, NULL);
+ str = promptexpand(prompt3, 0, NULL, NULL);
zputs(str, stderr);
free(str);
fflush(stderr);
diff --git a/Src/params.c b/Src/params.c
index b76fb8a6b..c0a9791da 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -522,7 +522,7 @@ newparamtable(int size, char const *name)
}
/**/
-static HashNode
+static Param
loadparamnode(HashTable ht, Param pm, const char *nam)
{
if (pm && (pm->node.flags & PM_AUTOLOAD) && pm->u.str) {
@@ -544,17 +544,17 @@ loadparamnode(HashTable ht, Param pm, const char *nam)
nam);
}
}
- return (HashNode)pm;
+ return pm;
}
/**/
static HashNode
getparamnode(HashTable ht, const char *nam)
{
- HashNode hn = loadparamnode(ht, (Param)gethashnode2(ht, nam), nam);
- if (hn && ht == realparamtab && !(hn->flags & PM_UNSET))
- hn = resolve_nameref((Param)hn, NULL);
- return hn;
+ Param pm = loadparamnode(ht, (Param)gethashnode2(ht, nam), nam);
+ if (pm && ht == realparamtab && !(pm->node.flags & PM_UNSET))
+ pm = resolve_nameref(pm);
+ return (HashNode)pm;
}
/* Copy a parameter hash table */
@@ -1043,12 +1043,14 @@ createparam(char *name, int flags)
(oldpm->level == locallevel ?
!(oldpm->node.flags & PM_RO_BY_DESIGN) : !(flags & PM_LOCAL)) &&
(oldpm->node.flags & PM_NAMEREF)) {
- Param lastpm;
- struct asgment stop;
- stop.flags = PM_NAMEREF;
- stop.name = "";
- stop.value.scalar = NULL;
- lastpm = (Param)resolve_nameref(oldpm, &stop);
+ /**
+ * Here we only have to deal with namerefs that refer to
+ * not-yet-defined or unset variable. All other namerefs
+ * have already been taken care of by the resolve_nameref
+ * in typeset_single. It's unclear why these can't be
+ * handled there too.
+ **/
+ Param lastpm = resolve_nameref_rec(oldpm, NULL, 1);
if (lastpm) {
if (lastpm->node.flags & PM_NAMEREF) {
char *refname = GETREFNAME(lastpm);
@@ -2236,13 +2238,8 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
*ss = 0;
}
Param p1 = (Param)gethashnode2(paramtab, ref);
- if (p1) {
- if (pm->node.flags & PM_UPPER)
- pm = upscope_upper(p1, pm->level - 1);
- else
- pm = upscope(p1, pm->base);
- pm = (Param)loadparamnode(paramtab, pm, ref);
- }
+ if (p1)
+ pm = loadparamnode(paramtab, upscope(p1, pm), ref);
if (!(p1 && pm) ||
((pm->node.flags & PM_UNSET) &&
!(pm->node.flags & PM_DECLARED)))
@@ -3329,11 +3326,7 @@ assignsparam(char *s, char *val, int flags)
}
}
- if (v->pm->node.flags & PM_NAMEREF)
- v->pm->node.flags |= PM_NEWREF;
assignstrvalue(v, val, flags);
- if (v->pm->node.flags & PM_NAMEREF)
- v->pm->node.flags &= ~PM_NEWREF;
unqueue_signals();
return v->pm;
}
@@ -6307,12 +6300,17 @@ printparamnode(HashNode hn, int printflags)
}
/**/
-mod_export HashNode
-resolve_nameref(Param pm, const Asgment stop)
+mod_export Param
+resolve_nameref(Param pm)
{
- HashNode hn = (HashNode)pm;
- const char *seek = stop ? stop->value.scalar : NULL;
+ return resolve_nameref_rec(pm, NULL, 0);
+}
+/**/
+static Param
+resolve_nameref_rec(Param pm, const Param stop, int keep_lastref)
+{
+ Param hn = pm;
if (pm && (pm->node.flags & PM_NAMEREF)) {
char *refname = GETREFNAME(pm);
if (pm->node.flags & PM_TAGGED) {
@@ -6321,63 +6319,25 @@ resolve_nameref(Param pm, const Asgment stop)
} else if (pm->node.flags & PM_UNSET) {
/* Semaphore with createparam() */
pm->node.flags &= ~PM_UNSET;
- if (pm->node.flags & PM_NEWREF) /* See setloopvar() */
- return NULL;
- return (HashNode) pm;
- } else if (refname) {
- if (stop && strcmp(refname, stop->name) == 0) {
- /* zwarnnam(refname, "invalid self reference"); */
- return (HashNode)pm;
- }
- if (*refname)
- seek = refname;
+ return pm;
}
- }
- else if (pm) {
- if (!(stop && (stop->flags & PM_NAMEREF)))
- return (HashNode)pm;
- if (!(pm->node.flags & PM_NAMEREF))
- return (pm->level < locallevel ? NULL : (HashNode)pm);
- }
- if (seek) {
- queue_signals();
/* pm->width is the offset of any subscript */
- if (pm && (pm->node.flags & PM_NAMEREF) && pm->width) {
- if (stop) {
- if (stop->flags & PM_NAMEREF)
- hn = (HashNode)pm;
- else
- hn = NULL;
- } else {
- /* this has to be the end of any chain */
- hn = (HashNode)pm; /* see fetchvalue() */
- }
- } else if ((hn = gethashnode2(realparamtab, seek))) {
- if (pm) {
- if (!(stop && (stop->flags & (PM_LOCAL)))) {
- if ((pm->node.flags & PM_NAMEREF) &&
- (pm->node.flags & PM_UPPER))
- hn = (HashNode)upscope_upper((Param)hn, pm->level - 1);
- else
- hn = (HashNode)upscope((Param)hn,
- (pm->node.flags & PM_NAMEREF) ?
- (pm->base) : ((Param)hn)->level);
+ /* If present, it has to be the end of any chain, see fetchvalue() */
+ if (refname && *refname && !pm->width) {
+ queue_signals();
+ if ((hn = (Param)gethashnode2(realparamtab, refname))) {
+ if ((hn = loadparamnode(paramtab, upscope(hn, pm), refname)) &&
+ hn != stop && !(hn->node.flags & PM_UNSET)) {
+ /* user can't tag a nameref, safe for loop detection */
+ pm->node.flags |= PM_TAGGED;
+ hn = resolve_nameref_rec(hn, stop, keep_lastref);
+ pm->node.flags &= ~PM_TAGGED;
}
- hn = loadparamnode(paramtab, (Param)hn, seek);
- /* user can't tag a nameref, safe for loop detection */
- pm->node.flags |= PM_TAGGED;
- }
- if (hn) {
- if (!(hn->flags & PM_UNSET))
- hn = resolve_nameref((Param)hn, stop);
- }
- if (pm)
- pm->node.flags &= ~PM_TAGGED;
- } else if (stop && (stop->flags & PM_NAMEREF))
- hn = (pm && (pm->node.flags & PM_NEWREF)) ? NULL : (HashNode)pm;
- unqueue_signals();
+ } else if (keep_lastref)
+ hn = pm;
+ unqueue_signals();
+ }
}
-
return hn;
}
@@ -6396,10 +6356,7 @@ setloopvar(char *name, char *value)
pm->base = pm->width = 0;
SETREFNAME(pm, ztrdup(value));
pm->node.flags &= ~PM_UNSET;
- pm->node.flags |= PM_NEWREF;
setscope(pm);
- if (!errflag)
- pm->node.flags &= ~PM_NEWREF;
} else
setsparam(name, ztrdup(value));
}
@@ -6409,9 +6366,8 @@ static void
setscope(Param pm)
{
queue_signals();
- if (pm->node.flags & PM_NAMEREF) do {
- Param basepm;
- struct asgment stop;
+ if (pm->node.flags & PM_NAMEREF) {
+ Param basepm = NULL;
char *refname = GETREFNAME(pm);
char *t = refname ? itype_end(refname, INAMESPC, 0) : NULL;
int q = queue_signal_level();
@@ -6432,7 +6388,7 @@ setscope(Param pm)
if (!(pm->node.flags & PM_UPPER) && refname &&
(basepm = (Param)gethashnode2(realparamtab, refname)) &&
(basepm = (Param)loadparamnode(realparamtab, basepm, refname)) &&
- (!(basepm->node.flags & PM_NEWREF) || (basepm = basepm->old))) {
+ (basepm != pm || !basepm->old || (basepm = basepm->old))) {
pm->base = basepm->level;
}
if (pm->base > pm->level) {
@@ -6446,60 +6402,27 @@ setscope(Param pm)
}
/* Check for self references */
- stop.name = pm->node.nam;
- stop.value.scalar = NULL;
- stop.flags = PM_NAMEREF;
- dont_queue_signals(); /* Prevent unkillable loops */
- basepm = (Param)resolve_nameref(pm, &stop);
- restore_queue_signals(q);
- if (basepm) {
- if (basepm->node.flags & PM_NAMEREF) {
- if (pm == basepm) {
- if (pm->base == pm->level) {
- if (refname && *refname &&
- strcmp(pm->node.nam, refname) == 0) {
- zerr("%s: invalid self reference", refname);
- unsetparam_pm(pm, 0, 1);
- break;
- }
- }
- } else if ((t = GETREFNAME(basepm))) {
- if (basepm->base <= basepm->level &&
- strcmp(pm->node.nam, t) == 0) {
- zerr("%s: invalid self reference", refname);
- unsetparam_pm(pm, 0, 1);
- break;
- }
- }
- }
+ if (refname && *refname && !pm->width && basepm != pm) {
+ dont_queue_signals(); /* Prevent unkillable loops */
+ basepm = resolve_nameref_rec(pm, pm, 0);
+ restore_queue_signals(q);
}
- if (refname && upscope(pm, pm->base) == pm &&
- strcmp(pm->node.nam, refname) == 0) {
+ if (pm == basepm) {
zerr("%s: invalid self reference", refname);
unsetparam_pm(pm, 0, 1);
}
- } while (0);
- unqueue_signals();
-}
-
-/**/
-static Param
-upscope(Param pm, int reflevel)
-{
- Param up = pm->old;
- while (up && up->level >= reflevel) {
- pm = up;
- up = up->old;
}
- return pm;
+ unqueue_signals();
}
/**/
static Param
-upscope_upper(Param pm, int reflevel)
+upscope(Param pm, const Param ref)
{
- while (pm && pm->level > reflevel)
- pm = pm->old;
+ if (ref->node.flags & PM_UPPER)
+ while (pm->level > ref->level - 1 && (pm = pm->old));
+ else
+ for (; pm->old && pm->old->level >= ref->base; pm = pm->old);
return pm;
}
diff --git a/Src/prompt.c b/Src/prompt.c
index 25392b4c2..7467cdfb9 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -174,7 +174,7 @@ promptpath(char *p, int npath, int tilde)
/**/
mod_export char *
-promptexpand(char *s, int ns, const char *marker, char *rs, char *Rs)
+promptexpand(char *s, int ns, char *rs, char *Rs)
{
struct buf_vars new_vars;
@@ -218,11 +218,6 @@ promptexpand(char *s, int ns, const char *marker, char *rs, char *Rs)
new_vars.bp1 = NULL;
new_vars.truncwidth = 0;
- if (marker && *s) {
- *new_vars.bp++ = Inpar;
- strucpy(&new_vars.bp, (char *) marker);
- *new_vars.bp++ = Outpar;
- }
putpromptchar(1, '\0');
addbufspc(2);
if (new_vars.dontcount)
@@ -326,7 +321,7 @@ parsecolorchar(zattr arg, int is_fg)
*ep = '\0';
/* expand the contents of the argument so you can use
* %v for example */
- coll = col = promptexpand(bv->fm, 0, NULL, NULL, NULL);
+ coll = col = promptexpand(bv->fm, 0, NULL, NULL);
*ep = oc;
arg = match_colour((const char **)&coll, is_fg, 0);
free(col);
@@ -1841,19 +1836,6 @@ match_named_colour(const char **teststrp)
return -1;
}
-static int
-truecolor_terminal()
-{
- char **f, **flist = getaparam(".term.extensions");
- int result;
- for (f = flist; f && *f; f++) {
- result = **f != '-';
- if (!strcmp(*f + !result, "truecolor"))
- return result;
- }
- return 0; /* disabled by default */
-}
-
/*
* Match just the colour part of a highlight specification.
* If teststrp is NULL, use the already parsed numeric colour.
@@ -1897,10 +1879,7 @@ match_colour(const char **teststrp, int is_fg, int colour)
return TXT_ERROR;
*teststrp = end;
colour = runhookdef(GETCOLORATTR, &color) - 1;
- if (colour == -1 && !truecolor_terminal() &&
- !load_module("zsh/nearcolor", NULL, 1))
- colour = runhookdef(GETCOLORATTR, &color) - 1;
- if (colour == -1) { /* use true color (24-bit) */
+ if (colour == -1) { /* no hook function added, try true color (24-bit) */
colour = (((color.red << 8) + color.green) << 8) + color.blue;
return on | (is_fg ? TXT_ATTR_FG_24BIT : TXT_ATTR_BG_24BIT) |
(zattr)colour << shft;
diff --git a/Src/subst.c b/Src/subst.c
index 8d730163e..be2333ca5 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -4001,7 +4001,7 @@ colonsubscript:
char *tmps;
untokenize(*ap);
txtunknownattrs = TXT_ATTR_ALL;
- tmps = promptexpand(*ap, 0, NULL, NULL, NULL);
+ tmps = promptexpand(*ap, 0, NULL, NULL);
*ap = dupstring(tmps);
free(tmps);
}
@@ -4011,7 +4011,7 @@ colonsubscript:
val = dupstring(val), copied = 1;
untokenize(val);
txtunknownattrs = TXT_ATTR_ALL;
- tmps = promptexpand(val, 0, NULL, NULL, NULL);
+ tmps = promptexpand(val, 0, NULL, NULL);
val = dupstring(tmps);
free(tmps);
}
diff --git a/Src/utils.c b/Src/utils.c
index a1d7c8cc2..e7e3f4f8d 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1556,7 +1556,7 @@ preprompt(void)
eolmark = "%B%S%#%s%b";
opts[PROMPTPERCENT] = 1;
txtunknownattrs = TXT_ATTR_ALL;
- str = promptexpand(eolmark, 1, NULL, NULL, NULL);
+ str = promptexpand(eolmark, 1, NULL, NULL);
countprompt(str, &w, 0, -1);
opts[PROMPTPERCENT] = percents;
zputs(str, shout);
@@ -1726,7 +1726,7 @@ printprompt4(void)
opts[XTRACE] = 0;
unmetafy(s, &l);
s = unmetafy(promptexpand(metafy(s, l, META_NOALLOC),
- 0, NULL, NULL, NULL), &l);
+ 0, NULL, NULL), &l);
opts[XTRACE] = t;
fprintf(xtrerr, "%s", s);
@@ -3275,7 +3275,7 @@ spckword(char **s, int hist, int cmd, int ask)
x = 'n';
} else if (shout) {
char *pptbuf;
- pptbuf = promptexpand(sprompt, 0, NULL, best, guess);
+ pptbuf = promptexpand(sprompt, 0, best, guess);
zputs(pptbuf, shout);
free(pptbuf);
fflush(shout);
diff --git a/Src/zsh.h b/Src/zsh.h
index b82c35aea..af90d6e75 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1936,8 +1936,6 @@ struct tieddata {
#define PM_NAMEDDIR (1<<29) /* has a corresponding nameddirtab entry */
#define PM_NAMEREF (1<<30) /* pointer to a different parameter */
-#define PM_NEWREF PM_SINGLE /* Overload in for-loop namerefs */
-
/* The option string corresponds to the first of the variables above */
#define TYPESET_OPTSTR "aiEFALRZlurtxUhHT"
@@ -2674,9 +2672,7 @@ struct ttyinfo {
#define TCBACKSPACE 34
#define TCFGCOLOUR 35
#define TCBGCOLOUR 36
-#define TCCURINV 37
-#define TCCURVIS 38
-#define TC_COUNT 39
+#define TC_COUNT 37
#define tccan(X) (tclen[X])
@@ -3237,10 +3233,7 @@ enum {
ZLE_CMD_REFRESH,
ZLE_CMD_SET_KEYMAP,
ZLE_CMD_GET_KEY,
- ZLE_CMD_SET_HIST_LINE,
- ZLE_CMD_PREEXEC,
- ZLE_CMD_POSTEXEC,
- ZLE_CMD_CHPWD
+ ZLE_CMD_SET_HIST_LINE
};
/***************************************/
diff --git a/Test/K01nameref.ztst b/Test/K01nameref.ztst
index 5d229a94e..5a8dc2c7d 100644
--- a/Test/K01nameref.ztst
+++ b/Test/K01nameref.ztst
@@ -469,6 +469,14 @@ F:unexpected side-effects of previous tests
}
0:regression: not a self reference (test 2)
+ typeset ptr2=foo
+ () {
+ typeset -n ptr1=ptr2
+ typeset -n ptr2=ptr1
+ }
+0:regression: not a self reference (test 3)
+
+
unset -n ptr2
typeset -n ptr2='path[2]'
print -r -- $ptr2
@@ -1527,4 +1535,38 @@ F:converting from association/array to string should work here too
>typeset -A var=( [z]=Z )
>typeset -A var=( [z]=Z )
+ typeset ptr1=foo
+ () {
+ typeset -n ptr1
+ typeset -n ptr2=ptr1
+ ptr1=ptr2
+ echo ptr1=$ptr1
+ }
+1:regression: reference loop with same name enclosing variable
+?(anon):3: ptr2: invalid self reference
+
+ typeset -n ref=ref[1]
+1:self reference with subscript
+*?*: ref: invalid self reference
+
+ typeset var=foo
+ typeset -n ref=var
+ () {
+ typeset -n ref
+ ref=""
+ ref=ref
+ echo $ref
+ }
+0:reference always prefers enclosing variable over itself
+>foo
+
+ typeset -n ref1
+ () {
+ typeset -n ref2=ref3
+ ref1=ref2
+ typeset -nu ref3=ref1
+ }
+1:self reference via upper reference
+?(anon):3: ref1: invalid self reference
+
%clean
diff --git a/Test/X04zlehighlight.ztst b/Test/X04zlehighlight.ztst
index ecb309605..87a59fde5 100644
--- a/Test/X04zlehighlight.ztst
+++ b/Test/X04zlehighlight.ztst
@@ -12,7 +12,6 @@
zpty zsh "${(q)ZTST_testdir}/../Src/zsh -fiV +Z"
zpty -w zsh "module_path=( ${(j< >)${(@q-)module_path}} \$module_path )"
zpty -w zsh 'zle_highlight=( fg_start_code:"CDE|3" fg_end_code:"|" bg_start_code:"BCDE|4" bg_end_code:"|" )'
- zpty -w zsh '.term.extensions=( -query truecolor -bracketed-paste -integration )'
}
zpty_input() {
zpty ${${(M)2:#nonl}:+-n} -w zsh "$1"
@@ -20,7 +19,7 @@
zpty_enable_zle() {
zpty -w zsh "tcfunc() { REPLY=""; }"
# This line will not be echoed back, behaving like ! -o zle
- zpty -w zsh "setopt zle; zle -T tc tcfunc"
+ zpty -w zsh "setopt zle; zle -T tc tcfunc; unset zle_bracketed_paste"
}
zpty_line() {
setopt localoptions extendedglob noshwordsplit
diff --git a/Test/X06termquery.ztst b/Test/X06termquery.ztst
deleted file mode 100644
index 5f3a81aae..000000000
--- a/Test/X06termquery.ztst
+++ /dev/null
@@ -1,110 +0,0 @@
-# Tests for handling terminal responses to escape sequences
-%prep
-
- if zmodload zsh/zpty 2> /dev/null; then
- termresp() {
- setopt localoptions extendedglob
- export PS1= PS2= COLORTERM= TERM=
- typeset +x -m .term.\*
- zpty -d
- zpty zsh "${(q)ZTST_testdir}/../Src/zsh -fiV +Z"
- zpty -w zsh "module_path=( ${(j< >)${(@q-)module_path}} \$module_path )"
- zpty -w zsh ".term.extensions=( -bracketed-paste -integration )"
- zpty -w zsh "setopt zle"
- zpty -r zsh REPLY $'\e*\r'
- zpty -n -w zsh "$1"
- zpty -w zsh "typeset -p -m .term.\*"
- zpty -w zsh 'exit'
- { zpty -r zsh } | tr -d '\015' | grep -v '^ '
- zpty -d
- }
- else
- ZTST_unimplemented='the zsh/zpty module is not available'
- fi
-
-%test
-
- termresp $'\e]11;rgb:ffff/ffff/dddd\e\\\e]10;rgb:0000/0000/0000\e\\\e[?0u\eP1+r524742=38\e\\\eP>|foot(1.20.2)\e\\\e[?62;4;22;28c'
-0:foot response to terminal queries
->typeset .term.id=foot
->typeset .term.fg='#000000'
->typeset .term.bg='#ffffdd'
->typeset .term.version=1.20.2
->typeset .term.mode=light
->typeset -a .term.extensions=( -bracketed-paste -integration modkeys-kitty truecolor )
-
- termresp $'\e]11;rgb:0/0/0\e\\\e]10;rgb:ff/ff/ff\e\\\eP>|Wayst(0.0.0)\e\\\e[?63;1;4c'
-0:wayst response to terminal queries (shorter colour sequences)
->typeset .term.id=Wayst
->typeset .term.fg='#ffffff'
->typeset .term.bg='#000000'
->typeset .term.version=0.0.0
->typeset .term.mode=dark
->typeset -a .term.extensions=( -bracketed-paste -integration )
-
- termresp $'\e]11;rgb:0000/0000/0000\e\\\e]10;rgb:b2b2/b2b2/b2b2\e\\\eP1+r524742=382F382F38\e\\\eP>|WezTerm 20240203-110809-5046fc22\e\\\e[?65;4;6;18;22c'
-0:WezTerm response to terminal queries (space separates version and longer RGB response)
->typeset .term.id=WezTerm
->typeset .term.fg='#b2b2b2'
->typeset .term.bg='#000000'
->typeset .term.version=20240203-110809-5046fc22
->typeset .term.mode=dark
->typeset -a .term.extensions=( -bracketed-paste -integration truecolor )
-
- termresp $'\e]11;rgb:9600/8700/7900\e\e]10;rgb:0000/0000/0000\e\e[?1;2c'
-0:urxvt response to terminal queries (bug in end of colour sequences)
->typeset .term.fg='#000000'
->typeset .term.bg='#968779'
->typeset .term.mode=light
->typeset -a .term.extensions=( -bracketed-paste -integration )
-
- termresp $'\e]11;rgb:0000/0000/0000\e\\\e]10;rgb:dddd/dddd/dddd\e\\\e[?0u\eP0+r524742\e\\\eP>|kitty(0.36.4)\e\\\e[?62;c'
-0:kitty response to terminal queries (responds with error to RGB request)
->typeset .term.id=kitty
->typeset .term.fg='#dddddd'
->typeset .term.bg='#000000'
->typeset .term.version=0.36.4
->typeset .term.mode=dark
->typeset -a .term.extensions=( -bracketed-paste -integration modkeys-kitty )
-
- termresp $'\e]11;rgb:0000/ffff/8c8c\e\\\e]10;rgb:0000/0000/0000\e\\\eP1+r524742=38\e\\\eP>|XTerm(396)\e\\\e[?64;1;2;6;9;15;16;17;18;21;22;28c'
-0:xterm response to terminal queries
->typeset .term.id=XTerm
->typeset .term.fg='#000000'
->typeset .term.bg='#00ff8c'
->typeset .term.version=396
->typeset .term.mode=light
->typeset -a .term.extensions=( -bracketed-paste -integration truecolor )
-
- termresp $'echo type\e]11;rgb:0/0/0\aah\e]10;rgb:A/B/C\aea\e[?0u\eP0+r\e\\d\n\e[?0;c'
-0:type-ahead
->typeahead
->typeset .term.fg='#0a0b0c'
->typeset .term.bg='#000000'
->typeset .term.mode=dark
->typeset -a .term.extensions=( -bracketed-paste -integration modkeys-kitty )
-
- termresp ''
-0:no response - timeout
->typeset -a .term.extensions=( -bracketed-paste -integration )
-
-# Following three vi-put tests also cover 0, 1 and 2 `=' padding
-# characters in the base64 decoding.
- termresp $'\e[?0;cbindkey -v\necho \e"*p\e]52;p;YWZ0ZXI=\aa\n'
-0:paste after from clipboard
->after
->typeset -a .term.extensions=( -bracketed-paste -integration )
-
- termresp $'\e[?0;cbindkey -v\necho X\e"*P\e]52;p;YmVmb3Jl\aa\n'
-0:paste before from clipboard
->beforeX
->typeset -a .term.extensions=( -bracketed-paste -integration )
-
- termresp $'\e[?0;cbindkey -v\necho X\ev"*p\e]52;p;cmVwbGFjZQ==\aa\n'
-0:paste over from clipboard
->replace
->typeset -a .term.extensions=( -bracketed-paste -integration )
-
-%clean
-
- zmodload -ui zsh/zpty
Messages sorted by:
Reverse Date,
Date,
Thread,
Author