aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/os/env.c35
-rw-r--r--src/nvim/os/fs.c2
-rw-r--r--src/nvim/search.c63
-rw-r--r--src/nvim/testdir/test_textobjects.vim25
-rw-r--r--test/functional/ui/wildmode_spec.lua30
5 files changed, 120 insertions, 35 deletions
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 8a8220b6e7..e7bfbc8240 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -150,28 +150,47 @@ int os_unsetenv(const char *name)
char *os_getenvname_at_index(size_t index)
{
+#ifdef _WIN32
+ // Check if index is inside the environ array and is not the last element.
+ for (size_t i = 0; i <= index; i++) {
+ if (_wenviron[i] == NULL) {
+ return NULL;
+ }
+ }
+ wchar_t *utf16_str = _wenviron[index];
+ char *utf8_str;
+ int conversion_result = utf16_to_utf8(utf16_str, &utf8_str);
+ if (conversion_result != 0) {
+ EMSG2("utf16_to_utf8 failed: %d", conversion_result);
+ return NULL;
+ }
+ size_t namesize = 0;
+ while (utf8_str[namesize] != '=' && utf8_str[namesize] != NUL) {
+ namesize++;
+ }
+ char *name = (char *)vim_strnsave((char_u *)utf8_str, namesize);
+ xfree(utf8_str);
+ return name;
+#else
# if defined(HAVE__NSGETENVIRON)
char **environ = *_NSGetEnviron();
-# elif !defined(__WIN32__)
- // Borland C++ 5.2 has this in a header file.
+# else
extern char **environ;
# endif
- // check if index is inside the environ array
- for (size_t i = 0; i < index; i++) {
+ // Check if index is inside the environ array and is not the last element.
+ for (size_t i = 0; i <= index; i++) {
if (environ[i] == NULL) {
return NULL;
}
}
char *str = environ[index];
- if (str == NULL) {
- return NULL;
- }
size_t namesize = 0;
while (str[namesize] != '=' && str[namesize] != NUL) {
namesize++;
}
char *name = (char *)vim_strnsave((char_u *)str, namesize);
return name;
+#endif
}
/// Get the process ID of the Neovim process.
@@ -404,7 +423,7 @@ void expand_env_esc(char_u *restrict srcp,
var = NULL;
} else {
if (src[1] == '{') {
- ++tail;
+ tail++;
}
#endif
*var = NUL;
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 109ea6c487..7f2ebeec2f 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -1104,7 +1104,7 @@ char *os_resolve_shortcut(const char *fname)
if (hr == S_OK && wsz[0] != NUL) {
const int conversion_result = utf16_to_utf8(wsz, &rfname);
if (conversion_result != 0) {
- EMSG2("utf16_to_utf8 failed: %s", uv_strerror(conversion_result));
+ EMSG2("utf16_to_utf8 failed: %d", conversion_result);
}
}
diff --git a/src/nvim/search.c b/src/nvim/search.c
index b09931b337..f6b80d1b79 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -3687,11 +3687,12 @@ current_quote(
int col_end;
int col_start = curwin->w_cursor.col;
bool inclusive = false;
- int vis_empty = TRUE; /* Visual selection <= 1 char */
- int vis_bef_curs = FALSE; /* Visual starts before cursor */
- int inside_quotes = FALSE; /* Looks like "i'" done before */
- int selected_quote = FALSE; /* Has quote inside selection */
+ int vis_empty = true; // Visual selection <= 1 char
+ int vis_bef_curs = false; // Visual starts before cursor
+ int inside_quotes = false; // Looks like "i'" done before
+ int selected_quote = false; // Has quote inside selection
int i;
+ int restore_vis_bef = false; // resotre VIsual on abort
// Correct cursor when 'selection' is "exclusive".
if (VIsual_active) {
@@ -3709,6 +3710,7 @@ current_quote(
curwin->w_cursor = VIsual;
VIsual = t;
vis_bef_curs = true;
+ restore_vis_bef = true;
}
dec_cursor();
}
@@ -3749,8 +3751,9 @@ current_quote(
/* Assume we are on a closing quote: move to after the next
* opening quote. */
col_start = find_next_quote(line, col_start + 1, quotechar, NULL);
- if (col_start < 0)
- return FALSE;
+ if (col_start < 0) {
+ goto abort_search;
+ }
col_end = find_next_quote(line, col_start + 1, quotechar,
curbuf->b_p_qe);
if (col_end < 0) {
@@ -3760,8 +3763,9 @@ current_quote(
}
} else {
col_end = find_prev_quote(line, col_start, quotechar, NULL);
- if (line[col_end] != quotechar)
- return FALSE;
+ if (line[col_end] != quotechar) {
+ goto abort_search;
+ }
col_start = find_prev_quote(line, col_end, quotechar,
curbuf->b_p_qe);
if (line[col_start] != quotechar) {
@@ -3789,17 +3793,20 @@ current_quote(
for (;; ) {
/* Find open quote character. */
col_start = find_next_quote(line, col_start, quotechar, NULL);
- if (col_start < 0 || col_start > first_col)
- return FALSE;
- /* Find close quote character. */
+ if (col_start < 0 || col_start > first_col) {
+ goto abort_search;
+ }
+ // Find close quote character.
col_end = find_next_quote(line, col_start + 1, quotechar,
curbuf->b_p_qe);
- if (col_end < 0)
- return FALSE;
- /* If is cursor between start and end quote character, it is
- * target text object. */
- if (col_start <= first_col && first_col <= col_end)
+ if (col_end < 0) {
+ goto abort_search;
+ }
+ // If is cursor between start and end quote character, it is
+ // target text object.
+ if (col_start <= first_col && first_col <= col_end) {
break;
+ }
col_start = col_end + 1;
}
} else {
@@ -3808,15 +3815,17 @@ current_quote(
if (line[col_start] != quotechar) {
/* No quote before the cursor, look after the cursor. */
col_start = find_next_quote(line, col_start, quotechar, NULL);
- if (col_start < 0)
- return FALSE;
+ if (col_start < 0) {
+ goto abort_search;
+ }
}
/* Find close quote character. */
col_end = find_next_quote(line, col_start + 1, quotechar,
- curbuf->b_p_qe);
- if (col_end < 0)
- return FALSE;
+ curbuf->b_p_qe);
+ if (col_end < 0) {
+ goto abort_search;
+ }
}
/* When "include" is TRUE, include spaces after closing quote or before
@@ -3893,6 +3902,18 @@ current_quote(
}
return OK;
+
+abort_search:
+ if (VIsual_active && *p_sel == 'e') {
+ inc_cursor();
+ if (restore_vis_bef) {
+ pos_T t = curwin->w_cursor;
+
+ curwin->w_cursor = VIsual;
+ VIsual = t;
+ }
+ }
+ return false;
}
diff --git a/src/nvim/testdir/test_textobjects.vim b/src/nvim/testdir/test_textobjects.vim
index 6a2f5044cc..9194e0014d 100644
--- a/src/nvim/testdir/test_textobjects.vim
+++ b/src/nvim/testdir/test_textobjects.vim
@@ -52,6 +52,31 @@ func Test_quote_selection_selection_exclusive()
bw!
endfunc
+func Test_quote_selection_selection_exclusive_abort()
+ new
+ set selection=exclusive
+ call setline(1, "'abzzc'")
+ let exp_curs = [0, 1, 6, 0]
+ call cursor(1,1)
+ exe 'norm! fcdvi"'
+ " make sure to end visual mode to have a clear state
+ exe "norm! \<esc>"
+ call assert_equal(exp_curs, getpos('.'))
+ call cursor(1,1)
+ exe 'norm! fcvi"'
+ exe "norm! \<esc>"
+ call assert_equal(exp_curs, getpos('.'))
+ call cursor(1,2)
+ exe 'norm! vfcoi"'
+ exe "norm! \<esc>"
+ let exp_curs = [0, 1, 2, 0]
+ let exp_visu = [0, 1, 7, 0]
+ call assert_equal(exp_curs, getpos('.'))
+ call assert_equal(exp_visu, getpos("'>"))
+ set selection&vim
+ bw!
+endfunc
+
" Tests for string and html text objects
func Test_string_html_objects()
enew!
diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua
index ffe71cfadf..7cd09fb222 100644
--- a/test/functional/ui/wildmode_spec.lua
+++ b/test/functional/ui/wildmode_spec.lua
@@ -171,19 +171,21 @@ end)
describe('command line completion', function()
local screen
-
before_each(function()
- clear()
screen = Screen.new(40, 5)
- screen:attach()
- screen:set_default_attr_ids({[1]={bold=true, foreground=Screen.colors.Blue}})
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {foreground = Screen.colors.Grey0, background = Screen.colors.Yellow},
+ [3] = {bold = true, reverse = true},
+ })
end)
-
after_each(function()
os.remove('Xtest-functional-viml-compl-dir')
end)
it('lists directories with empty PATH', function()
+ clear()
+ screen:attach()
local tmp = funcs.tempname()
command('e '.. tmp)
command('cd %:h')
@@ -198,6 +200,24 @@ describe('command line completion', function()
:!Xtest-functional-viml-compl-dir^ |
]])
end)
+
+ it('completes (multibyte) env var names #9655', function()
+ clear({env={
+ ['XTEST_1AaあB']='foo',
+ ['XTEST_2']='bar',
+ }})
+ screen:attach()
+ command('set wildmode=full')
+ command('set wildmenu')
+ feed(':!echo $XTEST_<tab>')
+ screen:expect([[
+ |
+ {1:~ }|
+ {1:~ }|
+ {2:XTEST_1AaあB}{3: XTEST_2 }|
+ :!echo $XTEST_1AaあB^ |
+ ]])
+ end)
end)
describe('ui/ext_wildmenu', function()