diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/buffer_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/edit.c | 5 | ||||
-rw-r--r-- | src/nvim/eval.c | 438 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 2 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 1 | ||||
-rw-r--r-- | src/nvim/getchar.c | 7 | ||||
-rw-r--r-- | src/nvim/globals.h | 1 | ||||
-rw-r--r-- | src/nvim/main.c | 1 | ||||
-rw-r--r-- | src/nvim/os/server.c | 7 | ||||
-rw-r--r-- | src/nvim/screen.c | 2 | ||||
-rw-r--r-- | src/nvim/testdir/Makefile | 3 | ||||
-rw-r--r-- | src/nvim/testdir/test86.in | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_insertcount.in | 14 | ||||
-rw-r--r-- | src/nvim/testdir/test_insertcount.ok | 3 | ||||
-rw-r--r-- | src/nvim/version.c | 4 |
15 files changed, 274 insertions, 217 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index de1b0985bb..84d55fb730 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -255,6 +255,7 @@ struct wininfo_S { typedef struct arglist { garray_T al_ga; /* growarray with the array of file names */ int al_refcount; /* number of windows using this arglist */ + int id; ///< id of this arglist } alist_T; /* diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 10bee8023e..b3f4e4d449 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -6919,8 +6919,9 @@ ins_esc ( State &= ~REPLACE_FLAG; (void)start_redo_ins(); - if (cmdchar == 'r' || cmdchar == 'v') - stuffReadbuff(ESC_STR); /* no ESC in redo buffer */ + if (cmdchar == 'r' || cmdchar == 'v') { + stuffRedoReadbuff(ESC_STR); // No ESC in redo buffer + } ++RedrawingDisabled; disabled_redraw = TRUE; return FALSE; /* repeat the insert */ diff --git a/src/nvim/eval.c b/src/nvim/eval.c index f0badb5802..7793f5040c 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6306,11 +6306,10 @@ static struct fst { {"acos", 1, 1, f_acos}, /* WJMc */ {"add", 2, 2, f_add}, {"and", 2, 2, f_and}, - {"api_close", 1, 1, f_api_close}, - {"api_spawn", 1, 2, f_api_spawn}, {"append", 2, 2, f_append}, {"argc", 0, 0, f_argc}, {"argidx", 0, 0, f_argidx}, + {"arglistid", 0, 2, f_arglistid}, {"argv", 0, 1, f_argv}, {"asin", 1, 1, f_asin}, /* WJMc */ {"atan", 1, 1, f_atan}, @@ -6436,9 +6435,9 @@ static struct fst { {"isdirectory", 1, 1, f_isdirectory}, {"islocked", 1, 1, f_islocked}, {"items", 1, 1, f_items}, - {"jobstart", 2, 3, f_job_start}, - {"jobstop", 1, 1, f_job_stop}, - {"jobwrite", 2, 2, f_job_write}, + {"jobsend", 2, 2, f_jobsend}, + {"jobstart", 2, 3, f_jobstart}, + {"jobstop", 1, 1, f_jobstop}, {"join", 1, 2, f_join}, {"keys", 1, 1, f_keys}, {"last_buffer_nr", 0, 0, f_last_buffer_nr}, /* obsolete */ @@ -6485,6 +6484,10 @@ static struct fst { {"resolve", 1, 1, f_resolve}, {"reverse", 1, 1, f_reverse}, {"round", 1, 1, f_round}, + {"rpcnotify", 2, 64, f_rpcnotify}, + {"rpcrequest", 2, 64, f_rpcrequest}, + {"rpcstart", 1, 2, f_rpcstart}, + {"rpcstop", 1, 1, f_rpcstop}, {"screenattr", 2, 2, f_screenattr}, {"screenchar", 2, 2, f_screenchar}, {"screencol", 0, 0, f_screencol}, @@ -6494,8 +6497,6 @@ static struct fst { {"searchpair", 3, 7, f_searchpair}, {"searchpairpos", 3, 7, f_searchpairpos}, {"searchpos", 1, 4, f_searchpos}, - {"send_call", 2, 64, f_send_call}, - {"send_event", 2, 64, f_send_event}, {"setbufvar", 3, 3, f_setbufvar}, {"setcmdpos", 1, 1, f_setcmdpos}, {"setline", 2, 2, f_setline}, @@ -7055,83 +7056,6 @@ static void f_and(typval_T *argvars, typval_T *rettv) & get_tv_number_chk(&argvars[1], NULL); } -// "api_close(prog, argv)" function -static void f_api_close(typval_T *argvars, typval_T *rettv) -{ - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = 0; - - if (check_restricted() || check_secure()) { - return; - } - - if (argvars[0].v_type != VAR_NUMBER) { - // Wrong argument types - EMSG(_(e_invarg)); - return; - } - - rettv->vval.v_number = channel_close(argvars[0].vval.v_number); -} - - -// "api_spawn(prog, argv)" function -static void f_api_spawn(typval_T *argvars, typval_T *rettv) -{ - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = 0; - - if (check_restricted() || check_secure()) { - return; - } - - if (argvars[0].v_type != VAR_STRING - || (argvars[1].v_type != VAR_LIST && argvars[1].v_type != VAR_UNKNOWN)) { - // Wrong argument types - EMSG(_(e_invarg)); - return; - } - - list_T *args = NULL; - int argsl = 0; - if (argvars[1].v_type == VAR_LIST) { - args = argvars[1].vval.v_list; - argsl = args->lv_len; - // Assert that all list items are strings - for (listitem_T *arg = args->lv_first; arg != NULL; arg = arg->li_next) { - if (arg->li_tv.v_type != VAR_STRING) { - EMSG(_(e_invarg)); - return; - } - } - } - - // Allocate extra memory for the argument vector and the NULL pointer - int argvl = argsl + 2; - char **argv = xmalloc(sizeof(char_u *) * argvl); - - // Copy program name - argv[0] = xstrdup((char *)argvars[0].vval.v_string); - - int i = 1; - // Copy arguments to the vector - if (argsl > 0) { - for (listitem_T *arg = args->lv_first; arg != NULL; arg = arg->li_next) { - argv[i++] = xstrdup((char *)arg->li_tv.vval.v_string); - } - } - - // The last item of argv must be NULL - argv[i] = NULL; - uint64_t channel_id = channel_from_job(argv); - - if (!channel_id) { - EMSG(_(e_api_spawn_failed)); - } - - rettv->vval.v_number = (varnumber_T)channel_id; -} - /* * "append(lnum, string/list)" function */ @@ -7203,6 +7127,32 @@ static void f_argidx(typval_T *argvars, typval_T *rettv) rettv->vval.v_number = curwin->w_arg_idx; } +/// "arglistid" function +static void f_arglistid(typval_T *argvars, typval_T *rettv) +{ + rettv->vval.v_number = -1; + if (argvars[0].v_type != VAR_UNKNOWN) { + tabpage_T *tp = NULL; + if (argvars[1].v_type != VAR_UNKNOWN) { + long n = get_tv_number(&argvars[1]); + if (n >= 0) { + tp = find_tabpage(n); + } + } else { + tp = curtab; + } + + if (tp != NULL) { + win_T *wp = find_win_by_nr(&argvars[0], tp); + if (wp != NULL) { + rettv->vval.v_number = wp->w_alist->id; + } + } + } else { + rettv->vval.v_number = curwin->w_alist->id; + } +} + /* * "argv(nr)" function */ @@ -9892,7 +9842,7 @@ static void f_has(typval_T *argvars, typval_T *rettv) "windows", "winaltkeys", "writebackup", - "neovim", + "nvim", NULL }; @@ -10558,8 +10508,40 @@ static void f_items(typval_T *argvars, typval_T *rettv) dict_list(argvars, rettv, 2); } +// "jobsend()" function +static void f_jobsend(typval_T *argvars, typval_T *rettv) +{ + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; + + if (check_restricted() || check_secure()) { + return; + } + + if (argvars[0].v_type != VAR_NUMBER || argvars[1].v_type != VAR_STRING) { + // First argument is the job id and second is the string to write to + // the job's stdin + EMSG(_(e_invarg)); + return; + } + + Job *job = job_find(argvars[0].vval.v_number); + + if (!job) { + // Invalid job id + EMSG(_(e_invjob)); + return; + } + + WBuffer *buf = wstream_new_buffer(xstrdup((char *)argvars[1].vval.v_string), + strlen((char *)argvars[1].vval.v_string), + 1, + free); + rettv->vval.v_number = job_write(job, buf); +} + // "jobstart()" function -static void f_job_start(typval_T *argvars, typval_T *rettv) +static void f_jobstart(typval_T *argvars, typval_T *rettv) { list_T *args = NULL; listitem_T *arg; @@ -10637,7 +10619,7 @@ static void f_job_start(typval_T *argvars, typval_T *rettv) } // "jobstop()" function -static void f_job_stop(typval_T *argvars, typval_T *rettv) +static void f_jobstop(typval_T *argvars, typval_T *rettv) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -10664,38 +10646,6 @@ static void f_job_stop(typval_T *argvars, typval_T *rettv) rettv->vval.v_number = 1; } -// "jobwrite()" function -static void f_job_write(typval_T *argvars, typval_T *rettv) -{ - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = 0; - - if (check_restricted() || check_secure()) { - return; - } - - if (argvars[0].v_type != VAR_NUMBER || argvars[1].v_type != VAR_STRING) { - // First argument is the job id and second is the string to write to - // the job's stdin - EMSG(_(e_invarg)); - return; - } - - Job *job = job_find(argvars[0].vval.v_number); - - if (!job) { - // Invalid job id - EMSG(_(e_invjob)); - return; - } - - WBuffer *buf = wstream_new_buffer(xstrdup((char *)argvars[1].vval.v_string), - strlen((char *)argvars[1].vval.v_string), - 1, - free); - rettv->vval.v_number = job_write(job, buf); -} - /* * "join()" function */ @@ -12420,6 +12370,169 @@ static void f_round(typval_T *argvars, typval_T *rettv) rettv->vval.v_float = 0.0; } +// "rpcnotify()" function +static void f_rpcnotify(typval_T *argvars, typval_T *rettv) +{ + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; + + if (check_restricted() || check_secure()) { + return; + } + + if (argvars[0].v_type != VAR_NUMBER || argvars[0].vval.v_number < 0) { + EMSG2(_(e_invarg2), "Channel id must be a positive integer"); + return; + } + + if (argvars[1].v_type != VAR_STRING) { + EMSG2(_(e_invarg2), "Event type must be a string"); + return; + } + + Array args = ARRAY_DICT_INIT; + + for (typval_T *tv = argvars + 2; tv->v_type != VAR_UNKNOWN; tv++) { + ADD(args, vim_to_object(tv)); + } + + if (!channel_send_event((uint64_t)argvars[0].vval.v_number, + (char *)argvars[1].vval.v_string, + args)) { + EMSG2(_(e_invarg2), "Channel doesn't exist"); + return; + } + + rettv->vval.v_number = 1; +} + +// "rpcrequest()" function +static void f_rpcrequest(typval_T *argvars, typval_T *rettv) +{ + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; + + if (check_restricted() || check_secure()) { + return; + } + + if (argvars[0].v_type != VAR_NUMBER || argvars[0].vval.v_number <= 0) { + EMSG2(_(e_invarg2), "Channel id must be a positive integer"); + return; + } + + if (argvars[1].v_type != VAR_STRING) { + EMSG2(_(e_invarg2), "Method name must be a string"); + return; + } + + Array args = ARRAY_DICT_INIT; + + for (typval_T *tv = argvars + 2; tv->v_type != VAR_UNKNOWN; tv++) { + ADD(args, vim_to_object(tv)); + } + + bool errored; + Object result; + if (!channel_send_call((uint64_t)argvars[0].vval.v_number, + (char *)argvars[1].vval.v_string, + args, + &result, + &errored)) { + EMSG2(_(e_invarg2), "Channel doesn't exist"); + return; + } + + if (errored) { + vim_report_error(result.data.string); + goto end; + } + + Error conversion_error = {.set = false}; + if (!object_to_vim(result, rettv, &conversion_error)) { + EMSG(_("Error converting the call result")); + } + +end: + api_free_object(result); +} + +// "rpcstart()" function +static void f_rpcstart(typval_T *argvars, typval_T *rettv) +{ + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; + + if (check_restricted() || check_secure()) { + return; + } + + if (argvars[0].v_type != VAR_STRING + || (argvars[1].v_type != VAR_LIST && argvars[1].v_type != VAR_UNKNOWN)) { + // Wrong argument types + EMSG(_(e_invarg)); + return; + } + + list_T *args = NULL; + int argsl = 0; + if (argvars[1].v_type == VAR_LIST) { + args = argvars[1].vval.v_list; + argsl = args->lv_len; + // Assert that all list items are strings + for (listitem_T *arg = args->lv_first; arg != NULL; arg = arg->li_next) { + if (arg->li_tv.v_type != VAR_STRING) { + EMSG(_(e_invarg)); + return; + } + } + } + + // Allocate extra memory for the argument vector and the NULL pointer + int argvl = argsl + 2; + char **argv = xmalloc(sizeof(char_u *) * argvl); + + // Copy program name + argv[0] = xstrdup((char *)argvars[0].vval.v_string); + + int i = 1; + // Copy arguments to the vector + if (argsl > 0) { + for (listitem_T *arg = args->lv_first; arg != NULL; arg = arg->li_next) { + argv[i++] = xstrdup((char *)arg->li_tv.vval.v_string); + } + } + + // The last item of argv must be NULL + argv[i] = NULL; + uint64_t channel_id = channel_from_job(argv); + + if (!channel_id) { + EMSG(_(e_api_spawn_failed)); + } + + rettv->vval.v_number = (varnumber_T)channel_id; +} + +// "rpcstop()" function +static void f_rpcstop(typval_T *argvars, typval_T *rettv) +{ + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; + + if (check_restricted() || check_secure()) { + return; + } + + if (argvars[0].v_type != VAR_NUMBER) { + // Wrong argument types + EMSG(_(e_invarg)); + return; + } + + rettv->vval.v_number = channel_close(argvars[0].vval.v_number); +} + /* * "screenattr()" function */ @@ -12759,93 +12872,6 @@ do_searchpair ( return retval; } -// "send_call()" function -static void f_send_call(typval_T *argvars, typval_T *rettv) -{ - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = 0; - - if (check_restricted() || check_secure()) { - return; - } - - if (argvars[0].v_type != VAR_NUMBER || argvars[0].vval.v_number <= 0) { - EMSG2(_(e_invarg2), "Channel id must be a positive integer"); - return; - } - - if (argvars[1].v_type != VAR_STRING) { - EMSG2(_(e_invarg2), "Method name must be a string"); - return; - } - - Array args = ARRAY_DICT_INIT; - - for (typval_T *tv = argvars + 2; tv->v_type != VAR_UNKNOWN; tv++) { - ADD(args, vim_to_object(tv)); - } - - bool errored; - Object result; - if (!channel_send_call((uint64_t)argvars[0].vval.v_number, - (char *)argvars[1].vval.v_string, - args, - &result, - &errored)) { - EMSG2(_(e_invarg2), "Channel doesn't exist"); - return; - } - - if (errored) { - vim_report_error(result.data.string); - goto end; - } - - Error conversion_error = {.set = false}; - if (!object_to_vim(result, rettv, &conversion_error)) { - EMSG(_("Error converting the call result")); - } - -end: - api_free_object(result); -} - -// "send_event()" function -static void f_send_event(typval_T *argvars, typval_T *rettv) -{ - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = 0; - - if (check_restricted() || check_secure()) { - return; - } - - if (argvars[0].v_type != VAR_NUMBER || argvars[0].vval.v_number < 0) { - EMSG2(_(e_invarg2), "Channel id must be a positive integer"); - return; - } - - if (argvars[1].v_type != VAR_STRING) { - EMSG2(_(e_invarg2), "Event type must be a string"); - return; - } - - Array args = ARRAY_DICT_INIT; - - for (typval_T *tv = argvars + 2; tv->v_type != VAR_UNKNOWN; tv++) { - ADD(args, vim_to_object(tv)); - } - - if (!channel_send_event((uint64_t)argvars[0].vval.v_number, - (char *)argvars[1].vval.v_string, - args)) { - EMSG2(_(e_invarg2), "Channel doesn't exist"); - return; - } - - rettv->vval.v_number = 1; -} - /* * "searchpos()" function */ diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 17905c3046..c3d34e9991 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -1914,7 +1914,7 @@ void ex_listdo(exarg_T *eap) break; } } - if (buf_still_exists) { + if (!buf_still_exists) { break; } diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index dacd0f9e31..1117b6fbcf 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5504,6 +5504,7 @@ void alist_new(void) { curwin->w_alist = xmalloc(sizeof(*curwin->w_alist)); curwin->w_alist->al_refcount = 1; + curwin->w_alist->id = ++max_alist_id; alist_init(curwin->w_alist); } diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 6c772a8a66..0d61172d69 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -601,6 +601,13 @@ void stuffReadbuff(char_u *s) add_buff(&readbuf1, s, -1L); } +/// Append string "s" to the redo stuff buffer. +/// @remark CSI and K_SPECIAL must already have been escaped. +void stuffRedoReadbuff(char_u *s) +{ + add_buff(&readbuf2, s, -1L); +} + void stuffReadbuffLen(char_u *s, long len) { add_buff(&readbuf1, s, len); diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 49a4a2f604..674786ff08 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -568,6 +568,7 @@ EXTERN int mf_dont_release INIT(= FALSE); /* don't release blocks */ * to this when the window is using the global argument list. */ EXTERN alist_T global_alist; /* global argument list */ +EXTERN int max_alist_id INIT(= 0); ///< the previous argument list id EXTERN int arg_had_last INIT(= FALSE); /* accessed last file in global_alist */ diff --git a/src/nvim/main.c b/src/nvim/main.c index fc1826975a..7dc299e73b 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -192,6 +192,7 @@ int main(int argc, char **argv) init_yank(); /* init yank buffers */ alist_init(&global_alist); /* Init the argument list to empty. */ + global_alist.id = 0; /* * Set the default values for the options. diff --git a/src/nvim/os/server.c b/src/nvim/os/server.c index 2e8934ecfb..66dd0ecd88 100644 --- a/src/nvim/os/server.c +++ b/src/nvim/os/server.c @@ -17,6 +17,7 @@ #define MAX_CONNECTIONS 32 #define ADDRESS_MAX_SIZE 256 #define NEOVIM_DEFAULT_TCP_PORT 7450 +#define LISTEN_ADDRESS_ENV_VAR "NVIM_LISTEN_ADDRESS" typedef enum { kServerTypeTcp, @@ -51,13 +52,13 @@ void server_init(void) { servers = pmap_new(cstr_t)(); - if (!os_getenv("NEOVIM_LISTEN_ADDRESS")) { + if (!os_getenv(LISTEN_ADDRESS_ENV_VAR)) { char *listen_address = (char *)vim_tempname(); - os_setenv("NEOVIM_LISTEN_ADDRESS", listen_address, 1); + os_setenv(LISTEN_ADDRESS_ENV_VAR, listen_address, 1); free(listen_address); } - server_start((char *)os_getenv("NEOVIM_LISTEN_ADDRESS")); + server_start((char *)os_getenv(LISTEN_ADDRESS_ENV_VAR)); } /// Teardown the server module diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 29e5af5cee..122c23ed84 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -3565,7 +3565,7 @@ win_line ( } else if (c != NUL) { p_extra = transchar(c); if (n_extra == 0) { - n_extra = byte2cells(c); + n_extra = byte2cells(c) - 1; } if ((dy_flags & DY_UHEX) && wp->w_p_rl) rl_mirror(p_extra); /* reverse "<12>" */ diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 92fd47ff6b..81dc49e800 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -33,7 +33,8 @@ SCRIPTS := test_autoformat_join.out \ test106.out test107.out \ test_options.out \ test_listlbr.out test_listlbr_utf8.out \ - test_breakindent.out + test_breakindent.out \ + test_insertcount.out SCRIPTS_GUI := test16.out diff --git a/src/nvim/testdir/test86.in b/src/nvim/testdir/test86.in index ecb06bafd3..11ff35cfd3 100644 --- a/src/nvim/testdir/test86.in +++ b/src/nvim/testdir/test86.in @@ -9,7 +9,7 @@ STARTTEST :so small.vim :set encoding=latin1 :set noswapfile -:if !has('python') || has('neovim') | e! test.ok | wq! test.out | endif +:if !has('python') || has('nvim') | e! test.ok | wq! test.out | endif :lang C :fun Test() :py import vim diff --git a/src/nvim/testdir/test_insertcount.in b/src/nvim/testdir/test_insertcount.in new file mode 100644 index 0000000000..7a40573e63 --- /dev/null +++ b/src/nvim/testdir/test_insertcount.in @@ -0,0 +1,14 @@ +Tests for repeating insert and replace. + +STARTTEST +:so small.vim +:/Second +4gro +:/^First/,$wq! test.out +:" get here when failed and in Insert mode +:.wq! test.out +ENDTEST + +First line +Second line +Last line diff --git a/src/nvim/testdir/test_insertcount.ok b/src/nvim/testdir/test_insertcount.ok new file mode 100644 index 0000000000..57afab00ff --- /dev/null +++ b/src/nvim/testdir/test_insertcount.ok @@ -0,0 +1,3 @@ +First line +ooooecond line +Last line diff --git a/src/nvim/version.c b/src/nvim/version.c index 68c62d8e61..b32da8937e 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -208,7 +208,7 @@ static int included_patches[] = { //390, //389, 388, - //387, + 387, //386, //385, //384 NA @@ -283,7 +283,7 @@ static int included_patches[] = { 315, 314, //313, - //312, + 312, //311, //310, 309, |