diff options
-rw-r--r-- | runtime/autoload/tutor.vim | 10 | ||||
-rw-r--r-- | runtime/doc/api.txt | 2 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/api.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/api_keysets.lua | 1 | ||||
-rw-r--r-- | runtime/tutor/en/vim-01-beginner.tutor | 18 | ||||
-rw-r--r-- | src/nvim/api/keysets.h | 1 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 1 | ||||
-rw-r--r-- | src/nvim/buffer.c | 1 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 6 | ||||
-rw-r--r-- | src/nvim/bufwrite.c | 4 | ||||
-rw-r--r-- | src/nvim/drawline.c | 33 | ||||
-rw-r--r-- | src/nvim/edit.c | 16 | ||||
-rw-r--r-- | src/nvim/highlight_group.c | 3 | ||||
-rw-r--r-- | test/functional/api/highlight_spec.lua | 11 | ||||
-rw-r--r-- | test/functional/autocmd/textchanged_spec.lua | 150 | ||||
-rw-r--r-- | test/functional/editor/completion_spec.lua | 87 | ||||
-rw-r--r-- | test/functional/plugin/tutor_spec.lua | 95 | ||||
-rw-r--r-- | test/functional/ui/decorations_spec.lua | 15 | ||||
-rw-r--r-- | test/old/testdir/test_autocmd.vim | 60 |
19 files changed, 385 insertions, 131 deletions
diff --git a/runtime/autoload/tutor.vim b/runtime/autoload/tutor.vim index 80c09488d5..a546f7007e 100644 --- a/runtime/autoload/tutor.vim +++ b/runtime/autoload/tutor.vim @@ -220,6 +220,7 @@ function! tutor#TutorCmd(tutor_name) call tutor#SetupVim() exe "edit ".l:to_open + call tutor#ApplyTransform() endfunction function! tutor#TutorCmdComplete(lead,line,pos) @@ -227,3 +228,12 @@ function! tutor#TutorCmdComplete(lead,line,pos) let l:names = uniq(sort(map(l:tutors, 'fnamemodify(v:val, ":t:r")'), 's:Sort')) return join(l:names, "\n") endfunction + +function! tutor#ApplyTransform() + if has('win32') + sil! %s/{unix:(\(.\{-}\)),win:(\(.\{-}\))}/\2/g + else + sil! %s/{unix:(\(.\{-}\)),win:(\(.\{-}\))}/\1/g + endif + normal! gg0 +endfunction diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 766faee304..1eebd0bb18 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -1458,6 +1458,8 @@ nvim_set_hl({ns_id}, {name}, {*val}) *nvim_set_hl()* • cterm: cterm attribute map, like |highlight-args|. If not set, cterm attributes will match those from the attribute map documented above. + • force: if true force update the highlight group when it + exists. nvim_set_hl_ns({ns_id}) *nvim_set_hl_ns()* Set active namespace for highlights defined with |nvim_set_hl()|. This can diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 5c51fbd146..68ef54eb2f 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1866,6 +1866,8 @@ function vim.api.nvim_set_decoration_provider(ns_id, opts) end --- • cterm: cterm attribute map, like `highlight-args`. If not --- set, cterm attributes will match those from the attribute --- map documented above. +--- • force: if true force update the highlight group when it +--- exists. function vim.api.nvim_set_hl(ns_id, name, val) end --- Set active namespace for highlights defined with `nvim_set_hl()`. This can diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index b249f6629f..eaaa32d7b3 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -165,6 +165,7 @@ error('Cannot require a meta file') --- @field blend? integer --- @field fg_indexed? boolean --- @field bg_indexed? boolean +--- @field force? boolean --- @class vim.api.keyset.highlight_cterm --- @field bold? boolean diff --git a/runtime/tutor/en/vim-01-beginner.tutor b/runtime/tutor/en/vim-01-beginner.tutor index 71b196d189..2824f7ae83 100644 --- a/runtime/tutor/en/vim-01-beginner.tutor +++ b/runtime/tutor/en/vim-01-beginner.tutor @@ -629,7 +629,7 @@ NOTE: All `:`{vim} commands are executed when you press `<Enter>`{normal}. ** To save the changes made to the text, type `:w`{vim} FILENAME. ** - 1. Type `:!ls`{vim} to get a listing of your directory. + 1. Type `:!{unix:(ls),win:(dir)}`{vim} to get a listing of your directory. You already know you must hit `<Enter>`{normal} after this. 2. Choose a filename that does not exist yet, such as TEST. @@ -641,14 +641,14 @@ NOTE: All `:`{vim} commands are executed when you press `<Enter>`{normal}. (where TEST is the filename you chose.) 4. This saves the current file under the name TEST. - To verify this, type `:!ls`{vim} again to see your directory. + To verify this, type `:!{unix:(ls),win:(dir)}`{vim} again to see your directory. NOTE: If you were to exit Neovim and start it again with `nvim TEST`, the file would be an exact copy of the tutorial when you saved it. 5. Now remove the file by typing: ~~~ cmd - :!rm TEST + :!{unix:(rm),win:(del)} TEST ~~~ # Lesson 5.3: SELECTING TEXT TO WRITE @@ -675,7 +675,7 @@ NOTE: If you were to exit Neovim and start it again with `nvim TEST`, the file before you press `<Enter>`{normal}. - 5. Neovim will write the selected lines to the file TEST. Use `:!ls`{vim} to see it. + 5. Neovim will write the selected lines to the file TEST. Use `:!{unix:(ls),win:(dir)}`{vim} to see it. Do not remove it yet! We will use it in the next lesson. NOTE: Pressing [v](v) starts [Visual selection](visual-mode). You can move the cursor around to @@ -703,7 +703,7 @@ NOTE: After executing Step 2 you will see text from Lesson 5.3. Then move NOTE: You can also read the output of an external command. For example, - `:r !ls`{vim} + `:r !{unix:(ls),win:(dir)}`{vim} reads the output of the `ls` command and puts it below the cursor. @@ -712,8 +712,8 @@ NOTE: You can also read the output of an external command. For example, 1. [:!command](:!cmd) executes an external command. Some useful examples are: - `:!ls`{vim} - shows a directory listing - `:!rm FILENAME`{vim} - removes file FILENAME + `:!{unix:(ls ),win:(dir)}`{vim} - shows a directory listing + `:!{unix:(rm ),win:(del)} FILENAME`{vim} - removes file FILENAME 2. [:w](:w) FILENAME writes the current Neovim file to disk with name FILENAME. @@ -724,7 +724,7 @@ NOTE: You can also read the output of an external command. For example, 4. [:r](:r) FILENAME retrieves disk file FILENAME and puts it below the cursor position. - 5. [:r !dir](:r!) reads the output of the dir command and + 5. {unix:([:r !ls](:r!) ),win:([:r !dir](:r!))} reads the output of the {unix:(ls),win:(dir)} command and puts it below the cursor position. # Lesson 6.1: THE OPEN COMMAND @@ -928,7 +928,7 @@ To start using more features create an "init.vim" file. ** Command line completion with `<C-d>`{normal} and `<Tab>`{normal}. ** - 1. List the contents of the current directory: `:!ls`{vim} + 1. List the contents of the current directory: `:!{unix:(ls),win:(dir)}`{vim} 2. Type the start of a command: `:e`{vim} diff --git a/src/nvim/api/keysets.h b/src/nvim/api/keysets.h index 736ca9ce07..236e75983e 100644 --- a/src/nvim/api/keysets.h +++ b/src/nvim/api/keysets.h @@ -169,6 +169,7 @@ typedef struct { Integer blend; Boolean fg_indexed; Boolean bg_indexed; + Boolean force; } Dict(highlight); typedef struct { diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 78396edef5..00641c633d 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -151,6 +151,7 @@ Dictionary nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena *arena, E /// - cterm: cterm attribute map, like |highlight-args|. If not set, /// cterm attributes will match those from the attribute map /// documented above. +/// - force: if true force update the highlight group when it exists. /// @param[out] err Error details, if any /// // TODO(bfredl): val should take update vs reset flag diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 7a3e65e10e..15fbf7df7b 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -354,6 +354,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) // Set last_changedtick to avoid triggering a TextChanged autocommand right // after it was added. curbuf->b_last_changedtick = buf_get_changedtick(curbuf); + curbuf->b_last_changedtick_i = buf_get_changedtick(curbuf); curbuf->b_last_changedtick_pum = buf_get_changedtick(curbuf); // require "!" to overwrite the file, because it wasn't read completely diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index ff0fca1a56..f267dbb2f1 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -418,10 +418,10 @@ struct file_buffer { /// This is a dictionary item used to store b:changedtick. ChangedtickDictItem changedtick_di; - varnumber_T b_last_changedtick; // b:changedtick when TextChanged or - // TextChangedI was last triggered. - varnumber_T b_last_changedtick_pum; // b:changedtick when TextChangedP was + varnumber_T b_last_changedtick; // b:changedtick when TextChanged was // last triggered. + varnumber_T b_last_changedtick_i; // b:changedtick for TextChangedI + varnumber_T b_last_changedtick_pum; // b:changedtick for TextChangedP bool b_saving; // Set to true if we are in the middle of // saving the buffer. diff --git a/src/nvim/bufwrite.c b/src/nvim/bufwrite.c index 0c95314c52..2f13586dcc 100644 --- a/src/nvim/bufwrite.c +++ b/src/nvim/bufwrite.c @@ -1797,8 +1797,8 @@ restore_backup: unchanged(buf, true, false); const varnumber_T changedtick = buf_get_changedtick(buf); if (buf->b_last_changedtick + 1 == changedtick) { - // b:changedtick may be incremented in unchanged() but that - // should not trigger a TextChanged event. + // b:changedtick may be incremented in unchanged() but that should not + // trigger a TextChanged event. buf->b_last_changedtick = changedtick; } u_unchanged(buf); diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 1e5798db32..9da421e79b 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -207,6 +207,16 @@ static void margin_columns_win(win_T *wp, int *left_col, int *right_col) prev_col_off = cur_col_off; } +/// If one half of a double-width char will be overwritten, +/// change the other half to a space so that grid redraws properly. +static void line_check_overwrite(schar_T *dest, int cells, int maxcells, bool rl) +{ + assert(cells > 0); + if (cells < maxcells && dest[rl ? -cells + 1 : cells] == 0) { + dest[rl ? -cells : cells] = schar_from_ascii(' '); + } +} + /// Put a single char from an UTF-8 buffer into a line buffer. /// /// Handles composing chars and arabic shaping state. @@ -216,12 +226,17 @@ static int line_putchar(buf_T *buf, LineState *s, schar_T *dest, int maxcells, b int cells = utf_ptr2cells(p); int c_len = utfc_ptr2len(p); int u8c, u8cc[MAX_MCO]; + assert(maxcells > 0); if (cells > maxcells) { return -1; } u8c = utfc_ptr2char(p, u8cc); if (*p == TAB) { cells = MIN(tabstop_padding(vcol, buf->b_p_ts, buf->b_p_vts_array), maxcells); + } + + line_check_overwrite(dest, cells, maxcells, rl); + if (*p == TAB) { for (int c = 0; c < cells; c++) { dest[rl ? -c : c] = schar_from_ascii(' '); } @@ -304,8 +319,9 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int kv_push(win_extmark_arr, m); } if (kv_size(item->decor.virt_text)) { + int vcol = wp->w_p_rl ? col_off - item->draw_col : item->draw_col - col_off; col = draw_virt_text_item(buf, item->draw_col, item->decor.virt_text, - item->decor.hl_mode, max_col, item->draw_col - col_off, wp->w_p_rl); + item->decor.hl_mode, max_col, vcol, wp->w_p_rl); } item->draw_col = INT_MIN; // deactivate if (item->decor.virt_text_pos == kVTEndOfLine && do_eol) { @@ -356,13 +372,15 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, attr = virt_attr; } schar_T dummy[2]; - bool rl_overwrote_double_width = linebuf_char[col] == 0; + int maxcells = rl ? col - max_col : max_col - col; int cells = line_putchar(buf, &s, through ? dummy : &linebuf_char[col], - rl ? col - max_col : max_col - col, rl, vcol); + maxcells, rl, vcol); // If we failed to emit a char, we still need to put a space and advance. if (cells < 1) { - linebuf_char[col] = schar_from_ascii(' '); + assert(!through); cells = 1; + line_check_overwrite(&linebuf_char[col], cells, maxcells, rl); + linebuf_char[col] = schar_from_ascii(' '); } for (int c = 0; c < cells; c++) { linebuf_attr[col] = attr; @@ -372,13 +390,6 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, col++; } } - // If one half of a double-width char is overwritten, - // change the other half to a space so that grid redraws properly, - // but don't advance the current column. - if ((rl && col > max_col && rl_overwrote_double_width) - || (!rl && col < max_col && linebuf_char[col] == 0)) { - linebuf_char[col] = schar_from_ascii(' '); - } vcol += cells; } return col; diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 520d3bc2b3..8def1bf35d 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -878,6 +878,10 @@ static int insert_handle_key(InsertState *s) case K_EVENT: // some event state_handle_k_event(); + // If CTRL-G U was used apply it to the next typed key. + if (dont_sync_undo == kTrue) { + dont_sync_undo = kNone; + } goto check_pum; case K_COMMAND: // <Cmd>command<CR> @@ -1306,9 +1310,9 @@ void ins_redraw(bool ready) last_cursormoved = curwin->w_cursor; } - // Trigger TextChangedI if changedtick differs. + // Trigger TextChangedI if changedtick_i differs. if (ready && has_event(EVENT_TEXTCHANGEDI) - && curbuf->b_last_changedtick != buf_get_changedtick(curbuf) + && curbuf->b_last_changedtick_i != buf_get_changedtick(curbuf) && !pum_visible()) { aco_save_T aco; varnumber_T tick = buf_get_changedtick(curbuf); @@ -1317,16 +1321,16 @@ void ins_redraw(bool ready) aucmd_prepbuf(&aco, curbuf); apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, false, curbuf); aucmd_restbuf(&aco); - curbuf->b_last_changedtick = buf_get_changedtick(curbuf); + curbuf->b_last_changedtick_i = buf_get_changedtick(curbuf); if (tick != buf_get_changedtick(curbuf)) { // see ins_apply_autocmds() u_save(curwin->w_cursor.lnum, (linenr_T)(curwin->w_cursor.lnum + 1)); } } - // Trigger TextChangedP if changedtick differs. When the popupmenu closes - // TextChangedI will need to trigger for backwards compatibility, thus use - // different b_last_changedtick* variables. + // Trigger TextChangedP if changedtick_pum differs. When the popupmenu + // closes TextChangedI will need to trigger for backwards compatibility, + // thus use different b_last_changedtick* variables. if (ready && has_event(EVENT_TEXTCHANGEDP) && curbuf->b_last_changedtick_pum != buf_get_changedtick(curbuf) && pum_visible()) { diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index 84cf19ba69..eeed58a9ab 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -799,11 +799,10 @@ int lookup_color(const int idx, const bool foreground, TriState *const boldp) void set_hl_group(int id, HlAttrs attrs, Dict(highlight) *dict, int link_id) { int idx = id - 1; // Index is ID minus one. - bool is_default = attrs.rgb_ae_attr & HL_DEFAULT; // Return if "default" was used and the group already has settings - if (is_default && hl_has_settings(idx, true)) { + if (is_default && hl_has_settings(idx, true) && !dict->force) { return; } diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua index 5d6aaa57e6..1a054741ef 100644 --- a/test/functional/api/highlight_spec.lua +++ b/test/functional/api/highlight_spec.lua @@ -625,4 +625,15 @@ describe('API: get highlight', function() eq('FooBarA xxx cterm=bold,italic guifg=#ffffff', exec_capture('highlight FooBarA')) end) + + it('can override exist highlight group by force #20323', function() + local white = tonumber('ffffff', 16) + local green = tonumber('00ff00', 16) + meths.set_hl(0, 'Foo', { fg=white }) + meths.set_hl(0, 'Foo', { fg=green, force = true }) + eq({ fg = green },meths.get_hl(0, {name = 'Foo'})) + meths.set_hl(0, 'Bar', {link = 'Comment', default = true}) + meths.set_hl(0, 'Bar', {link = 'Foo',default = true, force = true}) + eq({link ='Foo', default = true}, meths.get_hl(0, {name = 'Bar'})) + end) end) diff --git a/test/functional/autocmd/textchanged_spec.lua b/test/functional/autocmd/textchanged_spec.lua new file mode 100644 index 0000000000..ffeb76835d --- /dev/null +++ b/test/functional/autocmd/textchanged_spec.lua @@ -0,0 +1,150 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear = helpers.clear +local exec = helpers.exec +local command = helpers.command +local feed = helpers.feed +local eq = helpers.eq +local eval = helpers.eval +local poke_eventloop = helpers.poke_eventloop + +before_each(clear) + +-- oldtest: Test_ChangedP() +it('TextChangedI and TextChangedP autocommands', function() + -- The oldtest uses feedkeys() with 'x' flag, which never triggers TextChanged. + -- So don't add TextChanged autocommand here. + exec([[ + call setline(1, ['foo', 'bar', 'foobar']) + set complete=. completeopt=menuone + au! TextChangedI <buffer> let g:autocmd ..= 'I' + au! TextChangedP <buffer> let g:autocmd ..= 'P' + call cursor(3, 1) + ]]) + + command([[let g:autocmd = '']]) + feed('o') + poke_eventloop() + feed('<esc>') + eq('I', eval('g:autocmd')) + + command([[let g:autocmd = '']]) + feed('S') + poke_eventloop() + feed('f') + poke_eventloop() + eq('II', eval('g:autocmd')) + feed('<esc>') + + command([[let g:autocmd = '']]) + feed('S') + poke_eventloop() + feed('f') + poke_eventloop() + feed('<C-N>') + poke_eventloop() + eq('IIP', eval('g:autocmd')) + feed('<esc>') + + command([[let g:autocmd = '']]) + feed('S') + poke_eventloop() + feed('f') + poke_eventloop() + feed('<C-N>') + poke_eventloop() + feed('<C-N>') + poke_eventloop() + eq('IIPP', eval('g:autocmd')) + feed('<esc>') + + command([[let g:autocmd = '']]) + feed('S') + poke_eventloop() + feed('f') + poke_eventloop() + feed('<C-N>') + poke_eventloop() + feed('<C-N>') + poke_eventloop() + feed('<C-N>') + poke_eventloop() + eq('IIPPP', eval('g:autocmd')) + feed('<esc>') + + command([[let g:autocmd = '']]) + feed('S') + poke_eventloop() + feed('f') + poke_eventloop() + feed('<C-N>') + poke_eventloop() + feed('<C-N>') + poke_eventloop() + feed('<C-N>') + poke_eventloop() + feed('<C-N>') + eq('IIPPPP', eval('g:autocmd')) + feed('<esc>') + + eq({'foo', 'bar', 'foobar', 'foo'}, eval('getline(1, "$")')) +end) + +-- oldtest: Test_TextChangedI_with_setline() +it('TextChangedI with setline()', function() + exec([[ + let g:setline_handled = v:false + func SetLineOne() + if !g:setline_handled + call setline(1, "(x)") + let g:setline_handled = v:true + endif + endfunc + autocmd TextChangedI <buffer> call SetLineOne() + ]]) + + feed('i') + poke_eventloop() + feed('(') + poke_eventloop() + feed('<CR>') + poke_eventloop() + feed('<Esc>') + eq('(', eval('getline(1)')) + eq('x)', eval('getline(2)')) + command('undo') + eq('', eval('getline(1)')) + eq('', eval('getline(2)')) +end) + +-- oldtest: Test_Changed_ChangedI() +it('TextChanged is triggerd after TextChangedI', function() + exec([[ + let [g:autocmd_i, g:autocmd_n] = ['',''] + + func! TextChangedAutocmdI(char) + let g:autocmd_{tolower(a:char)} = a:char .. b:changedtick + endfunc + + augroup Test_TextChanged + au! + au TextChanged <buffer> :call TextChangedAutocmdI('N') + au TextChangedI <buffer> :call TextChangedAutocmdI('I') + augroup END + ]]) + + feed('i') + poke_eventloop() + feed('f') + poke_eventloop() + feed('o') + poke_eventloop() + feed('o') + poke_eventloop() + feed('<esc>') + eq('N5', eval('g:autocmd_n')) + eq('I5', eval('g:autocmd_i')) + + command([[call feedkeys("yyp", 'tnix')]]) + eq('N6', eval('g:autocmd_n')) + eq('I5', eval('g:autocmd_i')) +end) diff --git a/test/functional/editor/completion_spec.lua b/test/functional/editor/completion_spec.lua index dcd7ef720f..8c299636cc 100644 --- a/test/functional/editor/completion_spec.lua +++ b/test/functional/editor/completion_spec.lua @@ -1032,93 +1032,6 @@ describe('completion', function() ]]) end) - -- oldtest: Test_ChangedP() - it('TextChangedI and TextChangedP autocommands', function() - curbufmeths.set_lines(0, 1, false, { 'foo', 'bar', 'foobar'}) - source([[ - set complete=. completeopt=menuone - let g:foo = [] - autocmd! TextChanged * :call add(g:foo, "N") - autocmd! TextChangedI * :call add(g:foo, "I") - autocmd! TextChangedP * :call add(g:foo, "P") - call cursor(3, 1) - ]]) - - command('let g:foo = []') - feed('o') - poke_eventloop() - feed('<esc>') - eq({'I'}, eval('g:foo')) - - command('let g:foo = []') - feed('S') - poke_eventloop() - feed('f') - poke_eventloop() - eq({'I', 'I'}, eval('g:foo')) - feed('<esc>') - - command('let g:foo = []') - feed('S') - poke_eventloop() - feed('f') - poke_eventloop() - feed('<C-N>') - poke_eventloop() - eq({'I', 'I', 'P'}, eval('g:foo')) - feed('<esc>') - - command('let g:foo = []') - feed('S') - poke_eventloop() - feed('f') - poke_eventloop() - feed('<C-N>') - poke_eventloop() - feed('<C-N>') - poke_eventloop() - eq({'I', 'I', 'P', 'P'}, eval('g:foo')) - feed('<esc>') - - command('let g:foo = []') - feed('S') - poke_eventloop() - feed('f') - poke_eventloop() - feed('<C-N>') - poke_eventloop() - feed('<C-N>') - poke_eventloop() - feed('<C-N>') - poke_eventloop() - eq({'I', 'I', 'P', 'P', 'P'}, eval('g:foo')) - feed('<esc>') - - command('let g:foo = []') - feed('S') - poke_eventloop() - feed('f') - poke_eventloop() - feed('<C-N>') - poke_eventloop() - feed('<C-N>') - poke_eventloop() - feed('<C-N>') - poke_eventloop() - feed('<C-N>') - eq({'I', 'I', 'P', 'P', 'P', 'P'}, eval('g:foo')) - feed('<esc>') - - eq({'foo', 'bar', 'foobar', 'foo'}, eval('getline(1, "$")')) - - source([[ - au! TextChanged - au! TextChangedI - au! TextChangedP - set complete&vim completeopt&vim - ]]) - end) - it('CompleteChanged autocommand', function() curbufmeths.set_lines(0, 1, false, { 'foo', 'bar', 'foobar', ''}) source([[ diff --git a/test/functional/plugin/tutor_spec.lua b/test/functional/plugin/tutor_spec.lua new file mode 100644 index 0000000000..bd214e9c03 --- /dev/null +++ b/test/functional/plugin/tutor_spec.lua @@ -0,0 +1,95 @@ +local Screen = require('test.functional.ui.screen') +local helpers = require('test.functional.helpers')(after_each) +local clear = helpers.clear +local command = helpers.command +local feed = helpers.feed +local is_os = helpers.is_os + +describe(':Tutor', function() + local screen + + before_each(function() + clear({ args = { '--clean' } }) + command('set cmdheight=0') + command('Tutor') + screen = Screen.new(80, 30) + screen:set_default_attr_ids({ + [0] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray }, + [1] = { bold = true }, + [2] = { underline = true, foreground = tonumber('0x0088ff') }, + [3] = { foreground = Screen.colors.SlateBlue }, + [4] = { bold = true, foreground = Screen.colors.Brown }, + [5] = { bold = true, foreground = Screen.colors.Magenta1 }, + }) + screen:attach() + end) + + it('applies {unix:…,win:…} transform', function() + local expected = is_os('win') and [[ + {0: }^ | + {0: } 3. To verify that a file was retrieved, cursor back and notice that there | + {0: } are now two copies of Lesson 5.3, the original and the retrieved version. | + {0: } | + {0: }{1:NOTE}: You can also read the output of an external command. For example, | + {0: } | + {0: } :r {4:!}dir | + {0: } | + {0: } reads the output of the ls command and puts it below the cursor. | + {0: } | + {0: }{3:#}{5: Lesson 5 SUMMARY} | + {0: } | + {0: } 1. {2::!command} executes an external command. | + {0: } | + {0: } Some useful examples are: | + {0: } :{4:!}dir - shows a directory listing | + {0: } :{4:!}del FILENAME - removes file FILENAME | + {0: } | + {0: } 2. {2::w} FILENAME writes the current Neovim file to disk with | + {0: } name FILENAME. | + {0: } | + {0: } 3. {2:v} motion :w FILENAME saves the Visually selected lines in file | + {0: } FILENAME. | + {0: } | + {0: } 4. {2::r} FILENAME retrieves disk file FILENAME and puts it | + {0: } below the cursor position. | + {0: } | + {0: } 5. {2::r !dir} reads the output of the dir command and | + {0: } puts it below the cursor position. | + {0: } | + ]] or [[ + {0: }^ | + {0: } 3. To verify that a file was retrieved, cursor back and notice that there | + {0: } are now two copies of Lesson 5.3, the original and the retrieved version. | + {0: } | + {0: }{1:NOTE}: You can also read the output of an external command. For example, | + {0: } | + {0: } :r {4:!}ls | + {0: } | + {0: } reads the output of the ls command and puts it below the cursor. | + {0: } | + {0: }{3:#}{5: Lesson 5 SUMMARY} | + {0: } | + {0: } 1. {2::!command} executes an external command. | + {0: } | + {0: } Some useful examples are: | + {0: } :{4:!}ls - shows a directory listing | + {0: } :{4:!}rm FILENAME - removes file FILENAME | + {0: } | + {0: } 2. {2::w} FILENAME writes the current Neovim file to disk with | + {0: } name FILENAME. | + {0: } | + {0: } 3. {2:v} motion :w FILENAME saves the Visually selected lines in file | + {0: } FILENAME. | + {0: } | + {0: } 4. {2::r} FILENAME retrieves disk file FILENAME and puts it | + {0: } below the cursor position. | + {0: } | + {0: } 5. {2::r !ls} reads the output of the ls command and | + {0: } puts it below the cursor position. | + {0: } | + ]] + + feed(':700<CR>zt') + screen:expect(expected) + end) +end) diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index f378c50792..f535bdd1a6 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -1963,23 +1963,20 @@ describe('extmark decorations', function() it('works with double width char and rightleft', function() screen:try_resize(50, 3) - insert('abcdefghij口klmnop') + insert('abcdefghij口klmnopqrstu口vwx口yz') feed('0') command('set rightleft') screen:expect{grid=[[ - ponmlk口jihgfedcb^a| + zy口xwv口utsrqponmlk口jihgfedcb^a| {1: ~}| | ]]} meths.buf_set_extmark(0, ns, 0, 2, { virt_text = {{'overlayed', 'Underlined'}}, virt_text_pos = 'overlay' }) + meths.buf_set_extmark(0, ns, 0, 14, { virt_text = {{'古', 'Underlined'}}, virt_text_pos = 'overlay' }) + meths.buf_set_extmark(0, ns, 0, 20, { virt_text = {{'\t', 'Underlined'}}, virt_text_pos = 'overlay' }) + meths.buf_set_extmark(0, ns, 0, 29, { virt_text = {{'古', 'Underlined'}}, virt_text_pos = 'overlay' }) screen:expect{grid=[[ - ponmlk {28:deyalrevo}b^a| - {1: ~}| - | - ]]} - meths.buf_set_extmark(0, ns, 0, 15, { virt_text = {{'古', 'Underlined'}}, virt_text_pos = 'overlay' }) - screen:expect{grid=[[ - po{28:古}lk {28:deyalrevo}b^a| + zy {28:古}wv {28: }qpon{28:古}k {28:deyalrevo}b^a| {1: ~}| | ]]} diff --git a/test/old/testdir/test_autocmd.vim b/test/old/testdir/test_autocmd.vim index b3238e8214..d80c505d80 100644 --- a/test/old/testdir/test_autocmd.vim +++ b/test/old/testdir/test_autocmd.vim @@ -104,6 +104,22 @@ if has('timers') set updatetime& endfunc + func Test_cursorhold_insert_ctrl_g_U() + au CursorHoldI * : + set updatetime=20 + new + call timer_start(100, { -> feedkeys("\<Left>foo\<Esc>", 't') }) + call feedkeys("i()\<C-g>U", 'tx!') + sleep 200m + call assert_equal('(foo)', getline(1)) + undo + call assert_equal('', getline(1)) + + bwipe! + au! CursorHoldI + set updatetime& + endfunc + func Test_OptionSet_modeline() CheckFunction test_override call test_override('starting', 1) @@ -2442,7 +2458,7 @@ endfunc " Test TextChangedI and TextChangedP func Test_ChangedP() - throw 'Skipped: use test/functional/editor/completion_spec.lua' + throw 'Skipped: use test/functional/autocmd/textchanged_spec.lua' new call setline(1, ['foo', 'bar', 'foobar']) call test_override("char_avail", 1) @@ -2452,6 +2468,7 @@ func Test_ChangedP() let g:autocmd .= a:char endfunc + " TextChanged will not be triggered, only check that it isn't. au! TextChanged <buffer> :call TextChangedAutocmd('N') au! TextChangedI <buffer> :call TextChangedAutocmd('I') au! TextChangedP <buffer> :call TextChangedAutocmd('P') @@ -2505,7 +2522,7 @@ func SetLineOne() endfunc func Test_TextChangedI_with_setline() - CheckFunction test_override + throw 'Skipped: use test/functional/autocmd/textchanged_spec.lua' new call test_override('char_avail', 1) autocmd TextChangedI <buffer> call SetLineOne() @@ -3433,6 +3450,45 @@ func Test_autocmd_vimgrep() augroup END endfunc +" Test TextChangedI and TextChanged +func Test_Changed_ChangedI() + throw 'Skipped: use test/functional/autocmd/textchanged_spec.lua' + new + call test_override("char_avail", 1) + let [g:autocmd_i, g:autocmd_n] = ['',''] + + func! TextChangedAutocmdI(char) + let g:autocmd_{tolower(a:char)} = a:char .. b:changedtick + endfunc + + augroup Test_TextChanged + au! + au TextChanged <buffer> :call TextChangedAutocmdI('N') + au TextChangedI <buffer> :call TextChangedAutocmdI('I') + augroup END + + call feedkeys("ifoo\<esc>", 'tnix') + " TODO: Test test does not seem to trigger TextChanged autocommand, this + " requires running Vim in a terminal window. + " call assert_equal('N3', g:autocmd_n) + call assert_equal('I3', g:autocmd_i) + + call feedkeys("yyp", 'tnix') + " TODO: Test test does not seem to trigger TextChanged autocommand. + " call assert_equal('N4', g:autocmd_n) + call assert_equal('I3', g:autocmd_i) + + " CleanUp + call test_override("char_avail", 0) + au! TextChanged <buffer> + au! TextChangedI <buffer> + augroup! Test_TextChanged + delfu TextChangedAutocmdI + unlet! g:autocmd_i g:autocmd_n + + bw! +endfunc + func Test_closing_autocmd_window() let lines =<< trim END edit Xa.txt |