diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/buffer.c | 10 | ||||
-rw-r--r-- | src/nvim/api/window.c | 4 | ||||
-rw-r--r-- | src/nvim/eval.c | 26 | ||||
-rw-r--r-- | src/nvim/eval.lua | 1 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 16 | ||||
-rw-r--r-- | src/nvim/if_cscope.c | 6 | ||||
-rw-r--r-- | src/nvim/option.c | 23 | ||||
-rw-r--r-- | src/nvim/os/env.c | 4 | ||||
-rw-r--r-- | src/nvim/testdir/test_alot.vim | 6 | ||||
-rw-r--r-- | src/nvim/testdir/test_glob2regpat.vim | 4 | ||||
-rw-r--r-- | src/nvim/testdir/test_modeline.vim | 22 | ||||
-rw-r--r-- | src/nvim/testdir/test_regexp_latin.vim | 12 | ||||
-rw-r--r-- | src/nvim/testdir/test_window_id.vim | 20 | ||||
-rw-r--r-- | src/nvim/window.c | 35 |
14 files changed, 148 insertions, 41 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 9a5ffecad4..06d7c1810c 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -487,7 +487,7 @@ end: try_end(err); } -/// Returns the byte offset for a line. +/// Returns the byte offset of a line (0-indexed). |api-indexing| /// /// Line 1 (index=0) has offset 0. UTF-8 bytes are counted. EOL is one byte. /// 'fileformat' and 'fileencoding' are ignored. The line index just after the @@ -879,7 +879,9 @@ void buffer_insert(Buffer buffer, nvim_buf_set_lines(0, buffer, lnum, lnum, true, lines, err); } -/// Return a tuple (row,col) representing the position of the named mark +/// Return a tuple (row,col) representing the position of the named mark. +/// +/// Marks are (1,0)-indexed. |api-indexing| /// /// @param buffer Buffer handle, or 0 for current buffer /// @param name Mark name @@ -993,8 +995,8 @@ Integer nvim_buf_add_highlight(Buffer buffer, /// Clears namespaced objects, highlights and virtual text, from a line range /// -/// To clear the namespace in the entire buffer, pass in 0 and -1 to -/// line_start and line_end respectively. +/// Lines are 0-indexed. |api-indexing| To clear the namespace in the entire +/// buffer, specify line_start=0 and line_end=-1. /// /// @param buffer Buffer handle, or 0 for current buffer /// @param ns_id Namespace to clear, or -1 to clear all namespaces. diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index e1c50cb89d..9fd1818a5c 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -74,7 +74,7 @@ void nvim_win_set_buf(Window window, Buffer buffer, Error *err) restore_win(save_curwin, save_curtab, false); } -/// Gets the cursor position in the window +/// Gets the (1,0)-indexed cursor position in the window. |api-indexing| /// /// @param window Window handle /// @param[out] err Error details, if any @@ -93,7 +93,7 @@ ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Error *err) return rv; } -/// Sets the cursor position in the window +/// Sets the (1,0)-indexed cursor position in the window. |api-indexing| /// /// @param window Window handle /// @param pos (row, col) tuple representing the new position diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 58285a7716..9f56b42fba 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -8868,8 +8868,8 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr) } else { len = strlen(fname); size_t usedlen = 0; - (void)modify_fname((char_u *)mods, &usedlen, (char_u **)&fname, &fbuf, - &len); + (void)modify_fname((char_u *)mods, false, &usedlen, + (char_u **)&fname, &fbuf, &len); } rettv->v_type = VAR_STRING; @@ -17888,6 +17888,25 @@ static void f_winheight(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } +// "winlayout()" function +static void f_winlayout(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + tabpage_T *tp; + + tv_list_alloc_ret(rettv, 2); + + if (argvars[0].v_type == VAR_UNKNOWN) { + tp = curtab; + } else { + tp = find_tabpage((int)tv_get_number(&argvars[0])); + if (tp == NULL) { + return; + } + } + + get_framelayout(tp->tp_topframe, rettv->vval.v_list, true); +} + /* * "winline()" function */ @@ -22639,6 +22658,7 @@ void reset_v_option_vars(void) int modify_fname( char_u *src, // string with modifiers + bool tilde_file, // "~" is a file name, not $HOME size_t *usedlen, // characters after src that are used char_u **fnamep, // file name so far char_u **bufp, // buffer for allocated file name or NULL @@ -22668,8 +22688,8 @@ repeat: || (*fnamep)[1] == '\\' # endif || (*fnamep)[1] == NUL) - #endif + && !(tilde_file && (*fnamep)[1] == NUL) ) { *fnamep = expand_env_save(*fnamep); xfree(*bufp); /* free any allocated file name */ diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index aad2de5d30..dea00c3edd 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -352,6 +352,7 @@ return { winbufnr={args=1}, wincol={}, winheight={args=1}, + winlayout={args={0, 1}}, winline={}, winnr={args={0, 1}}, winrestcmd={}, diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 979daf24fe..aa76355bad 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -8552,6 +8552,7 @@ eval_vars ( size_t resultlen; buf_T *buf; int valid = VALID_HEAD | VALID_PATH; // Assume valid result. + bool tilde_file = false; int skip_mod = false; char strbuf[30]; @@ -8608,9 +8609,11 @@ eval_vars ( case SPEC_PERC: /* '%': current file */ if (curbuf->b_fname == NULL) { result = (char_u *)""; - valid = 0; /* Must have ":p:h" to be valid */ - } else + valid = 0; // Must have ":p:h" to be valid + } else { result = curbuf->b_fname; + tilde_file = STRCMP(result, "~") == 0; + } break; case SPEC_HASH: /* '#' or "#99": alternate file */ @@ -8659,9 +8662,11 @@ eval_vars ( *lnump = ECMD_LAST; if (buf->b_fname == NULL) { result = (char_u *)""; - valid = 0; /* Must have ":p:h" to be valid */ - } else + valid = 0; // Must have ":p:h" to be valid + } else { result = buf->b_fname; + tilde_file = STRCMP(result, "~") == 0; + } } break; @@ -8746,7 +8751,8 @@ eval_vars ( resultlen = (size_t)(s - result); } } else if (!skip_mod) { - valid |= modify_fname(src, usedlen, &result, &resultbuf, &resultlen); + valid |= modify_fname(src, tilde_file, usedlen, &result, + &resultbuf, &resultlen); if (result == NULL) { *errormsg = (char_u *)""; return NULL; diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c index 4cb0c9a4ae..84721ee96c 100644 --- a/src/nvim/if_cscope.c +++ b/src/nvim/if_cscope.c @@ -425,9 +425,11 @@ cs_add_common( expand_env((char_u *)arg1, (char_u *)fname, MAXPATHL); size_t len = STRLEN(fname); fbuf = (char_u *)fname; - (void)modify_fname((char_u *)":p", &usedlen, (char_u **)&fname, &fbuf, &len); - if (fname == NULL) + (void)modify_fname((char_u *)":p", false, &usedlen, + (char_u **)&fname, &fbuf, &len); + if (fname == NULL) { goto add_err; + } fname = (char *)vim_strnsave((char_u *)fname, len); xfree(fbuf); FileInfo file_info; diff --git a/src/nvim/option.c b/src/nvim/option.c index 743f6c8311..43ee6bf451 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1239,7 +1239,7 @@ int do_set( } len++; if (opt_idx == -1) { - key = find_key_option(arg + 1); + key = find_key_option(arg + 1, true); } } else { len = 0; @@ -1253,7 +1253,7 @@ int do_set( } opt_idx = findoption_len((const char *)arg, (size_t)len); if (opt_idx == -1) { - key = find_key_option(arg); + key = find_key_option(arg, false); } } @@ -1986,7 +1986,7 @@ static char_u *illegal_char(char_u *errbuf, size_t errbuflen, int c) static int string_to_key(char_u *arg) { if (*arg == '<') { - return find_key_option(arg + 1); + return find_key_option(arg + 1, true); } if (*arg == '^') { return Ctrl_chr(arg[1]); @@ -4957,19 +4957,20 @@ char *set_option_value(const char *const name, const long number, return NULL; } -/* - * Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number. - */ -int find_key_option_len(const char_u *arg, size_t len) +// Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number. +// When "has_lt" is true there is a '<' before "*arg_arg". +// Returns 0 when the key is not recognized. +int find_key_option_len(const char_u *arg_arg, size_t len, bool has_lt) { - int key; + int key = 0; int modifiers; + const char_u *arg = arg_arg; // Don't use get_special_key_code() for t_xx, we don't want it to call // add_termcap_entry(). if (len >= 4 && arg[0] == 't' && arg[1] == '_') { key = TERMCAP2KEY(arg[2], arg[3]); - } else { + } else if (has_lt) { arg--; // put arg at the '<' modifiers = 0; key = find_special_key(&arg, len + 1, &modifiers, true, true, false); @@ -4980,9 +4981,9 @@ int find_key_option_len(const char_u *arg, size_t len) return key; } -static int find_key_option(const char_u *arg) +static int find_key_option(const char_u *arg, bool has_lt) { - return find_key_option_len(arg, STRLEN(arg)); + return find_key_option_len(arg, STRLEN(arg), has_lt); } /* diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index 7d1021962c..b067de608b 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -870,8 +870,8 @@ size_t home_replace(const buf_T *const buf, const char_u *src, size_t usedlen = 0; size_t flen = strlen(homedir_env_mod); char_u *fbuf = NULL; - (void)modify_fname((char_u *)":p", &usedlen, (char_u **)&homedir_env_mod, - &fbuf, &flen); + (void)modify_fname((char_u *)":p", false, &usedlen, + (char_u **)&homedir_env_mod, &fbuf, &flen); flen = strlen(homedir_env_mod); assert(homedir_env_mod != homedir_env); if (vim_ispathsep(homedir_env_mod[flen - 1])) { diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index d5f19057d0..30e29bd05d 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -29,27 +29,25 @@ source test_lambda.vim source test_mapping.vim source test_menu.vim source test_messages.vim +source test_modeline.vim source test_move.vim source test_partial.vim source test_popup.vim source test_put.vim source test_recover.vim -source test_regexp_utf8.vim source test_scroll_opt.vim source test_sort.vim -source test_source_utf8.vim source test_sha256.vim source test_statusline.vim source test_suspend.vim source test_syn_attr.vim source test_tabline.vim -" source test_tabpage.vim +source test_tabpage.vim source test_tagcase.vim source test_tagjump.vim source test_taglist.vim source test_true_false.vim source test_unlet.vim -source test_utf8.vim source test_virtualedit.vim source test_window_cmd.vim source test_wnext.vim diff --git a/src/nvim/testdir/test_glob2regpat.vim b/src/nvim/testdir/test_glob2regpat.vim index fdf17946b6..e6e41f13e7 100644 --- a/src/nvim/testdir/test_glob2regpat.vim +++ b/src/nvim/testdir/test_glob2regpat.vim @@ -1,12 +1,12 @@ " Test glob2regpat() -func Test_invalid() +func Test_glob2regpat_invalid() call assert_fails('call glob2regpat(1.33)', 'E806:') call assert_fails('call glob2regpat("}")', 'E219:') call assert_fails('call glob2regpat("{")', 'E220:') endfunc -func Test_valid() +func Test_glob2regpat_valid() call assert_equal('^foo\.', glob2regpat('foo.*')) call assert_equal('^foo.$', glob2regpat('foo?')) call assert_equal('\.vim$', glob2regpat('*.vim')) diff --git a/src/nvim/testdir/test_modeline.vim b/src/nvim/testdir/test_modeline.vim index 75fe1d993c..091a833774 100644 --- a/src/nvim/testdir/test_modeline.vim +++ b/src/nvim/testdir/test_modeline.vim @@ -1,11 +1,15 @@ +" Tests for parsing the modeline. + func Test_modeline_invalid() - let modeline = &modeline - set modeline - call assert_fails('set Xmodeline', 'E518:') + " This was reading allocated memory in the past. + call writefile(['vi:0', 'nothing'], 'Xmodeline') + let modeline = &modeline + set modeline + call assert_fails('set Xmodeline', 'E518:') - let &modeline = modeline - bwipe! - call delete('Xmodeline') + let &modeline = modeline + bwipe! + call delete('Xmodeline') endfunc func Test_modeline_filetype() @@ -40,6 +44,9 @@ func Test_modeline_syntax() endfunc func Test_modeline_keymap() + if !has('keymap') + return + endif call writefile(['vim: set keymap=greek :', 'nothing'], 'Xmodeline_keymap') let modeline = &modeline set modeline @@ -80,5 +87,8 @@ func Test_modeline_syntax_fails() endfunc func Test_modeline_keymap_fails() + if !has('keymap') + return + endif call s:modeline_fails('keymap', 'keymap=evil$CMD') endfunc diff --git a/src/nvim/testdir/test_regexp_latin.vim b/src/nvim/testdir/test_regexp_latin.vim index 0619e9c027..de209fa9ec 100644 --- a/src/nvim/testdir/test_regexp_latin.vim +++ b/src/nvim/testdir/test_regexp_latin.vim @@ -73,3 +73,15 @@ func Test_backref() call assert_fails('call search("\\%#=2\\(e\\1\\)")', 'E65:') bwipe! endfunc + +func Test_multi_failure() + set re=1 + call assert_fails('/a**', 'E61:') + call assert_fails('/a*\+', 'E62:') + call assert_fails('/a\{a}', 'E554:') + set re=2 + call assert_fails('/a**', 'E871:') + call assert_fails('/a*\+', 'E871:') + call assert_fails('/a\{a}', 'E870:') + set re=0 +endfunc diff --git a/src/nvim/testdir/test_window_id.vim b/src/nvim/testdir/test_window_id.vim index b3b506d04d..d10d831650 100644 --- a/src/nvim/testdir/test_window_id.vim +++ b/src/nvim/testdir/test_window_id.vim @@ -101,3 +101,23 @@ func Test_win_getid_curtab() call assert_equal(win_getid(1), win_getid(1, 1)) tabclose! endfunc + +func Test_winlayout() + let w1 = win_getid() + call assert_equal(['leaf', w1], winlayout()) + + split + let w2 = win_getid() + call assert_equal(['col', [['leaf', w2], ['leaf', w1]]], winlayout()) + + split + let w3 = win_getid() + call assert_equal(['col', [['leaf', w3], ['leaf', w2], ['leaf', w1]]], winlayout()) + + 2wincmd w + vsplit + let w4 = win_getid() + call assert_equal(['col', [['leaf', w3], ['row', [['leaf', w4], ['leaf', w2]]], ['leaf', w1]]], winlayout()) + + only! +endfunc diff --git a/src/nvim/window.c b/src/nvim/window.c index 2ce3b7067b..e6b19cf88d 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6658,6 +6658,41 @@ void win_findbuf(typval_T *argvars, list_T *list) } } +// Get the layout of the given tab page for winlayout(). +void get_framelayout(const frame_T *fr, list_T *l, bool outer) +{ + list_T *fr_list; + + if (fr == NULL) { + return; + } + + if (outer) { + // outermost call from f_winlayout() + fr_list = l; + } else { + fr_list = tv_list_alloc(2); + tv_list_append_list(l, fr_list); + } + + if (fr->fr_layout == FR_LEAF) { + if (fr->fr_win != NULL) { + tv_list_append_string(fr_list, "leaf", -1); + tv_list_append_number(fr_list, fr->fr_win->handle); + } + } else { + tv_list_append_string(fr_list, fr->fr_layout == FR_ROW ? "row" : "col", -1); + + list_T *const win_list = tv_list_alloc(kListLenUnknown); + tv_list_append_list(fr_list, win_list); + const frame_T *child = fr->fr_child; + while (child != NULL) { + get_framelayout(child, win_list, false); + child = child->fr_next; + } + } +} + void win_ui_flush_positions(void) { FOR_ALL_TAB_WINDOWS(tp, wp) { |