# HG changeset patch # User Bram Moolenaar # Date 1437486507 -7200 # Node ID 1efa7c2b9368b7d550a382dbe8b5502bb14416d1 # Parent c56ef0540cd55241413ee9083babe424415237b5 patch 7.4.792 Problem: Can only conceal text by defining syntax items. Solution: Use matchadd() to define concealing. (Christian Brabandt) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -4430,9 +4430,18 @@ matchadd({group}, {pattern}[, {priority} message will appear and the match will not be added. An ID is specified as a positive integer (zero excluded). IDs 1, 2 and 3 are reserved for |:match|, |:2match| and |:3match|, - respectively. If the {id} argument is not specified, + respectively. If the {id} argument is not specified or -1, |matchadd()| automatically chooses a free ID. + The optional {dict} argmument allows for further custom + values. Currently this is used to specify a match specifc + conceal character that will be shown for |hl-Conceal| + highlighted matches. The dict can have the following members: + + conceal Special character to show instead of the + match (only for |hl-Conceal| highlighed + matches, see |:syn-cchar|) + The number of matches is not limited, as it is the case with the |:match| commands. @@ -4446,7 +4455,7 @@ matchadd({group}, {pattern}[, {priority} available from |getmatches()|. All matches can be deleted in one operation by |clearmatches()|. -matchaddpos({group}, {pos}[, {priority}[, {id}]]) *matchaddpos()* +matchaddpos({group}, {pos}[, {priority}[, {id}[, {dict}]]]) *matchaddpos()* Same as |matchadd()|, but requires a list of positions {pos} instead of a pattern. This command is faster than |matchadd()| because it does not require to handle regular expressions and diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -8224,8 +8224,8 @@ static struct fst {"maparg", 1, 4, f_maparg}, {"mapcheck", 1, 3, f_mapcheck}, {"match", 2, 4, f_match}, - {"matchadd", 2, 4, f_matchadd}, - {"matchaddpos", 2, 4, f_matchaddpos}, + {"matchadd", 2, 5, f_matchadd}, + {"matchaddpos", 2, 5, f_matchaddpos}, {"matcharg", 1, 1, f_matcharg}, {"matchdelete", 1, 1, f_matchdelete}, {"matchend", 2, 4, f_matchend}, @@ -12031,6 +12031,15 @@ f_getmatches(argvars, rettv) dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id)); dict_add_nr_str(dict, "priority", (long)cur->priority, NULL); dict_add_nr_str(dict, "id", (long)cur->id, NULL); +# ifdef FEAT_CONCEAL + if (cur->conceal_char) + { + char_u buf[MB_MAXBYTES + 1]; + + buf[(*mb_char2bytes)((int)cur->conceal_char, buf)] = NUL; + dict_add_nr_str(dict, "conceal", 0L, (char_u *)&buf); + } +# endif list_append_dict(rettv->vval.v_list, dict); cur = cur->next; } @@ -14589,6 +14598,7 @@ f_matchadd(argvars, rettv) int prio = 10; /* default priority */ int id = -1; int error = FALSE; + char_u *conceal_char = NULL; rettv->vval.v_number = -1; @@ -14598,7 +14608,21 @@ f_matchadd(argvars, rettv) { prio = get_tv_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) + { id = get_tv_number_chk(&argvars[3], &error); + if (argvars[4].v_type != VAR_UNKNOWN) + { + if (argvars[4].v_type != VAR_DICT) + { + EMSG(_(e_dictreq)); + return; + } + if (dict_find(argvars[4].vval.v_dict, + (char_u *)"conceal", -1) != NULL) + conceal_char = get_dict_string(argvars[4].vval.v_dict, + (char_u *)"conceal", FALSE); + } + } } if (error == TRUE) return; @@ -14608,7 +14632,8 @@ f_matchadd(argvars, rettv) return; } - rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL); + rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL, + conceal_char); #endif } @@ -14627,6 +14652,7 @@ f_matchaddpos(argvars, rettv) int id = -1; int error = FALSE; list_T *l; + char_u *conceal_char = NULL; rettv->vval.v_number = -1; @@ -14647,7 +14673,21 @@ f_matchaddpos(argvars, rettv) { prio = get_tv_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) + { id = get_tv_number_chk(&argvars[3], &error); + if (argvars[4].v_type != VAR_UNKNOWN) + { + if (argvars[4].v_type != VAR_DICT) + { + EMSG(_(e_dictreq)); + return; + } + if (dict_find(argvars[4].vval.v_dict, + (char_u *)"conceal", -1) != NULL) + conceal_char = get_dict_string(argvars[4].vval.v_dict, + (char_u *)"conceal", FALSE); + } + } } if (error == TRUE) return; @@ -14659,7 +14699,8 @@ f_matchaddpos(argvars, rettv) return; } - rettv->vval.v_number = match_add(curwin, group, NULL, prio, id, l); + rettv->vval.v_number = match_add(curwin, group, NULL, prio, id, l, + conceal_char); #endif } @@ -17165,9 +17206,12 @@ f_setmatches(argvars, rettv) int i = 0; char_u buf[5]; dictitem_T *di; + char_u *group; + int priority; + int id; + char_u *conceal; d = li->li_tv.vval.v_dict; - if (dict_find(d, (char_u *)"pattern", -1) == NULL) { if (s == NULL) @@ -17193,18 +17237,22 @@ f_setmatches(argvars, rettv) break; } } + + group = get_dict_string(d, (char_u *)"group", FALSE); + priority = (int)get_dict_number(d, (char_u *)"priority"); + id = (int)get_dict_number(d, (char_u *)"id"); + conceal = dict_find(d, (char_u *)"conceal", -1) != NULL + ? get_dict_string(d, (char_u *)"conceal", FALSE) + : NULL; if (i == 0) { - match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE), + match_add(curwin, group, get_dict_string(d, (char_u *)"pattern", FALSE), - (int)get_dict_number(d, (char_u *)"priority"), - (int)get_dict_number(d, (char_u *)"id"), NULL); - } - else - { - match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE), - NULL, (int)get_dict_number(d, (char_u *)"priority"), - (int)get_dict_number(d, (char_u *)"id"), s); + priority, id, NULL, conceal); + } + else + { + match_add(curwin, group, NULL, priority, id, s, conceal); list_unref(s); s = NULL; } diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -12079,7 +12079,7 @@ ex_match(eap) c = *end; *end = NUL; - match_add(curwin, g, p + 1, 10, id, NULL); + match_add(curwin, g, p + 1, 10, id, NULL, NULL); vim_free(g); *end = c; } diff --git a/src/proto/window.pro b/src/proto/window.pro --- a/src/proto/window.pro +++ b/src/proto/window.pro @@ -76,7 +76,7 @@ void restore_win __ARGS((win_T *save_cur void switch_buffer __ARGS((buf_T **save_curbuf, buf_T *buf)); void restore_buffer __ARGS((buf_T *save_curbuf)); int win_hasvertsplit __ARGS((void)); -int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id, list_T *pos_list)); +int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id, list_T *pos_list, char_u *conceal_char)); int match_delete __ARGS((win_T *wp, int id, int perr)); void clear_matches __ARGS((win_T *wp)); matchitem_T *get_match __ARGS((win_T *wp, int id)); diff --git a/src/screen.c b/src/screen.c --- a/src/screen.c +++ b/src/screen.c @@ -3047,6 +3047,8 @@ win_line(wp, lnum, startrow, endrow, noc wrapping */ int vcol_off = 0; /* offset for concealed characters */ int did_wcol = FALSE; + int match_conc = FALSE; /* cchar for match functions */ + int has_match_conc = FALSE; /* match wants to conceal */ int old_boguscols = 0; # define VCOL_HLC (vcol - vcol_off) # define FIX_FOR_BOGUSCOLS \ @@ -3580,6 +3582,9 @@ win_line(wp, lnum, startrow, endrow, noc */ for (;;) { +#ifdef FEAT_CONCEAL + has_match_conc = FALSE; +#endif /* Skip this quickly when working on the text. */ if (draw_state != WL_LINE) { @@ -3923,13 +3928,26 @@ win_line(wp, lnum, startrow, endrow, noc shl->endcol = tmp_col; #endif shl->attr_cur = shl->attr; +#ifdef FEAT_CONCEAL + if (cur != NULL && syn_name2id((char_u *)"Conceal") + == cur->hlg_id) + { + has_match_conc = TRUE; + match_conc = cur->conceal_char; + } + else + has_match_conc = match_conc = FALSE; +#endif } else if (v == (long)shl->endcol) { shl->attr_cur = 0; +#ifdef FEAT_CONCEAL + prev_syntax_id = 0; +#endif next_search_hl(wp, shl, lnum, (colnr_T)v, cur); pos_inprogress = cur == NULL || cur->pos.cur == 0 - ? FALSE : TRUE; + ? FALSE : TRUE; /* Need to get the line again, a multi-line regexp * may have made it invalid. */ @@ -4873,19 +4891,22 @@ win_line(wp, lnum, startrow, endrow, noc #ifdef FEAT_CONCEAL if ( wp->w_p_cole > 0 && (wp != curwin || lnum != wp->w_cursor.lnum || - conceal_cursor_line(wp)) - && (syntax_flags & HL_CONCEAL) != 0 + conceal_cursor_line(wp) ) + && ( (syntax_flags & HL_CONCEAL) != 0 || has_match_conc) && !(lnum_in_visual_area && vim_strchr(wp->w_p_cocu, 'v') == NULL)) { char_attr = conceal_attr; if (prev_syntax_id != syntax_seqnr - && (syn_get_sub_char() != NUL || wp->w_p_cole == 1) + && (syn_get_sub_char() != NUL || match_conc + || wp->w_p_cole == 1) && wp->w_p_cole != 3) { /* First time at this concealed item: display one * character. */ - if (syn_get_sub_char() != NUL) + if (match_conc) + c = match_conc; + else if (syn_get_sub_char() != NUL) c = syn_get_sub_char(); else if (lcs_conceal != NUL) c = lcs_conceal; diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -2021,6 +2021,9 @@ struct matchitem regmmatch_T match; /* regexp program for pattern */ posmatch_T pos; /* position matches */ match_T hl; /* struct for doing the actual highlighting */ +#ifdef FEAT_CONCEAL + int conceal_char; /* cchar for Conceal highlighting */ +#endif }; /* diff --git a/src/testdir/Make_amiga.mak b/src/testdir/Make_amiga.mak --- a/src/testdir/Make_amiga.mak +++ b/src/testdir/Make_amiga.mak @@ -54,6 +54,7 @@ SCRIPTS = test1.out test3.out test4.out test_listlbr_utf8.out \ test_mapping.out \ test_marks.out \ + test_match_conceal.out \ test_nested_function.out \ test_options.out \ test_perl.out \ @@ -205,6 +206,7 @@ test_listlbr.out: test_listlbr.in test_listlbr_utf8.out: test_listlbr_utf8.in test_mapping.out: test_mapping.in test_marks.out: test_marks.in +test_match_conceal.out: test_match_conceal.in test_nested_function.out: test_nested_function.in test_options.out: test_options.in test_perl.out: test_perl.in diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak --- a/src/testdir/Make_dos.mak +++ b/src/testdir/Make_dos.mak @@ -53,6 +53,7 @@ SCRIPTS = test3.out test4.out test5.out test_listlbr_utf8.out \ test_mapping.out \ test_marks.out \ + test_match_conceal.out \ test_nested_function.out \ test_options.out \ test_perl.out \ diff --git a/src/testdir/Make_ming.mak b/src/testdir/Make_ming.mak --- a/src/testdir/Make_ming.mak +++ b/src/testdir/Make_ming.mak @@ -75,6 +75,7 @@ SCRIPTS = test3.out test4.out test5.out test_listlbr_utf8.out \ test_mapping.out \ test_marks.out \ + test_match_conceal.out \ test_nested_function.out \ test_options.out \ test_perl.out \ diff --git a/src/testdir/Make_os2.mak b/src/testdir/Make_os2.mak --- a/src/testdir/Make_os2.mak +++ b/src/testdir/Make_os2.mak @@ -55,6 +55,7 @@ SCRIPTS = test1.out test3.out test4.out test_listlbr_utf8.out \ test_mapping.out \ test_marks.out \ + test_match_conceal.out \ test_nested_function.out \ test_options.out \ test_perl.out \ diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms --- a/src/testdir/Make_vms.mms +++ b/src/testdir/Make_vms.mms @@ -114,6 +114,7 @@ SCRIPT = test1.out test2.out test3.out test_listlbr_utf8.out \ test_mapping.out \ test_marks.out \ + test_match_conceal.out \ test_nested_function.out \ test_options.out \ test_perl.out \ diff --git a/src/testdir/Makefile b/src/testdir/Makefile --- a/src/testdir/Makefile +++ b/src/testdir/Makefile @@ -51,6 +51,7 @@ SCRIPTS = test1.out test2.out test3.out test_listlbr_utf8.out \ test_mapping.out \ test_marks.out \ + test_match_conceal.out \ test_nested_function.out \ test_options.out \ test_perl.out \ diff --git a/src/testdir/test_match_conceal.in b/src/testdir/test_match_conceal.in new file mode 100644 --- /dev/null +++ b/src/testdir/test_match_conceal.in @@ -0,0 +1,159 @@ +Test for matchadd() and conceal feature + +STARTTEST +:so small.vim +:if !has("conceal") | e! test.ok | w! test.out | qa! | endif +:set term=ansi +:so mbyte.vim +:if &enc !=? 'utf-8'|:e! test.ok|:w! test.out|qa!|endif +:10new|:vsp|:vert resize 20 +:put =\"\#\ This\ is\ a\ Test\" +:norm! mazt +:fu! ScreenChar(width, lines) +: let c='' +: for j in range(1,a:lines) +: for i in range(1,a:width) +: let c.=nr2char(screenchar(j, i)) +: endfor +: let c.="\n" +: endfor +: return c +:endfu +:fu! ScreenAttr(line, pos, eval) +: let g:attr=[] +: for col in a:pos +: call add(g:attr, screenattr(a:line,col)) +: endfor +: " In case all values are zero, probably the terminal +: " isn't set correctly, so catch that case +: let null = (eval(join(g:attr, '+')) == 0) +: let str=substitute(a:eval, '\d\+', 'g:attr[&]', 'g') +: if null || eval(str) +: :let g:attr_test="OK: ". str +: else +: :let g:attr_test="FAILED: ".str +: :let g:attr_test.="\n". join(g:attr, ' ') +: :let g:attr_test.="\n TERM: ". &term +: endif +:endfu +:fu! DoRecordScreen() +: wincmd l +: $put =printf(\"\n%s\", g:test) +: $put =g:line +: $put =g:attr_test +: wincmd p +:endfu +:let g:test ="Test 1: simple addmatch()" +:call matchadd('Conceal', '\%2l ') +:redraw! +:let line=ScreenChar(winwidth(0),1) +:call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5") +:call DoRecordScreen() +: +:let g:test ="Test 2: simple addmatch() and conceal (should be: #XThisXisXaXTest)" +:norm! 'azt +:call clearmatches() +:syntax on +:set concealcursor=n conceallevel=1 +:call matchadd('Conceal', '\%2l ', 10, -1, {'conceal': 'X'}) +:redraw! +:let line=ScreenChar(winwidth(0),1) +:call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5") +:call DoRecordScreen() +: +:let g:test ="Test 3: addmatch() and conceallevel=3 (should be: #ThisisaTest)" +:norm! 'azt +:set conceallevel=3 +:call clearmatches() +:call matchadd('Conceal', '\%2l ', 10, -1, {'conceal': 'X'}) +:redraw! +:let line=ScreenChar(winwidth(0),1) +:call ScreenAttr(1,[1,2,7,10,12,16], "0==1 && 1==2 && 1==3 && 1==4 && 0!=5") +:call DoRecordScreen() +: +:let g:test ="Test 4: more match() (should be: #Thisisa Test)" +:norm! 'azt +:call matchadd('ErrorMsg', '\%2l Test', 20, -1, {'conceal': 'X'}) +:redraw! +:let line=ScreenChar(winwidth(0),1) +:call ScreenAttr(1,[1,2,7,10,12,16], "0==1 && 1==2 && 0!=3 && 3==4 && 0!=5 && 3!=5") +:call DoRecordScreen() +: +:let g:test ="Test 5/1: default conceal char (should be: # This is a Test)" +:norm! 'azt +:call clearmatches() +:set conceallevel=1 +:call matchadd('Conceal', '\%2l ', 10, -1, {}) +:redraw! +:let line=ScreenChar(winwidth(0),1) +:call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5") +:call DoRecordScreen() +:let g:test ="Test 5/2: default conceal char (should be: #+This+is+a+Test)" +:norm! 'azt +:set listchars=conceal:+ +:let line=ScreenChar(winwidth(0),1) +:call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5") +:call DoRecordScreen() +:set listchars&vim +: +:let g:test ="Test 6/1: syn and match conceal (should be: #ZThisZisZaZTest)" +:norm! 'azt +:call clearmatches() +:set conceallevel=1 +:call matchadd('Conceal', '\%2l ', 10, -1, {'conceal': 'Z'}) +:syn match MyConceal /\%2l / conceal containedin=ALL cchar=* +:redraw! +:let line=ScreenChar(winwidth(0),1) +:call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5") +:call DoRecordScreen() +:let g:test ="Test 6/2: syn and match conceal (should be: #*This*is*a*Test)" +:norm! 'azt +:call clearmatches() +:let line=ScreenChar(winwidth(0),1) +:call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5") +:call DoRecordScreen() +: +:let g:test ="Test 7/1: clear matches" +:norm! 'azt +:syn on +:call matchadd('Conceal', '\%2l ', 10, -1, {'conceal': 'Z'}) +:let a=getmatches() +:call clearmatches() +:redraw! +:let line=ScreenChar(winwidth(0),1) +:call ScreenAttr(1,[1,2,7,10,12,16], "0==1 && 0==2 && 0==3 && 0==4 && 0==5") +:call DoRecordScreen() +:$put =a +:call setmatches(a) +:norm! 'azt +:let g:test ="Test 7/2: reset match using setmatches()" +:norm! 'azt +:let line=ScreenChar(winwidth(0),1) +:call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5") +:call DoRecordScreen() +: +:let g:test ="Test 8: using matchaddpos() (should be #Pis a Test" +:norm! 'azt +:call clearmatches() +:call matchaddpos('Conceal', [[2,2,6]], 10, -1, {'conceal': 'P'}) +:let a=getmatches() +:redraw! +:let line=ScreenChar(winwidth(0),1) +:call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1!=2 && 0==2 && 0==3 && 0!=4 && 0!=5 && 4==5") +:call DoRecordScreen() +:$put =a +: +:let g:test ="Test 9: match using multibyte conceal char (should be: #ˑThisˑisˑaˑTest)" +:norm! 'azt +:call clearmatches() +:call matchadd('Conceal', '\%2l ', 20, -1, {'conceal': "\u02d1"}) +:redraw! +:let line=ScreenChar(winwidth(0),1) +:call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5") +:call DoRecordScreen() +: +:"sleep 10 +:%w! test.out +:qa! +ENDTEST +dummy text diff --git a/src/testdir/test_match_conceal.ok b/src/testdir/test_match_conceal.ok new file mode 100644 --- /dev/null +++ b/src/testdir/test_match_conceal.ok @@ -0,0 +1,52 @@ + +# This is a Test + +Test 1: simple addmatch() +# This is a Test +OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5] + +Test 2: simple addmatch() and conceal (should be: #XThisXisXaXTest) +#XThisXisXaXTest +OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5] + +Test 3: addmatch() and conceallevel=3 (should be: #ThisisaTest) +#ThisisaTest +OK: g:attr[0]==g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]!=g:attr[5] + +Test 4: more match() (should be: #Thisisa Test) +#Thisisa Test +OK: g:attr[0]==g:attr[1] && g:attr[1]==g:attr[2] && g:attr[0]!=g:attr[3] && g:attr[3]==g:attr[4] && g:attr[0]!=g:attr[5] && g:attr[3]!=g:attr[5] + +Test 5/1: default conceal char (should be: # This is a Test) +# This is a Test +OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5] + +Test 5/2: default conceal char (should be: #+This+is+a+Test) +#+This+is+a+Test +OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5] + +Test 6/1: syn and match conceal (should be: #ZThisZisZaZTest) +#ZThisZisZaZTest +OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5] + +Test 6/2: syn and match conceal (should be: #*This*is*a*Test) +#*This*is*a*Test +OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5] + +Test 7/1: clear matches +# This is a Test +OK: g:attr[0]==g:attr[1] && g:attr[0]==g:attr[2] && g:attr[0]==g:attr[3] && g:attr[0]==g:attr[4] && g:attr[0]==g:attr[5] +{'group': 'Conceal', 'pattern': '\%2l ', 'priority': 10, 'id': 10, 'conceal': 'Z'} + +Test 7/2: reset match using setmatches() +#ZThisZisZaZTest +OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5] + +Test 8: using matchaddpos() (should be #Pis a Test +#Pis a Test +OK: g:attr[0]!=g:attr[1] && g:attr[1]!=g:attr[2] && g:attr[0]==g:attr[2] && g:attr[0]==g:attr[3] && g:attr[0]!=g:attr[4] && g:attr[0]!=g:attr[5] && g:attr[4]==g:attr[5] +{'group': 'Conceal', 'id': 11, 'priority': 10, 'pos1': [2, 2, 6], 'conceal': 'P'} + +Test 9: match using multibyte conceal char (should be: #ˑThisˑisˑaˑTest) +#ˑThisˑisˑaˑTest +OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5] diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 792, +/**/ 791, /**/ 790, diff --git a/src/window.c b/src/window.c --- a/src/window.c +++ b/src/window.c @@ -6943,13 +6943,14 @@ win_hasvertsplit() * Return ID of added match, -1 on failure. */ int -match_add(wp, grp, pat, prio, id, pos_list) +match_add(wp, grp, pat, prio, id, pos_list, conceal_char) win_T *wp; char_u *grp; char_u *pat; int prio; int id; list_T *pos_list; + char_u *conceal_char UNUSED; /* pointer to conceal replacement char */ { matchitem_T *cur; matchitem_T *prev; @@ -7009,6 +7010,11 @@ match_add(wp, grp, pat, prio, id, pos_li m->match.regprog = regprog; m->match.rmm_ic = FALSE; m->match.rmm_maxcol = 0; +#ifdef FEAT_CONCEAL + m->conceal_char = 0; + if (conceal_char != NULL) + m->conceal_char = (*mb_ptr2char)(conceal_char); +#endif /* Set up position matches */ if (pos_list != NULL)