aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval.c1
-rw-r--r--src/nvim/eval.h1
-rw-r--r--src/nvim/eval/funcs.c11
-rw-r--r--src/nvim/ex_cmds.c18
-rw-r--r--src/nvim/ex_cmds2.c21
-rw-r--r--src/nvim/ex_docmd.c3
-rw-r--r--src/nvim/testdir/test_cmdline.vim15
-rw-r--r--src/nvim/testdir/test_excmd.vim126
-rw-r--r--src/nvim/testdir/test_fnameescape.vim6
-rw-r--r--src/nvim/testdir/test_ga.vim9
-rw-r--r--src/nvim/testdir/test_global.vim8
-rw-r--r--src/nvim/testdir/test_move.vim5
-rw-r--r--src/nvim/testdir/test_options.vim19
-rw-r--r--src/nvim/testdir/test_sort.vim210
-rw-r--r--src/nvim/testdir/test_substitute.vim2
-rw-r--r--src/nvim/testdir/test_writefile.vim63
16 files changed, 501 insertions, 17 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 079c0dc3c0..d67db94339 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -228,6 +228,7 @@ static struct vimvar {
VV(VV_EVENT, "event", VAR_DICT, VV_RO),
VV(VV_ECHOSPACE, "echospace", VAR_NUMBER, VV_RO),
VV(VV_ARGV, "argv", VAR_LIST, VV_RO),
+ VV(VV_COLLATE, "collate", VAR_STRING, VV_RO),
VV(VV_EXITING, "exiting", VAR_NUMBER, VV_RO),
// Neovim
VV(VV_STDERR, "stderr", VAR_NUMBER, VV_RO),
diff --git a/src/nvim/eval.h b/src/nvim/eval.h
index 8188502987..41120b3c78 100644
--- a/src/nvim/eval.h
+++ b/src/nvim/eval.h
@@ -157,6 +157,7 @@ typedef enum {
VV_EVENT,
VV_ECHOSPACE,
VV_ARGV,
+ VV_COLLATE,
VV_EXITING,
// Neovim
VV_STDERR,
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 865abcc110..911b3c2c2f 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -9154,6 +9154,7 @@ static void f_sockconnect(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// struct storing information about current sort
typedef struct {
int item_compare_ic;
+ bool item_compare_lc;
bool item_compare_numeric;
bool item_compare_numbers;
bool item_compare_float;
@@ -9228,10 +9229,10 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero)
p2 = "";
}
if (!sortinfo->item_compare_numeric) {
- if (sortinfo->item_compare_ic) {
- res = STRICMP(p1, p2);
+ if (sortinfo->item_compare_lc) {
+ res = strcoll(p1, p2);
} else {
- res = STRCMP(p1, p2);
+ res = sortinfo->item_compare_ic ? STRICMP(p1, p2): STRCMP(p1, p2);
}
} else {
double n1, n2;
@@ -9366,6 +9367,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
}
info.item_compare_ic = false;
+ info.item_compare_lc = false;
info.item_compare_numeric = false;
info.item_compare_numbers = false;
info.item_compare_float = false;
@@ -9410,6 +9412,9 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
} else if (strcmp(info.item_compare_func, "i") == 0) {
info.item_compare_func = NULL;
info.item_compare_ic = true;
+ } else if (strcmp(info.item_compare_func, "l") == 0) {
+ info.item_compare_func = NULL;
+ info.item_compare_lc = true;
}
}
}
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 3e330b88a2..349c7d6280 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -358,6 +358,7 @@ static int linelen(int *has_tab)
static char_u *sortbuf1;
static char_u *sortbuf2;
+static int sort_lc; ///< sort using locale
static int sort_ic; ///< ignore case
static int sort_nr; ///< sort on number
static int sort_rx; ///< sort on regex instead of skipping it
@@ -381,6 +382,13 @@ typedef struct {
} st_u;
} sorti_T;
+static int string_compare(const void *s1, const void *s2) FUNC_ATTR_NONNULL_ALL
+{
+ if (sort_lc) {
+ return strcoll((char *)s1, (char *)s2);
+ }
+ return sort_ic ? STRICMP(s1, s2) : STRCMP(s1, s2);
+}
static int sort_compare(const void *s1, const void *s2)
{
@@ -424,8 +432,7 @@ static int sort_compare(const void *s1, const void *s2)
l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr + 1);
sortbuf2[l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr] = NUL;
- result = sort_ic ? STRICMP(sortbuf1, sortbuf2)
- : STRCMP(sortbuf1, sortbuf2);
+ result = string_compare(sortbuf1, sortbuf2);
}
/* If two lines have the same value, preserve the original line order. */
@@ -466,7 +473,7 @@ void ex_sort(exarg_T *eap)
regmatch.regprog = NULL;
sorti_T *nrs = xmalloc(count * sizeof(sorti_T));
- sort_abort = sort_ic = sort_rx = sort_nr = sort_flt = 0;
+ sort_abort = sort_ic = sort_lc = sort_rx = sort_nr = sort_flt = 0;
size_t format_found = 0;
bool change_occurred = false; // Buffer contents changed.
@@ -474,6 +481,8 @@ void ex_sort(exarg_T *eap)
if (ascii_iswhite(*p)) {
} else if (*p == 'i') {
sort_ic = true;
+ } else if (*p == 'l') {
+ sort_lc = true;
} else if (*p == 'r') {
sort_rx = true;
} else if (*p == 'n') {
@@ -645,8 +654,7 @@ void ex_sort(exarg_T *eap)
s = ml_get(get_lnum);
size_t bytelen = STRLEN(s) + 1; // include EOL in bytelen
old_count += bytelen;
- if (!unique || i == 0
- || (sort_ic ? STRICMP(s, sortbuf1) : STRCMP(s, sortbuf1)) != 0) {
+ if (!unique || i == 0 || string_compare(s, sortbuf1) != 0) {
// Copy the line into a buffer, it may become invalid in
// ml_append(). And it's needed for "unique".
STRCPY(sortbuf1, s);
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 7f28c001f9..0a2802397d 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -3621,6 +3621,14 @@ void set_lang_var(void)
loc = get_locale_val(LC_TIME);
# endif
set_vim_var_string(VV_LC_TIME, loc, -1);
+
+# ifdef HAVE_GET_LOCALE_VAL
+ loc = get_locale_val(LC_COLLATE);
+# else
+ // setlocale() not supported: use the default value
+ loc = "C";
+# endif
+ set_vim_var_string(VV_COLLATE, loc, -1);
}
#ifdef HAVE_WORKING_LIBINTL
@@ -3661,6 +3669,10 @@ void ex_language(exarg_T *eap)
what = LC_TIME;
name = skipwhite(p);
whatstr = "time ";
+ } else if (STRNICMP(eap->arg, "collate", p - eap->arg) == 0) {
+ what = LC_COLLATE;
+ name = skipwhite(p);
+ whatstr = "collate ";
}
}
@@ -3705,7 +3717,7 @@ void ex_language(exarg_T *eap)
// Reset $LC_ALL, otherwise it would overrule everything.
os_setenv("LC_ALL", "", 1);
- if (what != LC_TIME) {
+ if (what != LC_TIME && what != LC_COLLATE) {
// Tell gettext() what to translate to. It apparently doesn't
// use the currently effective locale.
if (what == LC_ALL) {
@@ -3720,7 +3732,7 @@ void ex_language(exarg_T *eap)
}
}
- // Set v:lang, v:lc_time and v:ctype to the final result.
+ // Set v:lang, v:lc_time, v:collate and v:ctype to the final result.
set_lang_var();
maketitle();
}
@@ -3805,12 +3817,15 @@ char_u *get_lang_arg(expand_T *xp, int idx)
if (idx == 2) {
return (char_u *)"time";
}
+ if (idx == 3) {
+ return (char_u *)"collate";
+ }
init_locales();
if (locales == NULL) {
return NULL;
}
- return locales[idx - 3];
+ return locales[idx - 4];
}
/// Function given to ExpandGeneric() to obtain the available locales.
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index ae5c334592..555029c1fb 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -3642,7 +3642,8 @@ const char * set_one_cmd_context(
} else {
if (strncmp(arg, "messages", p - arg) == 0
|| strncmp(arg, "ctype", p - arg) == 0
- || strncmp(arg, "time", p - arg) == 0) {
+ || strncmp(arg, "time", p - arg) == 0
+ || strncmp(arg, "collate", p - arg) == 0) {
xp->xp_context = EXPAND_LOCALES;
xp->xp_pattern = skipwhite((const char_u *)p);
} else {
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 489b2477e6..a1968807ac 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -615,10 +615,20 @@ func Test_cmdline_complete_bang()
endfunc
funct Test_cmdline_complete_languages()
+ let lang = substitute(execute('language time'), '.*"\(.*\)"$', '\1', '')
+ call assert_equal(lang, v:lc_time)
+
+ let lang = substitute(execute('language ctype'), '.*"\(.*\)"$', '\1', '')
+ call assert_equal(lang, v:ctype)
+
+ let lang = substitute(execute('language collate'), '.*"\(.*\)"$', '\1', '')
+ call assert_equal(lang, v:collate)
+
let lang = substitute(execute('language messages'), '.*"\(.*\)"$', '\1', '')
+ call assert_equal(lang, v:lang)
call feedkeys(":language \<c-a>\<c-b>\"\<cr>", 'tx')
- call assert_match('^"language .*\<ctype\>.*\<messages\>.*\<time\>', @:)
+ call assert_match('^"language .*\<collate\>.*\<ctype\>.*\<messages\>.*\<time\>', @:)
if has('unix')
" TODO: these tests don't work on Windows. lang appears to be 'C'
@@ -633,6 +643,9 @@ funct Test_cmdline_complete_languages()
call feedkeys(":language time \<c-a>\<c-b>\"\<cr>", 'tx')
call assert_match('^"language .*\<' . lang . '\>', @:)
+
+ call feedkeys(":language collate \<c-a>\<c-b>\"\<cr>", 'tx')
+ call assert_match('^"language .*\<' . lang . '\>', @:)
endif
endfunc
diff --git a/src/nvim/testdir/test_excmd.vim b/src/nvim/testdir/test_excmd.vim
index 4c7452fe69..ed2bb2c06b 100644
--- a/src/nvim/testdir/test_excmd.vim
+++ b/src/nvim/testdir/test_excmd.vim
@@ -54,6 +54,132 @@ func Test_buffers_lastused()
bwipeout bufc
endfunc
+" Test for the :copy command
+func Test_copy()
+ new
+
+ call setline(1, ['L1', 'L2', 'L3', 'L4'])
+ " copy lines in a range to inside the range
+ 1,3copy 2
+ call assert_equal(['L1', 'L2', 'L1', 'L2', 'L3', 'L3', 'L4'], getline(1, 7))
+
+ close!
+endfunc
+
+" Test for the :file command
+func Test_file_cmd()
+ call assert_fails('3file', 'E474:')
+ call assert_fails('0,0file', 'E474:')
+ call assert_fails('0file abc', 'E474:')
+endfunc
+
+" Test for the :drop command
+func Test_drop_cmd()
+ call writefile(['L1', 'L2'], 'Xfile')
+ enew | only
+ drop Xfile
+ call assert_equal('L2', getline(2))
+ " Test for switching to an existing window
+ below new
+ drop Xfile
+ call assert_equal(1, winnr())
+ " Test for splitting the current window
+ enew | only
+ set modified
+ drop Xfile
+ call assert_equal(2, winnr('$'))
+ " Check for setting the argument list
+ call assert_equal(['Xfile'], argv())
+ enew | only!
+ call delete('Xfile')
+endfunc
+
+" Test for the :append command
+func Test_append_cmd()
+ new
+ call setline(1, [' L1'])
+ call feedkeys(":append\<CR> L2\<CR> L3\<CR>.\<CR>", 'xt')
+ call assert_equal([' L1', ' L2', ' L3'], getline(1, '$'))
+ %delete _
+ " append after a specific line
+ call setline(1, [' L1', ' L2', ' L3'])
+ call feedkeys(":2append\<CR> L4\<CR> L5\<CR>.\<CR>", 'xt')
+ call assert_equal([' L1', ' L2', ' L4', ' L5', ' L3'], getline(1, '$'))
+ %delete _
+ " append with toggling 'autoindent'
+ call setline(1, [' L1'])
+ call feedkeys(":append!\<CR> L2\<CR> L3\<CR>.\<CR>", 'xt')
+ call assert_equal([' L1', ' L2', ' L3'], getline(1, '$'))
+ call assert_false(&autoindent)
+ %delete _
+ " append with 'autoindent' set and toggling 'autoindent'
+ set autoindent
+ call setline(1, [' L1'])
+ call feedkeys(":append!\<CR> L2\<CR> L3\<CR>.\<CR>", 'xt')
+ call assert_equal([' L1', ' L2', ' L3'], getline(1, '$'))
+ call assert_true(&autoindent)
+ set autoindent&
+ close!
+endfunc
+
+" Test for the :insert command
+func Test_insert_cmd()
+ set noautoindent " test assumes noautoindent, but it's on by default in Nvim
+ new
+ call setline(1, [' L1'])
+ call feedkeys(":insert\<CR> L2\<CR> L3\<CR>.\<CR>", 'xt')
+ call assert_equal([' L2', ' L3', ' L1'], getline(1, '$'))
+ %delete _
+ " insert before a specific line
+ call setline(1, [' L1', ' L2', ' L3'])
+ call feedkeys(":2insert\<CR> L4\<CR> L5\<CR>.\<CR>", 'xt')
+ call assert_equal([' L1', ' L4', ' L5', ' L2', ' L3'], getline(1, '$'))
+ %delete _
+ " insert with toggling 'autoindent'
+ call setline(1, [' L1'])
+ call feedkeys(":insert!\<CR> L2\<CR> L3\<CR>.\<CR>", 'xt')
+ call assert_equal([' L2', ' L3', ' L1'], getline(1, '$'))
+ call assert_false(&autoindent)
+ %delete _
+ " insert with 'autoindent' set and toggling 'autoindent'
+ set autoindent
+ call setline(1, [' L1'])
+ call feedkeys(":insert!\<CR> L2\<CR> L3\<CR>.\<CR>", 'xt')
+ call assert_equal([' L2', ' L3', ' L1'], getline(1, '$'))
+ call assert_true(&autoindent)
+ set autoindent&
+ close!
+endfunc
+
+" Test for the :change command
+func Test_change_cmd()
+ set noautoindent " test assumes noautoindent, but it's on by default in Nvim
+ new
+ call setline(1, [' L1', 'L2', 'L3'])
+ call feedkeys(":change\<CR> L4\<CR> L5\<CR>.\<CR>", 'xt')
+ call assert_equal([' L4', ' L5', 'L2', 'L3'], getline(1, '$'))
+ %delete _
+ " change a specific line
+ call setline(1, [' L1', ' L2', ' L3'])
+ call feedkeys(":2change\<CR> L4\<CR> L5\<CR>.\<CR>", 'xt')
+ call assert_equal([' L1', ' L4', ' L5', ' L3'], getline(1, '$'))
+ %delete _
+ " change with toggling 'autoindent'
+ call setline(1, [' L1', 'L2', 'L3'])
+ call feedkeys(":change!\<CR> L4\<CR> L5\<CR>.\<CR>", 'xt')
+ call assert_equal([' L4', ' L5', 'L2', 'L3'], getline(1, '$'))
+ call assert_false(&autoindent)
+ %delete _
+ " change with 'autoindent' set and toggling 'autoindent'
+ set autoindent
+ call setline(1, [' L1', 'L2', 'L3'])
+ call feedkeys(":change!\<CR> L4\<CR> L5\<CR>.\<CR>", 'xt')
+ call assert_equal([' L4', ' L5', 'L2', 'L3'], getline(1, '$'))
+ call assert_true(&autoindent)
+ set autoindent&
+ close!
+endfunc
+
" Test for the :confirm command dialog
func Test_confirm_cmd()
CheckNotGui
diff --git a/src/nvim/testdir/test_fnameescape.vim b/src/nvim/testdir/test_fnameescape.vim
index 5382b89aa6..0bafdc29fb 100644
--- a/src/nvim/testdir/test_fnameescape.vim
+++ b/src/nvim/testdir/test_fnameescape.vim
@@ -18,4 +18,10 @@ func Test_fnameescape()
endtry
call assert_true(status, "ExclamationMark")
call delete(fname)
+
+ call assert_equal('\-', fnameescape('-'))
+ call assert_equal('\+', fnameescape('+'))
+ call assert_equal('\>', fnameescape('>'))
endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_ga.vim b/src/nvim/testdir/test_ga.vim
index 87f1382342..ce31edfc7a 100644
--- a/src/nvim/testdir/test_ga.vim
+++ b/src/nvim/testdir/test_ga.vim
@@ -18,6 +18,7 @@ func Test_ga_command()
call assert_equal("\nNUL", Do_ga(''))
call assert_equal("\n<^A> 1, Hex 01, Oct 001, Digr SH", Do_ga("\x01"))
call assert_equal("\n<^I> 9, Hex 09, Oct 011, Digr HT", Do_ga("\t"))
+ call assert_equal("\n<^@> 0, Hex 00, Octal 000", Do_ga("\n"))
call assert_equal("\n<e> 101, Hex 65, Octal 145", Do_ga('e'))
@@ -30,5 +31,13 @@ func Test_ga_command()
call assert_equal("\n<e> 101, Hex 65, Octal 145 < ́> 769, Hex 0301, Octal 1401", Do_ga("e\u0301"))
call assert_equal("\n<e> 101, Hex 65, Octal 145 < ́> 769, Hex 0301, Octal 1401 < ̱> 817, Hex 0331, Octal 1461", Do_ga("e\u0301\u0331"))
call assert_equal("\n<e> 101, Hex 65, Octal 145 < ́> 769, Hex 0301, Octal 1401 < ̱> 817, Hex 0331, Octal 1461 < ̸> 824, Hex 0338, Octal 1470", Do_ga("e\u0301\u0331\u0338"))
+
+ " When using Mac fileformat, CR instead of NL is used for line termination
+ enew!
+ set fileformat=mac
+ call assert_equal("\n<^J> 10, Hex 0a, Oct 012, Digr NU", Do_ga("\r"))
+
bwipe!
endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_global.vim b/src/nvim/testdir/test_global.vim
index 7ccf2812ff..2de2c412de 100644
--- a/src/nvim/testdir/test_global.vim
+++ b/src/nvim/testdir/test_global.vim
@@ -29,3 +29,11 @@ func Test_nested_global()
call assert_equal(['nothing', '++found', 'found bad', 'bad'], getline(1, 4))
bwipe!
endfunc
+
+func Test_global_error()
+ call assert_fails('g\\a', 'E10:')
+ call assert_fails('g', 'E148:')
+ call assert_fails('g/\(/y', 'E476:')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_move.vim b/src/nvim/testdir/test_move.vim
index d774c93dbd..f666a904b0 100644
--- a/src/nvim/testdir/test_move.vim
+++ b/src/nvim/testdir/test_move.vim
@@ -35,6 +35,11 @@ func Test_move()
call assert_fails('1,2move 1', 'E134')
call assert_fails('2,3move 2', 'E134')
+ call assert_fails("move -100", 'E16:')
+ call assert_fails("move +100", 'E16:')
+ call assert_fails('move', 'E16:')
%bwipeout!
endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index 5aef33cb09..8796af7a20 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -629,6 +629,25 @@ func Test_visualbell()
set belloff=all
endfunc
+" Test for the 'write' option
+func Test_write()
+ new
+ call setline(1, ['L1'])
+ set nowrite
+ call assert_fails('write Xfile', 'E142:')
+ set write
+ close!
+endfunc
+
+" Test for 'buftype' option
+func Test_buftype()
+ new
+ call setline(1, ['L1'])
+ set buftype=nowrite
+ call assert_fails('write', 'E382:')
+ close!
+endfunc
+
" Test for setting option values using v:false and v:true
func Test_opt_boolean()
set number&
diff --git a/src/nvim/testdir/test_sort.vim b/src/nvim/testdir/test_sort.vim
index 7533eaf2e8..6d55889641 100644
--- a/src/nvim/testdir/test_sort.vim
+++ b/src/nvim/testdir/test_sort.vim
@@ -13,6 +13,37 @@ func Test_sort_strings()
" numbers compared as strings
call assert_equal([1, 2, 3], sort([3, 2, 1]))
call assert_equal([13, 28, 3], sort([3, 28, 13]))
+
+ call assert_equal(['A', 'O', 'P', 'a', 'o', 'p', 'Ä', 'Ô', 'ä', 'ô', 'Œ', 'œ'],
+ \ sort(['A', 'O', 'P', 'a', 'o', 'p', 'Ä', 'Ô', 'ä', 'ô', 'œ', 'Œ']))
+
+ call assert_equal(['A', 'a', 'o', 'O', 'p', 'P', 'Ä', 'Ô', 'ä', 'ô', 'Œ', 'œ'],
+ \ sort(['A', 'a', 'o', 'O', 'œ', 'Œ', 'p', 'P', 'Ä', 'ä', 'ô', 'Ô'], 'i'))
+
+ " This does not appear to work correctly on Mac.
+ if !has('mac')
+ if v:collate =~? '^\(en\|fr\)_ca.utf-\?8$'
+ " with Canadian English capitals come before lower case.
+ " 'Œ' is omitted because it can sort before or after 'œ'
+ call assert_equal(['A', 'a', 'Ä', 'ä', 'O', 'o', 'Ô', 'ô', 'œ', 'P', 'p'],
+ \ sort(['A', 'a', 'o', 'O', 'œ', 'p', 'P', 'Ä', 'ä', 'ô', 'Ô'], 'l'))
+ elseif v:collate =~? '^\(en\|es\|de\|fr\|it\|nl\).*\.utf-\?8$'
+ " With the following locales, the accentuated letters are ordered
+ " similarly to the non-accentuated letters...
+ call assert_equal(['a', 'A', 'ä', 'Ä', 'o', 'O', 'ô', 'Ô', 'œ', 'Œ', 'p', 'P'],
+ \ sort(['A', 'a', 'o', 'O', 'œ', 'Œ', 'p', 'P', 'Ä', 'ä', 'ô', 'Ô'], 'l'))
+ elseif v:collate =~? '^sv.*utf-\?8$'
+ " ... whereas with a Swedish locale, the accentuated letters are ordered
+ " after Z.
+ call assert_equal(['a', 'A', 'o', 'O', 'p', 'P', 'ä', 'Ä', 'œ', 'œ', 'ô', 'Ô'],
+ \ sort(['A', 'a', 'o', 'O', 'œ', 'œ', 'p', 'P', 'Ä', 'ä', 'ô', 'Ô'], 'l'))
+ endif
+ endif
+endfunc
+
+func Test_sort_null_string()
+ " null strings are sorted as empty strings.
+ call assert_equal(['', 'a', 'b'], sort(['b', v:_null_string, 'a']))
endfunc
func Test_sort_numeric()
@@ -1150,7 +1181,7 @@ func Test_sort_cmd()
\ 'input' : [
\ '1.234',
\ '0.88',
- \ '123.456',
+ \ ' + 123.456',
\ '1.15e-6',
\ '-1.1e3',
\ '-1.01e3',
@@ -1165,7 +1196,7 @@ func Test_sort_cmd()
\ '1.15e-6',
\ '0.88',
\ '1.234',
- \ '123.456'
+ \ ' + 123.456'
\ ]
\ },
\ {
@@ -1197,8 +1228,133 @@ func Test_sort_cmd()
\ 'cc',
\ ]
\ },
+ \ {
+ \ 'name' : 'sort one line buffer',
+ \ 'cmd' : 'sort',
+ \ 'input' : [
+ \ 'single line'
+ \ ],
+ \ 'expected' : [
+ \ 'single line'
+ \ ]
+ \ },
+ \ {
+ \ 'name' : 'sort ignoring case',
+ \ 'cmd' : '%sort i',
+ \ 'input' : [
+ \ 'BB',
+ \ 'Cc',
+ \ 'aa'
+ \ ],
+ \ 'expected' : [
+ \ 'aa',
+ \ 'BB',
+ \ 'Cc'
+ \ ]
+ \ },
\ ]
+ " This does not appear to work correctly on Mac.
+ if !has('mac')
+ if v:collate =~? '^\(en\|fr\)_ca.utf-\?8$'
+ " en_CA.utf-8 sorts capitals before lower case
+ " 'Œ' is omitted because it can sort before or after 'œ'
+ let tests += [
+ \ {
+ \ 'name' : 'sort with locale ' .. v:collate,
+ \ 'cmd' : '%sort l',
+ \ 'input' : [
+ \ 'A',
+ \ 'E',
+ \ 'O',
+ \ 'À',
+ \ 'È',
+ \ 'É',
+ \ 'Ô',
+ \ 'Z',
+ \ 'a',
+ \ 'e',
+ \ 'o',
+ \ 'à',
+ \ 'è',
+ \ 'é',
+ \ 'ô',
+ \ 'œ',
+ \ 'z'
+ \ ],
+ \ 'expected' : [
+ \ 'A',
+ \ 'a',
+ \ 'À',
+ \ 'à',
+ \ 'E',
+ \ 'e',
+ \ 'É',
+ \ 'é',
+ \ 'È',
+ \ 'è',
+ \ 'O',
+ \ 'o',
+ \ 'Ô',
+ \ 'ô',
+ \ 'œ',
+ \ 'Z',
+ \ 'z'
+ \ ]
+ \ },
+ \ ]
+ elseif v:collate =~? '^\(en\|es\|de\|fr\|it\|nl\).*\.utf-\?8$'
+ " With these locales, the accentuated letters are ordered
+ " similarly to the non-accentuated letters.
+ let tests += [
+ \ {
+ \ 'name' : 'sort with locale ' .. v:collate,
+ \ 'cmd' : '%sort l',
+ \ 'input' : [
+ \ 'A',
+ \ 'E',
+ \ 'O',
+ \ 'À',
+ \ 'È',
+ \ 'É',
+ \ 'Ô',
+ \ 'Œ',
+ \ 'Z',
+ \ 'a',
+ \ 'e',
+ \ 'o',
+ \ 'à',
+ \ 'è',
+ \ 'é',
+ \ 'ô',
+ \ 'œ',
+ \ 'z'
+ \ ],
+ \ 'expected' : [
+ \ 'a',
+ \ 'A',
+ \ 'à',
+ \ 'À',
+ \ 'e',
+ \ 'E',
+ \ 'é',
+ \ 'É',
+ \ 'è',
+ \ 'È',
+ \ 'o',
+ \ 'O',
+ \ 'ô',
+ \ 'Ô',
+ \ 'œ',
+ \ 'Œ',
+ \ 'z',
+ \ 'Z'
+ \ ]
+ \ },
+ \ ]
+ endif
+ endif
+
for t in tests
enew!
call append(0, t.input)
@@ -1217,7 +1373,11 @@ func Test_sort_cmd()
endif
endfor
- call assert_fails('sort no', 'E474')
+ " Needs atleast two lines for this test
+ call setline(1, ['line1', 'line2'])
+ call assert_fails('sort no', 'E474:')
+ call assert_fails('sort c', 'E475:')
+ call assert_fails('sort #pat%', 'E682:')
enew!
endfunc
@@ -1319,4 +1479,46 @@ func Test_sort_cmd_report()
" the output comes from the :g command, not from the :sort
call assert_match("6 fewer lines", res)
enew!
- endfunc
+endfunc
+
+" Test for a :sort command followed by another command
+func Test_sort_followed_by_cmd()
+ new
+ let var = ''
+ call setline(1, ['cc', 'aa', 'bb'])
+ %sort | let var = "sortcmdtest"
+ call assert_equal(var, "sortcmdtest")
+ call assert_equal(['aa', 'bb', 'cc'], getline(1, '$'))
+ " Test for :sort followed by a comment
+ call setline(1, ['3b', '1c', '2a'])
+ %sort /\d\+/ " sort alphabetically
+ call assert_equal(['2a', '3b', '1c'], getline(1, '$'))
+ close!
+endfunc
+
+" Test for :sort using last search pattern
+func Test_sort_last_search_pat()
+ new
+ let @/ = '\d\+'
+ call setline(1, ['3b', '1c', '2a'])
+ sort //
+ call assert_equal(['2a', '3b', '1c'], getline(1, '$'))
+ close!
+endfunc
+
+" Test for retaining marks across a :sort
+func Test_sort_with_marks()
+ new
+ call setline(1, ['cc', 'aa', 'bb'])
+ call setpos("'c", [0, 1, 0, 0])
+ call setpos("'a", [0, 2, 0, 0])
+ call setpos("'b", [0, 3, 0, 0])
+ %sort
+ call assert_equal(['aa', 'bb', 'cc'], getline(1, '$'))
+ call assert_equal(2, line("'a"))
+ call assert_equal(3, line("'b"))
+ call assert_equal(1, line("'c"))
+ close!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim
index 32167a45ba..e7f9bb76f2 100644
--- a/src/nvim/testdir/test_substitute.vim
+++ b/src/nvim/testdir/test_substitute.vim
@@ -426,6 +426,8 @@ func Test_substitute_errors()
call assert_fails('s/FOO/bar/', 'E486:')
call assert_fails('s/foo/bar/@', 'E488:')
call assert_fails('s/\(/bar/', 'E476:')
+ call assert_fails('s afooabara', 'E146:')
+ call assert_fails('s\\a', 'E10:')
setl nomodifiable
call assert_fails('s/foo/bar/', 'E21:')
diff --git a/src/nvim/testdir/test_writefile.vim b/src/nvim/testdir/test_writefile.vim
index c62c01d5f3..c7710ff198 100644
--- a/src/nvim/testdir/test_writefile.vim
+++ b/src/nvim/testdir/test_writefile.vim
@@ -164,6 +164,69 @@ func Test_writefile_autowrite_nowrite()
set noautowrite
endfunc
+" Test for ':w !<cmd>' to pipe lines from the current buffer to an external
+" command.
+func Test_write_pipe_to_cmd()
+ if !has('unix')
+ return
+ endif
+ new
+ call setline(1, ['L1', 'L2', 'L3', 'L4'])
+ 2,3w !cat > Xfile
+ call assert_equal(['L2', 'L3'], readfile('Xfile'))
+ close!
+ call delete('Xfile')
+endfunc
+
+" Test for :saveas
+func Test_saveas()
+ call assert_fails('saveas', 'E471:')
+ call writefile(['L1'], 'Xfile')
+ new Xfile
+ new
+ call setline(1, ['L1'])
+ call assert_fails('saveas Xfile', 'E139:')
+ close!
+ enew | only
+ call delete('Xfile')
+endfunc
+
+func Test_write_errors()
+ " Test for writing partial buffer
+ call writefile(['L1', 'L2', 'L3'], 'Xfile')
+ new Xfile
+ call assert_fails('1,2write', 'E140:')
+ close!
+
+ " Try to overwrite a directory
+ if has('unix')
+ call mkdir('Xdir1')
+ call assert_fails('write Xdir1', 'E17:')
+ call delete('Xdir1', 'd')
+ endif
+
+ " Test for :wall for a buffer with no name
+ enew | only
+ call setline(1, ['L1'])
+ call assert_fails('wall', 'E141:')
+ enew!
+
+ " Test for writing a 'readonly' file
+ new Xfile
+ set readonly
+ call assert_fails('write', 'E45:')
+ close
+
+ " Test for writing to a read-only file
+ new Xfile
+ call setfperm('Xfile', 'r--r--r--')
+ call assert_fails('write', 'E505:')
+ call setfperm('Xfile', 'rw-rw-rw-')
+ close
+
+ call delete('Xfile')
+endfunc
+
func Test_writefile_sync_dev_stdout()
if !has('unix')
return