diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/auevents.lua | 1 | ||||
-rw-r--r-- | src/nvim/buffer.c | 10 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/edit.c | 17 | ||||
-rw-r--r-- | src/nvim/eval.c | 29 | ||||
-rw-r--r-- | src/nvim/eval.h | 3 | ||||
-rw-r--r-- | src/nvim/eval_defs.h | 2 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 6 | ||||
-rw-r--r-- | src/nvim/fileio.c | 35 | ||||
-rw-r--r-- | src/nvim/log.c | 2 | ||||
-rw-r--r-- | src/nvim/memline.c | 6 | ||||
-rw-r--r-- | src/nvim/memline_defs.h | 2 | ||||
-rw-r--r-- | src/nvim/normal.c | 7 | ||||
-rw-r--r-- | src/nvim/ops.c | 4 | ||||
-rw-r--r-- | src/nvim/option.c | 117 | ||||
-rw-r--r-- | src/nvim/option_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/options.lua | 8 | ||||
-rw-r--r-- | src/nvim/os/env.c | 33 | ||||
-rw-r--r-- | src/nvim/os/shell.c | 3 | ||||
-rw-r--r-- | src/nvim/os/signal.c | 12 | ||||
-rw-r--r-- | src/nvim/path.c | 3 | ||||
-rw-r--r-- | src/nvim/po/it.po | 46 | ||||
-rw-r--r-- | src/nvim/search.c | 19 | ||||
-rw-r--r-- | src/nvim/shada.c | 307 | ||||
-rw-r--r-- | src/nvim/testdir/test53.in | 4 | ||||
-rw-r--r-- | src/nvim/testdir/test53.ok | 1 | ||||
-rw-r--r-- | src/nvim/version.c | 24 |
27 files changed, 428 insertions, 275 deletions
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index 7624dd2303..aa4a8d8332 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -57,6 +57,7 @@ return { 'InsertLeave', -- when leaving Insert mode 'JobActivity', -- when job sent some data 'MenuPopup', -- just before popup menu is displayed + 'OptionSet', -- after setting any option 'QuickFixCmdPost', -- after :make, :grep etc. 'QuickFixCmdPre', -- before :make, :grep etc. 'QuitPre', -- before :quit diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 7978dc8969..762cd3efd3 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1414,7 +1414,6 @@ buflist_new ( return NULL; if (aborting()) /* autocmds may abort script processing */ return NULL; - /* buf->b_nwindows = 0; why was this here? */ free_buffer_stuff(buf, FALSE); /* delete local variables et al. */ /* Init the options. */ @@ -1475,6 +1474,9 @@ buflist_new ( fmarks_check_names(buf); /* check file marks for this file */ buf->b_p_bl = (flags & BLN_LISTED) ? TRUE : FALSE; /* init 'buflisted' */ if (!(flags & BLN_DUMMY)) { + // Tricky: these autocommands may change the buffer list. They could also + // split the window with re-using the one empty buffer. This may result in + // unexpectedly losing the empty buffer. apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, buf); if (!buf_valid(buf)) { return NULL; @@ -3745,8 +3747,10 @@ int build_stl_str_hl( // Put a `<` to mark where we truncated at *trunc_p = '<'; - // Advance the pointer to the end of the string - trunc_p = trunc_p + STRLEN(trunc_p); + if (width + 1 < maxwidth) { + // Advance the pointer to the end of the string + trunc_p = trunc_p + STRLEN(trunc_p); + } // Fill up for half a double-wide character. while (++width < maxwidth) { diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 3eabb7ee43..6b5bbe3b00 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -612,6 +612,7 @@ struct file_buffer { char_u *b_p_cfu; /* 'completefunc' */ char_u *b_p_ofu; /* 'omnifunc' */ int b_p_eol; /* 'endofline' */ + int b_p_fixeol; /* 'fixendofline' */ int b_p_et; /* 'expandtab' */ int b_p_et_nobin; /* b_p_et saved for binary mode */ char_u *b_p_fenc; /* 'fileencoding' */ diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 8dc2844d8e..9ba5d96e16 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -5017,8 +5017,9 @@ insertchar ( int textwidth; char_u *p; int fo_ins_blank; + int force_format = flags & INSCHAR_FORMAT; - textwidth = comp_textwidth(flags & INSCHAR_FORMAT); + textwidth = comp_textwidth(force_format); fo_ins_blank = has_format_option(FO_INS_BLANK); /* @@ -5037,7 +5038,7 @@ insertchar ( * before 'textwidth' */ if (textwidth > 0 - && ((flags & INSCHAR_FORMAT) + && (force_format || (!ascii_iswhite(c) && !((State & REPLACE_FLAG) && !(State & VREPLACE_FLAG) @@ -5051,8 +5052,11 @@ insertchar ( /* Format with 'formatexpr' when it's set. Use internal formatting * when 'formatexpr' isn't set or it returns non-zero. */ int do_internal = TRUE; + colnr_T virtcol = get_nolist_virtcol() + + char2cells(c != NUL ? c : gchar_cursor()); - if (*curbuf->b_p_fex != NUL && (flags & INSCHAR_NO_FEX) == 0) { + if (*curbuf->b_p_fex != NUL && (flags & INSCHAR_NO_FEX) == 0 + && (force_format || virtcol > (colnr_T)textwidth)) { do_internal = (fex_format(curwin->w_cursor.lnum, 1L, c) != 0); /* It may be required to save for undo again, e.g. when setline() * was called. */ @@ -7427,15 +7431,14 @@ static int ins_bs(int c, int mode, int *inserted_space_p) * delete newline! */ if (curwin->w_cursor.col == 0) { - lnum = Insstart_orig.lnum; + lnum = Insstart.lnum; if (curwin->w_cursor.lnum == lnum || revins_on) { if (u_save((linenr_T)(curwin->w_cursor.lnum - 2), (linenr_T)(curwin->w_cursor.lnum + 1)) == FAIL) { return FALSE; } - --Insstart_orig.lnum; - Insstart_orig.col = MAXCOL; - Insstart = Insstart_orig; + --Insstart.lnum; + Insstart.col = MAXCOL; } /* * In replace mode: diff --git a/src/nvim/eval.c b/src/nvim/eval.c index f104098dbf..b60886704e 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -373,6 +373,9 @@ static struct vimvar { {VV_NAME("progpath", VAR_STRING), VV_RO}, {VV_NAME("command_output", VAR_STRING), 0}, {VV_NAME("completed_item", VAR_DICT), VV_RO}, + {VV_NAME("option_new", VAR_STRING), VV_RO}, + {VV_NAME("option_old", VAR_STRING), VV_RO}, + {VV_NAME("option_type", VAR_STRING), VV_RO}, {VV_NAME("msgpack_types", VAR_DICT), VV_RO}, }; @@ -5648,6 +5651,14 @@ bool garbage_collect(void) ABORTING(set_ref_in_ht)(&fc->l_avars.dv_hashtab, copyID, NULL); } + // Jobs + { + TerminalJobData *data; + map_foreach_value(jobs, data, { + ABORTING(set_ref_dict)(data->self, copyID); + }) + } + // v: vars ABORTING(set_ref_in_ht)(&vimvarht, copyID, NULL); @@ -5725,8 +5736,7 @@ static int free_unref_items(int copyID) // Go through the list of dicts and free items without the copyID. // Don't free dicts that are referenced internally. for (dict_T *dd = first_dict; dd != NULL; ) { - if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK) - && !dd->internal_refcount) { + if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)) { // Free the Dictionary and ordinary items it contains, but don't // recurse into Lists and Dictionaries, they will be in the list // of dicts or list of lists. */ @@ -5967,7 +5977,6 @@ dict_T *dict_alloc(void) FUNC_ATTR_NONNULL_RET d->dv_scope = 0; d->dv_refcount = 0; d->dv_copyID = 0; - d->internal_refcount = 0; QUEUE_INIT(&d->watchers); return d; @@ -21238,9 +21247,13 @@ void ex_oldfiles(exarg_T *eap) } } - - - +// reset v:option_new, v:option_old and v:option_type +void reset_v_option_vars(void) +{ + set_vim_var_string(VV_OPTION_NEW, NULL, -1); + set_vim_var_string(VV_OPTION_OLD, NULL, -1); + set_vim_var_string(VV_OPTION_TYPE, NULL, -1); +} /* * Adjust a filename, according to a string of modifiers. @@ -21613,7 +21626,6 @@ static inline bool common_job_callbacks(dict_T *vopts, ufunc_T **on_stdout, if (get_dict_callback(vopts, "on_stdout", on_stdout) && get_dict_callback(vopts, "on_stderr", on_stderr) && get_dict_callback(vopts, "on_exit", on_exit)) { - vopts->internal_refcount++; vopts->dv_refcount++; return true; } @@ -21675,7 +21687,6 @@ static inline void free_term_job_data_event(void **argv) } if (data->self) { - data->self->internal_refcount--; dict_unref(data->self); } queue_free(data->events); @@ -21926,7 +21937,7 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments) true, NULL); - arguments->lv_refcount--; + list_unref(arguments); // Restore caller scope information restore_funccal(provider_caller_scope.funccalp); provider_caller_scope = saved_provider_caller_scope; diff --git a/src/nvim/eval.h b/src/nvim/eval.h index 8ccf71068c..19a1bbb083 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -108,6 +108,9 @@ enum { VV_PROGPATH, VV_COMMAND_OUTPUT, VV_COMPLETED_ITEM, + VV_OPTION_NEW, + VV_OPTION_OLD, + VV_OPTION_TYPE, VV_MSGPACK_TYPES, VV_LEN, /* number of v: vars */ }; diff --git a/src/nvim/eval_defs.h b/src/nvim/eval_defs.h index bd50d6b829..ed419268d2 100644 --- a/src/nvim/eval_defs.h +++ b/src/nvim/eval_defs.h @@ -118,8 +118,6 @@ struct dictvar_S { dict_T *dv_copydict; /* copied dict used by deepcopy() */ dict_T *dv_used_next; /* next dict in used dicts list */ dict_T *dv_used_prev; /* previous dict in used dicts list */ - int internal_refcount; // number of internal references to - // prevent garbage collection QUEUE watchers; // dictionary key watchers set by user code }; diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 3f19421a75..d902234ef7 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2112,7 +2112,6 @@ do_ecmd ( goto theend; if (buf->b_ml.ml_mfp == NULL) { /* no memfile yet */ oldbuf = FALSE; - buf->b_nwindows = 0; } else { /* existing memfile */ oldbuf = TRUE; (void)buf_check_timestamp(buf, FALSE); @@ -2138,7 +2137,7 @@ do_ecmd ( * Make the (new) buffer the one used by the current window. * If the old buffer becomes unused, free it if ECMD_HIDE is FALSE. * If the current buffer was empty and has no file name, curbuf - * is returned by buflist_new(). + * is returned by buflist_new(), nothing to do here. */ if (buf != curbuf) { /* @@ -2225,8 +2224,7 @@ do_ecmd ( } xfree(new_name); au_new_curbuf = NULL; - } else - ++curbuf->b_nwindows; + } curwin->w_pcmark.lnum = 1; curwin->w_pcmark.col = 0; diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 5ac133a0c3..1a6c85abaa 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -1544,6 +1544,11 @@ rewind_retry: /* First try finding a NL, for Dos and Unix */ if (try_dos || try_unix) { for (p = ptr; p < ptr + size; ++p) { + // Reset the carriage return counter. + if (try_mac) { + try_mac = 1; + } + if (*p == NL) { if (!try_unix || (try_dos && p > ptr && p[-1] == CAR)) @@ -1551,6 +1556,8 @@ rewind_retry: else fileformat = EOL_UNIX; break; + } else if (*p == CAR && try_mac) { + try_mac++; } } @@ -1571,6 +1578,10 @@ rewind_retry: if (try_mac > try_unix) fileformat = EOL_MAC; } + } else if (fileformat == EOL_UNKNOWN && try_mac == 1) { + // Looking for CR but found no end-of-line markers at all: + // use the default format. + fileformat = default_fileformat(); } } @@ -1922,10 +1933,10 @@ failed: check_marks_read(); /* - * Trick: We remember if the last line of the read didn't have - * an eol even when 'binary' is off, for when writing it again with - * 'binary' on. This is required for - * ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work. + * We remember if the last line of the read didn't have + * an eol even when 'binary' is off, to support turning 'fixeol' off, + * or writing the read again with 'binary' on. The latter is required + * for ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work. */ curbuf->b_no_eol_lnum = read_no_eol_lnum; @@ -3310,7 +3321,7 @@ restore_backup: /* write failed or last line has no EOL: stop here */ if (end == 0 || (lnum == end - && write_bin + && (write_bin || !buf->b_p_fixeol) && (lnum == buf->b_no_eol_lnum || (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol)))) { ++lnum; /* written the line, count it */ @@ -4331,8 +4342,6 @@ void shorten_fnames(int force) /// @return [allocated] - A new filename, made up from: /// * fname + ext, if fname not NULL. /// * current dir + ext, if fname is NULL. -/// On Windows, and if ext starts with ".", a "_" is -/// preprended to ext (for filename to be valid). /// Result is guaranteed to: /// * be ended by <ext>. /// * have a basename with at most BASENAMELEN chars: @@ -4386,15 +4395,6 @@ char *modname(const char *fname, const char *ext, bool prepend_dot) char *s; s = ptr + strlen(ptr); -#if defined(WIN3264) - // If there is no file name, and the extension starts with '.', put a - // '_' before the dot, because just ".ext" may be invalid if it's on a - // FAT partition, and on HPFS it doesn't matter. - else if ((fname == NULL || *fname == NUL) && *ext == '.') { - *s++ = '_'; - } -#endif - // Append the extension. // ext can start with '.' and cannot exceed 3 more characters. strcpy(s, ext); @@ -6418,7 +6418,7 @@ apply_autocmds_group ( * invalid. */ if (fname_io == NULL) { - if (event == EVENT_COLORSCHEME) + if (event == EVENT_COLORSCHEME || event == EVENT_OPTIONSET) autocmd_fname = NULL; else if (fname != NULL && *fname != NUL) autocmd_fname = fname; @@ -6468,6 +6468,7 @@ apply_autocmds_group ( if (event == EVENT_COLORSCHEME || event == EVENT_FILETYPE || event == EVENT_FUNCUNDEFINED + || event == EVENT_OPTIONSET || event == EVENT_QUICKFIXCMDPOST || event == EVENT_QUICKFIXCMDPRE || event == EVENT_REMOTEREPLY diff --git a/src/nvim/log.c b/src/nvim/log.c index 08b6d0483e..5767da03af 100644 --- a/src/nvim/log.c +++ b/src/nvim/log.c @@ -14,7 +14,7 @@ # include <unistd.h> #endif -#define USR_LOG_FILE "$HOME/.nvimlog" +#define USR_LOG_FILE "$HOME" _PATHSEPSTR ".nvimlog" static uv_mutex_t mutex; diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 0ba8dd98d0..c91a25df6e 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -3954,8 +3954,10 @@ long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp) if (ffdos) size += lnum - 1; - /* Don't count the last line break if 'bin' and 'noeol'. */ - if (buf->b_p_bin && !buf->b_p_eol && buf->b_ml.ml_line_count == lnum) { + /* Don't count the last line break if 'noeol' and ('bin' or + * 'nofixeol'). */ + if ((!buf->b_p_fixeol || buf->b_p_bin) && !buf->b_p_eol + && buf->b_ml.ml_line_count == lnum) { size -= ffdos + 1; } } diff --git a/src/nvim/memline_defs.h b/src/nvim/memline_defs.h index bcc1c673d2..34a002af5d 100644 --- a/src/nvim/memline_defs.h +++ b/src/nvim/memline_defs.h @@ -41,7 +41,7 @@ typedef struct memline { int ml_flags; infoptr_T *ml_stack; /* stack of pointer blocks (array of IPTRs) */ - int ml_stack_top; /* current top if ml_stack */ + int ml_stack_top; /* current top of ml_stack */ int ml_stack_size; /* total number of entries in ml_stack */ linenr_T ml_line_lnum; /* line number of cached line, 0 if not valid */ diff --git a/src/nvim/normal.c b/src/nvim/normal.c index ad53e9bf24..a2e473fcb8 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -7466,6 +7466,13 @@ static void nv_object(cmdarg_T *cap) flag = current_block(cap->oap, cap->count1, include, '<', '>'); break; case 't': /* "at" = a tag block (xml and html) */ + // Do not adjust oap->end in do_pending_operator() + // otherwise there are different results for 'dit' + // (note leading whitespace in last line): + // 1) <b> 2) <b> + // foobar foobar + // </b> </b> + cap->retval |= CA_NO_ADJ_OP_END; flag = current_tagblock(cap->oap, cap->count1, include); break; case 'p': /* "ap" = a paragraph */ diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 956b9c7758..bef0ebaeed 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -4964,7 +4964,7 @@ void cursor_pos_info(void) &char_count_cursor, len, eol_size); if (lnum == curbuf->b_ml.ml_line_count && !curbuf->b_p_eol - && curbuf->b_p_bin + && (curbuf->b_p_bin || !curbuf->b_p_fixeol) && (long)STRLEN(s) < len) byte_count_cursor -= eol_size; } @@ -4985,7 +4985,7 @@ void cursor_pos_info(void) } /* Correction for when last line doesn't have an EOL. */ - if (!curbuf->b_p_eol && curbuf->b_p_bin) + if (!curbuf->b_p_eol && (curbuf->b_p_bin || !curbuf->b_p_fixeol)) byte_count -= eol_size; if (l_VIsual_active) { diff --git a/src/nvim/option.c b/src/nvim/option.c index f5080c7a91..486f2083a6 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -122,6 +122,7 @@ static char_u *p_cpt; static char_u *p_cfu; static char_u *p_ofu; static int p_eol; +static int p_fixeol; static int p_et; static char_u *p_fenc; static char_u *p_ff; @@ -1018,12 +1019,9 @@ void set_init_2(void) */ void set_init_3(void) { -#if defined(UNIX) || defined(WIN3264) - /* - * Set 'shellpipe' and 'shellredir', depending on the 'shell' option. - * This is done after other initializations, where 'shell' might have been - * set, but only if they have not been set before. - */ + // Set 'shellpipe' and 'shellredir', depending on the 'shell' option. + // This is done after other initializations, where 'shell' might have been + // set, but only if they have not been set before. int idx_srr; int do_srr; int idx_sp; @@ -1080,8 +1078,6 @@ void set_init_3(void) } xfree(p); } -#endif - set_title_defaults(); } @@ -1503,9 +1499,10 @@ do_set ( } else if (opt_idx >= 0) { /* string */ char_u *save_arg = NULL; char_u *s = NULL; - char_u *oldval; /* previous value if *varp */ + char_u *oldval = NULL; // previous value if *varp char_u *newval; - char_u *origval; + char_u *origval = NULL; + char_u *saved_origval = NULL; unsigned newlen; int comma; int bs; @@ -1772,14 +1769,37 @@ do_set ( /* Set the new value. */ *(char_u **)(varp) = newval; + if (!starting && origval != NULL) { + // origval may be freed by + // did_set_string_option(), make a copy. + saved_origval = vim_strsave(origval); + } + /* Handle side effects, and set the global value for * ":set" on local options. */ errmsg = did_set_string_option(opt_idx, (char_u **)varp, new_value_alloced, oldval, errbuf, opt_flags); - /* If error detected, print the error message. */ - if (errmsg != NULL) + // If error detected, print the error message. + if (errmsg != NULL) { + xfree(saved_origval); goto skip; + } + + if (saved_origval != NULL) { + char_u buf_type[7]; + vim_snprintf((char *)buf_type, ARRAY_SIZE(buf_type), "%s", + (opt_flags & OPT_LOCAL) ? "local" : "global"); + set_vim_var_string(VV_OPTION_NEW, + *(char_u **)varp, -1); + set_vim_var_string(VV_OPTION_OLD, saved_origval, -1); + set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); + apply_autocmds(EVENT_OPTIONSET, + (char_u *)options[opt_idx].fullname, + NULL, false, NULL); + reset_v_option_vars(); + xfree(saved_origval); + } } else { // key code option(FIXME(tarruda): Show a warning or something // similar) @@ -2329,6 +2349,7 @@ set_string_option ( char_u *s; char_u **varp; char_u *oldval; + char_u *saved_oldval = NULL; char_u *r = NULL; if (options[opt_idx].var == NULL) /* don't set hidden option */ @@ -2342,10 +2363,30 @@ set_string_option ( : opt_flags); oldval = *varp; *varp = s; - if ((r = did_set_string_option(opt_idx, varp, TRUE, oldval, NULL, + + if (!starting) { + saved_oldval = vim_strsave(oldval); + } + + if ((r = did_set_string_option(opt_idx, varp, (int)true, oldval, NULL, opt_flags)) == NULL) did_set_option(opt_idx, opt_flags, TRUE); + // call autocommand after handling side effects + if (saved_oldval != NULL) { + char_u buf_type[7]; + vim_snprintf((char *)buf_type, ARRAY_SIZE(buf_type), "%s", + (opt_flags & OPT_LOCAL) ? "local" : "global"); + set_vim_var_string(VV_OPTION_NEW, *varp, -1); + set_vim_var_string(VV_OPTION_OLD, saved_oldval, -1); + set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); + apply_autocmds(EVENT_OPTIONSET, + (char_u *)options[opt_idx].fullname, + NULL, false, NULL); + reset_v_option_vars(); + xfree(saved_oldval); + } + return r; } @@ -3547,6 +3588,9 @@ set_bool_option ( /* when 'endofline' is changed, redraw the window title */ else if ((int *)varp == &curbuf->b_p_eol) { redraw_titles(); + } else if ((int *)varp == &curbuf->b_p_fixeol) { + // when 'fixeol' is changed, redraw the window title + redraw_titles(); } /* when 'bomb' is changed, redraw the window title and tab page text */ else if ((int *)varp == &curbuf->b_p_bomb) { @@ -3814,8 +3858,29 @@ set_bool_option ( * End of handling side effects for bool options. */ + // after handling side effects, call autocommand + options[opt_idx].flags |= P_WAS_SET; + if (!starting) { + char_u buf_old[2]; + char_u buf_new[2]; + char_u buf_type[7]; + vim_snprintf((char *)buf_old, ARRAY_SIZE(buf_old), "%d", + old_value ? true: false); + vim_snprintf((char *)buf_new, ARRAY_SIZE(buf_new), "%d", + value ? true: false); + vim_snprintf((char *)buf_type, ARRAY_SIZE(buf_type), "%s", + (opt_flags & OPT_LOCAL) ? "local" : "global"); + set_vim_var_string(VV_OPTION_NEW, buf_new, -1); + set_vim_var_string(VV_OPTION_OLD, buf_old, -1); + set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); + apply_autocmds(EVENT_OPTIONSET, + (char_u *) options[opt_idx].fullname, + NULL, false, NULL); + reset_v_option_vars(); + } + comp_col(); /* in case 'ruler' or 'showcmd' changed */ if (curwin->w_curswant != MAXCOL && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) @@ -4187,6 +4252,23 @@ set_num_option ( options[opt_idx].flags |= P_WAS_SET; + if (!starting && errmsg == NULL) { + char_u buf_old[NUMBUFLEN]; + char_u buf_new[NUMBUFLEN]; + char_u buf_type[7]; + vim_snprintf((char *)buf_old, ARRAY_SIZE(buf_old), "%ld", old_value); + vim_snprintf((char *)buf_new, ARRAY_SIZE(buf_new), "%ld", value); + vim_snprintf((char *)buf_type, ARRAY_SIZE(buf_type), "%s", + (opt_flags & OPT_LOCAL) ? "local" : "global"); + set_vim_var_string(VV_OPTION_NEW, buf_new, -1); + set_vim_var_string(VV_OPTION_OLD, buf_old, -1); + set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); + apply_autocmds(EVENT_OPTIONSET, + (char_u *) options[opt_idx].fullname, + NULL, false, NULL); + reset_v_option_vars(); + } + comp_col(); /* in case 'columns' or 'ls' changed */ if (curwin->w_curswant != MAXCOL && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) @@ -5221,6 +5303,7 @@ static char_u *get_varp(vimoption_T *p) case PV_CFU: return (char_u *)&(curbuf->b_p_cfu); case PV_OFU: return (char_u *)&(curbuf->b_p_ofu); case PV_EOL: return (char_u *)&(curbuf->b_p_eol); + case PV_FIXEOL: return (char_u *)&(curbuf->b_p_fixeol); case PV_ET: return (char_u *)&(curbuf->b_p_et); case PV_FENC: return (char_u *)&(curbuf->b_p_fenc); case PV_FF: return (char_u *)&(curbuf->b_p_ff); @@ -5465,6 +5548,7 @@ void buf_copy_options(buf_T *buf, int flags) buf->b_p_bin = p_bin; buf->b_p_bomb = p_bomb; buf->b_p_et = p_et; + buf->b_p_fixeol = p_fixeol; buf->b_p_et_nobin = p_et_nobin; buf->b_p_ml = p_ml; buf->b_p_ml_nobin = p_ml_nobin; @@ -6400,6 +6484,7 @@ void save_file_ff(buf_T *buf) * from when editing started (save_file_ff() called). * Also when 'endofline' was changed and 'binary' is set, or when 'bomb' was * changed and 'binary' is not set. + * Also when 'endofline' was changed and 'fixeol' is not set. * When "ignore_empty" is true don't consider a new, empty buffer to be * changed. */ @@ -6414,9 +6499,9 @@ bool file_ff_differs(buf_T *buf, bool ignore_empty) && *ml_get_buf(buf, (linenr_T)1, FALSE) == NUL) return FALSE; if (buf->b_start_ffc != *buf->b_p_ff) - return TRUE; - if (buf->b_p_bin && buf->b_start_eol != buf->b_p_eol) - return TRUE; + return true; + if ((buf->b_p_bin || !buf->b_p_fixeol) && buf->b_start_eol != buf->b_p_eol) + return true; if (!buf->b_p_bin && buf->b_start_bomb != buf->b_p_bomb) return TRUE; if (buf->b_start_fenc == NULL) diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index d4d3410d5c..c72e1cf0bb 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -665,6 +665,7 @@ enum { , BV_DEF , BV_INC , BV_EOL + , BV_FIXEOL , BV_EP , BV_ET , BV_FENC diff --git a/src/nvim/options.lua b/src/nvim/options.lua index b22e994efe..5187340629 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -799,6 +799,14 @@ return { defaults={if_true={vi="vert:|,fold:-"}} }, { + full_name='fixendofline', abbreviation='fixeol', + type='bool', scope={'buffer'}, + vi_def=true, + redraw={'statuslines'}, + varname='p_fixeol', + defaults={if_true={vi=true}} + }, + { full_name='fkmap', abbreviation='fk', type='bool', scope={'global'}, vi_def=true, diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index bf6db97fcf..a791dca39c 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -46,7 +46,19 @@ bool os_env_exists(const char *name) int os_setenv(const char *name, const char *value, int overwrite) FUNC_ATTR_NONNULL_ALL { +#ifdef HAVE_SETENV return setenv(name, value, overwrite); +#elif defined(HAVE_PUTENV_S) + if (!overwrite && os_getenv(name) != NULL) { + return 0; + } + if (_putenv_s(name, value) == 0) { + return 0; + } + return -1; +#else +# error "This system has no implementation available for os_setenv()" +#endif } /// Unset environment variable @@ -141,6 +153,27 @@ void init_homedir(void) char_u *var = (char_u *)os_getenv("HOME"); +#ifdef WIN32 + // Typically, $HOME is not defined on Windows, unless the user has + // specifically defined it for Vim's sake. However, on Windows NT + // platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for + // each user. Try constructing $HOME from these. + if (var == NULL) { + const char *homedrive = os_getenv("HOMEDRIVE"); + const char *homepath = os_getenv("HOMEPATH"); + if (homepath == NULL) { + homepath = "\\"; + } + if (homedrive != NULL && strlen(homedrive) + strlen(homepath) < MAXPATHL) { + snprintf((char *)NameBuff, MAXPATHL, "%s%s", homedrive, homepath); + if (NameBuff[0] != NUL) { + var = NameBuff; + vim_setenv("HOME", (char *)NameBuff); + } + } + } +#endif + if (var != NULL) { #ifdef UNIX /* diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 57e25560de..3813c45726 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -418,7 +418,8 @@ static void read_input(DynamicBuffer *buf) // Finished a line, add a NL, unless this line should not have one. // FIXME need to make this more readable if (lnum != curbuf->b_op_end.lnum - || !curbuf->b_p_bin + || (!curbuf->b_p_bin + && curbuf->b_p_fixeol) || (lnum != curbuf->b_no_eol_lnum && (lnum != curbuf->b_ml.ml_line_count diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c index 7158721433..0ff6016e32 100644 --- a/src/nvim/os/signal.c +++ b/src/nvim/os/signal.c @@ -32,9 +32,13 @@ void signal_init(void) signal_watcher_init(&loop, &shup, NULL); signal_watcher_init(&loop, &squit, NULL); signal_watcher_init(&loop, &sterm, NULL); +#ifdef SIGPIPE signal_watcher_start(&spipe, on_signal, SIGPIPE); +#endif signal_watcher_start(&shup, on_signal, SIGHUP); +#ifdef SIGQUIT signal_watcher_start(&squit, on_signal, SIGQUIT); +#endif signal_watcher_start(&sterm, on_signal, SIGTERM); #ifdef SIGPWR signal_watcher_init(&loop, &spwr, NULL); @@ -82,12 +86,16 @@ static char * signal_name(int signum) case SIGPWR: return "SIGPWR"; #endif +#ifdef SIGPIPE case SIGPIPE: return "SIGPIPE"; +#endif case SIGTERM: return "SIGTERM"; +#ifdef SIGQUIT case SIGQUIT: return "SIGQUIT"; +#endif case SIGHUP: return "SIGHUP"; default: @@ -123,11 +131,15 @@ static void on_signal(SignalWatcher *handle, int signum, void *data) ml_sync_all(false, false); break; #endif +#ifdef SIGPIPE case SIGPIPE: // Ignore break; +#endif case SIGTERM: +#ifdef SIGQUIT case SIGQUIT: +#endif case SIGHUP: if (!rejecting_deadly) { deadly_signal(signum); diff --git a/src/nvim/path.c b/src/nvim/path.c index 877ef1565a..253035ed99 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -467,16 +467,13 @@ bool path_has_wildcard(const char_u *p) return false; } -#if defined(UNIX) /* * Unix style wildcard expansion code. - * It's here because it's used both for Unix and Mac. */ static int pstrcmp(const void *a, const void *b) { return pathcmp(*(char **)a, *(char **)b, -1); } -#endif /// Checks if a path has a character path_expand can expand. /// @param p The path to expand. diff --git a/src/nvim/po/it.po b/src/nvim/po/it.po index 7fe61c45bc..729697eee3 100644 --- a/src/nvim/po/it.po +++ b/src/nvim/po/it.po @@ -25,9 +25,8 @@ msgstr "" "Content-Transfer-Encoding: 8-bit\n" #: ../api/private/helpers.c:201 -#, fuzzy msgid "Unable to get option value" -msgstr "impossibile ottenere il valore di opzione" +msgstr "Impossibile ottenere il valore di opzione" #: ../api/private/helpers.c:204 msgid "internal error: unknown option type" @@ -827,18 +826,16 @@ msgid "sort() argument" msgstr "argomento di sort()" #: ../eval.c:13721 -#, fuzzy msgid "uniq() argument" -msgstr "argomento di add()" +msgstr "argomento di uniq()" #: ../eval.c:13776 msgid "E702: Sort compare function failed" msgstr "E702: Funzione confronto nel sort non riuscita" #: ../eval.c:13806 -#, fuzzy msgid "E882: Uniq compare function failed" -msgstr "E702: Funzione confronto nel sort non riuscita" +msgstr "E882: Funzione di comparazione 'uniq' fallita" #: ../eval.c:14085 msgid "(Invalid)" @@ -963,16 +960,12 @@ msgid "E129: Function name required" msgstr "E129: Nome funzione necessario" #: ../eval.c:17824 -#, fuzzy, c-format msgid "E128: Function name must start with a capital or \"s:\": %s" -msgstr "" -"E128: Il nome funzione deve iniziare con una maiuscola o contenere ':': %s" +msgstr "E128: Il nome funzione deve iniziare con una maiuscola o \"s:\": %s" #: ../eval.c:17833 -#, fuzzy, c-format msgid "E884: Function name cannot contain a colon: %s" -msgstr "" -"E128: Il nome funzione deve iniziare con una maiuscola o contenere ':': %s" +msgstr "E884: Il nome funzione non può contenere una virgola: %s" #: ../eval.c:18336 #, c-format @@ -2667,18 +2660,17 @@ msgid "E17: \"%s\" is a directory" msgstr "E17: \"%s\" è una directory" #: ../globals.h:1020 -#, fuzzy msgid "E900: Invalid job id" -msgstr "E49: Quantità di 'scroll' non valida" +msgstr "E900: 'Job id' non valido" #: ../globals.h:1021 msgid "E901: Job table is full" -msgstr "" +msgstr "E901: Job table piena" #: ../globals.h:1022 #, c-format msgid "E902: \"%s\" is not an executable" -msgstr "" +msgstr "E902: \"%s\" non è un esegubile" #: ../globals.h:1024 #, c-format @@ -2703,7 +2695,7 @@ msgstr "E22: Script troppo nidificati" #: ../globals.h:1031 msgid "E23: No alternate file" -msgstr "E23: Nessun file alternato" +msgstr "E23: Nessun file alternativo" #: ../globals.h:1032 msgid "E24: No such abbreviation" @@ -2791,9 +2783,8 @@ msgid "E37: No write since last change (add ! to override)" msgstr "E37: Non salvato dopo modifica (aggiungi ! per eseguire comunque)" #: ../globals.h:1055 -#, fuzzy msgid "E37: No write since last change" -msgstr "[Non salvato dopo l'ultima modifica]\n" +msgstr "E37: Non salvato dall'ultima modifica" #: ../globals.h:1056 msgid "E38: Null argument" @@ -2857,8 +2848,7 @@ msgstr "E46: Non posso cambiare la variabile read-only \"%s\"" #: ../globals.h:1075 #, c-format msgid "E794: Cannot set variable in the sandbox: \"%s\"" -msgstr "" -"E794: Non posso impostare la variabile read-only in ambiente protetto: \"%s\"" +msgstr "E794: Non posso impostare la variabile read-only in ambiente protetto: \"%s\"" #: ../globals.h:1076 msgid "E47: Error while reading errorfile" @@ -4869,9 +4859,8 @@ msgid "E777: String or List expected" msgstr "E777: aspettavo Stringa o Lista" #: ../regexp.c:359 -#, fuzzy, c-format msgid "E369: invalid item in %s%%[]" -msgstr "E239: Testo 'sign' non valido: %s" +msgstr "E369: elemento non valido in %s%%[]" #: ../regexp.c:374 #, c-format @@ -5004,7 +4993,7 @@ msgstr "E866: (NFA regexp) %c fuori posto" #: ../regexp_nfa.c:242 #, c-format msgid "E877: (NFA regexp) Invalid character class: %<PRId64>" -msgstr "" +msgstr "E877: (NFA regexp) Classe di caratteri non valida: %<PRId64>" #: ../regexp_nfa.c:1261 #, c-format @@ -5611,14 +5600,12 @@ msgid "E765: 'spellfile' does not have %<PRId64> entries" msgstr "E765: 'spellfile' non ha %<PRId64> elementi" #: ../spell.c:8074 -#, fuzzy, c-format msgid "Word '%.*s' removed from %s" -msgstr "Parola rimossa da %s" +msgstr "Parola '%.*s' rimossa da %s" #: ../spell.c:8117 -#, fuzzy, c-format msgid "Word '%.*s' added to %s" -msgstr "Parola aggiunta a %s" +msgstr "Parola '%.*s' aggiunta a %s" #: ../spell.c:8381 msgid "E763: Word characters differ between spell files" @@ -6100,9 +6087,8 @@ msgstr "Vim: Errore leggendo l'input, esco...\n" #. This happens when the FileChangedRO autocommand changes the #. * file in a way it becomes shorter. #: ../undo.c:379 -#, fuzzy msgid "E881: Line count changed unexpectedly" -msgstr "E834: Il conteggio delle righe è inaspettatamente cambiato" +msgstr "E881: Il conteggio delle righe è inaspettatamente cambiato" #: ../undo.c:627 #, c-format diff --git a/src/nvim/search.c b/src/nvim/search.c index cb461c9ef2..fb7dfa350b 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -918,7 +918,7 @@ static int first_submatch(regmmatch_T *rp) * Careful: If spats[0].off.line == TRUE and spats[0].off.off == 0 this * makes the movement linewise without moving the match position. * - * return 0 for failure, 1 for found, 2 for found and line offset added + * Return 0 for failure, 1 for found, 2 for found and line offset added. */ int do_search( oparg_T *oap, /* can be NULL */ @@ -3193,6 +3193,7 @@ current_tagblock ( int do_include = include; bool save_p_ws = p_ws; int retval = FAIL; + int is_inclusive = true; p_ws = false; @@ -3287,9 +3288,16 @@ again: if (inc_cursor() < 0) break; } else { - /* Exclude the '<' of the end tag. */ - if (*get_cursor_pos_ptr() == '<') + char_u *c = get_cursor_pos_ptr(); + // Exclude the '<' of the end tag. + // If the closing tag is on new line, do not decrement cursor, but make + // operation exclusive, so that the linefeed will be selected + if (*c == '<' && !VIsual_active && curwin->w_cursor.col == 0) { + // do not decrement cursor + is_inclusive = false; + } else if (*c == '<') { dec_cursor(); + } } end_pos = curwin->w_cursor; @@ -3334,8 +3342,9 @@ again: * on an empty area. */ curwin->w_cursor = start_pos; oap->inclusive = false; - } else - oap->inclusive = true; + } else { + oap->inclusive = is_inclusive; + } } retval = OK; diff --git a/src/nvim/shada.c b/src/nvim/shada.c index e21c6f17fe..340c14066a 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -10,7 +10,9 @@ #include <stdint.h> #include <inttypes.h> #include <errno.h> -#include <unistd.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif #include <assert.h> #include <msgpack.h> @@ -203,11 +205,11 @@ enum SRNIFlags { kSDReadHeader = (1 << kSDItemHeader), ///< Determines whether header should ///< be read (it is usually ignored). kSDReadUndisableableData = ( - (1 << kSDItemSearchPattern) - | (1 << kSDItemSubString) - | (1 << kSDItemJump)), ///< Data reading which cannot be disabled by &shada - ///< or other options except for disabling reading - ///< ShaDa as a whole. + (1 << kSDItemSearchPattern) + | (1 << kSDItemSubString) + | (1 << kSDItemJump)), ///< Data reading which cannot be disabled by + ///< &shada or other options except for disabling + ///< reading ShaDa as a whole. kSDReadRegisters = (1 << kSDItemRegister), ///< Determines whether registers ///< should be read (may only be ///< disabled when writing, but @@ -444,7 +446,7 @@ typedef struct sd_write_def { .attr = { __VA_ARGS__ } \ } \ } -#define DEFAULT_POS {1, 0, 0} +#define DEFAULT_POS { 1, 0, 0 } static const pos_T default_pos = DEFAULT_POS; static const ShadaEntry sd_default_values[] = { [kSDItemMissing] = { .type = kSDItemMissing, .timestamp = 0 }, @@ -531,11 +533,14 @@ static inline void hmll_init(HMLList *const hmll, const size_t size) /// /// @param hmll Pointer to the list. /// @param cur_entry Name of the variable to iterate over. +/// @param code Code to execute on each iteration. /// /// @return `for` cycle header (use `HMLL_FORALL(hmll, cur_entry) {body}`). -#define HMLL_FORALL(hmll, cur_entry) \ +#define HMLL_FORALL(hmll, cur_entry, code) \ for (HMLListEntry *cur_entry = (hmll)->first; cur_entry != NULL; \ - cur_entry = cur_entry->next) + cur_entry = cur_entry->next) { \ + code \ + } \ /// Remove entry from the linked list /// @@ -631,11 +636,14 @@ static inline void hmll_insert(HMLList *const hmll, /// @param hmll Pointer to the list. /// @param cur_entry Name of the variable to iterate over, must be already /// defined. +/// @param code Code to execute on each iteration. /// /// @return `for` cycle header (use `HMLL_FORALL(hmll, cur_entry) {body}`). -#define HMLL_ITER_BACK(hmll, cur_entry) \ +#define HMLL_ITER_BACK(hmll, cur_entry, code) \ for (cur_entry = (hmll)->last; cur_entry != NULL; \ - cur_entry = cur_entry->prev) + cur_entry = cur_entry->prev) { \ + code \ + } /// Free linked list /// @@ -957,11 +965,11 @@ static int shada_read_file(const char *const file, const int flags) if (p_verbose > 0) { verbose_enter(); smsg(_("Reading ShaDa file \"%s\"%s%s%s"), - fname, - (flags & kShaDaWantInfo) ? _(" info") : "", - (flags & kShaDaWantMarks) ? _(" marks") : "", - (flags & kShaDaGetOldfiles) ? _(" oldfiles") : "", - of_ret != 0 ? _(" FAILED") : ""); + fname, + (flags & kShaDaWantInfo) ? _(" info") : "", + (flags & kShaDaWantMarks) ? _(" marks") : "", + (flags & kShaDaGetOldfiles) ? _(" oldfiles") : "", + of_ret != 0 ? _(" FAILED") : ""); verbose_leave(); } @@ -1009,8 +1017,8 @@ static const void *shada_hist_iter(const void *const iter, .histtype = history_type, .string = (char *) hist_he.hisstr, .sep = (char) (history_type == HIST_SEARCH - ? (char) hist_he.hisstr[STRLEN(hist_he.hisstr) + 1] - : 0), + ? (char) hist_he.hisstr[STRLEN(hist_he.hisstr) + 1] + : 0), .additional_elements = hist_he.additional_elements, } } @@ -1072,11 +1080,11 @@ static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry, } } HMLListEntry *insert_after; - HMLL_ITER_BACK(hmll, insert_after) { + HMLL_ITER_BACK(hmll, insert_after, { if (insert_after->data.timestamp <= entry.timestamp) { break; } - } + }) hmll_insert(hmll, insert_after, entry, can_free_entry); } @@ -1134,14 +1142,14 @@ static inline void hms_to_he_array(const HistoryMergerState *const hms_p, FUNC_ATTR_NONNULL_ALL { histentry_T *hist = hist_array; - HMLL_FORALL(&hms_p->hmll, cur_entry) { + HMLL_FORALL(&hms_p->hmll, cur_entry, { hist->timestamp = cur_entry->data.timestamp; hist->hisnum = (int) (hist - hist_array) + 1; hist->hisstr = (char_u *) cur_entry->data.data.history_item.string; hist->additional_elements = cur_entry->data.data.history_item.additional_elements; hist++; - } + }) *new_hisnum = (int) (hist - hist_array); *new_hisidx = *new_hisnum - 1; } @@ -1159,10 +1167,11 @@ static inline void hms_dealloc(HistoryMergerState *const hms_p) /// /// @param[in] hms_p Merger structure to iterate over. /// @param[out] cur_entry Name of the iterator variable. +/// @param code Code to execute on each iteration. /// /// @return for cycle header. Use `HMS_ITER(hms_p, cur_entry) {body}`. -#define HMS_ITER(hms_p, cur_entry) \ - HMLL_FORALL(&((hms_p)->hmll), cur_entry) +#define HMS_ITER(hms_p, cur_entry, code) \ + HMLL_FORALL(&((hms_p)->hmll), cur_entry, code) /// Find buffer for given buffer name (cached) /// @@ -1339,18 +1348,18 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) (cur_entry.data.search_pattern.is_substitute_pattern ? &set_substitute_pattern : &set_search_pattern)((SearchPattern) { - .magic = cur_entry.data.search_pattern.magic, - .no_scs = !cur_entry.data.search_pattern.smartcase, - .off = { - .dir = cur_entry.data.search_pattern.search_backward ? '?' : '/', - .line = cur_entry.data.search_pattern.has_line_offset, - .end = cur_entry.data.search_pattern.place_cursor_at_end, - .off = cur_entry.data.search_pattern.offset, - }, - .pat = (char_u *) cur_entry.data.search_pattern.pat, - .additional_data = cur_entry.data.search_pattern.additional_data, - .timestamp = cur_entry.timestamp, - }); + .magic = cur_entry.data.search_pattern.magic, + .no_scs = !cur_entry.data.search_pattern.smartcase, + .off = { + .dir = cur_entry.data.search_pattern.search_backward ? '?' : '/', + .line = cur_entry.data.search_pattern.has_line_offset, + .end = cur_entry.data.search_pattern.place_cursor_at_end, + .off = cur_entry.data.search_pattern.offset, + }, + .pat = (char_u *) cur_entry.data.search_pattern.pat, + .additional_data = cur_entry.data.search_pattern.additional_data, + .timestamp = cur_entry.timestamp, + }); if (cur_entry.data.search_pattern.is_last_used) { set_last_used_pattern( cur_entry.data.search_pattern.is_substitute_pattern); @@ -2428,13 +2437,13 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, } const unsigned srni_flags = (unsigned) ( - kSDReadUndisableableData - | kSDReadUnknown - | (dump_history ? kSDReadHistory : 0) - | (dump_registers ? kSDReadRegisters : 0) - | (dump_global_vars ? kSDReadVariables : 0) - | (dump_global_marks ? kSDReadGlobalMarks : 0) - | (num_marked_files ? kSDReadLocalMarks | kSDReadChanges : 0)); + kSDReadUndisableableData + | kSDReadUnknown + | (dump_history ? kSDReadHistory : 0) + | (dump_registers ? kSDReadRegisters : 0) + | (dump_global_vars ? kSDReadVariables : 0) + | (dump_global_marks ? kSDReadGlobalMarks : 0) + | (num_marked_files ? kSDReadLocalMarks | kSDReadChanges : 0)); msgpack_packer *const packer = msgpack_packer_new(sd_writer, &msgpack_sd_writer_write); @@ -2893,16 +2902,16 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, for (size_t i = 0; i < HIST_COUNT; i++) { if (dump_one_history[i]) { hms_insert_whole_neovim_history(&wms->hms[i]); - HMS_ITER(&wms->hms[i], cur_entry) { + HMS_ITER(&wms->hms[i], cur_entry, { if (!shada_pack_encoded_entry( - packer, &sd_writer->sd_conv, (PossiblyFreedShadaEntry) { - .data = cur_entry->data, - .can_free_entry = cur_entry->can_free_entry, - }, max_kbyte)) { + packer, &sd_writer->sd_conv, (PossiblyFreedShadaEntry) { + .data = cur_entry->data, + .can_free_entry = cur_entry->can_free_entry, + }, max_kbyte)) { ret = kSDWriteFailed; break; } - } + }) hms_dealloc(&wms->hms[i]); if (ret == kSDWriteFailed) { goto shada_write_exit; @@ -3353,8 +3362,8 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv, entry_name " entry at position %" PRIu64 " " \ error_desc #define CHECK_KEY(key, expected) ( \ - key.via.str.size == sizeof(expected) - 1 \ - && STRNCMP(key.via.str.ptr, expected, sizeof(expected) - 1) == 0) + key.via.str.size == sizeof(expected) - 1 \ + && STRNCMP(key.via.str.ptr, expected, sizeof(expected) - 1) == 0) #define CLEAR_GA_AND_ERROR_OUT(ga) \ do { \ ga_clear(&ga); \ @@ -3377,18 +3386,17 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv, tgt = proc(obj.via.attr); \ } while (0) #define CHECK_KEY_IS_STR(entry_name) \ - do { \ - if (unpacked.data.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR) { \ - emsgu(_(READERR(entry_name, "has key which is not a string")), \ - initial_fpos); \ - CLEAR_GA_AND_ERROR_OUT(ad_ga); \ - } else if (unpacked.data.via.map.ptr[i].key.via.str.size == 0) { \ - emsgu(_(READERR(entry_name, "has empty key")), initial_fpos); \ - CLEAR_GA_AND_ERROR_OUT(ad_ga); \ - } \ - } while (0) + if (unpacked.data.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR) { \ + emsgu(_(READERR(entry_name, "has key which is not a string")), \ + initial_fpos); \ + CLEAR_GA_AND_ERROR_OUT(ad_ga); \ + } else if (unpacked.data.via.map.ptr[i].key.via.str.size == 0) { \ + emsgu(_(READERR(entry_name, "has empty key")), initial_fpos); \ + CLEAR_GA_AND_ERROR_OUT(ad_ga); \ + } #define CHECKED_KEY(entry_name, name, error_desc, tgt, condition, attr, proc) \ - if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, name)) { \ + else if (CHECK_KEY( /* NOLINT(readability/braces) */ \ + unpacked.data.via.map.ptr[i].key, name)) { \ CHECKED_ENTRY( \ condition, "has " name " key value " error_desc, \ entry_name, unpacked.data.via.map.ptr[i].val, \ @@ -3408,17 +3416,17 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv, #define INT_KEY(entry_name, name, tgt, proc) \ CHECKED_KEY( \ entry_name, name, "which is not an integer", tgt, \ - (unpacked.data.via.map.ptr[i].val.type \ - == MSGPACK_OBJECT_POSITIVE_INTEGER \ - || unpacked.data.via.map.ptr[i].val.type \ - == MSGPACK_OBJECT_NEGATIVE_INTEGER), \ + ((unpacked.data.via.map.ptr[i].val.type \ + == MSGPACK_OBJECT_POSITIVE_INTEGER) \ + || (unpacked.data.via.map.ptr[i].val.type \ + == MSGPACK_OBJECT_NEGATIVE_INTEGER)), \ i64, proc) #define INTEGER_KEY(entry_name, name, tgt) \ INT_KEY(entry_name, name, tgt, TOINT) #define LONG_KEY(entry_name, name, tgt) \ INT_KEY(entry_name, name, tgt, TOLONG) #define ADDITIONAL_KEY \ - { \ + else { /* NOLINT(readability/braces) */ \ ga_grow(&ad_ga, 1); \ memcpy(((char *)ad_ga.ga_data) + ((size_t) ad_ga.ga_len \ * sizeof(*unpacked.data.via.map.ptr)), \ @@ -3427,9 +3435,9 @@ static inline char *get_converted_string(const vimconv_T *const sd_conv, ad_ga.ga_len++; \ } #define CONVERTED(str, len) ( \ - sd_reader->sd_conv.vc_type != CONV_NONE \ - ? get_converted_string(&sd_reader->sd_conv, (str), (len)) \ - : xmemdupz((str), (len))) + sd_reader->sd_conv.vc_type != CONV_NONE \ + ? get_converted_string(&sd_reader->sd_conv, (str), (len)) \ + : xmemdupz((str), (len))) #define BIN_CONVERTED(b) CONVERTED(b.ptr, b.size) #define SET_ADDITIONAL_DATA(tgt, name) \ do { \ @@ -3623,38 +3631,28 @@ shada_read_next_item_start: garray_T ad_ga; ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1); for (size_t i = 0; i < unpacked.data.via.map.size; i++) { - CHECK_KEY_IS_STR("search pattern"); + CHECK_KEY_IS_STR("search pattern") BOOLEAN_KEY("search pattern", SEARCH_KEY_MAGIC, entry->data.search_pattern.magic) - else - BOOLEAN_KEY("search pattern", SEARCH_KEY_SMARTCASE, - entry->data.search_pattern.smartcase) - else - BOOLEAN_KEY("search pattern", SEARCH_KEY_HAS_LINE_OFFSET, - entry->data.search_pattern.has_line_offset) - else - BOOLEAN_KEY("search pattern", SEARCH_KEY_PLACE_CURSOR_AT_END, - entry->data.search_pattern.place_cursor_at_end) - else - BOOLEAN_KEY("search pattern", SEARCH_KEY_IS_LAST_USED, - entry->data.search_pattern.is_last_used) - else - BOOLEAN_KEY("search pattern", SEARCH_KEY_IS_SUBSTITUTE_PATTERN, - entry->data.search_pattern.is_substitute_pattern) - else - BOOLEAN_KEY("search pattern", SEARCH_KEY_HIGHLIGHTED, - entry->data.search_pattern.highlighted) - else - BOOLEAN_KEY("search pattern", SEARCH_KEY_BACKWARD, - entry->data.search_pattern.search_backward) - else - INTEGER_KEY("search pattern", SEARCH_KEY_OFFSET, - entry->data.search_pattern.offset) - else - CONVERTED_STRING_KEY("search pattern", SEARCH_KEY_PAT, - entry->data.search_pattern.pat) - else - ADDITIONAL_KEY + BOOLEAN_KEY("search pattern", SEARCH_KEY_SMARTCASE, + entry->data.search_pattern.smartcase) + BOOLEAN_KEY("search pattern", SEARCH_KEY_HAS_LINE_OFFSET, + entry->data.search_pattern.has_line_offset) + BOOLEAN_KEY("search pattern", SEARCH_KEY_PLACE_CURSOR_AT_END, + entry->data.search_pattern.place_cursor_at_end) + BOOLEAN_KEY("search pattern", SEARCH_KEY_IS_LAST_USED, + entry->data.search_pattern.is_last_used) + BOOLEAN_KEY("search pattern", SEARCH_KEY_IS_SUBSTITUTE_PATTERN, + entry->data.search_pattern.is_substitute_pattern) + BOOLEAN_KEY("search pattern", SEARCH_KEY_HIGHLIGHTED, + entry->data.search_pattern.highlighted) + BOOLEAN_KEY("search pattern", SEARCH_KEY_BACKWARD, + entry->data.search_pattern.search_backward) + INTEGER_KEY("search pattern", SEARCH_KEY_OFFSET, + entry->data.search_pattern.offset) + CONVERTED_STRING_KEY("search pattern", SEARCH_KEY_PAT, + entry->data.search_pattern.pat) + ADDITIONAL_KEY } if (entry->data.search_pattern.pat == NULL) { emsgu(_(READERR("search pattern", "has no pattern")), initial_fpos); @@ -3675,7 +3673,7 @@ shada_read_next_item_start: garray_T ad_ga; ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1); for (size_t i = 0; i < unpacked.data.via.map.size; i++) { - CHECK_KEY_IS_STR("mark"); + CHECK_KEY_IS_STR("mark") if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, KEY_NAME_CHAR)) { if (type_u64 == kSDItemJump || type_u64 == kSDItemChange) { emsgu(_(READERR("mark", "has n key which is only valid for " @@ -3688,15 +3686,11 @@ shada_read_next_item_start: "has n key value which is not an unsigned integer", "mark", unpacked.data.via.map.ptr[i].val, entry->data.filemark.name, u64, TOCHAR); - } else { - LONG_KEY("mark", KEY_LNUM, entry->data.filemark.mark.lnum) - else - INTEGER_KEY("mark", KEY_COL, entry->data.filemark.mark.col) - else - STRING_KEY("mark", KEY_FILE, entry->data.filemark.fname) - else - ADDITIONAL_KEY } + LONG_KEY("mark", KEY_LNUM, entry->data.filemark.mark.lnum) + INTEGER_KEY("mark", KEY_COL, entry->data.filemark.mark.col) + STRING_KEY("mark", KEY_FILE, entry->data.filemark.fname) + ADDITIONAL_KEY } if (entry->data.filemark.fname == NULL) { emsgu(_(READERR("mark", "is missing file name")), initial_fpos); @@ -3721,48 +3715,44 @@ shada_read_next_item_start: garray_T ad_ga; ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1); for (size_t i = 0; i < unpacked.data.via.map.size; i++) { - CHECK_KEY_IS_STR("register"); - TYPED_KEY("register", REG_KEY_TYPE, "an unsigned integer", - entry->data.reg.type, POSITIVE_INTEGER, u64, TOU8) - else - TYPED_KEY("register", KEY_NAME_CHAR, "an unsigned integer", - entry->data.reg.name, POSITIVE_INTEGER, u64, TOCHAR) - else - TYPED_KEY("register", REG_KEY_WIDTH, "an unsigned integer", - entry->data.reg.width, POSITIVE_INTEGER, u64, TOSIZE) - else - if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, - REG_KEY_CONTENTS)) { - if (unpacked.data.via.map.ptr[i].val.type != MSGPACK_OBJECT_ARRAY) { - emsgu(_(READERR( - "register", - "has " REG_KEY_CONTENTS " key with non-array value")), - initial_fpos); - CLEAR_GA_AND_ERROR_OUT(ad_ga); - } - if (unpacked.data.via.map.ptr[i].val.via.array.size == 0) { - emsgu(_(READERR("register", - "has " REG_KEY_CONTENTS " key with empty array")), - initial_fpos); + CHECK_KEY_IS_STR("register") + if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, + REG_KEY_CONTENTS)) { + if (unpacked.data.via.map.ptr[i].val.type != MSGPACK_OBJECT_ARRAY) { + emsgu(_(READERR("register", + "has " REG_KEY_CONTENTS + " key with non-array value")), + initial_fpos); + CLEAR_GA_AND_ERROR_OUT(ad_ga); + } + if (unpacked.data.via.map.ptr[i].val.via.array.size == 0) { + emsgu(_(READERR("register", + "has " REG_KEY_CONTENTS " key with empty array")), + initial_fpos); + CLEAR_GA_AND_ERROR_OUT(ad_ga); + } + const msgpack_object_array arr = + unpacked.data.via.map.ptr[i].val.via.array; + for (size_t i = 0; i < arr.size; i++) { + if (arr.ptr[i].type != MSGPACK_OBJECT_BIN) { + emsgu(_(READERR("register", "has " REG_KEY_CONTENTS " array " + "with non-binary value")), initial_fpos); CLEAR_GA_AND_ERROR_OUT(ad_ga); } - const msgpack_object_array arr = - unpacked.data.via.map.ptr[i].val.via.array; - for (size_t i = 0; i < arr.size; i++) { - if (arr.ptr[i].type != MSGPACK_OBJECT_BIN) { - emsgu(_(READERR("register", "has " REG_KEY_CONTENTS " array " - "with non-binary value")), initial_fpos); - CLEAR_GA_AND_ERROR_OUT(ad_ga); - } - } - entry->data.reg.contents_size = arr.size; - entry->data.reg.contents = xmalloc(arr.size * sizeof(char *)); - for (size_t i = 0; i < arr.size; i++) { - entry->data.reg.contents[i] = BIN_CONVERTED(arr.ptr[i].via.bin); - } - } else { - ADDITIONAL_KEY } + entry->data.reg.contents_size = arr.size; + entry->data.reg.contents = xmalloc(arr.size * sizeof(char *)); + for (size_t i = 0; i < arr.size; i++) { + entry->data.reg.contents[i] = BIN_CONVERTED(arr.ptr[i].via.bin); + } + } + TYPED_KEY("register", REG_KEY_TYPE, "an unsigned integer", + entry->data.reg.type, POSITIVE_INTEGER, u64, TOU8) + TYPED_KEY("register", KEY_NAME_CHAR, "an unsigned integer", + entry->data.reg.name, POSITIVE_INTEGER, u64, TOCHAR) + TYPED_KEY("register", REG_KEY_WIDTH, "an unsigned integer", + entry->data.reg.width, POSITIVE_INTEGER, u64, TOSIZE) + ADDITIONAL_KEY } if (entry->data.reg.contents == NULL) { emsgu(_(READERR("register", "has missing " REG_KEY_CONTENTS " array")), @@ -3830,8 +3820,8 @@ shada_read_next_item_hist_no_conv: + 1); // Separator character entry->data.history_item.string = xmalloc(strsize); memcpy(entry->data.history_item.string, - unpacked.data.via.array.ptr[1].via.bin.ptr, - unpacked.data.via.array.ptr[1].via.bin.size); + unpacked.data.via.array.ptr[1].via.bin.ptr, + unpacked.data.via.array.ptr[1].via.bin.size); } else { size_t len = unpacked.data.via.array.ptr[1].via.bin.size; char *const converted = string_convert( @@ -3951,17 +3941,14 @@ shada_read_next_item_hist_no_conv: const size_t j = i; { for (size_t i = 0; i < unpacked.data.via.map.size; i++) { - CHECK_KEY_IS_STR("buffer list entry"); + CHECK_KEY_IS_STR("buffer list entry") LONG_KEY("buffer list entry", KEY_LNUM, - entry->data.buffer_list.buffers[j].pos.lnum) - else - INTEGER_KEY("buffer list entry", KEY_COL, - entry->data.buffer_list.buffers[j].pos.col) - else - STRING_KEY("buffer list entry", KEY_FILE, - entry->data.buffer_list.buffers[j].fname) - else - ADDITIONAL_KEY + entry->data.buffer_list.buffers[j].pos.lnum) + INTEGER_KEY("buffer list entry", KEY_COL, + entry->data.buffer_list.buffers[j].pos.col) + STRING_KEY("buffer list entry", KEY_FILE, + entry->data.buffer_list.buffers[j].fname) + ADDITIONAL_KEY } } } diff --git a/src/nvim/testdir/test53.in b/src/nvim/testdir/test53.in index 8ca9c9ed29..7c35b2e853 100644 --- a/src/nvim/testdir/test53.in +++ b/src/nvim/testdir/test53.in @@ -23,6 +23,7 @@ jfXdit 0fXdit fXdat 0fXdat +dit :" :put =matchstr(\"abcd\", \".\", 0, 2) " b :put =matchstr(\"abcd\", \"..\", 0, 2) " bc @@ -97,6 +98,9 @@ voo "nah" sdf " asdf" sdf " sdf" sd -<b>asdX<i>a<i />sdf</i>asdf</b>- -<b>asdf<i>Xasdf</i>asdf</b>- -<b>asdX<i>as<b />df</i>asdf</b>- +-<b> +innertext object +</b> </begin> SEARCH: foobar diff --git a/src/nvim/testdir/test53.ok b/src/nvim/testdir/test53.ok index 0c0b9ded16..05206972a4 100644 --- a/src/nvim/testdir/test53.ok +++ b/src/nvim/testdir/test53.ok @@ -11,6 +11,7 @@ voo "zzzzzzzzzzzzzzzzzzzzzzzzzzzzsd -<b></b>- -<b>asdfasdf</b>- -- +-<b></b> </begin> b bc diff --git a/src/nvim/version.c b/src/nvim/version.c index 069574c087..c340211b02 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -95,7 +95,7 @@ static int included_patches[] = { // 901, // 900 NA // 899 NA - // 898, + 898, // 897, // 896, // 895, @@ -198,17 +198,17 @@ static int included_patches[] = { // 798, // 797, // 796 NA - // 795, + 795, // 794 NA 793, // 792, 791, - // 790, - // 789, + 790, + 789, // 788 NA - // 787, - // 786, - // 785, + 787, + 786, + 785, 784, // 783 NA // 782, @@ -335,10 +335,10 @@ static int included_patches[] = { // 661, 660, 659, - // 658, + 658, // 657 NA // 656, - // 655, + 655, // 654, 653, // 652 NA @@ -348,17 +348,17 @@ static int included_patches[] = { // 648 NA // 647 NA 646, - // 645, + 645, // 644 NA // 643, // 642, // 641, - // 640, + 640, // 639, // 638 NA 637, 636, - // 635, + 635, // 634, 633, // 632 NA |