Skip to content

Commit c3c27f9

Browse files
committed
Merge remote-tracking branch 'vim/master'
2 parents 08d6d41 + 470a141 commit c3c27f9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+415
-101
lines changed

runtime/doc/builtin.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ js_encode({expr}) String encode JS style JSON
325325
json_decode({string}) any decode JSON
326326
json_encode({expr}) String encode JSON
327327
keys({dict}) List keys in {dict}
328+
keytrans({string}) String translate internal keycodes to a form
329+
that can be used by |:map|
328330
len({expr}) Number the length of {expr}
329331
libcall({lib}, {func}, {arg}) String call {func} in library {lib} with {arg}
330332
libcallnr({lib}, {func}, {arg}) Number idem, but return a Number
@@ -5205,6 +5207,16 @@ keys({dict}) *keys()*
52055207
Can also be used as a |method|: >
52065208
mydict->keys()
52075209
5210+
keytrans({string}) *keytrans()*
5211+
Turn the internal byte representation of keys into a form that
5212+
can be used for |:map|. E.g. >
5213+
:let xx = "\<C-Home>"
5214+
:echo keytrans(xx)
5215+
< <C-Home>
5216+
5217+
Can also be used as a |method|: >
5218+
"\<C-Home>"->keytrans()
5219+
52085220
< *len()* *E701*
52095221
len({expr}) The result is a Number, which is the length of the argument.
52105222
When {expr} is a String or a Number the length in bytes is

runtime/doc/usr_41.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,8 @@ String manipulation: *string-functions*
737737
fnameescape() escape a file name for use with a Vim command
738738
tr() translate characters from one set to another
739739
strtrans() translate a string to make it printable
740+
keytrans() translate internal keycodes to a form that
741+
can be used by |:map|
740742
tolower() turn a string to lowercase
741743
toupper() turn a string to uppercase
742744
charclass() class of a character

runtime/filetype.vim

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,9 @@ au BufNewFile,BufRead *.sdl,*.pr setf sdl
17231723
" sed
17241724
au BufNewFile,BufRead *.sed setf sed
17251725

1726+
" SubRip
1727+
au BufNewFile,BufRead *.srt setf srt
1728+
17261729
" svelte
17271730
au BufNewFile,BufRead *.svelte setf svelte
17281731

src/debugger.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,14 @@ do_debug(char_u *cmd)
135135
ignore_script = TRUE;
136136
}
137137

138+
// don't debug any function call, e.g. from an expresion mapping
139+
n = debug_break_level;
140+
debug_break_level = -1;
141+
138142
vim_free(cmdline);
139143
cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL);
140144

