aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/autocmd.txt2
-rw-r--r--runtime/doc/eval.txt6
-rw-r--r--runtime/syntax/vim.vim2
-rw-r--r--src/nvim/eval.c31
-rw-r--r--src/nvim/fileio.c13
-rw-r--r--src/nvim/globals.h8
-rw-r--r--src/nvim/macros.h6
-rw-r--r--src/nvim/normal.c2
-rw-r--r--src/nvim/ops.c64
-rw-r--r--src/nvim/os/input.c4
-rw-r--r--src/nvim/terminal.c3
-rw-r--r--test/functional/clipboard/clipboard_provider_spec.lua14
-rw-r--r--test/functional/job/job_spec.lua49
-rw-r--r--third-party/cmake/BuildLuarocks.cmake1
-rw-r--r--third-party/utfTerminalDetailed.lua27
15 files changed, 151 insertions, 81 deletions
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index 1393131ab7..f771c225f4 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -791,7 +791,7 @@ ShellCmdPost After executing a shell command with |:!cmd|,
|:make| and |:grep|. Can be used to check for
any changed files.
For non-blocking shell commands, see
- |JobActivity|.
+ |job-control|.
*ShellFilterPost*
ShellFilterPost After executing a shell command with
":{range}!cmd", ":w !cmd" or ":r !cmd".
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 6215756f08..fc4bebbd6e 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -4059,9 +4059,9 @@ jobstop({job}) {Nvim} *jobstop()*
Stop a job created with |jobstart()| by sending a `SIGTERM`
to the corresponding process. If the process doesn't exit
cleanly soon, a `SIGKILL` will be sent. When the job is
- finally closed, a |JobActivity| event will trigger with
- `v:job_data[0]` set to `exited`. See |job-control| for more
- information.
+ finally closed, the exit handler provided to |jobstart()| or
+ |termopen()| will be run.
+ See |job-control| for more information.
jobwait({ids}[, {timeout}]) {Nvim} *jobwait()*
Wait for a set of jobs to finish. The {ids} argument is a list
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index 0842e53492..aadc3371f3 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -62,7 +62,7 @@ syn keyword vimErrSetting contained hardtabs ht w1200 w300 w9600
" AutoCmd Events {{{2
syn case ignore
-syn keyword vimAutoEvent contained BufAdd BufCreate BufDelete BufEnter BufFilePost BufFilePre BufHidden BufLeave BufNew BufNewFile BufRead BufReadCmd BufReadPost BufReadPre BufUnload BufWinEnter BufWinLeave BufWipeout BufWrite BufWriteCmd BufWritePost BufWritePre Cmd-event CmdwinEnter CmdwinLeave ColorScheme CompleteDone CursorHold CursorHoldI CursorMoved CursorMovedI EncodingChanged FileAppendCmd FileAppendPost FileAppendPre FileChangedRO FileChangedShell FileChangedShellPost FileEncoding FileReadCmd FileReadPost FileReadPre FileType FileWriteCmd FileWritePost FileWritePre FilterReadPost FilterReadPre FilterWritePost FilterWritePre FocusGained FocusLost FuncUndefined GUIEnter GUIFailed InsertChange InsertCharPre InsertEnter InsertLeave JobActivity MenuPopup QuickFixCmdPost QuickFixCmdPre QuitPre RemoteReply SessionLoadPost ShellCmdPost ShellFilterPost SourceCmd SourcePre SpellFileMissing StdinReadPost StdinReadPre SwapExists Syntax TabEnter TabLeave TabNew TabNewEntered TabClosed TermChanged TermResponse TextChanged TextChangedI User UserGettingBored VimEnter VimLeave VimLeavePre VimResized WinEnter WinLeave
+syn keyword vimAutoEvent contained BufAdd BufCreate BufDelete BufEnter BufFilePost BufFilePre BufHidden BufLeave BufNew BufNewFile BufRead BufReadCmd BufReadPost BufReadPre BufUnload BufWinEnter BufWinLeave BufWipeout BufWrite BufWriteCmd BufWritePost BufWritePre Cmd-event CmdwinEnter CmdwinLeave ColorScheme CompleteDone CursorHold CursorHoldI CursorMoved CursorMovedI EncodingChanged FileAppendCmd FileAppendPost FileAppendPre FileChangedRO FileChangedShell FileChangedShellPost FileEncoding FileReadCmd FileReadPost FileReadPre FileType FileWriteCmd FileWritePost FileWritePre FilterReadPost FilterReadPre FilterWritePost FilterWritePre FocusGained FocusLost FuncUndefined GUIEnter GUIFailed InsertChange InsertCharPre InsertEnter InsertLeave MenuPopup QuickFixCmdPost QuickFixCmdPre QuitPre RemoteReply SessionLoadPost ShellCmdPost ShellFilterPost SourceCmd SourcePre SpellFileMissing StdinReadPost StdinReadPre SwapExists Syntax TabEnter TabLeave TabNew TabNewEntered TabClosed TermChanged TermResponse TextChanged TextChangedI User UserGettingBored VimEnter VimLeave VimLeavePre VimResized WinEnter WinLeave
" Highlight commonly used Groupnames {{{2
syn keyword vimGroup contained Comment Constant String Character Number Boolean Float Identifier Function Statement Conditional Repeat Label Operator Keyword Exception PreProc Include Define Macro PreCondit Type StorageClass Structure Typedef Special SpecialChar Tag Delimiter SpecialComment Debug Underlined Ignore Error Todo
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 90ab471818..a3ef24f295 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -472,7 +472,7 @@ typedef struct {
#define JobEventFreer(x)
KMEMPOOL_INIT(JobEventPool, JobEvent, JobEventFreer)
static kmempool_t(JobEventPool) *job_event_pool = NULL;
-static bool defer_job_callbacks = true;
+static int disable_job_defer = 0;
/*
* Initialize the global and v: variables.
@@ -5963,11 +5963,12 @@ static bool get_dict_callback(dict_T *d, char *key, ufunc_T **result)
uint8_t *name = di->di_tv.vval.v_string;
uint8_t *n = name;
- ufunc_T *rv;
+ ufunc_T *rv = NULL;
if (*n > '9' || *n < '0') {
- n = trans_function_name(&n, false, TFN_INT|TFN_QUIET, NULL);
- rv = find_func(n);
- free(n);
+ if ((n = trans_function_name(&n, false, TFN_INT|TFN_QUIET, NULL))) {
+ rv = find_func(n);
+ free(n);
+ }
} else {
// dict function, name is already translated
rv = find_func(n);
@@ -10921,9 +10922,16 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv)
list_T *args = argvars[0].vval.v_list;
list_T *rv = list_alloc();
- // must temporarily disable job event deferring so the callbacks are
- // processed while waiting.
- defer_job_callbacks = false;
+ ui_busy_start();
+ // disable breakchecks, which could result in job callbacks being executed
+ // at unexpected places
+ disable_breakcheck++;
+ // disable job event deferring so the callbacks are processed while waiting.
+ if (!disable_job_defer++) {
+ // process any pending job events in the deferred queue, but only do this if
+ // deferred is not disabled(at the top-level `jobwait()` call)
+ event_process();
+ }
// For each item in the input list append an integer to the output list. -3
// is used to represent an invalid job id, -2 is for a interrupted job and
// -1 for jobs that were skipped or timed out.
@@ -10996,8 +11004,9 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv)
// job exits
data->status_ptr = NULL;
}
- // restore defer flag
- defer_job_callbacks = true;
+ disable_job_defer--;
+ disable_breakcheck--;
+ ui_busy_stop();
rv->lv_refcount++;
rettv->v_type = VAR_LIST;
@@ -20175,7 +20184,7 @@ static inline void push_job_event(Job *job, ufunc_T *callback,
event_push((Event) {
.handler = on_job_event,
.data = event_data
- }, defer_job_callbacks);
+ }, !disable_job_defer);
}
static void on_job_stdout(RStream *rstream, void *job, bool eof)
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 9e2707ffda..233a7d4aac 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -6584,16 +6584,15 @@ apply_autocmds_group (
fname = vim_strsave(fname); /* make a copy, so we can change it */
} else {
sfname = vim_strsave(fname);
- /* Don't try expanding FileType, Syntax, FuncUndefined, WindowID,
- * ColorScheme, QuickFixCmd or JobActivity */
- if (event == EVENT_FILETYPE
- || event == EVENT_SYNTAX
+ // don't try expanding the following events
+ if (event == EVENT_COLORSCHEME
+ || event == EVENT_FILETYPE
|| event == EVENT_FUNCUNDEFINED
+ || event == EVENT_QUICKFIXCMDPOST
+ || event == EVENT_QUICKFIXCMDPRE
|| event == EVENT_REMOTEREPLY
|| event == EVENT_SPELLFILEMISSING
- || event == EVENT_QUICKFIXCMDPRE
- || event == EVENT_COLORSCHEME
- || event == EVENT_QUICKFIXCMDPOST
+ || event == EVENT_SYNTAX
|| event == EVENT_TABCLOSED)
fname = vim_strsave(fname);
else
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 158125c878..9eb70d37df 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -898,6 +898,14 @@ EXTERN FILE *scriptout INIT(= NULL); /* stream to write script to */
/* volatile because it is used in signal handler catch_sigint(). */
EXTERN volatile int got_int INIT(= FALSE); /* set to TRUE when interrupt
signal occurred */
+EXTERN int disable_breakcheck INIT(= 0); // > 0 if breakchecks should be
+ // ignored. FIXME(tarruda): Hacky
+ // way to run functions that would
+ // result in *_breakcheck calls
+ // while events that would normally
+ // be deferred are being processed
+ // immediately. Ref:
+ // neovim/neovim#2371
EXTERN int bangredo INIT(= FALSE); /* set to TRUE with ! command */
EXTERN int searchcmdlen; /* length of previous search cmd */
EXTERN int reg_do_extmatch INIT(= 0); /* Used when compiling regexp:
diff --git a/src/nvim/macros.h b/src/nvim/macros.h
index 93812683d6..e14e998e7a 100644
--- a/src/nvim/macros.h
+++ b/src/nvim/macros.h
@@ -59,12 +59,12 @@
/* Use our own isdigit() replacement, because on MS-Windows isdigit() returns
* non-zero for superscript 1. Also avoids that isdigit() crashes for numbers
* below 0 and above 255. */
-#define VIM_ISDIGIT(c) ((unsigned)(c) - '0' < 10)
+#define VIM_ISDIGIT(c) ((unsigned)(c) >= '0' && (unsigned)(c) <= '9')
/* Like isalpha() but reject non-ASCII characters. Can't be used with a
* special key (negative value). */
-# define ASCII_ISLOWER(c) ((unsigned)(c) - 'a' < 26)
-# define ASCII_ISUPPER(c) ((unsigned)(c) - 'A' < 26)
+# define ASCII_ISLOWER(c) ((unsigned)(c) >= 'a' && (unsigned)(c) <= 'z')
+# define ASCII_ISUPPER(c) ((unsigned)(c) >= 'A' && (unsigned)(c) <= 'Z')
# define ASCII_ISALPHA(c) (ASCII_ISUPPER(c) || ASCII_ISLOWER(c))
# define ASCII_ISALNUM(c) (ASCII_ISALPHA(c) || VIM_ISDIGIT(c))
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index be52d6294a..4fcf6f9594 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -914,7 +914,7 @@ getcount:
&& !oap->op_type
&& (idx < 0 || !(nv_cmds[idx].cmd_flags & NV_KEEPREG))) {
clearop(oap);
- set_reg_var(0);
+ set_reg_var(get_default_register_name());
}
/* Get the length of mapped chars again after typing a count, second
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 4c5a002f81..6c67063739 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -79,7 +79,7 @@ static struct yankreg {
} y_regs[NUM_REGISTERS];
static struct yankreg *y_current; /* ptr to current yankreg */
-static int y_append; /* TRUE when appending */
+static bool y_append; /* true when appending */
static struct yankreg *y_previous = NULL; /* ptr to last written yankreg */
static bool clipboard_didwarn_unnamed = false;
@@ -773,36 +773,35 @@ typedef enum {
/// Obtain the location that would be read when pasting `regname`.
void get_yank_register(int regname, int mode)
{
- int i;
+ y_append = false;
- y_append = FALSE;
- int unnamedclip = cb_flags & CB_UNNAMEDMASK;
- if ((regname == 0 || regname == '"') && !unnamedclip && mode != YREG_YANK && y_previous != NULL) {
+ if (mode == YREG_PASTE && get_clipboard(regname, &y_current, false)) {
+ // y_current is set to clipboard contents.
+ return;
+ } else if (mode != YREG_YANK && (regname == 0 || regname == '"') && y_previous != NULL) {
y_current = y_previous;
return;
}
- i = regname;
- if (VIM_ISDIGIT(i))
- i -= '0';
- else if (ASCII_ISLOWER(i))
- i = CharOrdLow(i) + 10;
- else if (ASCII_ISUPPER(i)) {
- i = CharOrdUp(i) + 10;
- y_append = TRUE;
+
+ int i = 0; // when not 0-9, a-z, A-Z or '-'/'+'/'*': use register 0
+ if (VIM_ISDIGIT(regname))
+ i = regname - '0';
+ else if (ASCII_ISLOWER(regname))
+ i = CharOrdLow(regname) + 10;
+ else if (ASCII_ISUPPER(regname)) {
+ i = CharOrdUp(regname) + 10;
+ y_append = true;
} else if (regname == '-')
i = DELETION_REGISTER;
else if (regname == '*')
i = STAR_REGISTER;
else if (regname == '+')
i = PLUS_REGISTER;
- else /* not 0-9, a-z, A-Z or '-': use register 0 */
- i = 0;
y_current = &(y_regs[i]);
+
if (mode == YREG_YANK) {
// remember the written register for unnamed paste
y_previous = y_current;
- } else if (mode == YREG_PASTE) {
- get_clipboard(regname, &y_current, false);
}
}
@@ -5310,7 +5309,28 @@ static void free_register(struct yankreg *reg)
y_current = curr;
}
-// return target register
+/// Check if the default register (used in an unnamed paste) should be a
+/// clipboard register. This happens when `clipboard=unnamed[plus]` is set
+/// and a provider is available.
+///
+/// @returns the name of of a clipboard register that should be used, or `NUL` if none.
+int get_default_register_name(void)
+{
+ int name = NUL;
+ adjust_clipboard_name(&name, true, false);
+ return name;
+}
+
+/// Determine if register `*name` should be used as a clipboard.
+/// In an unnammed operation, `*name` is `NUL` and will be adjusted to `'*'/'+'` if
+/// `clipboard=unnamed[plus]` is set.
+///
+/// @param name The name of register, or `NUL` if unnamed.
+/// @param quiet Suppress error messages
+/// @param writing if we're setting the contents of the clipboard
+///
+/// @returns the yankreg that should be used, or `NULL`
+/// if the register isn't a clipboard or provider isn't available.
static struct yankreg* adjust_clipboard_name(int *name, bool quiet, bool writing) {
if (*name == '*' || *name == '+') {
if(!eval_has_provider("clipboard")) {
@@ -5345,11 +5365,11 @@ static struct yankreg* adjust_clipboard_name(int *name, bool quiet, bool writing
return NULL;
}
-static void get_clipboard(int name, struct yankreg** target, bool quiet)
+static bool get_clipboard(int name, struct yankreg** target, bool quiet)
{
struct yankreg* reg = adjust_clipboard_name(&name, quiet, false);
if (reg == NULL) {
- return;
+ return false;
}
free_register(reg);
@@ -5434,7 +5454,7 @@ static void get_clipboard(int name, struct yankreg** target, bool quiet)
}
*target = reg;
- return;
+ return true;
err:
if (reg->y_array) {
@@ -5446,6 +5466,8 @@ err:
reg->y_array = NULL;
reg->y_size = 0;
EMSG("clipboard: provider returned invalid data");
+ *target = reg;
+ return false;
}
static void set_clipboard(int name)
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index a409a9ed13..8002d528ed 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -128,7 +128,9 @@ bool os_char_avail(void)
// Check for CTRL-C typed by reading all available characters.
void os_breakcheck(void)
{
- event_poll(0);
+ if (!disable_breakcheck && !got_int) {
+ event_poll(0);
+ }
}
/// Test whether a file descriptor refers to a terminal.
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 7e5664230e..ea0cc88e58 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -895,8 +895,7 @@ static void on_refresh(Event event)
}
Terminal *term;
void *stub; (void)(stub);
- // dont process autocommands while updating terminal buffers. JobActivity can
- // be used act on terminal output.
+ // don't process autocommands while updating terminal buffers
block_autocmds();
map_foreach(invalidated_terminals, term, stub, {
// TODO(SplinterOfChaos): Find the condition that makes term->buf invalid.
diff --git a/test/functional/clipboard/clipboard_provider_spec.lua b/test/functional/clipboard/clipboard_provider_spec.lua
index e7ca183a0e..c5d8f57008 100644
--- a/test/functional/clipboard/clipboard_provider_spec.lua
+++ b/test/functional/clipboard/clipboard_provider_spec.lua
@@ -55,6 +55,12 @@ local function basic_register_test(noblock)
, stuff and some more
some textsome some text, stuff and some more]])
+ -- deleting a line does update ""
+ feed('ggdd""P')
+ expect([[
+ , stuff and some more
+ some textsome some text, stuff and some more]])
+
feed('ggw<c-v>jwyggP')
if noblock then
expect([[
@@ -72,6 +78,7 @@ end
describe('the unnamed register', function()
before_each(clear)
it('works without provider', function()
+ eq('"', eval('v:register'))
basic_register_test()
end)
end)
@@ -227,6 +234,13 @@ describe('clipboard usage', function()
a line]])
end)
+ it('supports v:register and getreg() without parameters', function()
+ eq('*', eval('v:register'))
+ execute("let g:test_clip['*'] = [['some block',''], 'b']")
+ eq('some block', eval('getreg()'))
+ eq('\02210', eval('getregtype()'))
+ end)
+
end)
it('supports :put', function()
diff --git a/test/functional/job/job_spec.lua b/test/functional/job/job_spec.lua
index c517ae4c1b..df989b3ef9 100644
--- a/test/functional/job/job_spec.lua
+++ b/test/functional/job/job_spec.lua
@@ -61,7 +61,6 @@ describe('jobs', function()
file:write("abc\0def\n")
file:close()
- -- v:job_data preserves NULs.
nvim('command', "let j = jobstart(['cat', '"..filename.."'], g:job_opts)")
eq({'notification', 'stdout', {0, {'abc\ndef', ''}}}, next_msg())
eq({'notification', 'exit', {0, 0}}, next_msg())
@@ -249,6 +248,52 @@ describe('jobs', function()
eq({'notification', 'wait', {{-2}}}, next_msg())
end)
+ it('can be called recursively', function()
+ source([[
+ let g:opts = {}
+ let g:counter = 0
+ function g:opts.on_stdout(id, msg)
+ if self.state == 0
+ if self.counter < 10
+ call Run()
+ endif
+ let self.state = 1
+ call jobsend(a:id, "line1\n")
+ elseif self.state == 1
+ let self.state = 2
+ call jobsend(a:id, "line2\n")
+ elseif self.state == 2
+ let self.state = 3
+ call jobsend(a:id, "line3\n")
+ else
+ call rpcnotify(g:channel, 'w', printf('job %d closed', self.counter))
+ call jobclose(a:id, 'stdin')
+ endif
+ endfunction
+ function g:opts.on_exit()
+ call rpcnotify(g:channel, 'w', printf('job %d exited', self.counter))
+ endfunction
+ function Run()
+ let g:counter += 1
+ let j = copy(g:opts)
+ let j.state = 0
+ let j.counter = g:counter
+ call jobwait([
+ \ jobstart([&sh, '-c', 'echo ready; cat -'], j),
+ \ ])
+ endfunction
+ ]])
+ execute('call Run()')
+ local r
+ for i = 10, 1, -1 do
+ r = next_msg()
+ eq('job '..i..' closed', r[3][1])
+ r = next_msg()
+ eq('job '..i..' exited', r[3][1])
+ end
+ eq(10, nvim('eval', 'g:counter'))
+ end)
+
describe('with timeout argument', function()
it('will return -1 if the wait timed out', function()
source([[
@@ -292,7 +337,7 @@ describe('jobs', function()
data[i] = data[i]:gsub('\n', '\000')
end
rv = table.concat(data, '\n')
- rv = rv:gsub('\r\n$', '')
+ rv = rv:gsub('\r\n$', ''):gsub('^\r\n', '')
if rv ~= '' then
break
end
diff --git a/third-party/cmake/BuildLuarocks.cmake b/third-party/cmake/BuildLuarocks.cmake
index baa3425918..d02b1939b5 100644
--- a/third-party/cmake/BuildLuarocks.cmake
+++ b/third-party/cmake/BuildLuarocks.cmake
@@ -57,7 +57,6 @@ add_custom_target(stable-busted-deps
add_custom_command(OUTPUT ${DEPS_BIN_DIR}/busted
COMMAND ${DEPS_BIN_DIR}/luarocks
ARGS build https://raw.githubusercontent.com/Olivine-Labs/busted/master/busted-scm-0.rockspec CC=${DEPS_C_COMPILER} LD=${DEPS_C_COMPILER}
- COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/utfTerminalDetailed.lua
${DEPS_INSTALL_DIR}/share/lua/5.1/busted/outputHandlers
DEPENDS stable-busted-deps)
add_custom_target(busted
diff --git a/third-party/utfTerminalDetailed.lua b/third-party/utfTerminalDetailed.lua
deleted file mode 100644
index 5a52dfa958..0000000000
--- a/third-party/utfTerminalDetailed.lua
+++ /dev/null
@@ -1,27 +0,0 @@
--- busted output handler that immediately prints file and test names before
--- tests are executed. It simplifies identifying which tests are
--- hanging/crashing
-if package.config:sub(1,1) == '\\' and not os.getenv("ANSICON") then
- -- Disable colors on Windows.
- colors = setmetatable({}, {__index = function() return function(s) return s end end})
-else
- colors = require 'term.colors'
-end
-
-return function(options, busted)
- local handler = require 'busted.outputHandlers.utfTerminal'(options, busted)
-
- handler.fileStart = function(name)
- io.write('\n' .. colors.cyan(name) .. ':')
- end
-
- handler.testStart = function(element, parent, status, debug)
- io.write('\n ' .. handler.getFullName(element) .. ' ... ')
- io.flush()
- end
-
- busted.subscribe({ 'file', 'start' }, handler.fileStart)
- busted.subscribe({ 'test', 'start' }, handler.testStart)
-
- return handler
-end