aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/autoload/tutor.vim10
-rw-r--r--runtime/doc/api.txt2
-rw-r--r--runtime/lua/vim/_meta/api.lua2
-rw-r--r--runtime/lua/vim/_meta/api_keysets.lua1
-rw-r--r--runtime/tutor/en/vim-01-beginner.tutor18
-rw-r--r--src/nvim/api/keysets.h1
-rw-r--r--src/nvim/api/vim.c1
-rw-r--r--src/nvim/buffer.c1
-rw-r--r--src/nvim/buffer_defs.h6
-rw-r--r--src/nvim/bufwrite.c4
-rw-r--r--src/nvim/drawline.c33
-rw-r--r--src/nvim/edit.c16
-rw-r--r--src/nvim/highlight_group.c3
-rw-r--r--test/functional/api/highlight_spec.lua11
-rw-r--r--test/functional/autocmd/textchanged_spec.lua150
-rw-r--r--test/functional/editor/completion_spec.lua87
-rw-r--r--test/functional/plugin/tutor_spec.lua95
-rw-r--r--test/functional/ui/decorations_spec.lua15
-rw-r--r--test/old/testdir/test_autocmd.vim60
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