diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/nvim/option.c | 6 | ||||
| -rw-r--r-- | src/nvim/strings.c | 13 | ||||
| -rw-r--r-- | src/nvim/testdir/test_functions.vim | 23 | ||||
| -rw-r--r-- | src/nvim/window.c | 34 |
4 files changed, 75 insertions, 1 deletions
diff --git a/src/nvim/option.c b/src/nvim/option.c index 23b488ea68..fb7a0446b6 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -7644,6 +7644,12 @@ int csh_like_shell(void) return strstr((char *)path_tail(p_sh), "csh") != NULL; } +/// Return true when 'shell' has "fish" in the tail. +bool fish_like_shell(void) +{ + return strstr((char *)path_tail(p_sh), "fish") != NULL; +} + /// Return the number of requested sign columns, based on current /// buffer signs and on user configuration. int win_signcol_count(win_T *wp) diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 0363afe02d..79a3db4843 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -190,6 +190,7 @@ char_u *vim_strsave_shellescape(const char_u *string, char_u *escaped_string; size_t l; int csh_like; + bool fish_like; /* Only csh and similar shells expand '!' within single quotes. For sh and * the like we must not put a backslash before it, it will be taken @@ -197,6 +198,10 @@ char_u *vim_strsave_shellescape(const char_u *string, * Csh also needs to have "\n" escaped twice when do_special is set. */ csh_like = csh_like_shell(); + // Fish shell uses '\' as an escape character within single quotes, so '\' + // itself must be escaped to get a literal '\'. + fish_like = fish_like_shell(); + /* First count the number of extra bytes required. */ size_t length = STRLEN(string) + 3; // two quotes and a trailing NUL for (const char_u *p = string; *p != NUL; MB_PTR_ADV(p)) { @@ -220,6 +225,9 @@ char_u *vim_strsave_shellescape(const char_u *string, ++length; /* insert backslash */ p += l - 1; } + if (*p == '\\' && fish_like) { + length++; // insert backslash + } } /* Allocate memory for the result and fill it. */ @@ -267,6 +275,11 @@ char_u *vim_strsave_shellescape(const char_u *string, *d++ = *p++; continue; } + if (*p == '\\' && fish_like) { + *d++ = '\\'; + *d++ = *p++; + continue; + } MB_COPY_CHAR(p, d); } diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index ed46730cbb..e82fefc7fc 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -1172,6 +1172,29 @@ func Test_shellescape() call assert_equal("'te\\\nxt'", shellescape("te\nxt")) call assert_equal("'te\\\\\nxt'", shellescape("te\nxt", 1)) + set shell=fish + call assert_equal("'text'", shellescape('text')) + call assert_equal("'te\"xt'", shellescape('te"xt')) + call assert_equal("'te'\\''xt'", shellescape("te'xt")) + + call assert_equal("'te%xt'", shellescape("te%xt")) + call assert_equal("'te\\%xt'", shellescape("te%xt", 1)) + call assert_equal("'te#xt'", shellescape("te#xt")) + call assert_equal("'te\\#xt'", shellescape("te#xt", 1)) + call assert_equal("'te!xt'", shellescape("te!xt")) + call assert_equal("'te\\!xt'", shellescape("te!xt", 1)) + + call assert_equal("'te\\\\xt'", shellescape("te\\xt")) + call assert_equal("'te\\\\xt'", shellescape("te\\xt", 1)) + call assert_equal("'te\\\\'\\''xt'", shellescape("te\\'xt")) + call assert_equal("'te\\\\'\\''xt'", shellescape("te\\'xt", 1)) + call assert_equal("'te\\\\!xt'", shellescape("te\\!xt")) + call assert_equal("'te\\\\\\!xt'", shellescape("te\\!xt", 1)) + call assert_equal("'te\\\\%xt'", shellescape("te\\%xt")) + call assert_equal("'te\\\\\\%xt'", shellescape("te\\%xt", 1)) + call assert_equal("'te\\\\#xt'", shellescape("te\\#xt")) + call assert_equal("'te\\\\\\#xt'", shellescape("te\\#xt", 1)) + let &shell = save_shell endfunc diff --git a/src/nvim/window.c b/src/nvim/window.c index 42fe2c0f49..55a7882401 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -737,6 +737,37 @@ void win_config_float(win_T *wp, FloatConfig fconfig) redraw_later(wp, NOT_VALID); } + // compute initial position + if (wp->w_float_config.relative == kFloatRelativeWindow) { + int row = wp->w_float_config.row; + int col = wp->w_float_config.col; + Error dummy = ERROR_INIT; + win_T *parent = find_window_by_handle(wp->w_float_config.window, &dummy); + if (parent) { + row += parent->w_winrow; + col += parent->w_wincol; + ScreenGrid *grid = &parent->w_grid; + int row_off = 0, col_off = 0; + screen_adjust_grid(&grid, &row_off, &col_off); + row += row_off; + col += col_off; + } + api_clear_error(&dummy); + if (wp->w_float_config.bufpos.lnum >= 0) { + pos_T pos = { wp->w_float_config.bufpos.lnum + 1, + wp->w_float_config.bufpos.col, 0 }; + int trow, tcol, tcolc, tcole; + textpos2screenpos(wp, &pos, &trow, &tcol, &tcolc, &tcole, true); + row += trow - 1; + col += tcol - 1; + } + wp->w_winrow = row; + wp->w_wincol = col; + } else { + wp->w_winrow = fconfig.row; + wp->w_wincol = fconfig.col; + } + // changing border style while keeping border only requires redrawing border if (fconfig.border) { wp->w_redr_border = true; @@ -770,7 +801,6 @@ int win_fdccol_count(win_T *wp) } } - void ui_ext_win_position(win_T *wp) { if (!wp->w_floating) { @@ -817,6 +847,8 @@ void ui_ext_win_position(win_T *wp) int comp_row = (int)row - (south ? wp->w_height : 0); int comp_col = (int)col - (east ? wp->w_width : 0); + comp_row += grid->comp_row; + comp_col += grid->comp_col; comp_row = MAX(MIN(comp_row, Rows-wp->w_height_outer-1), 0); comp_col = MAX(MIN(comp_col, Columns-wp->w_width_outer), 0); wp->w_winrow = comp_row; |
