diff options
-rw-r--r-- | runtime/optwin.vim | 4 | ||||
-rwxr-xr-x | scripts/vim-patch.sh | 55 | ||||
-rw-r--r-- | src/nvim/assert.h | 9 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 15 | ||||
-rw-r--r-- | src/nvim/globals.h | 1 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/remote_ui.c | 12 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 3 | ||||
-rw-r--r-- | src/nvim/screen.c | 54 | ||||
-rw-r--r-- | src/nvim/syntax.c | 66 | ||||
-rw-r--r-- | src/nvim/syntax_defs.h | 4 | ||||
-rw-r--r-- | src/nvim/testdir/Makefile | 1 | ||||
-rw-r--r-- | src/nvim/testdir/test_breakindent.in | 123 | ||||
-rw-r--r-- | src/nvim/testdir/test_breakindent.ok | 74 | ||||
-rw-r--r-- | src/nvim/tui/tui.c | 6 | ||||
-rw-r--r-- | src/nvim/ugrid.h | 2 | ||||
-rw-r--r-- | src/nvim/ui.c | 7 | ||||
-rw-r--r-- | src/nvim/ui.h | 3 | ||||
-rw-r--r-- | src/nvim/ui_bridge.c | 11 | ||||
-rw-r--r-- | src/nvim/version.c | 4 | ||||
-rw-r--r-- | test/functional/legacy/breakindent_spec.lua | 211 | ||||
-rw-r--r-- | test/functional/terminal/highlight_spec.lua | 6 | ||||
-rw-r--r-- | test/functional/ui/highlight_spec.lua | 310 | ||||
-rw-r--r-- | test/functional/ui/mouse_spec.lua | 17 | ||||
-rw-r--r-- | test/functional/ui/screen.lua | 9 |
24 files changed, 717 insertions, 290 deletions
diff --git a/runtime/optwin.vim b/runtime/optwin.vim index 07dcd31b1b..68444dde01 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -766,7 +766,7 @@ call append("$", "infercase\tadjust case of a keyword completion match") call append("$", "\t(local to buffer)") call <SID>BinOptionL("inf") if has("digraphs") - call append("$", "digraph\tenable entering digraps with c1 <BS> c2") + call append("$", "digraph\tenable entering digraphs with c1 <BS> c2") call <SID>BinOptionG("dg", &dg) endif call append("$", "tildeop\tthe \"~\" command behaves like an operator") @@ -1142,7 +1142,7 @@ if has("arabic") call <SID>BinOptionG("tbidi", &tbidi) endif if has("keymap") - call append("$", "keymap\tname of a keyboard mappping") + call append("$", "keymap\tname of a keyboard mapping") call <SID>OptionL("kmp") endif if has("langmap") diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index 751f50d290..7a0001769a 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -33,7 +33,11 @@ usage() { # Checks if a program is in the user's PATH, and is executable. check_executable() { - if [[ ! -x $(command -v "${1}") ]]; then + test -x "$(command -v "${1}")" +} + +require_executable() { + if ! check_executable "${1}"; then >&2 echo "${BASENAME}: '${1}' not found in PATH or not executable." exit 1 fi @@ -61,7 +65,7 @@ clean_files() { } get_vim_sources() { - check_executable git + require_executable git if [[ ! -d ${VIM_SOURCE_DIR} ]]; then echo "Cloning Vim sources into '${VIM_SOURCE_DIR}'." @@ -194,9 +198,28 @@ get_vim_patch() { echo " for more information." } +hub_pr() { + hub pull-request -m "$1" +} + +git_hub_pr() { + git hub pull new -m "$1" +} + submit_pr() { - check_executable git - check_executable hub + require_executable git + local push_first + push_first=1 + local submit_fn + if check_executable hub; then + submit_fn="hub_pr" + elif check_executable git-hub; then + push_first=0 + submit_fn="git_hub_pr" + else + >&2 echo "${BASENAME}: 'hub' or 'git-hub' not found in PATH or not executable." + exit 1 + fi cd "${NEOVIM_SOURCE_DIR}" local checked_out_branch @@ -219,14 +242,17 @@ submit_pr() { local pr_message pr_message="$(printf '[RFC] vim-patch:%s\n\n%s\n' "${pr_title#,}" "${pr_body}")" - echo "Pushing to 'origin/${checked_out_branch}'." - output="$(git push origin "${checked_out_branch}" 2>&1)" && - echo "✔ ${output}" || - (echo "✘ ${output}"; git reset --soft HEAD^1; false) + if [[ $push_first -ne 0 ]]; then + echo "Pushing to 'origin/${checked_out_branch}'." + output="$(git push origin "${checked_out_branch}" 2>&1)" && + echo "✔ ${output}" || + (echo "✘ ${output}"; git reset --soft HEAD^1; false) + + echo + fi - echo echo "Creating pull request." - output="$(hub pull-request -F - 2>&1 <<< "${pr_message}")" && + output="$(${submit_fn} "${pr_message}" 2>&1)" && echo "✔ ${output}" || (echo "✘ ${output}"; false) @@ -264,6 +290,9 @@ list_vim_patches() { is_missing="$(sed -n '/static int included_patches/,/}/p' "${NEOVIM_SOURCE_DIR}/src/nvim/version.c" | grep -x -e "[[:space:]]*//[[:space:]]${patch_number} NA.*" -e "[[:space:]]*${patch_number}," >/dev/null && echo "false" || echo "true")" vim_commit="${vim_tag#v}" + if (cd "${VIM_SOURCE_DIR}" && git show --name-only "v${vim_commit}" 2>/dev/null) | grep -q ^runtime; then + vim_commit="${vim_commit} (+runtime)" + fi else # Untagged Vim patch (e.g. runtime updates), check the Neovim git log: is_missing="$(cd "${NEOVIM_SOURCE_DIR}" && @@ -346,9 +375,9 @@ review_commit() { } review_pr() { - check_executable curl - check_executable nvim - check_executable jq + require_executable curl + require_executable nvim + require_executable jq get_vim_sources diff --git a/src/nvim/assert.h b/src/nvim/assert.h index 2c43777858..761636305e 100644 --- a/src/nvim/assert.h +++ b/src/nvim/assert.h @@ -65,9 +65,16 @@ # define STATIC_ASSERT_STATEMENT(cond, msg) _Static_assert(cond, msg) # undef STATIC_ASSERT_PRAGMA_START + +#if __GNUC__ >= 6 # define STATIC_ASSERT_PRAGMA_START \ _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-pedantic\"") \ + _Pragma("GCC diagnostic ignored \"-Wpedantic\"") +#else +# define STATIC_ASSERT_PRAGMA_START \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-pedantic\"") +#endif # undef STATIC_ASSERT_PRAGMA_END # define STATIC_ASSERT_PRAGMA_END \ diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 415d6ee460..86f1a16216 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -3816,16 +3816,17 @@ skip: EMSG2(_(e_patnotf2), get_search_pat()); } - if (do_ask && hasAnyFolding(curwin)) - /* Cursor position may require updating */ + if (do_ask && hasAnyFolding(curwin)) { + // Cursor position may require updating changed_window_setting(); + } - vim_regfree(regmatch.regprog); + vim_regfree(regmatch.regprog); - // Restore the flag values, they can be used for ":&&". - do_all = save_do_all; - do_ask = save_do_ask; - } + // Restore the flag values, they can be used for ":&&". + do_all = save_do_all; + do_ask = save_do_ask; +} /* * Give message for number of substitutions. diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 30fe97c8db..dafb75ca87 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -504,6 +504,7 @@ EXTERN int cterm_normal_fg_bold INIT(= 0); EXTERN int cterm_normal_bg_color INIT(= 0); EXTERN RgbValue normal_fg INIT(= -1); EXTERN RgbValue normal_bg INIT(= -1); +EXTERN RgbValue normal_sp INIT(= -1); EXTERN int autocmd_busy INIT(= FALSE); /* Is apply_autocmds() busy? */ EXTERN int autocmd_no_enter INIT(= FALSE); /* *Enter autocmds disabled */ diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/msgpack_rpc/remote_ui.c index f0d92b52a0..6ffcffe2e1 100644 --- a/src/nvim/msgpack_rpc/remote_ui.c +++ b/src/nvim/msgpack_rpc/remote_ui.c @@ -96,6 +96,7 @@ static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, ui->visual_bell = remote_ui_visual_bell; ui->update_fg = remote_ui_update_fg; ui->update_bg = remote_ui_update_bg; + ui->update_sp = remote_ui_update_sp; ui->flush = remote_ui_flush; ui->suspend = remote_ui_suspend; ui->set_title = remote_ui_set_title; @@ -285,6 +286,10 @@ static void remote_ui_highlight_set(UI *ui, HlAttrs attrs) PUT(hl, "background", INTEGER_OBJ(attrs.background)); } + if (attrs.special != -1) { + PUT(hl, "special", INTEGER_OBJ(attrs.special)); + } + ADD(args, DICTIONARY_OBJ(hl)); push_call(ui, "highlight_set", args); } @@ -323,6 +328,13 @@ static void remote_ui_update_bg(UI *ui, int bg) push_call(ui, "update_bg", args); } +static void remote_ui_update_sp(UI *ui, int sp) +{ + Array args = ARRAY_DICT_INIT; + ADD(args, INTEGER_OBJ(sp)); + push_call(ui, "update_sp", args); +} + static void remote_ui_flush(UI *ui) { UIData *data = ui->data; diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 17cb8a86aa..151b9d3790 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -160,9 +160,6 @@ qf_init ( { qf_info_T *qi = &ql_info; - if (efile == NULL) - return FAIL; - if (wp != NULL) { qi = ll_get_or_alloc_list(wp); } diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 10b5b6bba4..34eef83164 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -3385,11 +3385,9 @@ win_line ( && lcs_nbsp) || (c == ' ' && lcs_space && ptr - line <= trailcol))) { c = (c == ' ') ? lcs_space : lcs_nbsp; - if (area_attr == 0 && search_attr == 0) { - n_attr = 1; - extra_attr = hl_attr(HLF_8); - saved_attr2 = char_attr; // save current attr - } + n_attr = 1; + extra_attr = hl_attr(HLF_8); + saved_attr2 = char_attr; // save current attr mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { mb_utf8 = true; @@ -3402,11 +3400,9 @@ win_line ( if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ') { c = lcs_trail; - if (!attr_pri) { - n_attr = 1; - extra_attr = hl_attr(HLF_8); - saved_attr2 = char_attr; /* save current attr */ - } + n_attr = 1; + extra_attr = hl_attr(HLF_8); + saved_attr2 = char_attr; // save current attr mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { mb_utf8 = TRUE; @@ -3554,11 +3550,9 @@ win_line ( c = ' '; } lcs_eol_one = -1; - --ptr; /* put it back at the NUL */ - if (!attr_pri) { - extra_attr = hl_attr(HLF_AT); - n_attr = 1; - } + ptr--; // put it back at the NUL + extra_attr = hl_attr(HLF_AT); + n_attr = 1; mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { mb_utf8 = TRUE; @@ -3587,12 +3581,10 @@ win_line ( n_extra = byte2cells(c) - 1; c = *p_extra++; } - if (!attr_pri) { - n_attr = n_extra + 1; - extra_attr = hl_attr(HLF_8); - saved_attr2 = char_attr; /* save current attr */ - } - mb_utf8 = FALSE; /* don't draw as UTF-8 */ + n_attr = n_extra + 1; + extra_attr = hl_attr(HLF_8); + saved_attr2 = char_attr; // save current attr + mb_utf8 = false; // don't draw as UTF-8 } else if (VIsual_active && (VIsual_mode == Ctrl_V || VIsual_mode == 'v') @@ -3702,11 +3694,10 @@ win_line ( did_wcol = true; } - /* Don't override visual selection highlighting. */ - if (n_attr > 0 - && draw_state == WL_LINE - && !attr_pri) - char_attr = extra_attr; + // Don't override visual selection highlighting. + if (n_attr > 0 && draw_state == WL_LINE) { + char_attr = hl_combine_attr(char_attr, extra_attr); + } /* * Handle the case where we are in column 0 but not on the first @@ -3734,13 +3725,12 @@ win_line ( mb_utf8 = TRUE; u8cc[0] = 0; c = 0xc0; - } else - mb_utf8 = FALSE; /* don't draw as UTF-8 */ - if (!attr_pri) { - saved_attr3 = char_attr; /* save current attr */ - char_attr = hl_attr(HLF_AT); /* later copied to char_attr */ - n_attr3 = 1; + } else { + mb_utf8 = false; // don't draw as UTF-8 } + saved_attr3 = char_attr; // save current attr + char_attr = hl_attr(HLF_AT); // later copied to char_attr + n_attr3 = 1; } /* diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 765207928a..9a5484704e 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -62,8 +62,10 @@ struct hl_group { int sg_gui; // "gui=" highlighting attributes RgbValue sg_rgb_fg; // RGB foreground color RgbValue sg_rgb_bg; // RGB background color + RgbValue sg_rgb_sp; // RGB special color uint8_t *sg_rgb_fg_name; // RGB foreground color name uint8_t *sg_rgb_bg_name; // RGB background color name + uint8_t *sg_rgb_sp_name; // RGB special color name }; #define SG_CTERM 2 // cterm has been set @@ -6169,12 +6171,11 @@ do_highlight ( break; } - /* - * Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg" or - * "guibg"). - */ - while (*linep && !ascii_iswhite(*linep) && *linep != '=') - ++linep; + // Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg", + // "guibg" or "guisp"). + while (*linep && !ascii_iswhite(*linep) && *linep != '=') { + linep++; + } xfree(key); key = vim_strnsave_up(key_start, (int)(linep - key_start)); linep = skipwhite(linep); @@ -6452,7 +6453,23 @@ do_highlight ( normal_bg = HL_TABLE()[idx].sg_rgb_bg; } } else if (STRCMP(key, "GUISP") == 0) { - // Ignored for now + if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) { + if (!init) + HL_TABLE()[idx].sg_set |= SG_GUI; + + xfree(HL_TABLE()[idx].sg_rgb_sp_name); + if (STRCMP(arg, "NONE") != 0) { + HL_TABLE()[idx].sg_rgb_sp_name = (uint8_t *)xstrdup((char *)arg); + HL_TABLE()[idx].sg_rgb_sp = name_to_color(arg); + } else { + HL_TABLE()[idx].sg_rgb_sp_name = NULL; + HL_TABLE()[idx].sg_rgb_sp = -1; + } + } + + if (is_normal_group) { + normal_sp = HL_TABLE()[idx].sg_rgb_sp; + } } else if (STRCMP(key, "START") == 0 || STRCMP(key, "STOP") == 0) { // Ignored for now } else { @@ -6516,6 +6533,7 @@ void restore_cterm_colors(void) { normal_fg = -1; normal_bg = -1; + normal_sp = -1; cterm_normal_fg_color = 0; cterm_normal_fg_bold = 0; cterm_normal_bg_color = 0; @@ -6532,6 +6550,7 @@ static int hl_has_settings(int idx, int check_link) || HL_TABLE()[idx].sg_cterm_bg != 0 || HL_TABLE()[idx].sg_rgb_fg_name != NULL || HL_TABLE()[idx].sg_rgb_bg_name != NULL + || HL_TABLE()[idx].sg_rgb_sp_name != NULL || (check_link && (HL_TABLE()[idx].sg_set & SG_LINK)); } @@ -6548,14 +6567,18 @@ static void highlight_clear(int idx) HL_TABLE()[idx].sg_gui = 0; HL_TABLE()[idx].sg_rgb_fg = -1; HL_TABLE()[idx].sg_rgb_bg = -1; + HL_TABLE()[idx].sg_rgb_sp = -1; xfree(HL_TABLE()[idx].sg_rgb_fg_name); HL_TABLE()[idx].sg_rgb_fg_name = NULL; xfree(HL_TABLE()[idx].sg_rgb_bg_name); HL_TABLE()[idx].sg_rgb_bg_name = NULL; - /* Clear the script ID only when there is no link, since that is not - * cleared. */ - if (HL_TABLE()[idx].sg_link == 0) + xfree(HL_TABLE()[idx].sg_rgb_sp_name); + HL_TABLE()[idx].sg_rgb_sp_name = NULL; + // Clear the script ID only when there is no link, since that is not + // cleared. + if (HL_TABLE()[idx].sg_link == 0) { HL_TABLE()[idx].sg_scriptID = 0; + } } @@ -6597,7 +6620,8 @@ int get_attr_entry(attrentry_T *aep) && aep->cterm_bg_color == taep->cterm_bg_color && aep->rgb_ae_attr == taep->rgb_ae_attr && aep->rgb_fg_color == taep->rgb_fg_color - && aep->rgb_bg_color == taep->rgb_bg_color) { + && aep->rgb_bg_color == taep->rgb_bg_color + && aep->rgb_sp_color == taep->rgb_sp_color) { return i + ATTR_OFF; } } @@ -6635,6 +6659,7 @@ int get_attr_entry(attrentry_T *aep) taep->rgb_ae_attr = aep->rgb_ae_attr; taep->rgb_fg_color = aep->rgb_fg_color; taep->rgb_bg_color = aep->rgb_bg_color; + taep->rgb_sp_color = aep->rgb_sp_color; return table->ga_len - 1 + ATTR_OFF; } @@ -6696,6 +6721,10 @@ int hl_combine_attr(int char_attr, int prim_attr) if (spell_aep->rgb_bg_color >= 0) { new_en.rgb_bg_color = spell_aep->rgb_bg_color; } + + if (spell_aep->rgb_sp_color >= 0) { + new_en.rgb_sp_color = spell_aep->rgb_sp_color; + } } return get_attr_entry(&new_en); } @@ -6733,7 +6762,7 @@ static void highlight_list_one(int id) didh = highlight_list_arg(id, didh, LIST_STRING, 0, sgp->sg_rgb_bg_name, "guibg"); didh = highlight_list_arg(id, didh, LIST_STRING, - 0, NULL, "guisp"); + 0, sgp->sg_rgb_sp_name, "guisp"); if (sgp->sg_link && !got_int) { (void)syn_list_header(didh, 9999, id); @@ -6847,8 +6876,9 @@ highlight_color ( if (modec == 'g') { if (fg) return HL_TABLE()[id - 1].sg_rgb_fg_name; - if (sp) - return NULL; + if (sp) { + return HL_TABLE()[id - 1].sg_rgb_sp_name; + } return HL_TABLE()[id - 1].sg_rgb_bg_name; } if (font || sp) @@ -6935,10 +6965,12 @@ set_hl_attr ( // before setting attr_entry->{f,g}g_color to a other than -1 at_en.rgb_fg_color = sgp->sg_rgb_fg_name ? sgp->sg_rgb_fg : -1; at_en.rgb_bg_color = sgp->sg_rgb_bg_name ? sgp->sg_rgb_bg : -1; + at_en.rgb_sp_color = sgp->sg_rgb_sp_name ? sgp->sg_rgb_sp : -1; if (at_en.cterm_fg_color != 0 || at_en.cterm_bg_color != 0 || at_en.rgb_fg_color != -1 || at_en.rgb_bg_color != -1 - || at_en.cterm_ae_attr != 0 || at_en.rgb_ae_attr != 0) { + || at_en.rgb_sp_color != -1 || at_en.cterm_ae_attr != 0 + || at_en.rgb_ae_attr != 0) { sgp->sg_attr = get_attr_entry(&at_en); } } @@ -7271,6 +7303,10 @@ int highlight_changed(void) hlt[hlcnt + i].sg_rgb_bg = hlt[id - 1].sg_rgb_bg; } + if (hlt[id - 1].sg_rgb_sp != hlt[id_S - 1].sg_rgb_sp) { + hlt[hlcnt + i].sg_rgb_sp = hlt[id - 1].sg_rgb_sp; + } + highlight_ga.ga_len = hlcnt + i + 1; set_hl_attr(hlcnt + i); /* At long last we can apply */ highlight_stlnc[i] = syn_id2attr(hlcnt + i + 1); diff --git a/src/nvim/syntax_defs.h b/src/nvim/syntax_defs.h index 67cf672ef2..8d207e6286 100644 --- a/src/nvim/syntax_defs.h +++ b/src/nvim/syntax_defs.h @@ -69,8 +69,8 @@ struct syn_state { // Structure shared between syntax.c, screen.c typedef struct attr_entry { - short rgb_ae_attr, cterm_ae_attr; // HL_BOLD, etc. - RgbValue rgb_fg_color, rgb_bg_color; + int16_t rgb_ae_attr, cterm_ae_attr; // HL_BOLD, etc. + RgbValue rgb_fg_color, rgb_bg_color, rgb_sp_color; int cterm_fg_color, cterm_bg_color; } attrentry_T; diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 0e3149b912..90542a6a6c 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -32,7 +32,6 @@ SCRIPTS := \ test73.out \ test79.out \ test_listlbr.out \ - test_breakindent.out \ test_close_count.out \ test_marks.out \ diff --git a/src/nvim/testdir/test_breakindent.in b/src/nvim/testdir/test_breakindent.in deleted file mode 100644 index 5a8e580c4a..0000000000 --- a/src/nvim/testdir/test_breakindent.in +++ /dev/null @@ -1,123 +0,0 @@ -Test for breakindent - -STARTTEST -:so small.vim -:if !exists("+breakindent") | e! test.ok | w! test.out | qa! | endif -:set wildchar=^E -:10new|:vsp|:vert resize 20 -:put =\"\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP\" -:set ts=4 sw=4 sts=4 breakindent -:fu! ScreenChar(line, width) -: let c='' -: for i in range(1,a:width) -: let c.=nr2char(screenchar(a:line, i)) -: endfor -: let c.="\n" -: for i in range(1,a:width) -: let c.=nr2char(screenchar(a:line+1, i)) -: endfor -: let c.="\n" -: for i in range(1,a:width) -: let c.=nr2char(screenchar(a:line+2, i)) -: endfor -: return c -:endfu -:fu DoRecordScreen() -: wincmd l -: $put =printf(\"\n%s\", g:test) -: $put =g:line1 -: wincmd p -:endfu -:set briopt=min:0 -:let g:test="Test 1: Simple breakindent" -:let line1=ScreenChar(line('.'),8) -:call DoRecordScreen() -:let g:test="Test 2: Simple breakindent + sbr=>>" -:set sbr=>> -:let line1=ScreenChar(line('.'),8) -:call DoRecordScreen() -:let g:test ="Test 3: Simple breakindent + briopt:sbr" -:set briopt=sbr,min:0 sbr=++ -:let line1=ScreenChar(line('.'),8) -:call DoRecordScreen() -:let g:test ="Test 4: Simple breakindent + min width: 18" -:set sbr= briopt=min:18 -:let line1=ScreenChar(line('.'),8) -:call DoRecordScreen() -:let g:test =" Test 5: Simple breakindent + shift by 2" -:set briopt=shift:2,min:0 -:let line1=ScreenChar(line('.'),8) -:call DoRecordScreen() -:let g:test=" Test 6: Simple breakindent + shift by -1" -:set briopt=shift:-1,min:0 -:let line1=ScreenChar(line('.'),8) -:call DoRecordScreen() -:let g:test=" Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr" -:set briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 -:let line1=ScreenChar(line('.'),10) -:call DoRecordScreen() -:let g:test=" Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr" -:set briopt=shift:1,sbr,min:0 nu sbr=# list lcs&vi -:let line1=ScreenChar(line('.'),10) -:call DoRecordScreen() -:let g:test=" Test 9: breakindent + shift by +1 + 'nu' + sbr=# list" -:set briopt-=sbr -:let line1=ScreenChar(line('.'),10) -:call DoRecordScreen() -:let g:test=" Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n" -:set cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0 -:let line1=ScreenChar(line('.'),10) -:call DoRecordScreen() -:wincmd p -:let g:test="\n Test 11: strdisplaywidth when breakindent is on" -:set cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4 -:let text=getline(2) "skip leading tab when calculating text width -:let width = strlen(text[1:])+indent(2)*4+strlen(&sbr)*3 " text wraps 3 times -:$put =g:test -:$put =printf(\"strdisplaywidth: %d == calculated: %d\", strdisplaywidth(text), width) -:let g:str="\t\t\t\t\t{" -:let g:test=" Test 12: breakindent + long indent" -:wincmd p -:set all& breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4 -:$put =g:str -zt:let line1=ScreenChar(1,10) -:wincmd p -:call DoRecordScreen() -:" -:" Test, that the string " a\tb\tc\td\te" is correctly -:" displayed in a 20 column wide window (see bug report -:" https://groups.google.com/d/msg/vim_dev/ZOdg2mc9c9Y/TT8EhFjEy0IJ -:only -:vert 20new -:set all& breakindent briopt=min:10 -:call setline(1, [" a\tb\tc\td\te", " z y x w v"]) -:/^\s*a -fbgjyl:let line1 = @0 -:?^\s*z -fygjyl:let line2 = @0 -:quit! -:$put ='Test 13: breakindent with wrapping Tab' -:$put =line1 -:$put =line2 -:" -:let g:test="Test 14: breakindent + visual blockwise delete #1" -:set all& breakindent shada+=nX-test-breakindent.shada -:30vnew -:normal! 3a1234567890 -:normal! a abcde -:exec "normal! 0\<C-V>tex" -:let line1=ScreenChar(line('.'),8) -:call DoRecordScreen() -:" -:let g:test="Test 15: breakindent + visual blockwise delete #2" -:%d -:normal! 4a1234567890 -:exec "normal! >>\<C-V>3f0x" -:let line1=ScreenChar(line('.'),20) -:call DoRecordScreen() -:quit! -:" -:%w! test.out -:qa! -ENDTEST -dummy text diff --git a/src/nvim/testdir/test_breakindent.ok b/src/nvim/testdir/test_breakindent.ok deleted file mode 100644 index 995bd5f29c..0000000000 --- a/src/nvim/testdir/test_breakindent.ok +++ /dev/null @@ -1,74 +0,0 @@ - - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP - -Test 1: Simple breakindent - abcd - qrst - GHIJ - -Test 2: Simple breakindent + sbr=>> - abcd - >>qr - >>EF - -Test 3: Simple breakindent + briopt:sbr - abcd -++ qrst -++ GHIJ - -Test 4: Simple breakindent + min width: 18 - abcd - qrstuv - IJKLMN - - Test 5: Simple breakindent + shift by 2 - abcd - qr - EF - - Test 6: Simple breakindent + shift by -1 - abcd - qrstu - HIJKL - - Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr - 2 ab - ? m - ? x - - Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr - 2 ^Iabcd - # opq - # BCD - - Test 9: breakindent + shift by +1 + 'nu' + sbr=# list - 2 ^Iabcd - #op - #AB - - Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n - 2 ab -~ mn -~ yz - - Test 11: strdisplaywidth when breakindent is on -strdisplaywidth: 46 == calculated: 64 - { - - Test 12: breakindent + long indent -56 - -~ -Test 13: breakindent with wrapping Tab -d -w - -Test 14: breakindent + visual blockwise delete #1 -e -~ -~ - -Test 15: breakindent + visual blockwise delete #2 - 1234567890 -~ -~ diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 202c5666a1..62bc81ba64 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -100,6 +100,7 @@ UI *tui_start(void) ui->visual_bell = tui_visual_bell; ui->update_fg = tui_update_fg; ui->update_bg = tui_update_bg; + ui->update_sp = tui_update_sp; ui->flush = tui_flush; ui->suspend = tui_suspend; ui->set_title = tui_set_title; @@ -573,6 +574,11 @@ static void tui_update_bg(UI *ui, int bg) ((TUIData *)ui->data)->grid.bg = bg; } +static void tui_update_sp(UI *ui, int sp) +{ + // Do nothing; 'special' color is for GUI only +} + static void tui_flush(UI *ui) { TUIData *data = ui->data; diff --git a/src/nvim/ugrid.h b/src/nvim/ugrid.h index df51e1fced..ad6d96a168 100644 --- a/src/nvim/ugrid.h +++ b/src/nvim/ugrid.h @@ -21,7 +21,7 @@ struct ugrid { UCell **cells; }; -#define EMPTY_ATTRS ((HlAttrs){false, false, false, false, false, -1, -1}) +#define EMPTY_ATTRS ((HlAttrs){ false, false, false, false, false, -1, -1, -1 }) #define UGRID_FOREACH_CELL(grid, top, bot, left, right, code) \ do { \ diff --git a/src/nvim/ui.c b/src/nvim/ui.c index d32969f149..05322a6f64 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -155,6 +155,7 @@ void ui_resize(int new_width, int new_height) UI_CALL(update_fg, (ui->rgb ? normal_fg : cterm_normal_fg_color - 1)); UI_CALL(update_bg, (ui->rgb ? normal_bg : cterm_normal_bg_color - 1)); + UI_CALL(update_sp, (ui->rgb ? normal_sp : -1)); sr.top = 0; sr.bot = height - 1; @@ -388,7 +389,7 @@ static void parse_control_character(uint8_t c) static void set_highlight_args(int attr_code) { - HlAttrs rgb_attrs = { false, false, false, false, false, -1, -1 }; + HlAttrs rgb_attrs = { false, false, false, false, false, -1, -1, -1 }; HlAttrs cterm_attrs = rgb_attrs; if (attr_code == HL_NORMAL) { @@ -425,6 +426,10 @@ static void set_highlight_args(int attr_code) rgb_attrs.background = aep->rgb_bg_color; } + if (aep->rgb_sp_color != normal_sp) { + rgb_attrs.special = aep->rgb_sp_color; + } + if (cterm_normal_fg_color != aep->cterm_fg_color) { cterm_attrs.foreground = aep->cterm_fg_color - 1; } diff --git a/src/nvim/ui.h b/src/nvim/ui.h index 4c051fcfbf..5934d2fee9 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -7,7 +7,7 @@ typedef struct { bool bold, underline, undercurl, italic, reverse; - int foreground, background; + int foreground, background, special; } HlAttrs; typedef struct ui_t UI; @@ -35,6 +35,7 @@ struct ui_t { void (*flush)(UI *ui); void (*update_fg)(UI *ui, int fg); void (*update_bg)(UI *ui, int bg); + void (*update_sp)(UI *ui, int sp); void (*suspend)(UI *ui); void (*set_title)(UI *ui, char *title); void (*set_icon)(UI *ui, char *icon); diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c index 359fffe3bf..fd9d4671e3 100644 --- a/src/nvim/ui_bridge.c +++ b/src/nvim/ui_bridge.c @@ -49,6 +49,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler) rv->bridge.visual_bell = ui_bridge_visual_bell; rv->bridge.update_fg = ui_bridge_update_fg; rv->bridge.update_bg = ui_bridge_update_bg; + rv->bridge.update_sp = ui_bridge_update_sp; rv->bridge.flush = ui_bridge_flush; rv->bridge.suspend = ui_bridge_suspend; rv->bridge.set_title = ui_bridge_set_title; @@ -305,6 +306,16 @@ static void ui_bridge_update_bg_event(void **argv) ui->update_bg(ui, PTR2INT(argv[1])); } +static void ui_bridge_update_sp(UI *b, int sp) +{ + UI_CALL(b, update_sp, 2, b, INT2PTR(sp)); +} +static void ui_bridge_update_sp_event(void **argv) +{ + UI *ui = UI(argv[0]); + ui->update_sp(ui, PTR2INT(argv[1])); +} + static void ui_bridge_flush(UI *b) { UI_CALL(b, flush, 1, b); diff --git a/src/nvim/version.c b/src/nvim/version.c index 56ede1aa78..82a15f9833 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -625,9 +625,9 @@ static int included_patches[] = { // 1062 NA // 1061, // 1060 NA - // 1059, + 1059, // 1058, - // 1057, + 1057, // 1056, 1055, 1054, diff --git a/test/functional/legacy/breakindent_spec.lua b/test/functional/legacy/breakindent_spec.lua new file mode 100644 index 0000000000..a12d4add10 --- /dev/null +++ b/test/functional/legacy/breakindent_spec.lua @@ -0,0 +1,211 @@ +-- Test for breakindent + +local helpers = require('test.functional.helpers') +local feed, insert = helpers.feed, helpers.insert +local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect + +describe('breakindent', function() + setup(clear) + + it('is working', function() + insert('dummy text') + + execute('set wildchar=^E') + execute('10new') + execute('vsp') + execute('vert resize 20') + execute([[put =\"\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP\"]]) + execute('set ts=4 sw=4 sts=4 breakindent') + execute('fu! ScreenChar(line, width)') + execute(' let c=""') + execute(' for i in range(1,a:width)') + execute(' let c.=nr2char(screenchar(a:line, i))') + execute(' endfor') + execute([[ let c.="\n"]]) + execute(' for i in range(1,a:width)') + execute(' let c.=nr2char(screenchar(a:line+1, i))') + execute(' endfor') + execute([[ let c.="\n"]]) + execute(' for i in range(1,a:width)') + execute(' let c.=nr2char(screenchar(a:line+2, i))') + execute(' endfor') + execute(' return c') + execute('endfu') + execute('fu DoRecordScreen()') + execute(' wincmd l') + execute([[ $put =printf(\"\n%s\", g:test)]]) + execute(' $put =g:line1') + execute(' wincmd p') + execute('endfu') + execute('set briopt=min:0') + execute('let g:test="Test 1: Simple breakindent"') + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + execute('let g:test="Test 2: Simple breakindent + sbr=>>"') + execute('set sbr=>>') + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + execute('let g:test ="Test 3: Simple breakindent + briopt:sbr"') + execute('set briopt=sbr,min:0 sbr=++') + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + execute('let g:test ="Test 4: Simple breakindent + min width: 18"') + execute('set sbr= briopt=min:18') + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + execute('let g:test =" Test 5: Simple breakindent + shift by 2"') + execute('set briopt=shift:2,min:0') + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + execute('let g:test=" Test 6: Simple breakindent + shift by -1"') + execute('set briopt=shift:-1,min:0') + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + execute('let g:test=" Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr"') + execute('set briopt=shift:1,sbr,min:0 nu sbr=? nuw=4') + execute('let line1=ScreenChar(line("."),10)') + execute('call DoRecordScreen()') + execute('let g:test=" Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr"') + execute('set briopt=shift:1,sbr,min:0 nu sbr=# list lcs&vi') + execute('let line1=ScreenChar(line("."),10)') + execute('call DoRecordScreen()') + execute([[let g:test=" Test 9: breakindent + shift by +1 + 'nu' + sbr=# list"]]) + execute('set briopt-=sbr') + execute('let line1=ScreenChar(line("."),10)') + execute('call DoRecordScreen()') + execute([[let g:test=" Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n"]]) + execute('set cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0') + execute('let line1=ScreenChar(line("."),10)') + execute('call DoRecordScreen()') + execute('wincmd p') + execute([[let g:test="\n Test 11: strdisplaywidth when breakindent is on"]]) + execute('set cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4') + -- Skip leading tab when calculating text width. + execute('let text=getline(2)') + -- Text wraps 3 times. + execute('let width = strlen(text[1:])+indent(2)*4+strlen(&sbr)*3') + execute('$put =g:test') + execute([[$put =printf(\"strdisplaywidth: %d == calculated: %d\", strdisplaywidth(text), width)]]) + execute([[let g:str="\t\t\t\t\t{"]]) + execute('let g:test=" Test 12: breakindent + long indent"') + execute('wincmd p') + execute('set all& breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4') + execute('$put =g:str') + feed('zt') + execute('let line1=ScreenChar(1,10)') + execute('wincmd p') + execute('call DoRecordScreen()') + + -- Test, that the string " a\tb\tc\td\te" is correctly displayed in a + -- 20 column wide window (see bug report + -- https://groups.google.com/d/msg/vim_dev/ZOdg2mc9c9Y/TT8EhFjEy0IJ ). + execute('only') + execute('vert 20new') + execute('set all& breakindent briopt=min:10') + execute([[call setline(1, [" a\tb\tc\td\te", " z y x w v"])]]) + execute([[/^\s*a]]) + feed('fbgjyl') + execute('let line1 = @0') + execute([[?^\s*z]]) + feed('fygjyl') + execute('let line2 = @0') + execute('quit!') + execute([[$put ='Test 13: breakindent with wrapping Tab']]) + execute('$put =line1') + execute('$put =line2') + + execute('let g:test="Test 14: breakindent + visual blockwise delete #1"') + execute('set all& breakindent shada+=nX-test-breakindent.shada') + execute('30vnew') + execute('normal! 3a1234567890') + execute('normal! a abcde') + execute([[exec "normal! 0\<C-V>tex"]]) + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + + execute('let g:test="Test 15: breakindent + visual blockwise delete #2"') + execute('%d') + execute('normal! 4a1234567890') + execute([[exec "normal! >>\<C-V>3f0x"]]) + execute('let line1=ScreenChar(line("."),20)') + execute('call DoRecordScreen()') + execute('quit!') + + -- Assert buffer contents. + expect([[ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP + + Test 1: Simple breakindent + abcd + qrst + GHIJ + + Test 2: Simple breakindent + sbr=>> + abcd + >>qr + >>EF + + Test 3: Simple breakindent + briopt:sbr + abcd + ++ qrst + ++ GHIJ + + Test 4: Simple breakindent + min width: 18 + abcd + qrstuv + IJKLMN + + Test 5: Simple breakindent + shift by 2 + abcd + qr + EF + + Test 6: Simple breakindent + shift by -1 + abcd + qrstu + HIJKL + + Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr + 2 ab + ? m + ? x + + Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr + 2 ^Iabcd + # opq + # BCD + + Test 9: breakindent + shift by +1 + 'nu' + sbr=# list + 2 ^Iabcd + #op + #AB + + Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n + 2 ab + ~ mn + ~ yz + + Test 11: strdisplaywidth when breakindent is on + strdisplaywidth: 46 == calculated: 64 + { + + Test 12: breakindent + long indent + 56 + + ~ + Test 13: breakindent with wrapping Tab + d + w + + Test 14: breakindent + visual blockwise delete #1 + e + ~ + ~ + + Test 15: breakindent + visual blockwise delete #2 + 1234567890 + ~ + ~ ]]) + end) +end) diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua index 045f5aa42f..97875c5147 100644 --- a/test/functional/terminal/highlight_spec.lua +++ b/test/functional/terminal/highlight_spec.lua @@ -25,7 +25,7 @@ describe('terminal window highlighting', function() [5] = {background = 11}, [6] = {foreground = 130}, [7] = {reverse = true}, - [8] = {background = 11} + [8] = {background = 11}, }) screen:attach(false) execute('enew | call termopen(["'..nvim_dir..'/tty-test"]) | startinsert') @@ -121,7 +121,7 @@ describe('terminal window highlighting with custom palette', function() clear() screen = Screen.new(50, 7) screen:set_default_attr_ids({ - [1] = {foreground = 1193046} + [1] = {foreground = 1193046, special = Screen.colors.Black} }) screen:set_default_attr_ignore({ [1] = {bold = true}, @@ -130,7 +130,7 @@ describe('terminal window highlighting with custom palette', function() [5] = {background = 11}, [6] = {foreground = 130}, [7] = {reverse = true}, - [8] = {background = 11} + [8] = {background = 11}, }) screen:attach(true) nvim('set_var', 'terminal_color_3', '#123456') diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index 06139277b2..0229b8bbf7 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -1,7 +1,7 @@ local helpers = require('test.functional.helpers') local Screen = require('test.functional.ui.screen') local os = require('os') -local clear, feed = helpers.clear, helpers.feed +local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, request, eq = helpers.execute, helpers.request, helpers.eq @@ -303,3 +303,311 @@ describe('Default highlight groups', function() ]], {[1] = {foreground = Screen.colors.Red, background = Screen.colors.Green}}) end) end) + +describe('guisp (special/undercurl)', function() + local screen + + before_each(function() + clear() + screen = Screen.new(25,10) + screen:attach() + screen:set_default_attr_ignore({ + [1] = {bold = true, foreground = Screen.colors.Blue}, + [2] = {bold = true} + }) + end) + + it('can be set and is applied like foreground or background', function() + execute('syntax on') + execute('syn keyword TmpKeyword neovim') + execute('syn keyword TmpKeyword1 special') + execute('syn keyword TmpKeyword2 specialwithbg') + execute('syn keyword TmpKeyword3 specialwithfg') + execute('hi! Awesome guifg=red guibg=yellow guisp=red') + execute('hi! Awesome1 guisp=red') + execute('hi! Awesome2 guibg=yellow guisp=red') + execute('hi! Awesome3 guifg=red guisp=red') + execute('hi link TmpKeyword Awesome') + execute('hi link TmpKeyword1 Awesome1') + execute('hi link TmpKeyword2 Awesome2') + execute('hi link TmpKeyword3 Awesome3') + insert([[ + neovim + awesome neovim + wordcontainingneovim + special + specialwithbg + specialwithfg + ]]) + feed('Go<tab>neovim tabbed') + screen:expect([[ + {1:neovim} | + awesome {1:neovim} | + wordcontainingneovim | + {2:special} | + {3:specialwithbg} | + {4:specialwithfg} | + | + {1:neovim} tabbed^ | + ~ | + -- INSERT -- | + ]],{ + [1] = {background = Screen.colors.Yellow, foreground = Screen.colors.Red, + special = Screen.colors.Red}, + [2] = {special = Screen.colors.Red}, + [3] = {special = Screen.colors.Red, background = Screen.colors.Yellow}, + [4] = {foreground = Screen.colors.Red, special = Screen.colors.Red}, + }) + + end) +end) + +describe("'cursorline' with 'listchars'", function() + local screen + + local hlgroup_colors = { + NonText = Screen.colors.Blue, + Cursorline = Screen.colors.Grey90, + SpecialKey = Screen.colors.Red, + Visual = Screen.colors.LightGrey, + } + + before_each(function() + clear() + screen = Screen.new(20,5) + screen:attach() + end) + + after_each(function() + screen:detach() + end) + + it("'cursorline' and 'cursorcolumn'", function() + screen:set_default_attr_ids({[1] = {background=hlgroup_colors.Cursorline}}) + screen:set_default_attr_ignore( {{bold=true, foreground=hlgroup_colors.NonText}} ) + execute('highlight clear ModeMsg') + execute('set cursorline') + feed('i') + screen:expect([[ + {1:^ }| + ~ | + ~ | + ~ | + -- INSERT -- | + ]]) + feed('abcdefg<cr>kkasdf') + screen:expect([[ + abcdefg | + {1:kkasdf^ }| + ~ | + ~ | + -- INSERT -- | + ]]) + feed('<esc>') + screen:expect([[ + abcdefg | + {1:kkasd^f }| + ~ | + ~ | + | + ]]) + execute('set nocursorline') + screen:expect([[ + abcdefg | + kkasd^f | + ~ | + ~ | + :set nocursorline | + ]]) + feed('k') + screen:expect([[ + abcde^fg | + kkasdf | + ~ | + ~ | + :set nocursorline | + ]]) + feed('jjji<cr><cr><cr><esc>') + screen:expect([[ + kkasd | + | + | + ^f | + | + ]]) + execute('set cursorline') + execute('set cursorcolumn') + feed('kkiabcdefghijk<esc>hh') + screen:expect([[ + kkasd {1: } | + {1:abcdefgh^ijk }| + {1: } | + f {1: } | + | + ]]) + feed('khh') + screen:expect([[ + {1:kk^asd }| + ab{1:c}defghijk | + {1: } | + f {1: } | + | + ]]) + end) + + it("'cursorline' and with 'listchar' option: space, eol, tab, and trail", function() + screen:set_default_attr_ids({ + [1] = {background=hlgroup_colors.Cursorline}, + [2] = { + foreground=hlgroup_colors.SpecialKey, + background=hlgroup_colors.Cursorline, + }, + [3] = { + background=hlgroup_colors.Cursorline, + foreground=hlgroup_colors.NonText, + bold=true, + }, + [4] = { + foreground=hlgroup_colors.NonText, + bold=true, + }, + [5] = { + foreground=hlgroup_colors.SpecialKey, + }, + }) + execute('highlight clear ModeMsg') + execute('highlight SpecialKey guifg=#FF0000') + execute('set cursorline') + execute('set tabstop=8') + execute('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list') + feed('i\t abcd <cr>\t abcd <cr><esc>k') + screen:expect([[ + {5:>-------.}abcd{5:*}{4:¬} | + {2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }| + {4:¬} | + {4:~ }| + | + ]]) + feed('k') + screen:expect([[ + {2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }| + {5:>-------.}abcd{5:*}{4:¬} | + {4:¬} | + {4:~ }| + | + ]]) + execute('set nocursorline') + screen:expect([[ + {5:^>-------.}abcd{5:*}{4:¬} | + {5:>-------.}abcd{5:*}{4:¬} | + {4:¬} | + {4:~ }| + :set nocursorline | + ]]) + execute('set nowrap') + feed('ALorem ipsum dolor sit amet<ESC>0') + screen:expect([[ + {5:^>-------.}abcd{5:.}Lorem{4:>}| + {5:>-------.}abcd{5:*}{4:¬} | + {4:¬} | + {4:~ }| + | + ]]) + execute('set cursorline') + screen:expect([[ + {2:^>-------.}{1:abcd}{2:.}{1:Lorem}{4:>}| + {5:>-------.}abcd{5:*}{4:¬} | + {4:¬} | + {4:~ }| + :set cursorline | + ]]) + feed('$') + screen:expect([[ + {4:<}{1:r}{2:.}{1:sit}{2:.}{1:ame^t}{3:¬}{1: }| + {4:<} | + {4:<} | + {4:~ }| + :set cursorline | + ]]) + feed('G') + screen:expect([[ + {5:>-------.}abcd{5:.}Lorem{4:>}| + {5:>-------.}abcd{5:*}{4:¬} | + {3:^¬}{1: }| + {4:~ }| + :set cursorline | + ]]) + end) + + it("'listchar' in visual mode", function() + screen:set_default_attr_ids({ + [1] = {background=hlgroup_colors.Cursorline}, + [2] = { + foreground=hlgroup_colors.SpecialKey, + background=hlgroup_colors.Cursorline, + }, + [3] = { + background=hlgroup_colors.Cursorline, + foreground=hlgroup_colors.NonText, + bold=true, + }, + [4] = { + foreground=hlgroup_colors.NonText, + bold=true, + }, + [5] = { + foreground=hlgroup_colors.SpecialKey, + }, + [6] = { + background=hlgroup_colors.Visual, + }, + [7] = { + background=hlgroup_colors.Visual, + foreground=hlgroup_colors.SpecialKey, + }, + [8] = { + background=hlgroup_colors.Visual, + foreground=hlgroup_colors.NonText, + bold=true, + }, + }) + execute('highlight clear ModeMsg') + execute('highlight SpecialKey guifg=#FF0000') + execute('set cursorline') + execute('set tabstop=8') + execute('set nowrap') + execute('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list') + feed('i\t abcd <cr>\t abcd Lorem ipsum dolor sit amet<cr><esc>kkk0') + screen:expect([[ + {2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }| + {5:>-------.}abcd{5:.}Lorem{4:>}| + {4:¬} | + {4:~ }| + | + ]]) + feed('lllvj') + screen:expect([[ + {5:>-------.}a{6:bcd}{7:*}{8:¬} | + {7:>-------.}{6:a}^bcd{5:.}Lorem{4:>}| + {4:¬} | + {4:~ }| + -- VISUAL -- | + ]]) + feed('<esc>V') + screen:expect([[ + {5:>-------.}abcd{5:*}{4:¬} | + {7:>-------.}{6:a}^b{6:cd}{7:.}{6:Lorem}{4:>}| + {4:¬} | + {4:~ }| + -- VISUAL LINE -- | + ]]) + feed('<esc>$') + screen:expect([[ + {4:<} | + {4:<}{1:r}{2:.}{1:sit}{2:.}{1:ame^t}{3:¬}{1: }| + {4:<} | + {4:~ }| + | + ]]) + end) +end) diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index d0d791308b..993bbd5b0e 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -23,7 +23,12 @@ describe('Mouse input', function() screen:attach() screen:set_default_attr_ids({ [1] = {background = hlgroup_colors.Visual}, - [2] = {bold = true} + [2] = {bold = true}, + [3] = { + foreground = hlgroup_colors.NonText, + background = hlgroup_colors.Visual, + bold = true, + }, }) screen:set_default_attr_ignore( {{bold=true, foreground=hlgroup_colors.NonText}} ) feed('itesting<cr>mouse<cr>support and selection<esc>') @@ -225,14 +230,14 @@ describe('Mouse input', function() feed('<LeftDrag><2,2>') screen:expect([[ testing | - mo{1:use } | + mo{1:use}{3: } | {1:su}^pport and selection | ~ | {2:-- VISUAL --} | ]]) feed('<LeftDrag><0,0>') screen:expect([[ - ^t{1:esting } | + ^t{1:esting}{3: } | {1:mou}se | support and selection | ~ | @@ -293,7 +298,7 @@ describe('Mouse input', function() screen:expect([[ testing | mouse | - {1:su}^p{1:port and selection } | + {1:su}^p{1:port and selection}{3: } | ~ | {2:-- VISUAL LINE --} | ]]) @@ -321,8 +326,8 @@ describe('Mouse input', function() ]]) feed('<RightMouse><2,2>') screen:expect([[ - {1:testing } | - {1:mouse } | + {1:testing}{3: } | + {1:mouse}{3: } | {1:su}^pport and selection | ~ | {2:-- VISUAL --} | diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index a11fab18a2..6372cbe081 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -425,6 +425,10 @@ function Screen:_handle_update_bg(bg) self._bg = bg end +function Screen:_handle_update_sp(sp) + self._sp = sp +end + function Screen:_handle_suspend() self.suspended = true end @@ -573,7 +577,7 @@ function Screen:_pprint_attrs(attrs) local items = {} for f, v in pairs(attrs) do local desc = tostring(v) - if f == "foreground" or f == "background" then + if f == "foreground" or f == "background" or f == "special" then if Screen.colornames[v] ~= nil then desc = "Screen.colors."..Screen.colornames[v] end @@ -614,7 +618,8 @@ function Screen:_equal_attrs(a, b) a.underline == b.underline and a.undercurl == b.undercurl and a.italic == b.italic and a.reverse == b.reverse and a.foreground == b.foreground and - a.background == b.background + a.background == b.background and + a.special == b.special end function Screen:_attr_index(attrs, attr) |