1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-06-19 18:19:50 +02:00

28772: Update regions in region highlight dynamically

This commit is contained in:
Peter Stephenson 2011-02-18 22:08:45 +00:00
parent 6be3fe2fca
commit 212ca9edf9
9 changed files with 413 additions and 56 deletions

View File

@ -1,3 +1,10 @@
2011-02-18 Peter Stephenson <p.w.stephenson@ntlworld.com>
* 28772: Doc/Zsh/zle.yo, Src/Zle/compcore.c,
Src/Zle/compresult.c, Src/Zle/zle.h, Src/Zle/zle_refresh.c,
Src/Zle/zle_tricky.c, Src/Zle/zle_utils.c: update regions
in $region_highlight dynamically.
2011-02-17 Peter Stephenson <p.w.stephenson@ntlworld.com>
* 28761: Completion/Unix/Command/_sccs: file completion missing
@ -14215,5 +14222,5 @@
*****************************************************
* This is used by the shell to define $ZSH_PATCHLEVEL
* $Revision: 1.5200 $
* $Revision: 1.5201 $
*****************************************************

View File

@ -842,10 +842,7 @@ specifies that the first twenty characters of the text including
any predisplay string should be highlighted in bold.
Note that the effect of tt(region_highlight) is not saved and disappears
as soon as the line is accepted. The line editor makes no attempt to
keep the highlighting effect synchronised with the line as it is edited;
hence region highlighting is best limited to static effects within
user widgets.
as soon as the line is accepted.
)
vindex(WIDGET)
item(tt(WIDGET) (scalar))(

View File

@ -15,7 +15,7 @@ local -a bufwords lbufwords
local word
integer pos=1 cpos=$((CURSOR+1)) opos iword ichar
bufwords=(${(z)BUFFER})
bufwords=(${(Z+n+)BUFFER})
reply=()
while [[ ${BUFFER[pos]} = [[:space:]] ]]; do

View File

@ -1395,8 +1395,6 @@ set_comp_sep(void)
LinkNode n;
/* Save word position */
int owe = we, owb = wb;
/* Save cursor position and line length */
int ocs, oll;
/*
* Values of word beginning and end and cursor after subtractions
* due to separators. I think these are indexes into zlemetaline,
@ -1481,8 +1479,7 @@ set_comp_sep(void)
/* Put the string in the lexer buffer and call the lexer to *
* get the words we have to expand. */
ocs = zlemetacs;
oll = zlemetall;
zle_save_positions();
ol = zlemetaline;
addedx = 1;
noerrs = 1;
@ -1639,9 +1636,8 @@ set_comp_sep(void)
lexrestore();
wb = owb;
we = owe;
zlemetacs = ocs;
zlemetaline = ol;
zlemetall = oll;
zle_restore_positions();
if (cur < 0 || i < 1)
return 1;
owb = offs;

View File

@ -698,8 +698,10 @@ hasbrpsfx(Cmatch m, char *pre, char *suf)
{
char *op = lastprebr, *os = lastpostbr;
VARARR(char, oline, zlemetall);
int oll = zlemetall, ocs = zlemetacs, ole = lastend, opcs = brpcs, oscs = brscs, ret;
int oll = zlemetall, newll, ole = lastend;
int opcs = brpcs, oscs = brscs, ret;
zle_save_positions();
memcpy(oline, zlemetaline, zlemetall);
lastprebr = lastpostbr = NULL;
@ -710,7 +712,10 @@ hasbrpsfx(Cmatch m, char *pre, char *suf)
foredel(zlemetall, CUT_RAW);
spaceinline(oll);
memcpy(zlemetaline, oline, oll);
zlemetacs = ocs;
/* we do not want to restore zlemetall */
newll = zlemetall;
zle_restore_positions();
zlemetall = newll;
lastend = ole;
brpcs = opcs;
brscs = oscs;

View File

@ -385,6 +385,47 @@ enum suffixflags {
SUFFLAGS_SPACE = 0x0001 /* Add a space when removing suffix */
};
/* Flags for the region_highlight structure */
enum {
/* Offsets include predisplay */
ZRH_PREDISPLAY = 1
};
/*
* Attributes used for highlighting regions.
* and mark.
*/
struct region_highlight {
/* Attributes turned on in the region */
int atr;
/* Start of the region */
int start;
/* Start of the region in metafied ZLE line */
int start_meta;
/*
* End of the region: position of the first character not highlighted
* (the same system as for point and mark).
*/
int end;
/* End of the region in metafied ZLE line */
int end_meta;
/*
* Any of the flags defined above.
*/
int flags;
};
/*
* Count of special uses of region highlighting, which account
* for the first few elements of region_highlights.
* 0: region between point and mark
* 1: isearch region
* 2: suffix
*/
#define N_SPECIAL_HIGHLIGHTS (3)
#ifdef MULTIBYTE_SUPPORT
/*
* We use a wint_t here, since we need an invalid character as a
@ -420,15 +461,28 @@ typedef REFRESH_ELEMENT *REFRESH_STRING;
#if defined(MULTIBYTE_SUPPORT) && defined(__STDC_ISO_10646__)
/*
* With ISO 10646 there is a private range defined within
* the encoding. We use this for storing single-byte
* characters in sections of strings that wouldn't convert to wide
* characters. This allows to preserve the string when transformed
* back to multibyte strings.
*/
/* The start of the private range we use, for 256 characters */
#define ZSH_INVALID_WCHAR_BASE (0xe000U)
/* Detect a wide character within our range */
#define ZSH_INVALID_WCHAR_TEST(x) \
((unsigned)(x) >= ZSH_INVALID_WCHAR_BASE && \
(unsigned)(x) <= (ZSH_INVALID_WCHAR_BASE + 255u))
/* Turn a wide character in that range back to single byte */
#define ZSH_INVALID_WCHAR_TO_CHAR(x) \
((char)((unsigned)(x) - ZSH_INVALID_WCHAR_BASE))
/* Turn a wide character in that range to an integer */
#define ZSH_INVALID_WCHAR_TO_INT(x) \
((int)((unsigned)(x) - ZSH_INVALID_WCHAR_BASE))
#define ZSH_CHAR_TO_INVALID_WCHAR(x) \
/* Turn a single byte character into a private wide character */
#define ZSH_CHAR_TO_INVALID_WCHAR(x) \
((wchar_t)(STOUC(x) + ZSH_INVALID_WCHAR_BASE))
#endif

View File

@ -210,50 +210,21 @@ int predisplaylen, postdisplaylen;
static int default_atr_on, special_atr_on;
/* Flags for the region_highlight structure */
enum {
/* Offsets include predisplay */
ZRH_PREDISPLAY = 1
};
/*
* Attributes used for highlighting regions.
* and mark.
*/
struct region_highlight {
/* Attributes turned on in the region */
int atr;
/* Start of the region */
int start;
/*
* End of the region: position of the first character not highlighted
* (the same system as for point and mark).
*/
int end;
/*
* Any of the flags defined above.
*/
int flags;
};
/*
* Array of region highlights, no special termination.
* The first element (0) always describes the region between
* point and mark. Any other elements are set by the user
* via the parameter region_highlight.
*/
/**/
struct region_highlight *region_highlights;
/*
* Count of special uses of region highlighting, which account
* for the first few elements of region_highlights.
* 0: region between point and mark
* 1: isearch region
* 2: suffix
*/
#define N_SPECIAL_HIGHLIGHTS (3)
/*
* Number of elements in region_highlights.
* This includes the special elements above.
*/
/**/
int n_region_highlights;
/*

View File

@ -2675,14 +2675,13 @@ int
doexpandhist(void)
{
char *ol;
int oll, ocs, ne = noerrs, err, ona = noaliases;
int ne = noerrs, err, ona = noaliases;
UNMETACHECK();
pushheap();
metafy_line();
oll = zlemetall;
ocs = zlemetacs;
zle_save_positions();
ol = dupstring(zlemetaline);
expanding = 1;
excs = zlemetacs;
@ -2725,8 +2724,7 @@ doexpandhist(void)
}
strcpy(zlemetaline, ol);
zlemetall = oll;
zlemetacs = ocs;
zle_restore_positions();
unmetafy_line();
popheap();

View File

@ -179,6 +179,8 @@ zlecharasstring(ZLE_CHAR_T inchar, char *buf)
* string length, without the NULL byte.
*
* If outcsp is non-NULL, assign the new character position.
* If outcsp is &zlemetacs, update the positions in the region_highlight
* array, too. This is a bit of a hack.
*
* If useheap is 1, memory is returned from the heap, else is allocated
* for later freeing.
@ -190,6 +192,7 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp,
int *outcsp, int useheap)
{
int outcs, outll;
struct region_highlight *rhp;
#ifdef MULTIBYTE_SUPPORT
char *s;
@ -201,9 +204,22 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp,
outcs = 0;
memset(&mbs, 0, sizeof(mbs));
for (i=0; i < inll; i++, incs--) {
for (i=0; i < inll; i++) {
if (incs == 0)
outcs = mb_len;
incs--;
if (region_highlights && outcsp == &zlemetacs) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
if (rhp->start == 0)
rhp->start_meta = mb_len;
rhp->start--;
if (rhp->end == 0)
rhp->end_meta = mb_len;
rhp->end--;
}
}
#ifdef __STDC_ISO_10646__
if (ZSH_INVALID_WCHAR_TEST(instr[i])) {
s[mb_len++] = ZSH_INVALID_WCHAR_TO_CHAR(instr[i]);
@ -222,12 +238,30 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp,
}
if (incs == 0)
outcs = mb_len;
if (region_highlights && outcsp == &zlemetacs) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
if (rhp->start == 0)
rhp->start_meta = mb_len;
if (rhp->end == 0)
rhp->end_meta = mb_len;
}
}
s[mb_len] = '\0';
outll = mb_len;
#else
outll = inll;
outcs = incs;
if (region_highlights && outcsp == &zlemetacs) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
rhp->start_meta = rhp->start;
rhp->end_meta = rhp->end;
}
}
#endif
/*
@ -243,11 +277,33 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp,
#endif
char *stopcs = strp + outcs;
char *stopll = strp + outll;
char *startp = strp;
if (region_highlights && outcsp == &zlemetacs) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
/* Used as temporary storage */
rhp->start = rhp->start_meta;
rhp->end = rhp->end_meta;
}
}
while (strp < stopll) {
if (imeta(*strp)) {
if (strp < stopcs)
outcs++;
if (region_highlights && outcsp == &zlemetacs) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
if (strp < startp + rhp->start) {
rhp->start_meta++;
}
if (strp < startp + rhp->end) {
rhp->end_meta++;
}
}
}
outll++;
}
strp++;
@ -290,6 +346,9 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp,
* each metafied character) is converted into the corresponding
* character position in *outcs.
*
* If, further, outcs is &zlecs, we update the positions in the
* region_highlight array, too. (This is a bit of a hack.)
*
* Note that instr is modified in place, hence should be copied
* first if necessary;
*
@ -304,6 +363,7 @@ stringaszleline(char *instr, int incs, int *outll, int *outsz, int *outcs)
{
ZLE_STRING_T outstr;
int ll, sz;
struct region_highlight *rhp;
#ifdef MULTIBYTE_SUPPORT
mbstate_t mbs;
#endif
@ -316,10 +376,32 @@ stringaszleline(char *instr, int incs, int *outll, int *outsz, int *outcs)
* is all the processing required to calculate outcs.
*/
char *inptr = instr, *cspos = instr + incs;
while (*inptr && inptr < cspos) {
if (region_highlights && outcs == &zlecs) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
rhp->start = rhp->start_meta;
rhp->end = rhp->end_meta;
}
}
while (*inptr) {
if (*inptr == Meta) {
if (inptr < cspos) {
incs--;
}
if (region_highlights && outcs == &zlecs) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
if (inptr - instr < rhp->start) {
rhp->start_meta--;
}
if (inptr - instr < rhp->end) {
rhp->end_meta--;
}
}
}
inptr++;
incs--;
}
inptr++;
}
@ -385,6 +467,20 @@ stringaszleline(char *instr, int incs, int *outll, int *outsz, int *outcs)
int offs = inptr - instr;
if (offs <= incs && incs < offs + (int)cnt)
*outcs = outptr - outstr;
if (region_highlights && outcs == &zlecs) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
if (offs <= rhp->start_meta &&
rhp->start_meta < offs + (int)cnt) {
rhp->start = outptr - outstr;
}
if (offs <= rhp->end_meta &&
rhp->end_meta < offs + (int)cnt) {
rhp->end = outptr - outstr;
}
}
}
}
inptr += cnt;
@ -404,6 +500,14 @@ stringaszleline(char *instr, int incs, int *outll, int *outsz, int *outcs)
*outll = ll;
if (outcs)
*outcs = incs;
if (region_highlights && outcs == &zlecs) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
rhp->start = rhp->start_meta;
rhp->end = rhp->end_meta;
}
}
#endif
return outstr;
@ -432,6 +536,158 @@ zlegetline(int *ll, int *cs)
}
/* Forward reference */
struct zle_region;
/* A non-special entry in region_highlight */
struct zle_region {
struct zle_region *next;
/* Entries of region_highlight, as needed */
int atr;
int start;
int end;
int flags;
};
/* Forward reference */
struct zle_position;
/* A saved set of position information */
struct zle_position {
/* Link pointer */
struct zle_position *next;
/* Cursor position */
int cs;
/* Mark */
int mk;
/* Line length */
int ll;
struct zle_region *regions;
};
/* LIFO stack of positions */
struct zle_position *zle_positions;
/*
* Save positions including cursor, end-of-line and
* (non-special) region highlighting.
*
* Must be matched by a subsequent zle_restore_positions().
*/
/**/
void
zle_save_positions(void)
{
struct region_highlight *rhp;
struct zle_position *newpos;
struct zle_region **newrhpp, *newrhp;
newpos = (struct zle_position *)zalloc(sizeof(*newpos));
newpos->mk = mark;
if (zlemetaline) {
/* Use metafied information */
newpos->cs = zlemetacs;
newpos->ll = zlemetall;
} else {
/* Use unmetafied information */
newpos->cs = zlecs;
newpos->ll = zlell;
}
newrhpp = &newpos->regions;
*newrhpp = NULL;
if (region_highlights) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
/*
* This is a FIFO stack, so we preserve the order
* of entries when we restore region_highlights.
*/
newrhp = *newrhpp = (struct zle_region *)zalloc(sizeof(**newrhpp));
newrhp->next = NULL;
newrhp->atr = rhp->atr;
newrhp->flags = rhp->flags;
if (zlemetaline) {
newrhp->start = rhp->start_meta;
newrhp->end = rhp->end_meta;
} else {
newrhp->start = rhp->start;
newrhp->end = rhp->end;
}
newrhpp = &newrhp->next;
}
}
newpos->next = zle_positions;
zle_positions = newpos;
}
/*
* Restore positions previously saved.
* Relies on zlemetaline being restored correctly beforehand,
* so that it can tell whether to use metafied positions or not.
*/
/**/
void
zle_restore_positions(void)
{
struct zle_position *oldpos = zle_positions;
struct zle_region *oldrhp;
struct region_highlight *rhp;
int nreg;
zle_positions = oldpos->next;
mark = oldpos->mk;
if (zlemetaline) {
/* Use metafied information */
zlemetacs = oldpos->cs;
zlemetall = oldpos->ll;
} else {
/* Use unmetafied information */
zlecs = oldpos->cs;
zlell = oldpos->ll;
}
/* Count number of regions and see if the array needs resizing */
for (nreg = 0, oldrhp = oldpos->regions;
oldrhp;
nreg++, oldrhp = oldrhp->next)
;
if (nreg + N_SPECIAL_HIGHLIGHTS != n_region_highlights) {
n_region_highlights = nreg + N_SPECIAL_HIGHLIGHTS;
region_highlights = (struct region_highlight *)
zrealloc(region_highlights,
sizeof(struct region_highlight) * n_region_highlights);
}
oldrhp = oldpos->regions;
rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
while (oldrhp) {
struct zle_region *nextrhp = oldrhp->next;
rhp->atr = oldrhp->atr;
rhp->flags = oldrhp->flags;
if (zlemetaline) {
rhp->start_meta = oldrhp->start;
rhp->end_meta = oldrhp->end;
} else {
rhp->start = oldrhp->start;
rhp->end = oldrhp->end;
}
zfree(oldrhp, sizeof(*oldrhp));
oldrhp = nextrhp;
rhp++;
}
zfree(oldpos, sizeof(*oldpos));
}
/*
* Basic utility functions for adding to line or removing from line.
* At this level the counts supplied are raw character counts, so
@ -450,6 +706,7 @@ mod_export void
spaceinline(int ct)
{
int i;
struct region_highlight *rhp;
if (zlemetaline) {
sizeline(ct + zlemetall);
@ -460,6 +717,19 @@ spaceinline(int ct)
if (mark > zlemetacs)
mark += ct;
if (region_highlights) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
if (rhp->start_meta >= zlemetacs) {
rhp->start_meta += ct;
}
if (rhp->end_meta >= zlemetacs) {
rhp->end_meta += ct;
}
}
}
} else {
sizeline(ct + zlell);
for (i = zlell; --i >= zlecs;)
@ -469,26 +739,85 @@ spaceinline(int ct)
if (mark > zlecs)
mark += ct;
if (region_highlights) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
if (rhp->start >= zlecs) {
rhp->start += ct;
}
if (rhp->end >= zlecs) {
rhp->end += ct;
}
}
}
}
region_active = 0;
}
/*
* Within the ZLE line, cut the "cnt" characters from position "to".
*/
/**/
void
shiftchars(int to, int cnt)
{
struct region_highlight *rhp;
if (mark >= to + cnt)
mark -= cnt;
else if (mark > to)
mark = to;
if (zlemetaline) {
/* before to is updated... */
if (region_highlights) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
if (rhp->start_meta > to) {
if (rhp->start_meta > to + cnt)
rhp->start_meta -= cnt;
else
rhp->start_meta = to;
}
if (rhp->end_meta > to) {
if (rhp->end_meta > to + cnt)
rhp->end_meta -= cnt;
else
rhp->end_meta = to;
}
}
}
while (to + cnt < zlemetall) {
zlemetaline[to] = zlemetaline[to + cnt];
to++;
}
zlemetaline[zlemetall = to] = '\0';
} else {
/* before to is updated... */
if (region_highlights) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
rhp < region_highlights + n_region_highlights;
rhp++) {
if (rhp->start > to) {
if (rhp->start > to + cnt)
rhp->start -= cnt;
else
rhp->start = to;
}
if (rhp->end > to) {
if (rhp->end > to + cnt)
rhp->end -= cnt;
else
rhp->end = to;
}
}
}
while (to + cnt < zlell) {
zleline[to] = zleline[to + cnt];
to++;