145+
debug_break_level = n;
141146
if (typeahead_saved)
142147
{
143148
restore_typeahead(&typeaheadbuf, TRUE);

src/drawline.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -666,9 +666,11 @@ win_line(
666666
// syntax_attr
667667
int text_prop_id = 0; // active property ID
668668
int text_prop_flags = 0;
669+
int text_prop_above = FALSE; // first doing virtual text above
669670
int text_prop_follows = FALSE; // another text prop to display
670671
int saved_search_attr = 0; // search_attr to be used when n_extra
671672
// goes to zero
673+
int saved_area_attr = 0; // idem for area_attr
672674
#endif
673675
#ifdef FEAT_SPELL
674676
int has_spell = FALSE; // this buffer has spell checking
@@ -1784,6 +1786,7 @@ win_line(
17841786

17851787
// Sort the properties on priority and/or starting last.
17861788
// Then combine the attributes, highest priority last.
1789+
text_prop_above = FALSE;
17871790
text_prop_follows = FALSE;
17881791
sort_text_props(wp->w_buffer, text_props,
17891792
text_prop_idxs, text_props_active);
@@ -1817,6 +1820,8 @@ win_line(
18171820
char_u *p = ((char_u **)wp->w_buffer
18181821
->b_textprop_text.ga_data)[
18191822
-text_prop_id - 1];
1823+
int above = (tp->tp_flags
1824+
& TP_FLAG_ALIGN_ABOVE);
18201825

18211826
// reset the ID in the copy to avoid it being used
18221827
// again
@@ -1826,8 +1831,6 @@ win_line(
18261831
{
18271832
int right = (tp->tp_flags
18281833
& TP_FLAG_ALIGN_RIGHT);
1829-
int above = (tp->tp_flags
1830-
& TP_FLAG_ALIGN_ABOVE);
18311834
int below = (tp->tp_flags
18321835
& TP_FLAG_ALIGN_BELOW);
18331836
int wrap = (tp->tp_flags & TP_FLAG_WRAP);
@@ -1844,8 +1847,12 @@ win_line(
18441847
extra_for_textprop = TRUE;
18451848
extra_attr = used_attr;
18461849
n_attr = mb_charlen(p);
1850+
// restore search_attr and area_attr when n_extra
1851+
// is down to zero
18471852
saved_search_attr = search_attr;
1848-
search_attr = 0; // restore when n_extra is zero
1853+
saved_area_attr = area_attr;
1854+
search_attr = 0;
1855+
area_attr = 0;
18491856
text_prop_attr = 0;
18501857
text_prop_attr_comb = 0;
18511858
if (*ptr == NUL)
@@ -1902,6 +1909,9 @@ win_line(
19021909

19031910
// If another text prop follows the condition below at
19041911
// the last window column must know.
1912+
// If this is an "above" text prop and 'nowrap' the we
1913+
// must wrap anyway.
1914+
text_prop_above = above;
19051915
text_prop_follows = other_tpi != -1;
19061916
}
19071917
}
@@ -2198,6 +2208,8 @@ win_line(
21982208
in_linebreak = FALSE;
21992209
if (search_attr == 0)
22002210
search_attr = saved_search_attr;
2211+
if (area_attr == 0 && *ptr != NUL)
2212+
area_attr = saved_area_attr;
22012213
}
22022214
#endif
22032215
}
@@ -3585,7 +3597,7 @@ win_line(
35853597
|| filler_todo > 0
35863598
#endif
35873599
#ifdef FEAT_PROP_POPUP
3588-
|| text_prop_follows
3600+
|| text_prop_above || text_prop_follows
35893601
#endif
35903602
|| (wp->w_p_list && wp->w_lcs_chars.eol != NUL
35913603
&& wlv.p_extra != at_end_str)
@@ -3612,12 +3624,12 @@ win_line(
36123624
&& filler_todo <= 0
36133625
#endif
36143626
#ifdef FEAT_PROP_POPUP
3615-
&& !text_prop_follows
3627+
&& !text_prop_above && !text_prop_follows
36163628
#endif
36173629
) || lcs_eol_one == -1)
36183630
break;
36193631
#ifdef FEAT_PROP_POPUP
3620-
if (!wp->w_p_wrap && text_prop_follows)
3632+
if (!wp->w_p_wrap && text_prop_follows && !text_prop_above)
36213633
{
36223634
// do not output more of the line, only the "below" prop
36233635
ptr += STRLEN(ptr);
@@ -3651,7 +3663,7 @@ win_line(
36513663
&& filler_todo <= 0
36523664
#endif
36533665
#ifdef FEAT_PROP_POPUP
3654-
&& !text_prop_follows
3666+
&& !text_prop_above && !text_prop_follows
36553667
#endif
36563668
&& wp->w_width == Columns)
36573669
{

src/eval.c

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,6 @@
2929
*/
3030
static int current_copyID = 0;
3131

32-
/*
33-
* Info used by a ":for" loop.
34-
*/
35-
typedef struct
36-
{
37-
int fi_semicolon; // TRUE if ending in '; var]'
38-
int fi_varcount; // nr of variables in the list
39-
int fi_break_count; // nr of line breaks encountered
40-
listwatch_T fi_lw; // keep an eye on the item used.
41-
list_T *fi_list; // list being used
42-
int fi_bi; // index of blob
43-
blob_T *fi_blob; // blob being used
44-
char_u *fi_string; // copy of string being used
45-
int fi_byte_idx; // byte index in fi_string
46-
} forinfo_T;
47-
4832
static int eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
4933
static int eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
5034
static int eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
@@ -1914,7 +1898,8 @@ next_for_item(void *fi_void, char_u *arg)
19141898
? (ASSIGN_FINAL
19151899
// first round: error if variable exists
19161900
| (fi->fi_bi == 0 ? 0 : ASSIGN_DECL)
1917-
| ASSIGN_NO_MEMBER_TYPE)
1901+
| ASSIGN_NO_MEMBER_TYPE
1902+
| ASSIGN_UPDATE_BLOCK_ID)
19181903
: 0);
19191904
listitem_T *item;
19201905
int skip_assign = in_vim9script() && arg[0] == '_'

src/evalfunc.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ static void f_inputsecret(typval_T *argvars, typval_T *rettv);
8989
static void f_interrupt(typval_T *argvars, typval_T *rettv);
9090
static void f_invert(typval_T *argvars, typval_T *rettv);
9191
static void f_islocked(typval_T *argvars, typval_T *rettv);
92+
static void f_keytrans(typval_T *argvars, typval_T *rettv);
9293
static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv);
9394
static void f_libcall(typval_T *argvars, typval_T *rettv);
9495
static void f_libcallnr(typval_T *argvars, typval_T *rettv);
@@ -2058,6 +2059,8 @@ static funcentry_T global_functions[] =
20582059
ret_string, f_json_encode},
20592060
{"keys", 1, 1, FEARG_1, arg1_dict_any,
20602061
ret_list_string, f_keys},
2062+
{"keytrans", 1, 1, FEARG_1, arg1_string,
2063+
ret_string, f_keytrans},
20612064
{"last_buffer_nr", 0, 0, 0, NULL, // obsolete
20622065
ret_number, f_last_buffer_nr},
20632066
{"len", 1, 1, FEARG_1, arg1_len,
@@ -7170,6 +7173,24 @@ f_islocked(typval_T *argvars, typval_T *rettv)
71707173
clear_lval(&lv);
71717174
}
71727175

7176+
/*
7177+
* "keytrans()" function
7178+
*/
7179+
static void
7180+
f_keytrans(typval_T *argvars, typval_T *rettv)
7181+
{
7182+
char_u *escaped;
7183+
7184+
rettv->v_type = VAR_STRING;
7185+
if (check_for_string_arg(argvars, 0) == FAIL
7186+
|| argvars[0].vval.v_string == NULL)
7187+
return;
7188+
// Need to escape K_SPECIAL and CSI for mb_unescape().
7189+
escaped = vim_strsave_escape_csi(argvars[0].vval.v_string);
7190+
rettv->vval.v_string = str2special_save(escaped, TRUE, TRUE);
7191+
vim_free(escaped);
7192+
}
7193+
71737194
/*
71747195
* "last_buffer_nr()" function.
71757196
*/

src/evalvars.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3853,6 +3853,14 @@ set_var_const(
38533853
}
38543854

38553855
clear_tv(&di->di_tv);
3856+
3857+
if ((flags & ASSIGN_UPDATE_BLOCK_ID)
3858+
&& SCRIPT_ID_VALID(current_sctx.sc_sid))
3859+
{
3860+
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
3861+
3862+
update_script_var_block_id(name, si->sn_current_block_id);
3863+
}
38563864
}
38573865
else
38583866
{

src/ex_cmds.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4308,6 +4308,10 @@ ex_substitute(exarg_T *eap)
43084308
- regmatch.startpos[0].lnum;
43094309
search_match_endcol = regmatch.endpos[0].col
43104310
+ len_change;
4311+
if (search_match_lines == 0
4312+
&& search_match_endcol == 0)
4313+
// highlight at least one character for /^/
4314+
search_match_endcol = 1;
43114315
highlight_match = TRUE;
43124316

43134317
update_topline();

src/ex_eval.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,7 @@ ex_while(exarg_T *eap)
12081208
int skip;
12091209
int result;
12101210
cstack_T *cstack = eap->cstack;
1211+
int prev_cs_flags = 0;
12111212

12121213
if (cstack->cs_idx == CSTACK_LEN - 1)
12131214
eap->errmsg = _(e_while_for_nesting_too_deep);
@@ -1230,15 +1231,18 @@ ex_while(exarg_T *eap)
12301231
{
12311232
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
12321233
int i;
1234+
int first;
12331235
int func_defined = cstack->cs_flags[cstack->cs_idx]
12341236
& CSF_FUNC_DEF;
12351237

12361238
// Any variables defined in the previous round are no longer
12371239
// visible. Keep the first one for ":for", it is the loop
12381240
// variable that we reuse every time around.
1239-
for (i = cstack->cs_script_var_len[cstack->cs_idx]
1241+
// Do this backwards, so that vars defined in a later round are
1242+
// found first.
1243+
first = cstack->cs_script_var_len[cstack->cs_idx]
12401244
+ (eap->cmdidx == CMD_while ? 0 : 1);
1241-
i < si->sn_var_vals.ga_len; ++i)
1245+
for (i = si->sn_var_vals.ga_len - 1; i >= first; --i)
12421246
{
12431247
svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + i;
12441248

@@ -1250,8 +1254,15 @@ ex_while(exarg_T *eap)
12501254
// still exists, from sn_vars.
12511255
hide_script_var(si, i, func_defined);
12521256
}
1257+
1258+
// Start a new block ID, so that variables defined inside the
1259+
// loop are created new and not shared with the previous loop.
1260+
// Matters when used in a closure.
1261+
cstack->cs_block_id[cstack->cs_idx] = ++si->sn_last_block_id;
1262+
si->sn_current_block_id = si->sn_last_block_id;
12531263
}
12541264
}
1265+
prev_cs_flags = cstack->cs_flags[cstack->cs_idx];
12551266
cstack->cs_flags[cstack->cs_idx] =
12561267
eap->cmdidx == CMD_while ? CSF_WHILE : CSF_FOR;
12571268

@@ -1270,7 +1281,7 @@ ex_while(exarg_T *eap)
12701281
}
12711282
else
12721283
{
1273-
void *fi;
1284+
forinfo_T *fi;
12741285
evalarg_T evalarg;
12751286

12761287
/*
@@ -1304,9 +1315,18 @@ ex_while(exarg_T *eap)
13041315
result = next_for_item(fi, eap->arg);
13051316
else
13061317
result = FALSE;
1318+
if (fi != NULL)
1319+
// OR all the cs_flags together, if a function was defined in
1320+
// any round then the loop variable may have been used.
1321+
fi->fi_cs_flags |= prev_cs_flags;
13071322

13081323
if (!result)
13091324
{
1325+
// If a function was defined in any round then set the
1326+
// CSF_FUNC_DEF flag now, so that it's seen by leave_block().
1327+
if (fi != NULL && (fi->fi_cs_flags & CSF_FUNC_DEF))
1328+
cstack->cs_flags[cstack->cs_idx] |= CSF_FUNC_DEF;
1329+
13101330
free_for_info(fi);
13111331
cstack->cs_forinfo[cstack->cs_idx] = NULL;
13121332
}

0 commit comments

Comments
 (0)