aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt5
-rw-r--r--cmake/RunTests.cmake4
-rw-r--r--runtime/autoload/dist/ft.vim17
-rw-r--r--runtime/autoload/health.vim36
-rw-r--r--runtime/doc/autocmd.txt12
-rw-r--r--runtime/doc/eval.txt8
-rw-r--r--runtime/doc/index.txt2
-rw-r--r--runtime/doc/intro.txt4
-rw-r--r--runtime/doc/options.txt1
-rw-r--r--runtime/doc/quickref.txt3
-rw-r--r--runtime/doc/repeat.txt6
-rw-r--r--runtime/doc/vim_diff.txt5
-rw-r--r--runtime/filetype.vim3
-rw-r--r--runtime/ftplugin/checkhealth.vim20
-rw-r--r--runtime/syntax/checkhealth.vim28
-rw-r--r--src/nvim/auevents.lua4
-rw-r--r--src/nvim/autocmd.c6
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/eval/funcs.c5
-rw-r--r--src/nvim/generators/gen_char_blob.lua8
-rw-r--r--src/nvim/globals.h1
-rw-r--r--src/nvim/normal.c21
-rw-r--r--src/nvim/ops.c21
-rw-r--r--src/nvim/testdir/test_ex_mode.vim2
-rw-r--r--src/nvim/testdir/test_filetype.vim40
-rw-r--r--src/nvim/testdir/test_substitute.vim2
-rw-r--r--src/nvim/testdir/test_timers.vim2
-rw-r--r--src/nvim/tui/tui.c43
-rw-r--r--test/README.md6
-rw-r--r--test/functional/autocmd/cursormoved_spec.lua8
-rw-r--r--test/functional/autocmd/recording_spec.lua52
-rw-r--r--test/functional/editor/macro_spec.lua27
-rw-r--r--test/functional/plugin/health_spec.lua6
-rw-r--r--test/functional/terminal/channel_spec.lua28
-rw-r--r--third-party/CMakeLists.txt4
-rw-r--r--third-party/cmake/BuildLuajit.cmake10
36 files changed, 349 insertions, 102 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2c2587ec0b..2ca2385d8f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -553,7 +553,10 @@ if(NOT WIN32)
endif()
endforeach()
elseif(LUA_PRG MATCHES "luajit")
- set(LUAC_PRG "${LUA_PRG} -b -s %s -" CACHE STRING "Format for compiling to Lua bytecode")
+ check_lua_module(${LUA_PRG} "jit.bcsave" LUAJIT_HAS_JIT_BCSAVE)
+ if(LUAJIT_HAS_JIT_BCSAVE)
+ set(LUAC_PRG "${LUA_PRG} -b -s %s -" CACHE STRING "Format for compiling to Lua bytecode")
+ endif()
endif()
endif()
diff --git a/cmake/RunTests.cmake b/cmake/RunTests.cmake
index e78392562f..3adbcbbfc5 100644
--- a/cmake/RunTests.cmake
+++ b/cmake/RunTests.cmake
@@ -46,6 +46,10 @@ if(DEFINED ENV{TEST_FILTER} AND NOT "$ENV{TEST_FILTER}" STREQUAL "")
list(APPEND BUSTED_ARGS --filter $ENV{TEST_FILTER})
endif()
+if(DEFINED ENV{TEST_FILTER_OUT} AND NOT "$ENV{TEST_FILTER_OUT}" STREQUAL "")
+ list(APPEND BUSTED_ARGS --filter-out $ENV{TEST_FILTER_OUT})
+endif()
+
# TMPDIR: use relative test path (for parallel test runs / isolation).
set(ENV{TMPDIR} "${BUILD_DIR}/Xtest_tmpdir/${TEST_PATH}")
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory $ENV{TMPDIR})
diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim
index a3db4ae87a..366d7b009d 100644
--- a/runtime/autoload/dist/ft.vim
+++ b/runtime/autoload/dist/ft.vim
@@ -811,6 +811,23 @@ func dist#ft#Redif()
endwhile
endfunc
+" This function is called for all files under */debian/patches/*, make sure not
+" to non-dep3patch files, such as README and other text files.
+func dist#ft#Dep3patch()
+ if expand('%:t') ==# 'series'
+ return
+ endif
+
+ for ln in getline(1, 100)
+ if ln =~# '^\%(Description\|Subject\|Origin\|Bug\|Forwarded\|Author\|From\|Reviewed-by\|Acked-by\|Last-Updated\|Applied-Upstream\):'
+ setf dep3patch
+ return
+ elseif ln =~# '^---'
+ " end of headers found. stop processing
+ return
+ endif
+ endfor
+endfunc
" Restore 'cpoptions'
let &cpo = s:cpo_save
diff --git a/runtime/autoload/health.vim b/runtime/autoload/health.vim
index 73c1459f86..1d462ad02c 100644
--- a/runtime/autoload/health.vim
+++ b/runtime/autoload/health.vim
@@ -1,27 +1,3 @@
-function! s:enhance_syntax() abort
- syntax case match
-
- syntax keyword healthError ERROR[:]
- \ containedin=markdownCodeBlock,mkdListItemLine
- highlight default link healthError Error
-
- syntax keyword healthWarning WARNING[:]
- \ containedin=markdownCodeBlock,mkdListItemLine
- highlight default link healthWarning WarningMsg
-
- syntax keyword healthSuccess OK[:]
- \ containedin=markdownCodeBlock,mkdListItemLine
- highlight default healthSuccess guibg=#5fff00 guifg=#080808 ctermbg=82 ctermfg=232
-
- syntax match healthHelp "|.\{-}|" contains=healthBar
- \ containedin=markdownCodeBlock,mkdListItemLine
- syntax match healthBar "|" contained conceal
- highlight default link healthHelp Identifier
-
- " We do not care about markdown syntax errors in :checkhealth output.
- highlight! link markdownError Normal
-endfunction
-
" Runs the specified healthchecks.
" Runs all discovered healthchecks if a:plugin_names is empty.
function! health#check(plugin_names) abort
@@ -29,13 +5,9 @@ function! health#check(plugin_names) abort
\ ? s:discover_healthchecks()
\ : s:get_healthcheck(a:plugin_names)
- tabnew
- setlocal wrap breakindent linebreak
- setlocal filetype=markdown
- setlocal conceallevel=2 concealcursor=nc
- setlocal keywordprg=:help
- let &l:iskeyword='!-~,^*,^|,^",192-255'
- call s:enhance_syntax()
+ " create scratch-buffer
+ execute 'tab sbuffer' nvim_create_buf(v:true, v:true)
+ setfiletype checkhealth
if empty(healthchecks)
call setline(1, 'ERROR: No healthchecks found.')
@@ -70,8 +42,6 @@ function! health#check(plugin_names) abort
" needed for plasticboy/vim-markdown, because it uses fdm=expr
normal! zR
- setlocal nomodified
- setlocal bufhidden=hide
redraw|echo ''
endfunction
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index 242631d98c..3df8d5ced4 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -828,6 +828,18 @@ RemoteReply When a reply from a Vim that functions as
SearchWrapped After making a search with |n| or |N| if the
search wraps around the document back to
the start/finish respectively.
+ *RecordingEnter*
+RecordingEnter When a macro starts recording.
+ The pattern is the current file name, and
+ |reg_recording()| is the current register that
+ is used.
+ *RecordingLeave*
+RecordingLeave When a macro stops recording.
+ The pattern is the current file name, and
+ |reg_recording()| is the recorded
+ register.
+ |reg_recorded()| is only updated after this
+ event.
*SessionLoadPost*
SessionLoadPost After loading the session file created using
the |:mksession| command.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 75b782fbff..aef303195d 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2588,6 +2588,7 @@ readdir({dir} [, {expr}]) List file names in {dir} selected by {expr}
readfile({fname} [, {type} [, {max}]])
List get list of lines from file {fname}
reg_executing() String get the executing register name
+reg_recorded() String get the last recorded register name
reg_recording() String get the recording register name
reltime([{start} [, {end}]]) List get time value
reltimefloat({time}) Float turn the time value into a Float
@@ -7201,7 +7202,7 @@ mode([expr]) Return a string that indicates the current mode.
Rvc Virtual Replace mode completion |compl-generic|
Rvx Virtual Replace mode |i_CTRL-X| completion
c Command-line editing
- cv Vim Ex mode |Q| or |gQ|
+ cv Vim Ex mode |gQ|
r Hit-enter prompt
rm The -- more -- prompt
r? A |:confirm| query of some sort
@@ -7825,6 +7826,11 @@ reg_executing() *reg_executing()*
Returns an empty string when no register is being executed.
See |@|.
+reg_recorded() *reg_recorded()*
+ Returns the single letter name of the last recorded register.
+ Returns an empty string string when nothing was recorded yet.
+ See |q| and |Q|.
+
reg_recording() *reg_recording()*
Returns the single letter name of the register being recorded.
Returns an empty string string when not recording. See |q|.
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt
index baa7bc1992..d8689e2c65 100644
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -339,7 +339,6 @@ tag char note action in Normal mode ~
insert text, repeat N times
|P| ["x]P 2 put the text [from register x] before the
cursor N times
-|Q| Q switch to "Ex" mode
|R| R 2 enter replace mode: overtype existing
characters, repeat the entered text N-1
times
@@ -401,6 +400,7 @@ tag char note action in Normal mode ~
|q| q{0-9a-zA-Z"} record typed characters into named register
{0-9a-zA-Z"} (uppercase to append)
|q| q (while recording) stops recording
+|Q| Q replay last recorded macro
|q:| q: edit : command-line in command-line window
|q/| q/ edit / command-line in command-line window
|q?| q? edit ? command-line in command-line window
diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt
index a89263861b..0e0156ac6b 100644
--- a/runtime/doc/intro.txt
+++ b/runtime/doc/intro.txt
@@ -563,8 +563,8 @@ The command CTRL-\ CTRL-G or <C-\><C-G> can be used to go to Insert mode when
make sure Vim is in the mode indicated by 'insertmode', without knowing in
what mode Vim currently is.
- *gQ* *Q* *mode-Ex* *Ex-mode* *Ex* *EX* *E501*
-Q or gQ Switch to Ex mode. This is like typing ":" commands
+ *gQ* *mode-Ex* *Ex-mode* *Ex* *EX* *E501*
+gQ Switch to Ex mode. This is like typing ":" commands
one after another, except:
- You don't have to keep pressing ":".
- The screen doesn't get updated after each command.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 097cd38400..b75dd78b57 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -953,7 +953,6 @@ A jump table for the options with a short description can be found at |Q_op|.
error Other Error occurred (e.g. try to join last line)
(mostly used in |Normal-mode| or |Cmdline-mode|).
esc hitting <Esc> in |Normal-mode|.
- ex In |Visual-mode|, hitting |Q| results in an error.
hangul Ignored.
insertmode Pressing <Esc> in 'insertmode'.
lang Calling the beep module for Lua/Mzscheme/TCL.
diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt
index 8cabf05053..a229c8742f 100644
--- a/runtime/doc/quickref.txt
+++ b/runtime/doc/quickref.txt
@@ -489,6 +489,7 @@ In Insert or Command-line mode:
|q| q{a-z} record typed characters into register {a-z}
|q| q{A-Z} record typed characters, appended to register {a-z}
|q| q stop recording
+|Q| Q replay last recorded macro
|@| N @{a-z} execute the contents of register {a-z} (N times)
|@@| N @@ repeat previous @{a-z} (N times)
|:@| :@{a-z} execute the contents of register {a-z} as an Ex
@@ -997,7 +998,7 @@ Short explanation of each option: *option-list*
|:version| :ve[rsion] show version information
|:normal| :norm[al][!] {commands}
execute Normal mode commands
-|Q| Q switch to "Ex" mode
+|gQ| gQ switch to "Ex" mode
|:redir| :redir >{file} redirect messages to {file}
|:silent| :silent[!] {command} execute {command} silently
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index 7e8d93aa71..c7481ad290 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -103,7 +103,7 @@ Which is two characters shorter!
When using "global" in Ex mode, a special case is using ":visual" as a
command. This will move to a matching line, go to Normal mode to let you
-execute commands there until you use |Q| to return to Ex mode. This will be
+execute commands there until you use |gQ| to return to Ex mode. This will be
repeated for each matching line. While doing this you cannot use ":global".
To abort this type CTRL-C twice.
@@ -147,6 +147,10 @@ q Stops recording.
*@@* *E748*
@@ Repeat the previous @{0-9a-z":*} [count] times.
+ *Q*
+Q Repeat the last recorded register [count] times.
+ See |reg_recorded()|.
+
*:@*
:[addr]@{0-9a-z".=*+} Execute the contents of register {0-9a-z".=*+} as an Ex
command. First set cursor at line [addr] (default is
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index bc59ea785e..4fcaf15717 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -180,6 +180,8 @@ Commands:
|:match| can be invoked before highlight group is defined
Events:
+ |RecordingEnter|
+ |RecordingLeave|
|SearchWrapped|
|Signal|
|TabNewEntered|
@@ -356,7 +358,8 @@ Motion:
The |jumplist| avoids useless/phantom jumps.
Normal commands:
- |Q| is the same as |gQ|
+ |Q| replays the last recorded macro instead of switching to Ex mode.
+ Instead |gQ| can be used to enter Ex mode.
Options:
'ttimeout', 'ttimeoutlen' behavior was simplified
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 6dfdbeb275..57aaeab766 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -486,6 +486,9 @@ au BufNewFile,BufRead dict.conf,.dictrc setf dictconf
" Dictd config
au BufNewFile,BufRead dictd*.conf setf dictdconf
+" DEP3 formatted patch files
+au BufNewFile,BufRead */debian/patches/* call dist#ft#Dep3patch()
+
" Diff files
au BufNewFile,BufRead *.diff,*.rej setf diff
au BufNewFile,BufRead *.patch
diff --git a/runtime/ftplugin/checkhealth.vim b/runtime/ftplugin/checkhealth.vim
new file mode 100644
index 0000000000..3d8e9ace1a
--- /dev/null
+++ b/runtime/ftplugin/checkhealth.vim
@@ -0,0 +1,20 @@
+" Vim filetype plugin
+" Language: Neovim checkhealth buffer
+" Last Change: 2021 Dec 15
+
+if exists("b:did_ftplugin")
+ finish
+endif
+
+runtime! ftplugin/markdown.vim ftplugin/markdown_*.vim ftplugin/markdown/*.vim
+
+setlocal wrap breakindent linebreak
+setlocal conceallevel=2 concealcursor=nc
+setlocal keywordprg=:help
+let &l:iskeyword='!-~,^*,^|,^",192-255'
+
+if exists("b:undo_ftplugin")
+ let b:undo_ftplugin .= "|setl wrap< bri< lbr< cole< cocu< kp< isk<"
+else
+ let b:undo_ftplugin = "setl wrap< bri< lbr< cole< cocu< kp< isk<"
+endif
diff --git a/runtime/syntax/checkhealth.vim b/runtime/syntax/checkhealth.vim
new file mode 100644
index 0000000000..dff880a0bc
--- /dev/null
+++ b/runtime/syntax/checkhealth.vim
@@ -0,0 +1,28 @@
+" Vim syntax file
+" Language: Neovim checkhealth buffer
+" Last Change: 2021 Dec 15
+
+if exists("b:current_syntax")
+ finish
+endif
+
+runtime! syntax/markdown.vim
+unlet! b:current_syntax
+
+syn case match
+
+" We do not care about markdown syntax errors
+syn clear markdownError
+
+syn keyword healthError ERROR[:] containedin=markdownCodeBlock,mkdListItemLine
+syn keyword healthWarning WARNING[:] containedin=markdownCodeBlock,mkdListItemLine
+syn keyword healthSuccess OK[:] containedin=markdownCodeBlock,mkdListItemLine
+syn match healthHelp "|.\{-}|" containedin=markdownCodeBlock,mkdListItemLine contains=healthBar
+syn match healthBar "|" contained conceal
+
+hi def link healthError Error
+hi def link healthWarning WarningMsg
+hi def healthSuccess guibg=#5fff00 guifg=#080808 ctermbg=82 ctermfg=232
+hi def link healthHelp Identifier
+
+let b:current_syntax = "checkhealth"
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index 6227b08b26..8fe623fc96 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -75,6 +75,8 @@ return {
'QuickFixCmdPost', -- after :make, :grep etc.
'QuickFixCmdPre', -- before :make, :grep etc.
'QuitPre', -- before :quit
+ 'RecordingEnter', -- when starting to record a macro
+ 'RecordingLeave', -- just before a macro stops recording
'RemoteReply', -- upon string reception from a remote vim
'SearchWrapped', -- after the search wrapped around
'SessionLoadPost', -- after loading a session file
@@ -131,6 +133,8 @@ return {
BufModifiedSet=true,
DiagnosticChanged=true,
DirChanged=true,
+ RecordingEnter=true,
+ RecordingLeave=true,
Signal=true,
TabClosed=true,
TabNew=true,
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 3780cad1d6..463bd5e0e6 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -932,6 +932,12 @@ static int do_autocmd_event(event_T event, char_u *pat, bool once, int nested, c
last_mode = get_mode();
}
+ // If the event is CursorMoved, update the last cursor position
+ // position to avoid immediately triggering the autocommand
+ if (event == EVENT_CURSORMOVED && !has_event(EVENT_CURSORMOVED)) {
+ curwin->w_last_cursormoved = curwin->w_cursor;
+ }
+
ap->cmds = NULL;
*prev_ap = ap;
last_autopat[(int)event] = ap;
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 9a76b67de6..9507a12a02 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -277,6 +277,7 @@ return {
readfile={args={1, 3}, base=1},
reg_executing={},
reg_recording={},
+ reg_recorded={},
reltime={args={0, 2}, base=1},
reltimefloat={args=1, base=1},
reltimestr={args=1, base=1},
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 5252c940f7..d43eeb4a15 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -7398,6 +7398,11 @@ static void f_reg_recording(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return_register(reg_recording, rettv);
}
+static void f_reg_recorded(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ return_register(reg_recorded, rettv);
+}
+
/// list2proftime - convert a List to proftime_T
///
/// @param arg The input list, must be of type VAR_LIST and have
diff --git a/src/nvim/generators/gen_char_blob.lua b/src/nvim/generators/gen_char_blob.lua
index 70c034abc5..3ec1ff2caf 100644
--- a/src/nvim/generators/gen_char_blob.lua
+++ b/src/nvim/generators/gen_char_blob.lua
@@ -28,6 +28,7 @@ local target = io.open(target_file, 'w')
target:write('#include <stdint.h>\n\n')
+local warn_on_missing_compiler = true
local varnames = {}
for argi = 2, #arg, 2 do
local source_file = arg[argi]
@@ -42,10 +43,11 @@ for argi = 2, #arg, 2 do
local output
if options.c then
local luac = os.getenv("LUAC_PRG")
- if luac then
+ if luac and luac ~= "" then
output = io.popen(luac:format(source_file), "r"):read("*a")
- else
- print("LUAC_PRG is undefined")
+ elseif warn_on_missing_compiler then
+ print("LUAC_PRG is missing, embedding raw source")
+ warn_on_missing_compiler = false
end
end
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index dfbc80066e..697d4b11a7 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -632,6 +632,7 @@ EXTERN bool ex_no_reprint INIT(=false); // No need to print after z or p.
EXTERN int reg_recording INIT(= 0); // register for recording or zero
EXTERN int reg_executing INIT(= 0); // register being executed or zero
+EXTERN int reg_recorded INIT(= 0); // last recorded register or zero
EXTERN int no_mapping INIT(= false); // currently no mapping allowed
EXTERN int no_zero_mapping INIT(= 0); // mapping zero not allowed
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 95a521c0d8..3246596f16 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -229,7 +229,7 @@ static const struct nv_cmd {
{ 'N', nv_next, 0, SEARCH_REV },
{ 'O', nv_open, 0, 0 },
{ 'P', nv_put, 0, 0 },
- { 'Q', nv_exmode, NV_NCW, 0 },
+ { 'Q', nv_regreplay, 0, 0 },
{ 'R', nv_Replace, 0, false },
{ 'S', nv_subst, NV_KEEPREG, 0 },
{ 'T', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD },
@@ -4028,15 +4028,18 @@ dozet:
/*
* "Q" command.
*/
-static void nv_exmode(cmdarg_T *cap)
+static void nv_regreplay(cmdarg_T *cap)
{
- /*
- * Ignore 'Q' in Visual mode, just give a beep.
- */
- if (VIsual_active) {
- vim_beep(BO_EX);
- } else if (!checkclearop(cap->oap)) {
- do_exmode();
+ if (checkclearop(cap->oap)) {
+ return;
+ }
+
+ while (cap->count1-- && !got_int) {
+ if (do_execreg(reg_recorded, false, false, false) == false) {
+ clearopbeep(cap->oap);
+ break;
+ }
+ line_breakcheck();
}
}
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 9bc63477e9..c6f9c5f04f 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -912,13 +912,14 @@ int do_record(int c)
showmode();
regname = c;
retval = OK;
- }
- } else { // stop recording
- /*
- * Get the recorded key hits. K_SPECIAL and CSI will be escaped, this
- * needs to be removed again to put it in a register. exec_reg then
- * adds the escaping back later.
- */
+ apply_autocmds(EVENT_RECORDINGENTER, NULL, NULL, false, curbuf);
+ }
+ } else { // stop recording
+ // Get the recorded key hits. K_SPECIAL and CSI will be escaped, this
+ // needs to be removed again to put it in a register. exec_reg then
+ // adds the escaping back later.
+ apply_autocmds(EVENT_RECORDINGLEAVE, NULL, NULL, false, curbuf);
+ reg_recorded = reg_recording;
reg_recording = 0;
if (ui_has(kUIMessages)) {
showmode();
@@ -932,10 +933,8 @@ int do_record(int c)
// Remove escaping for CSI and K_SPECIAL in multi-byte chars.
vim_unescape_csi(p);
- /*
- * We don't want to change the default register here, so save and
- * restore the current register name.
- */
+ // We don't want to change the default register here, so save and
+ // restore the current register name.
old_y_previous = y_previous;
retval = stuff_yank(regname, p);
diff --git a/src/nvim/testdir/test_ex_mode.vim b/src/nvim/testdir/test_ex_mode.vim
index 1c645ad0f8..92e0559618 100644
--- a/src/nvim/testdir/test_ex_mode.vim
+++ b/src/nvim/testdir/test_ex_mode.vim
@@ -85,7 +85,7 @@ endfunc
func Test_ex_mode_count_overflow()
" this used to cause a crash
let lines =<< trim END
- call feedkeys("\<Esc>Q\<CR>")
+ call feedkeys("\<Esc>gQ\<CR>")
v9|9silent! vi|333333233333y32333333%O
call writefile(['done'], 'Xdidexmode')
qall!
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index 7ed9c68c96..dbe0cd8388 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -1004,4 +1004,44 @@ func Test_fs_file()
filetype off
endfunc
+func Test_dep3patch_file()
+ filetype on
+
+ call assert_true(mkdir('debian/patches', 'p'))
+
+ " series files are not patches
+ call writefile(['Description: some awesome patch'], 'debian/patches/series')
+ split debian/patches/series
+ call assert_notequal('dep3patch', &filetype)
+ bwipe!
+
+ " diff/patch files without the right headers should still show up as ft=diff
+ call writefile([], 'debian/patches/foo.diff')
+ split debian/patches/foo.diff
+ call assert_equal('diff', &filetype)
+ bwipe!
+
+ " Files with the right headers are detected as dep3patch, even if they don't
+ " have a diff/patch extension
+ call writefile(['Subject: dep3patches'], 'debian/patches/bar')
+ split debian/patches/bar
+ call assert_equal('dep3patch', &filetype)
+ bwipe!
+
+ " Files in sub-directories are detected
+ call assert_true(mkdir('debian/patches/s390x', 'p'))
+ call writefile(['Subject: dep3patches'], 'debian/patches/s390x/bar')
+ split debian/patches/s390x/bar
+ call assert_equal('dep3patch', &filetype)
+ bwipe!
+
+ " The detection stops when seeing the "header end" marker
+ call writefile(['---', 'Origin: the cloud'], 'debian/patches/baz')
+ split debian/patches/baz
+ call assert_notequal('dep3patch', &filetype)
+ bwipe!
+
+ call delete('debian/patches', 'rf')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim
index 113c85acef..20b760ac15 100644
--- a/src/nvim/testdir/test_substitute.vim
+++ b/src/nvim/testdir/test_substitute.vim
@@ -137,7 +137,7 @@ func Test_substitute_repeat()
" This caused an invalid memory access.
split Xfile
s/^/x
- call feedkeys("Qsc\<CR>y", 'tx')
+ call feedkeys("gQsc\<CR>y", 'tx')
bwipe!
endfunc
diff --git a/src/nvim/testdir/test_timers.vim b/src/nvim/testdir/test_timers.vim
index 5cc0da2586..aae315b2c5 100644
--- a/src/nvim/testdir/test_timers.vim
+++ b/src/nvim/testdir/test_timers.vim
@@ -279,7 +279,7 @@ func Test_ex_mode()
endfunc
let timer = timer_start(40, function('g:Foo'), {'repeat':-1})
" This used to throw error E749.
- exe "normal Qsleep 100m\rvi\r"
+ exe "normal gQsleep 100m\rvi\r"
call timer_stop(timer)
endfunc
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index bb75286369..e7a60aca49 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -308,23 +308,39 @@ static void terminfo_start(UI *ui)
// Enable bracketed paste
unibi_out_ext(ui, data->unibi_ext.enable_bracketed_paste);
+ int ret;
uv_loop_init(&data->write_loop);
if (data->out_isatty) {
- uv_tty_init(&data->write_loop, &data->output_handle.tty, data->out_fd, 0);
+ ret = uv_tty_init(&data->write_loop, &data->output_handle.tty, data->out_fd, 0);
+ if (ret) {
+ ELOG("uv_tty_init failed: %s", uv_strerror(ret));
+ }
#ifdef WIN32
- uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_RAW);
+ ret = uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_RAW);
+ if (ret) {
+ ELOG("uv_tty_set_mode failed: %s", uv_strerror(ret));
+ }
#else
int retry_count = 10;
// A signal may cause uv_tty_set_mode() to fail (e.g., SIGCONT). Retry a
// few times. #12322
- while (uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_IO) == UV_EINTR
+ while ((ret = uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_IO)) == UV_EINTR
&& retry_count > 0) {
retry_count--;
}
+ if (ret) {
+ ELOG("uv_tty_set_mode failed: %s", uv_strerror(ret));
+ }
#endif
} else {
- uv_pipe_init(&data->write_loop, &data->output_handle.pipe, 0);
- uv_pipe_open(&data->output_handle.pipe, data->out_fd);
+ ret = uv_pipe_init(&data->write_loop, &data->output_handle.pipe, 0);
+ if (ret) {
+ ELOG("uv_pipe_init failed: %s", uv_strerror(ret));
+ }
+ ret = uv_pipe_open(&data->output_handle.pipe, data->out_fd);
+ if (ret) {
+ ELOG("uv_pipe_open failed: %s", uv_strerror(ret));
+ }
}
flush_buf(ui);
}
@@ -1086,8 +1102,14 @@ static void tui_mode_change(UI *ui, String mode, Integer mode_idx)
// after calling uv_tty_set_mode. So, set the mode of the TTY again here.
// #13073
if (data->is_starting && data->input.in_fd == STDERR_FILENO) {
- uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_NORMAL);
- uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_IO);
+ int ret = uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_NORMAL);
+ if (ret) {
+ ELOG("uv_tty_set_mode failed: %s", uv_strerror(ret));
+ }
+ ret = uv_tty_set_mode(&data->output_handle.tty, UV_TTY_MODE_IO);
+ if (ret) {
+ ELOG("uv_tty_set_mode failed: %s", uv_strerror(ret));
+ }
}
#endif
tui_set_mode(ui, (ModeShape)mode_idx);
@@ -2081,8 +2103,11 @@ static void flush_buf(UI *ui)
fwrite(bufs[i].base, bufs[i].len, 1, data->screenshot);
}
} else {
- uv_write(&req, STRUCT_CAST(uv_stream_t, &data->output_handle),
- bufs, (unsigned)(bufp - bufs), NULL);
+ int ret = uv_write(&req, STRUCT_CAST(uv_stream_t, &data->output_handle),
+ bufs, (unsigned)(bufp - bufs), NULL);
+ if (ret) {
+ ELOG("uv_write failed: %s", uv_strerror(ret));
+ }
uv_run(&data->write_loop, UV_RUN_DEFAULT);
}
data->bufpos = 0;
diff --git a/test/README.md b/test/README.md
index 37aa54c157..c6e173ead2 100644
--- a/test/README.md
+++ b/test/README.md
@@ -116,7 +116,7 @@ Filtering Tests
### Filter by name
-Another filter method is by setting a pattern of test name to `TEST_FILTER`.
+Another filter method is by setting a pattern of test name to `TEST_FILTER` or `TEST_FILTER_OUT`.
``` lua
it('foo api',function()
@@ -131,6 +131,10 @@ To run only test with filter name:
TEST_FILTER='foo.*api' make functionaltest
+To run all tests except ones matching a filter:
+
+ TEST_FILTER_OUT='foo.*api' make functionaltest
+
### Filter by file
To run a *specific* unit test:
diff --git a/test/functional/autocmd/cursormoved_spec.lua b/test/functional/autocmd/cursormoved_spec.lua
index d0f46e689b..9641d4b096 100644
--- a/test/functional/autocmd/cursormoved_spec.lua
+++ b/test/functional/autocmd/cursormoved_spec.lua
@@ -31,4 +31,12 @@ describe('CursorMoved', function()
eq({'aaa'}, funcs.nvim_buf_get_lines(eval('g:buf'), 0, -1, true))
eq(0, eval('g:cursormoved'))
end)
+
+ it("is not triggered by cursor movement prior to first CursorMoved instantiation", function()
+ source([[
+ let g:cursormoved = 0
+ autocmd CursorMoved * let g:cursormoved += 1
+ ]])
+ eq(0, eval('g:cursormoved'))
+ end)
end)
diff --git a/test/functional/autocmd/recording_spec.lua b/test/functional/autocmd/recording_spec.lua
new file mode 100644
index 0000000000..81152758de
--- /dev/null
+++ b/test/functional/autocmd/recording_spec.lua
@@ -0,0 +1,52 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local eq = helpers.eq
+local eval = helpers.eval
+local source_vim = helpers.source
+
+describe('RecordingEnter', function()
+ before_each(clear)
+ it('works', function()
+ source_vim [[
+ let g:recorded = 0
+ autocmd RecordingEnter * let g:recorded += 1
+ execute "normal! qqyyq"
+ ]]
+ eq(1, eval('g:recorded'))
+ end)
+
+ it('gives a correct reg_recording()', function()
+ source_vim [[
+ let g:recording = ''
+ autocmd RecordingEnter * let g:recording = reg_recording()
+ execute "normal! qqyyq"
+ ]]
+ eq('q', eval('g:recording'))
+ end)
+end)
+
+describe('RecordingLeave', function()
+ before_each(clear)
+ it('works', function()
+ source_vim [[
+ let g:recorded = 0
+ autocmd RecordingLeave * let g:recorded += 1
+ execute "normal! qqyyq"
+ ]]
+ eq(1, eval('g:recorded'))
+ end)
+
+ it('gives the correct reg_recorded()', function()
+ source_vim [[
+ let g:recorded = 'a'
+ let g:recording = ''
+ autocmd RecordingLeave * let g:recording = reg_recording()
+ autocmd RecordingLeave * let g:recorded = reg_recorded()
+ execute "normal! qqyyq"
+ ]]
+ eq('q', eval 'g:recording')
+ eq('', eval 'g:recorded')
+ eq('q', eval 'reg_recorded()')
+ end)
+end)
diff --git a/test/functional/editor/macro_spec.lua b/test/functional/editor/macro_spec.lua
index 102d8fc723..c0c9256af2 100644
--- a/test/functional/editor/macro_spec.lua
+++ b/test/functional/editor/macro_spec.lua
@@ -6,6 +6,8 @@ local feed = helpers.feed
local clear = helpers.clear
local expect = helpers.expect
local command = helpers.command
+local insert = helpers.insert
+local curbufmeths = helpers.curbufmeths
describe('macros', function()
before_each(clear)
@@ -27,4 +29,29 @@ describe('macros', function()
expect('llllll')
eq(eval('@i'), 'lxxx')
end)
+
+ it('can be replayed with Q', function()
+ insert [[hello
+hello
+hello]]
+ feed [[gg]]
+
+ feed [[qqAFOO<esc>q]]
+ eq({'helloFOO', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false))
+
+ feed[[Q]]
+ eq({'helloFOOFOO', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false))
+
+ feed[[G3Q]]
+ eq({'helloFOOFOO', 'hello', 'helloFOOFOOFOO'}, curbufmeths.get_lines(0, -1, false))
+ end)
+end)
+
+describe('reg_recorded()', function()
+ before_each(clear)
+
+ it('returns the correct value', function()
+ feed [[qqyyq]]
+ eq('q', eval('reg_recorded()'))
+ end)
end)
diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua
index b567b3e20c..37de5d0ce6 100644
--- a/test/functional/plugin/health_spec.lua
+++ b/test/functional/plugin/health_spec.lua
@@ -156,7 +156,7 @@ describe('health.vim', function()
test_plug.submodule_failed: require("test_plug.submodule_failed.health").check()
========================================================================
- ERROR: Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception:
- function health#check, line 24]])
+ function health#check, line 20]])
eq(expected, received)
end)
@@ -167,7 +167,7 @@ describe('health.vim', function()
broken: health#broken#check
========================================================================
- ERROR: Failed to run healthcheck for "broken" plugin. Exception:
- function health#check[24]..health#broken#check, line 1
+ function health#check[20]..health#broken#check, line 1
caused an error
]])
end)
@@ -186,7 +186,7 @@ describe('health.vim', function()
test_plug.submodule_failed: require("test_plug.submodule_failed.health").check()
========================================================================
- ERROR: Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception:
- function health#check, line 24]])
+ function health#check, line 20]])
eq(expected, received)
end)
diff --git a/test/functional/terminal/channel_spec.lua b/test/functional/terminal/channel_spec.lua
index 7d37dcccc8..7223f5ba61 100644
--- a/test/functional/terminal/channel_spec.lua
+++ b/test/functional/terminal/channel_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
local command = helpers.command
-local exc_exec = helpers.exc_exec
+local pcall_err = helpers.pcall_err
local feed = helpers.feed
local sleep = helpers.sleep
local poke_eventloop = helpers.poke_eventloop
@@ -13,24 +13,22 @@ describe('associated channel is closed and later freed for terminal', function()
it('opened by nvim_open_term() and deleted by :bdelete!', function()
command([[let id = nvim_open_term(0, {})]])
-- channel hasn't been freed yet
- eq("Vim(call):Can't send data to closed stream", exc_exec([[bdelete! | call chansend(id, 'test')]]))
- -- process free_channel_event
- poke_eventloop()
- -- channel has been freed
- eq("Vim(call):E900: Invalid channel id", exc_exec([[call chansend(id, 'test')]]))
+ eq("Vim(call):Can't send data to closed stream", pcall_err(command, [[bdelete! | call chansend(id, 'test')]]))
+ -- channel has been freed after one main loop iteration
+ eq("Vim(call):E900: Invalid channel id", pcall_err(command, [[call chansend(id, 'test')]]))
end)
it('opened by termopen(), exited, and deleted by pressing a key', function()
command([[let id = termopen('echo')]])
sleep(500)
-- process has exited
- eq("Vim(call):Can't send data to closed stream", exc_exec([[call chansend(id, 'test')]]))
+ eq("Vim(call):Can't send data to closed stream", pcall_err(command, [[call chansend(id, 'test')]]))
-- delete terminal
feed('i<CR>')
- -- process term_delayed_free and free_channel_event
+ -- need to first process input
poke_eventloop()
- -- channel has been freed
- eq("Vim(call):E900: Invalid channel id", exc_exec([[call chansend(id, 'test')]]))
+ -- channel has been freed after another main loop iteration
+ eq("Vim(call):E900: Invalid channel id", pcall_err(command, [[call chansend(id, 'test')]]))
end)
-- This indirectly covers #16264
@@ -38,12 +36,10 @@ describe('associated channel is closed and later freed for terminal', function()
command([[let id = termopen('echo')]])
sleep(500)
-- process has exited
- eq("Vim(call):Can't send data to closed stream", exc_exec([[call chansend(id, 'test')]]))
+ eq("Vim(call):Can't send data to closed stream", pcall_err(command, [[call chansend(id, 'test')]]))
-- channel hasn't been freed yet
- eq("Vim(call):Can't send data to closed stream", exc_exec([[bdelete | call chansend(id, 'test')]]))
- -- process term_delayed_free and free_channel_event
- poke_eventloop()
- -- channel has been freed
- eq("Vim(call):E900: Invalid channel id", exc_exec([[call chansend(id, 'test')]]))
+ eq("Vim(call):Can't send data to closed stream", pcall_err(command, [[bdelete | call chansend(id, 'test')]]))
+ -- channel has been freed after one main loop iteration
+ eq("Vim(call):E900: Invalid channel id", pcall_err(command, [[call chansend(id, 'test')]]))
end)
end)
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index c5adf36908..b0b91df791 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -151,8 +151,8 @@ set(MSGPACK_URL https://github.com/msgpack/msgpack-c/releases/download/cpp-3.0.0
set(MSGPACK_SHA256 bfbb71b7c02f806393bc3cbc491b40523b89e64f83860c58e3e54af47de176e4)
# https://github.com/LuaJIT/LuaJIT/tree/v2.1
-set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/b4b2dce9fc3ffaaaede39b36d06415311e2aa516.tar.gz)
-set(LUAJIT_SHA256 6c9e46877db2df16ca0fa76db4043ed30a1ae60c89d9ba2c3e4d35eb2360cd4d)
+set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/1d20f33d2905db55fb7191076bbac10f570f9175.tar.gz)
+set(LUAJIT_SHA256 4b6e2fc726ed8bf51fe461d90db9fffbc5c894bbdc862a67d17a70190f1fb07f)
set(LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz)
set(LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333)
diff --git a/third-party/cmake/BuildLuajit.cmake b/third-party/cmake/BuildLuajit.cmake
index c4e5112dce..e02d7fe609 100644
--- a/third-party/cmake/BuildLuajit.cmake
+++ b/third-party/cmake/BuildLuajit.cmake
@@ -124,7 +124,9 @@ elseif(MINGW)
COMMAND ${CMAKE_COMMAND} -E copy ${DEPS_BUILD_DIR}/src/luajit/src/libluajit.a ${DEPS_INSTALL_DIR}/lib
COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/include/luajit-2.1
COMMAND ${CMAKE_COMMAND} -DFROM_GLOB=${DEPS_BUILD_DIR}/src/luajit/src/*.h -DTO=${DEPS_INSTALL_DIR}/include/luajit-2.1 -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CopyFilesGlob.cmake
- )
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/bin/lua/jit
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPS_BUILD_DIR}/src/luajit/src/jit ${DEPS_INSTALL_DIR}/bin/lua/jit
+ )
elseif(MSVC)
BuildLuaJit(
@@ -138,8 +140,10 @@ elseif(MSVC)
# Luv searches for luajit.lib
COMMAND ${CMAKE_COMMAND} -E copy ${DEPS_BUILD_DIR}/src/luajit/src/lua51.lib ${DEPS_INSTALL_DIR}/lib/luajit.lib
COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/include/luajit-2.1
- COMMAND ${CMAKE_COMMAND} -DFROM_GLOB=${DEPS_BUILD_DIR}/src/luajit/src/*.h -DTO=${DEPS_INSTALL_DIR}/include/luajit-2.1 -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CopyFilesGlob.cmake)
-
+ COMMAND ${CMAKE_COMMAND} -DFROM_GLOB=${DEPS_BUILD_DIR}/src/luajit/src/*.h -DTO=${DEPS_INSTALL_DIR}/include/luajit-2.1 -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CopyFilesGlob.cmake
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/bin/lua/jit
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPS_BUILD_DIR}/src/luajit/src/jit ${DEPS_INSTALL_DIR}/bin/lua/jit
+ )
else()
message(FATAL_ERROR "Trying to build luajit in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}")
endif()