fix(path): normalize separators (slashes) #39155

Problem:
Continue separators normalization, and try to keep it at the
nvim <-> external boundary, e.g., `fn.xxx`, `api.xxx`, `:xxx`

Solution:
some key changes
- normalize `$HOME-windows`
- normalize entry points of changing directory
  - `nvim_set_current_dir()`, `chdir()`
- normalize the named pipe
  - `--listen` arg, `--server` arg, `:restart`
  - `serverstart()`, `sockconnect()`, `serverstop()`
- make `expand()` respect 'shellslash' again
- clean up `did_set_shellslash`
- replace `forward_slash` with `TO_SLASH`
- remove obsolete `TMP_PATHSEPSTR`
- remove `slash_adjust` in `do_autocmd_dirchanged`?
- make `fnamemodify()` always return `/` (except when substituting
  separators via `:s`, `:gs` ?)

Note:
- these funcs still apply `slash_adjust` on return, as before:
  `:pwd`, `chdir()`, `exepath()`, `getcwd()`
- these funcs alwarys return `/`, unlike before the normalization PRs
  - `getcompletion()`, `finddir()`, `findfile()`

Also
- clean up code, comments, formatting and tests
- move `TO_SLASH` from `f_chdir` to `changedir_func`
- move `TO_SLASH` from `f_bufadd` to `buflist_new`

Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
This commit is contained in:
taoandJustin M. Keyes authored and GitHub committed 2026-07-12 13:23:44 -04:00
1 parent 543a96e491
commit 4a08596314
51 files changed
+802 -853

No files matched your search

+1 -2
View File
@@ -3459,8 +3459,7 @@ A jump table for the options with a short description can be found at |Q_op|.
attempt to set 'guifontwide' to a matching double-width font.
*'helpfile'* *'hf'*
'helpfile' 'hf' string (default (MS-Windows) "$VIMRUNTIME\doc\help.txt"
(others) "$VIMRUNTIME/doc/help.txt")
'helpfile' 'hf' string (default "$VIMRUNTIME/doc/help.txt")
global
Disallowed in |modeline|. |no-modeline-option|
Name of the main help file. All distributed help files should be
+1 -1
View File
@@ -9215,7 +9215,7 @@ serverstart([{address}]) *serverstart()*
< Example named pipe: >vim
if has('win32')
echo serverstart('\\.\pipe\nvim-pipe-1234')
echo serverstart('//./pipe/nvim-pipe-1234')
else
echo serverstart('nvim.sock')
endif
+1 -1
View File
@@ -8363,7 +8363,7 @@ function vim.fn.serverlist(opts) end
---
--- <Example named pipe: >vim
--- if has('win32')
--- echo serverstart('\\.\pipe\nvim-pipe-1234')
--- echo serverstart('//./pipe/nvim-pipe-1234')
--- else
--- echo serverstart('nvim.sock')
--- endif
+1 -5
View File
@@ -695,12 +695,8 @@ void nvim_set_current_dir(String dir, Error *err)
return;
});
char string[MAXPATHL];
memcpy(string, dir.data, dir.size);
string[dir.size] = NUL;
TRY_WRAP(err, {
changedir_func(string, kCdScopeGlobal);
changedir_func(dir.data, kCdScopeGlobal);
});
}
-24
View File
@@ -228,30 +228,6 @@ void alist_add(alist_T *al, char *fname, int set_fnum)
wp->w_locked--;
}
#ifdef BACKSLASH_IN_FILENAME
/// Adjust slashes in file names. Called after 'shellslash' was set.
void alist_slash_adjust(void)
{
for (int i = 0; i < GARGCOUNT; i++) {
if (GARGLIST[i].ae_fname != NULL) {
slash_adjust(GARGLIST[i].ae_fname);
}
}
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->w_alist != &global_alist) {
for (int i = 0; i < WARGCOUNT(wp); i++) {
if (WARGLIST(wp)[i].ae_fname != NULL) {
slash_adjust(WARGLIST(wp)[i].ae_fname);
}
}
}
}
}
#endif
/// Isolate one argument, taking backticks.
/// Changes the argument in-place, puts a NUL after it. Backticks remain.
///
+3 -32
View File
@@ -789,18 +789,9 @@ void do_autocmd(exarg_T *eap, char *arg_in, int forceit)
*cmd++ = NUL;
}
// Expand environment variables in the pattern. Set 'shellslash', we want
// forward slashes here.
// Expand environment variables in the pattern.
if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL) {
#ifdef BACKSLASH_IN_FILENAME
int p_ssl_save = p_ssl;
p_ssl = true;
#endif
envpat = expand_env_save(pat);
#ifdef BACKSLASH_IN_FILENAME
p_ssl = p_ssl_save;
#endif
if (envpat != NULL) {
pat = envpat;
}
@@ -1583,7 +1574,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
}
fname = xstrdup(fname); // make a copy, so we can change it
} else {
sfname = xstrdup(fname);
sfname = TO_SLASH_SAVE(fname);
// Don't try expanding the following events.
if (event == EVENT_CMDLINECHANGED
|| event == EVENT_CMDLINEENTER
@@ -1616,7 +1607,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
|| event == EVENT_WINCLOSED
|| event == EVENT_WINRESIZED
|| event == EVENT_WINSCROLLED) {
fname = xstrdup(fname);
fname = TO_SLASH_SAVE(fname);
autocmd_fname_full = true; // don't expand it later
} else {
fname = FullName_save(fname, false);
@@ -1635,15 +1626,6 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
save_changed = curbuf->b_changed;
old_curbuf = curbuf;
#ifdef BACKSLASH_IN_FILENAME
// Replace all backslashes with forward slashes. This makes the
// autocommand patterns portable between Unix and Windows.
if (sfname != NULL) {
forward_slash(sfname);
}
forward_slash(fname);
#endif
// Set the name to be used for <amatch>.
autocmd_match = fname;
@@ -2079,14 +2061,6 @@ bool has_autocmd(event_T event, char *sfname, buf_T *buf)
return false;
}
#ifdef BACKSLASH_IN_FILENAME
// Replace all backslashes with forward slashes. This makes the
// autocommand patterns portable between Unix and Windows.
sfname = xstrdup(sfname);
forward_slash(sfname);
forward_slash(fname);
#endif
AutoCmdVec *const acs = &autocmds[(int)event];
for (size_t i = 0; i < kv_size(*acs); i++) {
AutoPat *const ap = kv_A(*acs, i).pat;
@@ -2100,9 +2074,6 @@ bool has_autocmd(event_T event, char *sfname, buf_T *buf)
}
xfree(fname);
#ifdef BACKSLASH_IN_FILENAME
xfree(sfname);
#endif
return retval;
}
+9 -16
View File
@@ -2038,6 +2038,7 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags)
assert(sfname != NULL);
buf->b_ffname = ffname;
buf->b_sfname = xstrdup(sfname);
TO_SLASH(buf->b_sfname);
}
clear_wininfo(buf);
@@ -3119,6 +3120,7 @@ int setfname(buf_T *buf, char *ffname_arg, char *sfname_arg, bool message)
}
sfname = xstrdup(sfname);
#ifdef CASE_INSENSITIVE_FILENAME
TO_SLASH(sfname);
path_fix_case(sfname); // set correct case for short file name
#endif
if (buf->b_sfname != buf->b_ffname) {
@@ -3224,22 +3226,6 @@ int buflist_add(char *fname, int flags)
return 0;
}
#ifdef BACKSLASH_IN_FILENAME
/// Adjust slashes in file names. Called after 'shellslash' was set.
void buflist_slash_adjust(void)
{
FOR_ALL_BUFFERS(bp) {
if (bp->b_ffname != NULL) {
slash_adjust(bp->b_ffname);
}
if (bp->b_sfname != NULL) {
slash_adjust(bp->b_sfname);
}
}
}
#endif
/// Set alternate cursor position for the current buffer and window "win".
/// Also save the local window option values.
void buflist_altfpos(win_T *win)
@@ -3471,10 +3457,17 @@ void maketitle(void)
}
} else {
// Format: "fname + (path) (1 of 2) - Nvim".
#ifdef MSWIN
int p_ssl_save = p_ssl;
p_ssl = true;
#endif
char *default_titlestring = "%t%( %M%)%( (%{expand('%:p:~:h')})%)%a - Nvim";
build_stl_str_hl(curwin, buf, sizeof(buf), default_titlestring,
kOptTitlestring, 0, 0, maxlen, NULL, NULL, NULL, NULL);
title_str = buf;
#ifdef MSWIN
p_ssl = p_ssl_save;
#endif
}
}
bool mustset = value_change(title_str, &lasttitle);
+6 -13
View File
@@ -2768,11 +2768,13 @@ static int expand_files_and_dirs(expand_T *xp, char *pat, char ***matches, int *
xfree(pat);
}
#ifdef BACKSLASH_IN_FILENAME
if ((options & WILD_USE_COMPLETESLASH) && ((p_csl[0] == NUL && !p_ssl) || p_csl[0] == 'b')) {
if (((options & WILD_USE_SHELLSLASH) && !p_ssl)
|| ((options & WILD_USE_COMPLETESLASH)
&& ((p_csl[0] == NUL && !p_ssl) || p_csl[0] == 'b'))) {
for (int j = 0; j < *numMatches; j++) {
char *ptr = (*matches)[j];
for (; *ptr; ptr++) {
if (*ptr == '/') {
if (*ptr == PATHSEP) {
*ptr = '\\';
}
}
@@ -3721,14 +3723,6 @@ void globpath(char *path, char *file, garray_T *ga, int expand_options, bool dir
size_t filelen = strlen(file);
#ifdef MSWIN
// Using the platform's path separator (\) makes vim incorrectly
// treat it as an escape character, use '/' instead.
# define TMP_PATHSEPSTR "/"
#else
# define TMP_PATHSEPSTR PATHSEPSTR
#endif
// Loop over all entries in {path}.
while (*path != NUL) {
// Copy one item of the path to buf[] and concatenate the file name.
@@ -3736,11 +3730,11 @@ void globpath(char *path, char *file, garray_T *ga, int expand_options, bool dir
// length of the path portion of buf (including trailing slash).
size_t pathlen = copy_option_part(&path, buf, MAXPATHL, ",");
size_t seplen = (*buf != NUL && !after_pathsep(buf, buf + pathlen))
? STRLEN_LITERAL(TMP_PATHSEPSTR) : 0;
? STRLEN_LITERAL(PATHSEPSTR) : 0;
if (pathlen + seplen + filelen + 1 <= MAXPATHL) {
if (seplen > 0) {
xmemcpyz(buf + pathlen, S_LEN(TMP_PATHSEPSTR));
xmemcpyz(buf + pathlen, S_LEN(PATHSEPSTR));
pathlen += seplen;
}
xmemcpyz(buf + pathlen, file, filelen);
@@ -3765,7 +3759,6 @@ void globpath(char *path, char *file, garray_T *ga, int expand_options, bool dir
xfree(buf);
}
#undef TMP_PATHSEPSTR
/// Translate some keys pressed when 'wildmenu' is used.
int wildmenu_translate_key(CmdlineInfo *cclp, int key, expand_T *xp, bool did_wild_list)
+1
View File
@@ -44,6 +44,7 @@ enum {
WILD_MAY_EXPAND_PATTERN = 0x8000,
WILD_FUNC_TRIGGER = 0x10000, ///< called from wildtrigger()
WILD_NOINSERT = 0x20000,
WILD_USE_SHELLSLASH = 0x40000,
};
#include "cmdexpand.h.generated.h"
+1 -1
View File
@@ -10047,7 +10047,7 @@ M.funcs = {
<Example named pipe: >vim
if has('win32')
echo serverstart('\\.\pipe\nvim-pipe-1234')
echo serverstart('//./pipe/nvim-pipe-1234')
else
echo serverstart('nvim.sock')
endif
+15 -4
View File
@@ -64,14 +64,16 @@ static const char e_error_while_writing_str[] = N_("E80: Error while writing: %s
/// @param fnamep file name so far
/// @param bufp buffer for allocated file name or NULL
/// @param fnamelen length of fnamep
/// @param use_shellslash adjust separators in `*fnamep` according to 'shellslash'
int modify_fname(char *src, bool tilde_file, size_t *usedlen, char **fnamep, char **bufp,
size_t *fnamelen)
size_t *fnamelen, bool use_shellslash)
{
int valid = 0;
char *s, *p, *pbuf;
char dirname[MAXPATHL];
bool has_fullname = false;
bool has_homerelative = false;
bool didit = false;
repeat:
// ":p" - full path/file_name
@@ -303,13 +305,20 @@ repeat:
*usedlen += 2;
}
#ifdef BACKSLASH_IN_FILENAME
if (!didit && use_shellslash && *fnamep != NULL) {
*fnamep = xstrdup(*fnamep);
slash_adjust(*fnamep);
xfree(*bufp);
*bufp = *fnamep;
}
#endif
// ":s?pat?foo?" - substitute
// ":gs?pat?foo?" - global substitute
if (src[*usedlen] == ':'
&& (src[*usedlen + 1] == 's'
|| (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's'))) {
bool didit = false;
char *flags = "";
s = src + *usedlen + 2;
if (src[*usedlen + 1] == 'g') {
@@ -612,11 +621,13 @@ void f_fnamemodify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (mods == NULL || fname == NULL) {
fname = NULL;
} else {
fbuf = TO_SLASH_SAVE(fname);
fname = fbuf;
len = strlen(fname);
if (*mods != NUL) {
size_t usedlen = 0;
modify_fname((char *)mods, false, &usedlen,
(char **)&fname, &fbuf, &len);
(char **)&fname, &fbuf, &len, false);
}
}
+7 -14
View File
@@ -1402,14 +1402,8 @@ static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// "expand()" function
static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND|WILD_USE_SHELLSLASH;
bool error = false;
#ifdef BACKSLASH_IN_FILENAME
char *p_csl_save = p_csl;
// avoid using 'completeslash' here
p_csl = empty_string_option;
#endif
rettv->v_type = VAR_STRING;
if (argvars[1].v_type != VAR_UNKNOWN
@@ -1469,9 +1463,6 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_string = NULL;
}
}
#ifdef BACKSLASH_IN_FILENAME
p_csl = p_csl_save;
#endif
}
/// "menu_get(path [, modes])" function
@@ -6394,7 +6385,7 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
emsg(_(e_invarg));
return;
}
address = xstrdup(tv_get_string(argvars));
address = TO_SLASH_SAVE(tv_get_string(argvars));
} else {
address = server_address_new(NULL);
}
@@ -6859,7 +6850,7 @@ static void f_sockconnect(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
const char *mode = tv_get_string(&argvars[0]);
const char *address = tv_get_string(&argvars[1]);
const char *address = TO_SLASH_SAVE(tv_get_string(&argvars[1]));
bool tcp;
if (strcmp(mode, "tcp") == 0) {
@@ -6868,7 +6859,7 @@ static void f_sockconnect(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
tcp = false;
} else {
semsg(_(e_invarg2), "invalid mode");
return;
goto cleanup;
}
bool rpc = false;
@@ -6878,7 +6869,7 @@ static void f_sockconnect(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rpc = tv_dict_get_number(opts, "rpc") != 0;
if (!tv_dict_get_callback(opts, S_LEN("on_data"), &on_data.cb)) {
return;
goto cleanup;
}
on_data.buffered = tv_dict_get_number(opts, "data_buffered");
if (on_data.buffered && on_data.cb.type == kCallbackNone) {
@@ -6895,6 +6886,8 @@ static void f_sockconnect(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = (varnumber_T)id;
rettv->v_type = VAR_NUMBER;
cleanup:
XFREE_CLEAR(address);
}
/// "stdioopen()" function
+2 -3
View File
@@ -33,9 +33,8 @@ char *socket_address_tcp_host_end(const char *address)
return NULL;
}
// Windows drive letter path: "X:\..." or "X:/..." is a local path, not TCP.
if (ASCII_ISALPHA((uint8_t)address[0]) && address[1] == ':'
&& (address[2] == '\\' || address[2] == '/')) {
// Windows drive letter path: "X:/..." is a local path, not TCP.
if (ASCII_ISALPHA((uint8_t)address[0]) && address[1] == ':' && address[2] == '/') {
return NULL;
}
+17 -8
View File
@@ -5030,7 +5030,7 @@ static void ex_restart(exarg_T *eap)
if (next_li != NULL) {
const char *addr = tv_get_string(TV_LIST_ITEM_TV(next_li));
if (strstr(addr, ":") || strstr(addr, "/") || strstr(addr, "\\")) {
listen_arg = addr;
listen_arg = TO_SLASH_SAVE(addr);
#ifdef MSWIN
// On Windows, don't pass --listen to new server (named pipe can't be reused immediately).
// Instead pass the address via RPC; new server rebinds after startup.
@@ -5060,14 +5060,12 @@ static void ex_restart(exarg_T *eap)
// On Windows, --listen is omitted from child argv because the named pipe can't be reused immediately.
// Recover the canonical address from the Lua module state (set by the previous rebind_after_restart() call),
// and keep the current listener alive (new server reclaims it).
char *listen_arg_alloc = NULL;
if (listen_arg == NULL) {
Error lua_err = ERROR_INIT;
Object rv = NLUA_EXEC_STATIC("return require('vim._core.server').restart_canonical_addr",
(Array)ARRAY_DICT_INIT, kRetObject, NULL, &lua_err);
if (!ERROR_SET(&lua_err) && rv.type == kObjectTypeString && rv.data.string.size > 0) {
listen_arg_alloc = xstrdup(rv.data.string.data);
listen_arg = listen_arg_alloc;
listen_arg = xstrdup(rv.data.string.data);
}
api_free_object(rv);
api_clear_error(&lua_err);
@@ -5222,9 +5220,7 @@ fail_1:
if (server_stopped && server_start(listen_arg) != 0) {
semsg("couldn't resume listening on %s", listen_arg);
}
#ifdef MSWIN
xfree(listen_arg_alloc);
#endif
XFREE_CLEAR(listen_arg);
}
/// ":close": close current window, unless it is the last one
@@ -5713,6 +5709,7 @@ static char *findfunc_find_file(char *findarg, size_t findarg_len, int count)
findarg[findarg_len] = cc;
TO_SLASH(ret_fname);
return ret_fname;
}
@@ -6511,15 +6508,19 @@ bool changedir_func(char *new_dir, CdScope scope)
new_dir = NameBuff;
}
new_dir = TO_SLASH_SAVE(new_dir);
bool dir_differs = pdir == NULL || pathcmp(pdir, new_dir, -1) != 0;
if (dir_differs) {
do_autocmd_dirchanged(new_dir, scope, kCdCauseManual, true);
if (vim_chdir(new_dir) != 0) {
emsg(_(e_failed));
xfree(new_dir);
xfree(pdir);
return false;
}
}
xfree(new_dir);
char **pp;
switch (scope) {
@@ -7733,6 +7734,8 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
bool tilde_file = false;
bool skip_mod = false;
char strbuf[30];
// we want 'shellslash' for path expansions like "%", "#", "<afile>", etc.
bool use_shellslash = false;
*errormsg = NULL;
if (escaped != NULL) {
@@ -7785,6 +7788,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
result = curbuf->b_fname;
tilde_file = strcmp(result, "~") == 0;
}
use_shellslash = true;
break;
case SPEC_HASH: // '#' or "#99": alternate file
@@ -7798,6 +7802,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
skip_mod = true;
break;
}
use_shellslash = true;
char *s = src + 1;
if (*s == '<') { // "#<99" uses v:oldfiles.
s++;
@@ -7852,6 +7857,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
break;
case SPEC_AFILE: // file name for autocommand
use_shellslash = !autocmd_fname_full;
if (autocmd_fname != NULL && !autocmd_fname_full) {
// Still need to turn the fname into a full path. It was
// postponed to avoid a delay when <afile> is not used.
@@ -7887,6 +7893,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
break;
case SPEC_SFILE: // file name for ":so" command
use_shellslash = true;
result = estack_sfile(ESTACK_SFILE);
if (result == NULL) {
*errormsg = _(e_no_source_file_name_to_substitute_for_sfile);
@@ -7895,6 +7902,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
resultbuf = result; // remember allocated string
break;
case SPEC_STACK: // call stack
use_shellslash = true;
result = estack_sfile(ESTACK_STACK);
if (result == NULL) {
*errormsg = _(e_no_call_stack_to_substitute_for_stack);
@@ -7903,6 +7911,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
resultbuf = result; // remember allocated string
break;
case SPEC_SCRIPT: // script file name
use_shellslash = true;
result = estack_sfile(ESTACK_SCRIPT);
if (result == NULL) {
*errormsg = _(e_no_script_file_name_to_substitute_for_script);
@@ -7957,7 +7966,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum
}
} else if (!skip_mod) {
valid |= modify_fname(src, tilde_file, usedlen, &result,
&resultbuf, &resultlen);
&resultbuf, &resultlen, use_shellslash);
if (result == NULL) {
*errormsg = "";
return NULL;
-7
View File
@@ -1858,13 +1858,6 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause, bool pre
abort();
}
#ifdef BACKSLASH_IN_FILENAME
char new_dir_buf[MAXPATHL];
STRCPY(new_dir_buf, new_dir);
slash_adjust(new_dir_buf);
new_dir = new_dir_buf;
#endif
if (pre) {
tv_dict_add_str(dict, S_LEN("directory"), new_dir);
} else {
-16
View File
@@ -3284,22 +3284,6 @@ void write_lnum_adjust(linenr_T offset)
}
}
#ifdef BACKSLASH_IN_FILENAME
/// Convert all backslashes in fname to forward slashes in-place,
/// unless when it looks like a URL.
void forward_slash(char *fname)
{
if (path_with_url(fname)) {
return;
}
for (char *p = fname; *p != NUL; p++) {
if (*p == '\\') {
*p = '/';
}
}
}
#endif
/// Path to Nvim's own temp dir. Ends in a slash.
static char *vim_tempdir = NULL;
#ifdef HAVE_DIRFD_AND_FLOCK
-6
View File
@@ -761,12 +761,6 @@ EXTERN bool no_hlsearch INIT( = false);
EXTERN bool typebuf_was_filled INIT( = false); // received text from client
// or from feedkeys()
#ifdef BACKSLASH_IN_FILENAME
EXTERN char psepc INIT( = '\\'); // normal path separator character
EXTERN char psepcN INIT( = '/'); // abnormal path separator character
EXTERN char pseps[2] INIT( = { '\\', 0 }); // normal path separator string
#endif
// Set to kTrue when an operator is being executed with virtual editing
// kNone when no operator is being executed, kFalse otherwise.
EXTERN TriState virtual_op INIT( = kNone);
+4 -2
View File
@@ -1402,9 +1402,11 @@ static void command_line_scan(mparm_T *parmp)
parmp->pre_commands[parmp->n_pre_commands++] = argv[0];
} else if (strequal(argv[-1], "--listen")) {
// "--listen {address}"
TO_SLASH(argv[0]);
parmp->listen_addr = argv[0];
} else if (strequal(argv[-1], "--server")) {
// "--server {address}"
TO_SLASH(argv[0]);
parmp->server_addr = argv[0];
}
// "--startuptime <file>" already handled
@@ -1490,14 +1492,14 @@ scripterror:
// On Windows expand "~\" or "~/" prefix in file names to profile directory.
#ifdef MSWIN
if (*p == '~' && (p[1] == '\\' || p[1] == '/')) {
TO_SLASH(p);
if (*p == '~' && p[1] == '/') {
size_t size = strlen(os_homedir()) + strlen(p);
char *tilde_expanded = xmalloc(size);
snprintf(tilde_expanded, size, "%s%s", os_homedir(), p + 1);
xfree(p);
p = tilde_expanded;
}
TO_SLASH(p);
#endif
if (parmp->diff_mode && os_isdir(p) && GARGCOUNT > 0
+4 -3
View File
@@ -43,7 +43,7 @@ bool server_init(const char *listen_addr)
if (!listen_addr || listen_addr[0] == '\0') {
if (os_env_exists(ENV_LISTEN, true)) {
user_arg = kFalse; // User-provided env var.
listen_addr = os_getenv(ENV_LISTEN);
listen_addr = TO_SLASH_SAVE(os_getenv_noalloc(ENV_LISTEN));
} else {
user_arg = kNone; // Autogenerated server address.
listen_addr = server_address_new(NULL);
@@ -111,7 +111,7 @@ void server_teardown(void)
/// Generates unique address for local server.
///
/// Named pipe format:
/// - Windows: "\\.\pipe\<name>.<pid>.<counter>"
/// - Windows: "//./pipe/<name>.<pid>.<counter>"
/// - Other: "/tmp/nvim.user/xxx/<name>.<pid>.<counter>"
char *server_address_new(const char *name)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET
@@ -120,7 +120,7 @@ char *server_address_new(const char *name)
char fmt[ADDRESS_MAX_SIZE];
#ifdef MSWIN
(void)get_appname(true); // Writes appname to NameBuf.
int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32,
int r = snprintf(fmt, sizeof(fmt), "//./pipe/%s.%" PRIu64 ".%" PRIu32,
name ? name : NameBuff, os_get_pid(), count++);
#else
char *dir = stdpaths_get_xdg_var(kXDGRuntimeDir);
@@ -222,6 +222,7 @@ bool server_stop(const char *endpoint, bool keep_vservername)
// Trim to `ADDRESS_MAX_SIZE`
xstrlcpy(addr, endpoint, sizeof(addr));
TO_SLASH(addr);
int i = 0; // Index of the server whose address equals addr.
for (; i < watchers.ga_len; i++) {
-25
View File
@@ -2687,31 +2687,6 @@ static const char *did_set_scrollbind(optset_T *args)
return NULL;
}
#ifdef BACKSLASH_IN_FILENAME
/// Process the updated 'shellslash' option value.
/// TODO(ntdiary): Remove this once we're confident that the `shellslash`
/// option is no longer needed.
static const char *did_set_shellslash(optset_T *args FUNC_ATTR_UNUSED)
{
if (p_ssl) {
psepc = '/';
psepcN = '\\';
pseps[0] = '/';
} else {
psepc = '\\';
psepcN = '/';
pseps[0] = '\\';
}
// TODO(ntdiary): Remove these in the follow PR.
// need to adjust the file name arguments and buffer names.
// buflist_slash_adjust();
// alist_slash_adjust();
// scriptnames_slash_adjust();
return NULL;
}
#endif
/// Process the new 'shiftwidth' or the 'tabstop' option value.
static const char *did_set_shiftwidth_tabstop(optset_T *args)
{
+1 -3
View File
@@ -4259,8 +4259,7 @@ local options = {
cb = 'did_set_helpfile',
defaults = {
if_true = macros('DFLT_HELPFILE', 'string'),
doc = [[(MS-Windows) "$VIMRUNTIME\doc\help.txt"
(others) "$VIMRUNTIME/doc/help.txt"]],
doc = [["$VIMRUNTIME/doc/help.txt"]],
},
desc = [=[
Name of the main help file. All distributed help files should be
@@ -7868,7 +7867,6 @@ local options = {
},
{
abbreviation = 'ssl',
cb = 'did_set_shellslash',
defaults = {
condition = 'MSWIN',
if_true = false,
+7 -3
View File
@@ -412,7 +412,7 @@ void init_homedir(void)
char *homedrive = os_getenv("HOMEDRIVE");
char *homepath = os_getenv("HOMEPATH");
if (homepath == NULL) {
homepath = xstrdup("\\");
homepath = xstrdup(PATHSEPSTR);
}
if (homedrive != NULL
&& strlen(homedrive) + strlen(homepath) < MAXPATHL) {
@@ -473,7 +473,7 @@ void init_homedir(void)
}
#endif
if (var != NULL) {
homedir = xstrdup(var);
homedir = TO_SLASH_SAVE(var);
}
xfree(tofree);
}
@@ -619,6 +619,10 @@ size_t expand_env_esc(const char *restrict srcp, char *restrict dst, int dstlen,
#endif
*var = NUL;
var = vim_getenv(dst);
// Backslashes in `srcp` might just be used for escaping. Expanded env
// vars represent paths, so their backslashes can be safely normalized.
// Autocmd file patterns require this normalization.
TO_SLASH(var);
mustfree = true;
#ifdef UNIX
}
@@ -1042,7 +1046,7 @@ size_t home_replace(const buf_T *const buf, const char *src, char *const dst, si
size_t usedlen = 0;
size_t flen = strlen(homedir_env_mod);
char *fbuf = NULL;
modify_fname(":p", false, &usedlen, &homedir_env_mod, &fbuf, &flen);
modify_fname(":p", false, &usedlen, &homedir_env_mod, &fbuf, &flen, false);
flen = strlen(homedir_env_mod);
assert(homedir_env_mod != homedir_env);
if (vim_ispathsep(homedir_env_mod[flen - 1])) {
+2 -4
View File
@@ -75,6 +75,8 @@ const char *get_appname(bool namelike)
xstrlcpy(NameBuff, "nvim", sizeof(NameBuff));
}
TO_SLASH(NameBuff);
if (namelike) {
// Appname may be a relative path, replace slashes to make it name-like.
memchrsub(NameBuff, '/', '-', sizeof(NameBuff));
@@ -94,10 +96,6 @@ bool appname_is_valid(void)
|| strequal(appname, "\\")
|| strequal(appname, ".")
|| strequal(appname, "..")
#ifdef BACKSLASH_IN_FILENAME
|| strstr(appname, "\\..") != NULL
|| strstr(appname, "..\\") != NULL
#endif
|| strstr(appname, "/..") != NULL
|| strstr(appname, "../") != NULL) {
return false;
+7 -4
View File
@@ -1546,9 +1546,11 @@ void slash_adjust(char *p)
}
}
char from = p_ssl ? '\\' : PATHSEP;
char to = p_ssl ? PATHSEP : '\\';
while (*p) {
if (*p == psepcN) {
*p = psepc;
if (*p == from) {
*p = to;
}
MB_PTR_ADV(p);
}
@@ -1564,10 +1566,11 @@ char *path_to_backslash(char *p)
return p;
}
/// Convert all backslashes to forward slashes in-place.
/// Convert all backslashes to forward slashes in-place,
/// unless when it looks like a URL (e.g. `term://xxxC:\cmd.exe`).
char *path_to_slash(char *p)
{
if (p != NULL) {
if (p != NULL && !path_with_url(p)) {
strchrsub(p, '\\', PATHSEP);
}
return p;
-13
View File
@@ -2562,19 +2562,6 @@ void ex_scriptnames(exarg_T *eap)
}
}
#ifdef BACKSLASH_IN_FILENAME
/// Fix slashes in the list of script names for 'shellslash'.
void scriptnames_slash_adjust(void)
{
for (int i = 1; i <= script_items.ga_len; i++) {
if (SCRIPT_ITEM(i)->sn_name != NULL) {
slash_adjust(SCRIPT_ITEM(i)->sn_name);
}
}
}
#endif
/// Get a pointer to a script name. Used for ":verbose set".
/// Message appended to "Last set from "
///
+1
View File
@@ -3048,6 +3048,7 @@ void find_pattern_in_path(char *ptr, Direction dir, size_t len, bool whole, bool
FNAME_EXP|FNAME_INCL|FNAME_REL, 1, p_fname,
NULL);
}
TO_SLASH(new_fname);
bool already_searched = false;
if (new_fname != NULL) {
// Check whether we have already searched in this file
+233 -1
View File
@@ -9,7 +9,7 @@ local describe_lua_and_rpc = n.describe_lua_and_rpc(describe)
local api = n.api
local fn = n.fn
local request = n.request
local exec_lua = n.exec_lua
local exec, exec_lua = n.exec, n.exec_lua
local insert = n.insert
local NIL = vim.NIL
local command = n.command
@@ -2800,3 +2800,235 @@ describe('api/buf', function()
end)
end)
end)
describe('path sep in ffname/sfname #39382,', function()
if not t.is_os('win') then
return
end
local cwd, files = vim.uv.cwd(), {}
local expected_cwd = vim.fs.normalize(cwd)
for i = 1, 3 do
files[i] = ([[%s\Xtest\file%s]]):format(cwd, i)
end
local sfname_eq = function(expected, nr)
command(('buffer %s'):format(nr or ''))
eq(expected, api.nvim_eval_statusline('%f', {}).str)
end
setup(function()
t.mkdir('Xtest')
end)
teardown(function()
n.rmdir('Xtest')
end)
before_each(function()
clear()
end)
it('normalizes startup file arguments', function()
clear { args = files }
for i = 1, 3 do
eq(('%s/Xtest/file%s'):format(expected_cwd, i), api.nvim_buf_get_name(i))
sfname_eq(('Xtest/file%s'):format(i), i)
end
end)
it('normalizes :next arguments (FILES flag)', function()
command(('next %s'):format(table.concat(files, ' ')))
for i = 1, 3 do
eq(('%s/Xtest/file%s'):format(expected_cwd, i), api.nvim_buf_get_name(i))
sfname_eq(('%s/Xtest/file%s'):format(expected_cwd, i), i)
end
end)
it('normalizes :edit arguments (FILE1 flag)', function()
-- tilde prefix
command([[edit ~\foo\bar]])
eq(('%s/foo/bar'):format(fn.getenv('HOME')), api.nvim_buf_get_name(0))
sfname_eq('~/foo/bar')
-- absolute path
command(('edit %s'):format(files[1]))
eq(('%s/Xtest/file1'):format(expected_cwd), api.nvim_buf_get_name(0))
sfname_eq(('%s/Xtest/file1'):format(expected_cwd))
end)
it('normalizes bufadd() arguments', function()
local n = fn.bufadd(files[1])
eq(('%s/Xtest/file1'):format(expected_cwd), api.nvim_buf_get_name(n))
sfname_eq(('%s/Xtest/file1'):format(expected_cwd), n)
end)
it('normalizes bufnr() arguments', function()
local n = fn.bufnr(files[1], 1)
eq(('%s/Xtest/file1'):format(expected_cwd), api.nvim_buf_get_name(n))
sfname_eq(('%s/Xtest/file1'):format(expected_cwd), n)
end)
it('normalizes temp paths, <afile> and <amatch> for :diffpatch', function()
t.write_file('Xtest/patch', [[diff file]])
t.write_file('Xtest/test.txt', [[input file]])
command('edit Xtest/test.txt')
exec([[
fun MyPatch()
call writefile(['output file'], v:fname_out)
endfunc
set patchexpr=MyPatch()
]])
exec_lua([[
vim.api.nvim_create_autocmd('BufAdd', {
pattern = '*',
callback = function(ev)
vim.g.test_file = ev.file
vim.g.test_match = ev.match
end
})
]])
command('diffpatch Xtest/patch')
eq(('%s/Xtest/test.txt.new'):format(expected_cwd), api.nvim_buf_get_name(0))
sfname_eq('Xtest/test.txt.new')
local tmp = fn.getenv('TMPDIR')
local afile = fn.eval('g:test_file') ---@type string
local amatch = fn.eval('g:test_match') ---@type string
t.matches(tmp, afile, true)
t.not_matches('\\', afile, true)
t.matches(tmp, amatch, true)
t.not_matches('\\', amatch, true)
end)
it('normalizes :find results', function()
t.write_file('Xtest/file1', '')
command([[find Xtest\file1]])
eq(('%s/Xtest/file1'):format(expected_cwd), api.nvim_buf_get_name(0))
sfname_eq('Xtest/file1')
-- 'findfunc'
exec(([[
func FindFile(cmdarg, cmdcomplete)
return ['%s']
endfunc
set findfunc=FindFile
]]):format(files[2]))
command([[find file2]])
eq(('%s/Xtest/file2'):format(expected_cwd), api.nvim_buf_get_name(0))
sfname_eq(('%s/Xtest/file2'):format(expected_cwd))
end)
it('normalizes :scriptnames arguments', function()
command(('scriptnames %s'):format(files[1]))
eq(('%s/Xtest/file1'):format(expected_cwd), api.nvim_buf_get_name(0))
sfname_eq(('%s/Xtest/file1'):format(expected_cwd))
end)
it('normalizes gf targets', function()
t.write_file('Xtest/file1', '')
feed(('i%s<Esc>0gf'):format(files[1]))
eq(('%s/Xtest/file1'):format(expected_cwd), api.nvim_buf_get_name(0))
sfname_eq(('%s/Xtest/file1'):format(expected_cwd))
command('bw')
feed('<C-W>f')
eq(('%s/Xtest/file1'):format(expected_cwd), api.nvim_buf_get_name(0))
sfname_eq(('%s/Xtest/file1'):format(expected_cwd))
end)
it('normalizes macro definition targets and completions', function()
t.mkdir('Xtest/sub')
t.write_file(
'Xtest/sub/bar.h',
[[
#define MIN 0;
#define MAX 10;
]]
)
t.write_file(
'Xtest/foo.c',
[[
#include "sub\bar.h";
void main() {
int i = MIN;
}
]]
)
local screen = Screen.new(30, 10)
command([[set include=^\\s*#\\s*include]])
command([[set define=^\\s*#\\s*define]])
command('e Xtest/foo.c')
command('djump MIN')
eq(('%s/Xtest/sub/bar.h'):format(expected_cwd), api.nvim_buf_get_name(0))
sfname_eq('Xtest/sub/bar.h')
command('bw')
feed('/MIN<CR>lxxi<C-x><C-d>')
screen:expect({
any = {
'MIN Xtest/sub/bar.h',
'MAX Xtest/sub/bar.h',
},
})
end)
it('normalizes tag targets', function()
t.write_file(
'Xtest/tags',
[[
main .\\foo.c /^void main() /;" f typeref:typename:void
main2 $DIR\foo.c /^void main2() /;" f typeref:typename:void
main3 ./foo.c /^void main3() /;" f typeref:typename:void
]]
)
t.write_file(
'Xtest/foo.c',
[[
void main() {}
void main2() {};
void main3() {};
]]
)
command('cd Xtest')
command('tjump main')
eq(('%s/Xtest/foo.c'):format(expected_cwd), api.nvim_buf_get_name(0))
sfname_eq('.//foo.c')
command('bw')
fn.setenv('DIR', ([[%s\Xtest]]):format(cwd))
command('tjump main2')
eq(('%s/Xtest/foo.c'):format(expected_cwd), api.nvim_buf_get_name(0))
sfname_eq(('%s/Xtest/foo.c'):format(expected_cwd))
command('bw')
command('tjump main3')
eq(('%s/Xtest/foo.c'):format(expected_cwd), api.nvim_buf_get_name(0))
sfname_eq('./foo.c')
end)
it('normalizes quickfix targets', function()
t.write_file(
'Xtest/error',
[[
foo.c
.\Xtest\foo.c(3): error C2143: syntax error: missing ';' before 'return'
]]
)
local screen = Screen.new(40, 10)
command('cg Xtest/error')
command('copen')
screen:expect({
any = './Xtest/foo.c',
})
feed('<CR>')
eq(('%s/Xtest/foo.c'):format(expected_cwd), api.nvim_buf_get_name(0))
sfname_eq('./Xtest/foo.c')
end)
it('preserves backslashes in URIs', function()
local exe_path = fn.exepath('cmd')
t.not_matches('/', exe_path, true)
command(('e term://%s'):format(exe_path))
t.matches(exe_path, api.nvim_buf_get_name(0), true)
t.matches(exe_path, api.nvim_eval_statusline('%f', {}).str, true)
end)
end)
+14 -2
View File
@@ -9,7 +9,7 @@ local nvim_prog, command, fn = n.nvim_prog, n.command, n.fn
local source, next_msg = n.source, n.next_msg
local ok = t.ok
local api = n.api
local set_session = n.set_session
local new_session, set_session = n.new_session, n.set_session
local pcall_err = t.pcall_err
local assert_alive = n.assert_alive
@@ -328,7 +328,19 @@ describe('server -> client', function()
set_session(server)
local address = fn.serverlist()[1]
local first = string.sub(address, 1, 1)
ok(first == '/' or first == '\\')
ok(first == '/')
connect_test(server, 'pipe', address)
end)
it('via named pipe containing backslashes #39382', function()
t.skip(not t.is_os('win'), 'N/A for non-Windows')
local address = [[\\.\pipe\Xtest]]
local server = new_session(false, {
args_rm = { '--listen' },
args = { '--listen', address },
})
set_session(server)
eq(vim.fs.normalize(address), api.nvim_get_vvar('servername'))
connect_test(server, 'pipe', address)
end)
+21 -24
View File
@@ -1793,12 +1793,11 @@ describe('API', function()
eq(NIL, api.nvim_get_var('Unknown_script_func'))
-- Check if autoload works properly
local pathsep = n.get_pathsep()
local xhome = 'Xhome_api'
local xconfig = xhome .. pathsep .. 'Xconfig'
local xdata = xhome .. pathsep .. 'Xdata'
local autoload_folder = table.concat({ xconfig, 'nvim', 'autoload' }, pathsep)
local autoload_file = table.concat({ autoload_folder, 'testload.vim' }, pathsep)
local xconfig = ('%s/Xconfig'):format(xhome)
local xdata = ('%s/Xdata'):format(xhome)
local autoload_folder = ('%s/nvim/autoload'):format(xconfig)
local autoload_file = ('%s/testload.vim'):format(autoload_folder)
mkdir_p(autoload_folder)
write_file(autoload_file, [[let testload#value = 2]])
@@ -2845,7 +2844,7 @@ describe('API', function()
filter(map(add(
getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }),
'filter(
{ "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
{ "f": expand("#".v:val.bufnr.":p:gs?\\?/?"), "l": v:val.lnum },
{ k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
]]):gsub('\n', ''))),
@@ -3414,9 +3413,8 @@ describe('API', function()
local test_dir = 'Xtest_list_runtime_paths'
setup(function()
local pathsep = n.get_pathsep()
mkdir_p(test_dir .. pathsep .. 'a')
mkdir_p(test_dir .. pathsep .. 'b')
mkdir_p(('%s/a'):format(test_dir))
mkdir_p(('%s/b'):format(test_dir))
end)
teardown(function()
rmdir(test_dir)
@@ -3934,7 +3932,6 @@ describe('API', function()
end)
describe('nvim_get_runtime_file', function()
local p = t.fix_slashes
it('can find files', function()
eq({}, api.nvim_get_runtime_file('bork.borkbork', false))
eq({}, api.nvim_get_runtime_file('bork.borkbork', true))
@@ -3943,36 +3940,36 @@ describe('API', function()
local val = api.nvim_get_runtime_file('autoload/remote/*.vim', true)
eq(2, #val)
if endswith(val[1], 'define.vim') then
ok(endswith(p(val[1]), 'autoload/remote/define.vim'))
ok(endswith(p(val[2]), 'autoload/remote/host.vim'))
ok(endswith(val[1], 'autoload/remote/define.vim'))
ok(endswith(val[2], 'autoload/remote/host.vim'))
else
ok(endswith(p(val[1]), 'autoload/remote/host.vim'))
ok(endswith(p(val[2]), 'autoload/remote/define.vim'))
ok(endswith(val[1], 'autoload/remote/host.vim'))
ok(endswith(val[2], 'autoload/remote/define.vim'))
end
val = api.nvim_get_runtime_file('autoload/remote/*.vim', false)
eq(1, #val)
ok(
endswith(p(val[1]), 'autoload/remote/define.vim')
or endswith(p(val[1]), 'autoload/remote/host.vim')
endswith(val[1], 'autoload/remote/define.vim')
or endswith(val[1], 'autoload/remote/host.vim')
)
val = api.nvim_get_runtime_file('lua', true)
eq(1, #val)
ok(endswith(p(val[1]), 'lua'))
ok(endswith(val[1], 'lua'))
val = api.nvim_get_runtime_file('lua/vim', true)
eq(1, #val)
ok(endswith(p(val[1]), 'lua/vim'))
ok(endswith(val[1], 'lua/vim'))
end)
it('can find directories', function()
local val = api.nvim_get_runtime_file('lua/', true)
eq(1, #val)
ok(endswith(p(val[1]), 'lua/'))
ok(endswith(val[1], 'lua/'))
val = api.nvim_get_runtime_file('lua/vim/', true)
eq(1, #val)
ok(endswith(p(val[1]), 'lua/vim/'))
ok(endswith(val[1], 'lua/vim/'))
eq({}, api.nvim_get_runtime_file('foobarlang/', true))
end)
@@ -3993,8 +3990,8 @@ describe('API', function()
local val = api.nvim_get_runtime_file('vim.vim', true)
eq(2, #val)
eq(p(val[1]), vimruntime .. '/syntax/vim.vim')
eq(p(val[2]), vimruntime .. '/ftplugin/vim.vim')
eq(val[1], ('%s/syntax/vim.vim'):format(vimruntime))
eq(val[2], ('%s/ftplugin/vim.vim'):format(vimruntime))
end)
it('finds files via an 8.3 filename path #25019', function()
@@ -4006,8 +4003,8 @@ describe('API', function()
finally(function()
rmdir(path)
end)
local path_with_shortname =
p(fn.system(('for %%I in ("%s") do @echo %%~sI'):format(path), ''):gsub('\n', ''))
local path_with_shortname = fn.system(('for %%I in ("%s") do @echo %%~sI'):format(path), '')
path_with_shortname = vim.fs.normalize(vim.trim(path_with_shortname))
eq('XTEST_~1', vim.fs.basename(path_with_shortname))
exec_lua(('vim.opt.rtp:prepend("%s/*")'):format(path_with_shortname))
local val = api.nvim_get_runtime_file('lua/foo.lua', true)
+13
View File
@@ -855,4 +855,17 @@ describe('autocmd', function()
fn.execute('autocmd User ,,,there,is,,a,fly,,')
)
end)
it('normalizes path sep (slashes) in env var `pattern` #39382', function()
local path = t.is_os('win') and [[C:\foo\bar]] or 'C:/foo/bar'
fn.setenv('FOOBAR', path)
exec [[
autocmd User ~,$FOOBAR "
]]
local cmds = exec_lua(function()
return vim.api.nvim_get_autocmds({ event = 'User' })
end)
eq(vim.fs.normalize('~'), cmds[1].pattern)
eq(vim.fs.normalize(path), cmds[2].pattern)
end)
end)
-22
View File
@@ -178,28 +178,6 @@ describe('command-line option', function()
matches('Run "nvim %-V1 %-v"', n.spawn_wait('-v').stdout)
matches('fall%-back for %$VIM: .*Run :checkhealth', n.spawn_wait('-V1', '-v').stdout)
end)
if is_os('win') then
for _, prefix in ipairs({ '~/', '~\\' }) do
it('expands ' .. prefix .. ' on Windows', function()
local fname = os.getenv('USERPROFILE') .. '\\nvim_test.txt'
finally(function()
os.remove(fname)
end)
write_file(fname, 'some text')
eq(
'some text',
fn.system({
n.nvim_prog,
'-es',
'+%print',
'+q',
prefix .. 'nvim_test.txt',
}):gsub('\n', '')
)
end)
end
end
end)
describe('vim._core', function()
+61 -2
View File
@@ -12,6 +12,7 @@ local is_os = t.is_os
local mkdir = t.mkdir
local rmdir = n.rmdir
local write_file = t.write_file
local api = n.api
local function join_path(...)
return table.concat({ ... }, '/')
@@ -69,6 +70,64 @@ describe('path', function()
end)
end)
describe('startup', function()
local home, foo, bar = vim.fs.normalize('~'), 'Xtest-foo.lua', 'Xtest-bar.lua'
setup(function()
write_file(('%s/%s'):format(home, foo), 'local foo = 1;')
write_file(('%s/%s'):format(home, bar), '')
end)
teardown(function()
os.remove(('%s/%s'):format(home, foo))
os.remove(('%s/%s'):format(home, bar))
end)
it('expands tilde-prefixed paths #29380', function()
t.skip(not is_os('win'), 'N/A: shell expands ~ on Unix')
clear {
args = { ('~/%s'):format(foo), ('~\\%s'):format(bar) },
}
local expected = { ('%s/%s'):format(home, foo), ('%s/%s'):format(home, bar) }
eq(expected, vim.tbl_map(fn.bufname, api.nvim_list_bufs()))
eq(expected, fn.argv())
end)
it('normalizes v:progpath #39382', function()
clear()
eq(
n.nvim_prog,
fn.system({
is_os('win') and n.nvim_prog:gsub('/', '\\') or n.nvim_prog,
'--clean',
'--headless',
'+echo v:progpath',
'+q',
})
)
end)
it('normalizes -u arguments and triggers autocmd events #39382', function()
local file = ('%s/%s'):format(home, foo)
if is_os('win') then
file = file:gsub('/', '\\')
end
clear {
args_rm = { '--cmd', '-u' },
args = {
'--cmd',
('autocmd SourcePre */%s let g:matched = 1'):format(foo),
'-u',
file,
},
}
local scripts = fn.getscriptinfo({ name = foo })
eq(1, #scripts)
eq(('%s/%s'):format(home, foo), scripts[1].name)
t.ok(fn.eval('g:matched'))
end)
end)
describe('expand wildcard', function()
before_each(clear)
@@ -82,9 +141,9 @@ describe('expand wildcard', function()
}
for _, folder in ipairs(folders) do
mkdir(folder)
local file = join_path(folder, 'file.txt')
local file = ('%s%sfile.txt'):format(folder, n.get_pathsep())
write_file(file, '')
eq(file, eval('expand("' .. folder .. '/*")'))
eq(file, fn.expand(('%s/*'):format(folder)))
rmdir(folder)
end
end)
+37 -3
View File
@@ -87,7 +87,7 @@ describe('server', function()
-- v:servername and $NVIM take the next available server.
local servername = (
is_os('win') and [[\\.\pipe\Xtest-functional-server-pipe]]
is_os('win') and [[//./pipe/Xtest-functional-server-pipe]]
or './Xtest-functional-server-socket'
)
fn.serverstart(servername)
@@ -170,7 +170,7 @@ describe('server', function()
-- Add some servers.
local servs = (
is_os('win') and { [[\\.\pipe\Xtest-pipe0934]], [[\\.\pipe\Xtest-pipe4324]] }
is_os('win') and { [[//./pipe/Xtest-pipe0934]], [[//./pipe/Xtest-pipe4324]] }
or { [[./Xtest-pipe0934]], [[./Xtest-pipe4324]] }
)
for _, s in ipairs(servs) do
@@ -316,6 +316,40 @@ describe('server', function()
matches('Failed.*listen', result.stderr)
fn.serverstop(socket_path)
end)
it('normalizes sep in named pipe paths #39382', function()
t.skip(not is_os('win'), 'N/A: Named pipe is Windows feature')
local name, named_pipe = 'Xtest-server', [[\\.\pipe\Xtest-server]]
-- default address
clear { args_rm = { '--listen' } }
matches('//./pipe/', fn.eval('v:servername'), true)
clear({ args_rm = { '--listen' }, env = { NVIM_LISTEN_ADDRESS = named_pipe } })
eq(vim.fs.normalize(named_pipe), fn.eval('v:servername'))
clear({ args_rm = { '--listen' }, args = { '--listen', name } })
matches(vim.fs.normalize(named_pipe), fn.eval('v:servername'), true)
clear({ args_rm = { '--listen' }, args = { '--listen', named_pipe } })
eq(vim.fs.normalize(named_pipe), fn.eval('v:servername'))
local server = n.get_session()
local client = n.new_session(true)
n.set_session(client)
local res = fn.system({
n.nvim_prog,
'--clean',
'-es',
'--server',
named_pipe,
'--remote-expr',
'v:servername',
})
eq(vim.fs.normalize(named_pipe), res)
client:close()
n.set_session(server)
end)
end)
describe('startup --listen', function()
@@ -400,7 +434,7 @@ describe('startup --listen', function()
end)
it('sets v:servername, overrides $NVIM_LISTEN_ADDRESS', function()
local addr = (is_os('win') and [[\\.\pipe\Xtest-listen-pipe]] or './Xtest-listen-pipe')
local addr = (is_os('win') and [[//./pipe/Xtest-listen-pipe]] or './Xtest-listen-pipe')
clear({ env = { NVIM_LISTEN_ADDRESS = './Xtest-env-pipe' }, args = { '--listen', addr } })
eq('', eval('$NVIM_LISTEN_ADDRESS')) -- Cleared on startup.
eq(addr, api.nvim_get_vvar('servername'))
+2 -2
View File
@@ -127,8 +127,8 @@ describe('spellfile', function()
n.insert('abc')
n.feed('zg')
eq(
t.fix_slashes(fn.stdpath('data') .. '/site/spell/en.utf-8.add'),
t.fix_slashes(api.nvim_get_option_value('spellfile', {}))
('%s/site/spell/en.utf-8.add'):format(fn.stdpath('data')),
api.nvim_get_option_value('spellfile', {})
)
end)
+51 -75
View File
@@ -39,16 +39,10 @@ local testlog = 'Xtest-startupspec-log'
describe('startup', function()
it('--clean', function()
clear()
matches(
vim.pesc(t.fix_slashes(fn.stdpath('config'))),
t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
)
matches(vim.pesc(fn.stdpath('config')), api.nvim_get_option_value('runtimepath', {}))
clear('--clean')
ok(
not t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
:match(vim.pesc(t.fix_slashes(fn.stdpath('config'))))
)
ok(not api.nvim_get_option_value('runtimepath', {}):match(vim.pesc(fn.stdpath('config'))))
end)
it('prevents remote UI infinite loop', function()
@@ -1280,7 +1274,6 @@ describe('sysinit', function()
local xdgdir = 'Xxdg'
local vimdir = 'Xvim'
local xhome = 'Xhome'
local pathsep = n.get_pathsep()
before_each(function()
rmdir(xdgdir)
@@ -1288,9 +1281,9 @@ describe('sysinit', function()
rmdir(xhome)
mkdir(xdgdir)
mkdir(xdgdir .. pathsep .. 'nvim')
mkdir(('%s/nvim'):format(xdgdir))
write_file(
table.concat({ xdgdir, 'nvim', 'sysinit.vim' }, pathsep),
('%s/nvim/sysinit.vim'):format(xdgdir),
[[
let g:loaded = get(g:, "loaded", 0) + 1
let g:xdg = 1
@@ -1299,7 +1292,7 @@ describe('sysinit', function()
mkdir(vimdir)
write_file(
table.concat({ vimdir, 'sysinit.vim' }, pathsep),
('%s/sysinit.vim'):format(vimdir),
[[
let g:loaded = get(g:, "loaded", 0) + 1
let g:vim = 1
@@ -1340,11 +1333,8 @@ describe('sysinit', function()
it('respects NVIM_APPNAME in XDG_CONFIG_DIRS', function()
local appname = 'mysysinitapp'
mkdir(xdgdir .. pathsep .. appname)
write_file(
table.concat({ xdgdir, appname, 'sysinit.vim' }, pathsep),
[[let g:appname_sysinit = 1]]
)
mkdir(('%s/%s'):format(xdgdir, appname))
write_file(('%s/%s/sysinit.vim'):format(xdgdir, appname), [[let g:appname_sysinit = 1]])
clear {
args_rm = { '-u' },
env = { HOME = xhome, XDG_CONFIG_DIRS = xdgdir, NVIM_APPNAME = appname },
@@ -1357,16 +1347,15 @@ end)
describe('user config init', function()
local xhome = 'Xhome'
local pathsep = n.get_pathsep()
local xconfig = xhome .. pathsep .. 'Xconfig'
local xdata = xhome .. pathsep .. 'Xdata'
local init_lua_path = table.concat({ xconfig, 'nvim', 'init.lua' }, pathsep)
local xconfig = ('%s/Xconfig'):format(xhome)
local xdata = ('%s/Xdata'):format(xhome)
local init_lua_path = ('%s/nvim/init.lua'):format(xconfig)
local xenv = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata }
before_each(function()
rmdir(xhome)
mkdir_p(xconfig .. pathsep .. 'nvim')
mkdir_p(('%s/nvim'):format(xconfig))
mkdir_p(xdata)
write_file(init_lua_path, [[vim.g.lua_rc = 1]])
@@ -1430,7 +1419,7 @@ describe('user config init', function()
vim.g.exrc_file = '---'
]]
)
mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim'))
mkdir_p(('%s/%s'):format(xstate, is_os('win') and 'nvim-data' or 'nvim'))
end)
after_each(function()
@@ -1556,7 +1545,7 @@ describe('user config init', function()
end)
describe('with explicitly provided config', function()
local custom_lua_path = table.concat({ xhome, 'custom.lua' }, pathsep)
local custom_lua_path = ('%s/custom.lua'):format(xhome)
before_each(function()
write_file(
custom_lua_path,
@@ -1576,7 +1565,7 @@ describe('user config init', function()
describe('VIMRC also exists', function()
before_each(function()
write_file(
table.concat({ xconfig, 'nvim', 'init.vim' }, pathsep),
('%s/nvim/init.vim'):format(xconfig),
[[
let g:vim_rc = 1
]]
@@ -1600,7 +1589,7 @@ describe('user config init', function()
-- Remove init.lua from XDG_CONFIG_HOME so nvim falls back to XDG_CONFIG_DIRS
os.remove(init_lua_path)
rmdir(xdgdir)
mkdir_p(xdgdir .. pathsep .. 'nvim')
mkdir_p(('%s/nvim'):format(xdgdir))
end)
after_each(function()
@@ -1608,24 +1597,18 @@ describe('user config init', function()
end)
it('loads init.lua from XDG_CONFIG_DIRS when no config in XDG_CONFIG_HOME', function()
write_file(
table.concat({ xdgdir, 'nvim', 'init.lua' }, pathsep),
[[vim.g.xdg_config_dirs_lua = 1]]
)
write_file(('%s/nvim/init.lua'):format(xdgdir), [[vim.g.xdg_config_dirs_lua = 1]])
clear {
args_rm = { '-u' },
env = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata, XDG_CONFIG_DIRS = xdgdir },
}
eq(1, eval('g:xdg_config_dirs_lua'))
eq(
fn.fnamemodify(table.concat({ xdgdir, 'nvim', 'init.lua' }, pathsep), ':p'),
eval('$MYVIMRC')
)
eq(fn.fnamemodify(('%s/nvim/init.lua'):format(xdgdir), ':p'), eval('$MYVIMRC'))
end)
it('prefers init.lua over init.vim, shows E5422', function()
write_file(table.concat({ xdgdir, 'nvim', 'init.lua' }, pathsep), [[vim.g.xdg_lua = 1]])
write_file(table.concat({ xdgdir, 'nvim', 'init.vim' }, pathsep), [[let g:xdg_vim = 1]])
write_file(('%s/nvim/init.lua'):format(xdgdir), [[vim.g.xdg_lua = 1]])
write_file(('%s/nvim/init.vim'):format(xdgdir), [[let g:xdg_vim = 1]])
clear {
args_rm = { '-u' },
env = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata, XDG_CONFIG_DIRS = xdgdir },
@@ -1636,7 +1619,7 @@ describe('user config init', function()
end)
it('falls back to init.vim when no init.lua', function()
write_file(table.concat({ xdgdir, 'nvim', 'init.vim' }, pathsep), [[let g:xdg_vim = 1]])
write_file(('%s/nvim/init.vim'):format(xdgdir), [[let g:xdg_vim = 1]])
clear {
args_rm = { '-u' },
env = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata, XDG_CONFIG_DIRS = xdgdir },
@@ -1646,10 +1629,10 @@ describe('user config init', function()
it('respects NVIM_APPNAME', function()
local appname = 'mytestapp'
mkdir_p(xdgdir .. pathsep .. appname)
mkdir_p(('%s/%s'):format(xdgdir, appname))
-- Also create nvim/ with a config that should NOT be loaded
write_file(table.concat({ xdgdir, 'nvim', 'init.lua' }, pathsep), [[vim.g.wrong = 1]])
write_file(table.concat({ xdgdir, appname, 'init.lua' }, pathsep), [[vim.g.appname_lua = 1]])
write_file(('%s/nvim/init.lua'):format(xdgdir), [[vim.g.wrong = 1]])
write_file(('%s/%s/init.lua'):format(xdgdir, appname), [[vim.g.appname_lua = 1]])
clear {
args_rm = { '-u' },
env = {
@@ -1661,24 +1644,20 @@ describe('user config init', function()
}
eq(1, eval('g:appname_lua'))
eq(0, eval('get(g:, "wrong", 0)'))
eq(
fn.fnamemodify(table.concat({ xdgdir, appname, 'init.lua' }, pathsep), ':p'),
eval('$MYVIMRC')
)
eq(fn.fnamemodify(('%s/%s/init.lua'):format(xdgdir, appname), ':p'), eval('$MYVIMRC'))
end)
end)
end)
describe('runtime:', function()
local xhome = 'Xhome'
local pathsep = '/'
local xconfig = xhome .. pathsep .. 'Xconfig'
local xdata = xhome .. pathsep .. 'Xdata'
local xconfig = ('%s/Xconfig'):format(xhome)
local xdata = ('%s/Xdata'):format(xhome)
local xenv = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata }
setup(function()
rmdir(xhome)
mkdir_p(xconfig .. pathsep .. 'nvim')
mkdir_p(('%s/nvim'):format(xconfig))
mkdir_p(xdata)
end)
@@ -1687,8 +1666,8 @@ describe('runtime:', function()
end)
it('loads plugin/*.lua from XDG config home', function()
local plugin_folder_path = table.concat({ xconfig, 'nvim', 'plugin' }, pathsep)
local plugin_file_path = table.concat({ plugin_folder_path, 'plugin.lua' }, pathsep)
local plugin_folder_path = ('%s/nvim/plugin'):format(xconfig)
local plugin_file_path = ('%s/plugin.lua'):format(plugin_folder_path)
mkdir_p(plugin_folder_path)
finally(function()
rmdir(plugin_folder_path)
@@ -1701,10 +1680,9 @@ describe('runtime:', function()
end)
it('loads plugin/*.lua from start packages', function()
local plugin_path =
table.concat({ xconfig, 'nvim', 'pack', 'category', 'start', 'test_plugin' }, pathsep)
local plugin_folder_path = table.concat({ plugin_path, 'plugin' }, pathsep)
local plugin_file_path = table.concat({ plugin_folder_path, 'plugin.lua' }, pathsep)
local plugin_path = ('%s/nvim/pack/category/start/test_plugin'):format(xconfig)
local plugin_folder_path = ('%s/plugin'):format(plugin_path)
local plugin_file_path = ('%s/plugin.lua'):format(plugin_folder_path)
local profiler_file = 'test_startuptime.log'
mkdir_p(plugin_folder_path)
finally(function()
@@ -1734,12 +1712,11 @@ describe('runtime:', function()
it('loads plugin/*.lua from site packages', function()
local nvimdata = is_os('win') and 'nvim-data' or 'nvim'
local plugin_path =
table.concat({ xdata, nvimdata, 'site', 'pack', 'xa', 'start', 'yb' }, pathsep)
local plugin_folder_path = table.concat({ plugin_path, 'plugin' }, pathsep)
local plugin_after_path = table.concat({ plugin_path, 'after', 'plugin' }, pathsep)
local plugin_file_path = table.concat({ plugin_folder_path, 'plugin.lua' }, pathsep)
local plugin_after_file_path = table.concat({ plugin_after_path, 'helloo.lua' }, pathsep)
local plugin_path = ('%s/%s/site/pack/xa/start/yb'):format(xdata, nvimdata)
local plugin_folder_path = ('%s/plugin'):format(plugin_path)
local plugin_after_path = ('%s/after/plugin'):format(plugin_path)
local plugin_file_path = ('%s/plugin.lua'):format(plugin_folder_path)
local plugin_after_file_path = ('%s/helloo.lua'):format(plugin_after_path)
mkdir_p(plugin_folder_path)
mkdir_p(plugin_after_path)
finally(function()
@@ -1755,21 +1732,21 @@ describe('runtime:', function()
end)
it('no crash setting &rtp in plugins with :packloadall called before #18315', function()
local plugin_folder_path = table.concat({ xconfig, 'nvim', 'plugin' }, pathsep)
local plugin_folder_path = ('%s/nvim/plugin'):format(xconfig)
mkdir_p(plugin_folder_path)
finally(function()
rmdir(plugin_folder_path)
end)
write_file(
table.concat({ plugin_folder_path, 'plugin.vim' }, pathsep),
('%s/plugin.vim'):format(plugin_folder_path),
[[
let &runtimepath = &runtimepath
let g:vim_plugin = 1
]]
)
write_file(
table.concat({ plugin_folder_path, 'plugin.lua' }, pathsep),
('%s/plugin.lua'):format(plugin_folder_path),
[[
vim.o.runtimepath = vim.o.runtimepath
vim.g.lua_plugin = 1
@@ -1783,29 +1760,29 @@ describe('runtime:', function()
end)
it("loads ftdetect/*.{vim,lua} respecting 'rtp' order", function()
local rtp_folder = table.concat({ xconfig, 'nvim' }, pathsep)
local after_rtp_folder = table.concat({ rtp_folder, 'after' }, pathsep)
local ftdetect_folder = table.concat({ rtp_folder, 'ftdetect' }, pathsep)
local after_ftdetect_folder = table.concat({ after_rtp_folder, 'ftdetect' }, pathsep)
local rtp_folder = ('%s/nvim'):format(xconfig)
local after_rtp_folder = ('%s/after'):format(rtp_folder)
local ftdetect_folder = ('%s/ftdetect'):format(rtp_folder)
local after_ftdetect_folder = ('%s/ftdetect'):format(after_rtp_folder)
mkdir_p(ftdetect_folder)
mkdir_p(after_ftdetect_folder)
finally(function()
rmdir(ftdetect_folder)
rmdir(after_ftdetect_folder)
end)
write_file(table.concat({ rtp_folder, 'scripts.vim' }, pathsep), [[let g:aseq ..= 'S']])
write_file(table.concat({ after_rtp_folder, 'scripts.vim' }, pathsep), [[let g:aseq ..= 's']])
write_file(('%s/scripts.vim'):format(rtp_folder), [[let g:aseq ..= 'S']])
write_file(('%s/scripts.vim'):format(after_rtp_folder), [[let g:aseq ..= 's']])
-- A .lua file is loaded after a .vim file if they only differ in extension.
-- All files in after/ftdetect/ are loaded after all files in ftdetect/.
write_file(
table.concat({ ftdetect_folder, 'new-ft.vim' }, pathsep),
('%s/new-ft.vim'):format(ftdetect_folder),
[[
let g:seq ..= 'A'
autocmd BufRead,BufNewFile FTDETECT let g:aseq ..= 'A'
]]
)
write_file(
table.concat({ ftdetect_folder, 'new-ft.lua' }, pathsep),
('%s/new-ft.lua'):format(ftdetect_folder),
[[
vim.g.seq = vim.g.seq .. 'B'
vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile' }, {
@@ -1815,14 +1792,14 @@ describe('runtime:', function()
]]
)
write_file(
table.concat({ after_ftdetect_folder, 'new-ft.vim' }, pathsep),
('%s/new-ft.vim'):format(after_ftdetect_folder),
[[
let g:seq ..= 'a'
autocmd BufRead,BufNewFile FTDETECT let g:aseq ..= 'a'
]]
)
write_file(
table.concat({ after_ftdetect_folder, 'new-ft.lua' }, pathsep),
('%s/new-ft.lua'):format(after_ftdetect_folder),
[[
vim.g.seq = vim.g.seq .. 'b'
vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile' }, {
@@ -1853,8 +1830,7 @@ end)
describe('user session', function()
local xhome = 'Xhome'
local pathsep = n.get_pathsep()
local session_file = table.concat({ xhome, 'session.lua' }, pathsep)
local session_file = ('%s/session.lua'):format(xhome)
before_each(function()
rmdir(xhome)
@@ -1851,4 +1851,18 @@ describe('completion', function()
{5:-- File name completion (^F^N^P) }{9:Pattern not found} |
]])
end)
it('returns all entries in the directory #25791', function()
n.mkdir_p('Xtest/sub1')
n.mkdir_p('Xtest/sub2')
t.write_file('Xtest/A', '')
t.write_file('Xtest/sub1/B', '')
t.write_file('Xtest/sub2/C', '')
finally(function()
n.rmdir('Xtest')
end)
local path = ('%s/Xtest/**'):format(vim.fs.normalize(vim.uv.cwd()))
command(('set path=%s'):format(path))
eq({ 'A', 'B', 'C', 'sub1/', 'sub2/' }, fn.getcompletion('find ', 'cmdline'))
end)
end)
+83 -150
View File
@@ -13,7 +13,6 @@ local write_file = t.write_file
describe('runtime:', function()
local plug_dir = 'Test_Plugin'
local sep = n.get_pathsep()
local init = 'dummy_init.lua'
-- All test cases below use the same Nvim instance.
@@ -46,13 +45,13 @@ describe('runtime:', function()
end)
describe('colors', function()
local colorscheme_folder = plug_dir .. sep .. 'colors'
local colorscheme_folder = ('%s/colors'):format(plug_dir)
before_each(function()
mkdir_p(colorscheme_folder)
end)
it('Lua colorschemes work and are included in cmdline completion', function()
local colorscheme_file = table.concat({ colorscheme_folder, 'new_colorscheme.lua' }, sep)
local colorscheme_file = ('%s/new_colorscheme.lua'):format(colorscheme_folder)
write_file(colorscheme_file, [[vim.g.lua_colorscheme = 1]])
eq({ 'new_colorscheme' }, fn.getcompletion('new_c', 'color'))
@@ -71,51 +70,51 @@ describe('runtime:', function()
end)
exec('set pp+=' .. pack_dir)
local pack_opt_dir = table.concat({ pack_dir, 'pack', 'some_name', 'opt' }, sep)
local colors_opt_dir = table.concat({ pack_opt_dir, 'some_pack', 'colors' }, sep)
local pack_opt_dir = ('%s/pack/some_name/opt'):format(pack_dir)
local colors_opt_dir = ('%s/some_pack/colors'):format(pack_opt_dir)
mkdir_p(colors_opt_dir)
local after_colorscheme_folder = table.concat({ plug_dir, 'after', 'colors' }, sep)
local after_colorscheme_folder = ('%s/after/colors'):format(plug_dir)
mkdir_p(after_colorscheme_folder)
exec('set rtp+=' .. plug_dir .. '/after')
write_file(
table.concat({ colors_opt_dir, 'new_colorscheme.lua' }, sep),
('%s/new_colorscheme.lua'):format(colors_opt_dir),
[[vim.g.colorscheme = 'lua_pp']]
)
exec('colorscheme new_colorscheme')
eq('lua_pp', eval('g:colorscheme'))
write_file(
table.concat({ colors_opt_dir, 'new_colorscheme.vim' }, sep),
('%s/new_colorscheme.vim'):format(colors_opt_dir),
[[let g:colorscheme = 'vim_pp']]
)
exec('colorscheme new_colorscheme')
eq('vim_pp', eval('g:colorscheme'))
write_file(
table.concat({ after_colorscheme_folder, 'new_colorscheme.lua' }, sep),
('%s/new_colorscheme.lua'):format(after_colorscheme_folder),
[[vim.g.colorscheme = 'lua_rtp_after']]
)
exec('colorscheme new_colorscheme')
eq('lua_rtp_after', eval('g:colorscheme'))
write_file(
table.concat({ after_colorscheme_folder, 'new_colorscheme.vim' }, sep),
('%s/new_colorscheme.vim'):format(after_colorscheme_folder),
[[let g:colorscheme = 'vim_rtp_after']]
)
exec('colorscheme new_colorscheme')
eq('vim_rtp_after', eval('g:colorscheme'))
write_file(
table.concat({ colorscheme_folder, 'new_colorscheme.lua' }, sep),
('%s/new_colorscheme.lua'):format(colorscheme_folder),
[[vim.g.colorscheme = 'lua_rtp']]
)
exec('colorscheme new_colorscheme')
eq('lua_rtp', eval('g:colorscheme'))
write_file(
table.concat({ colorscheme_folder, 'new_colorscheme.vim' }, sep),
('%s/new_colorscheme.vim'):format(colorscheme_folder),
[[let g:colorscheme = 'vim_rtp']]
)
exec('colorscheme new_colorscheme')
@@ -124,13 +123,13 @@ describe('runtime:', function()
end)
describe('compiler', function()
local compiler_folder = table.concat({ plug_dir, 'compiler' }, sep)
local compiler_folder = ('%s/compiler'):format(plug_dir)
before_each(function()
mkdir_p(compiler_folder)
end)
it('Lua compilers work and are included in cmdline completion', function()
local compiler_file = compiler_folder .. sep .. 'new_compiler.lua'
local compiler_file = ('%s/new_compiler.lua'):format(compiler_folder)
write_file(compiler_file, [[vim.b.lua_compiler = 1]])
eq({ 'new_compiler' }, fn.getcompletion('new_c', 'compiler'))
@@ -142,24 +141,18 @@ describe('runtime:', function()
end)
it("'rtp' order is respected", function()
local after_compiler_folder = table.concat({ plug_dir, 'after', 'compiler' }, sep)
mkdir_p(table.concat({ compiler_folder, 'new_compiler' }, sep))
mkdir_p(table.concat({ after_compiler_folder, 'new_compiler' }, sep))
local after_compiler_folder = ('%s/after/compiler'):format(plug_dir)
mkdir_p(('%s/new_compiler'):format(compiler_folder))
mkdir_p(('%s/new_compiler'):format(after_compiler_folder))
exec('set rtp+=' .. plug_dir .. '/after')
exec('let g:seq = ""')
-- A .lua file is loaded after a .vim file if they only differ in extension.
-- All files in after/compiler/ are loaded after all files in compiler/.
write_file(table.concat({ compiler_folder, 'new_compiler.vim' }, sep), [[let g:seq ..= 'A']])
write_file(('%s/new_compiler.vim'):format(compiler_folder), [[let g:seq ..= 'A']])
write_file(('%s/new_compiler.lua'):format(compiler_folder), [[vim.g.seq = vim.g.seq .. 'B']])
write_file(('%s/new_compiler.vim'):format(after_compiler_folder), [[let g:seq ..= 'a']])
write_file(
table.concat({ compiler_folder, 'new_compiler.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'B']]
)
write_file(
table.concat({ after_compiler_folder, 'new_compiler.vim' }, sep),
[[let g:seq ..= 'a']]
)
write_file(
table.concat({ after_compiler_folder, 'new_compiler.lua' }, sep),
('%s/new_compiler.lua'):format(after_compiler_folder),
[[vim.g.seq = vim.g.seq .. 'b']]
)
exec('compiler new_compiler')
@@ -168,11 +161,11 @@ describe('runtime:', function()
end)
describe('ftplugin', function()
local ftplugin_folder = table.concat({ plug_dir, 'ftplugin' }, sep)
local ftplugin_folder = ('%s/ftplugin'):format(plug_dir)
it('Lua ftplugins work and are included in cmdline completion', function()
mkdir_p(ftplugin_folder)
local ftplugin_file = table.concat({ ftplugin_folder, 'new-ft.lua' }, sep)
local ftplugin_file = ('%s/new-ft.lua'):format(ftplugin_folder)
write_file(ftplugin_file, [[vim.b.lua_ftplugin = 1]])
eq({ 'new-ft' }, fn.getcompletion('new-f', 'filetype'))
@@ -183,47 +176,29 @@ describe('runtime:', function()
end)
it("'rtp' order is respected", function()
local after_ftplugin_folder = table.concat({ plug_dir, 'after', 'ftplugin' }, sep)
mkdir_p(table.concat({ ftplugin_folder, 'new-ft' }, sep))
mkdir_p(table.concat({ after_ftplugin_folder, 'new-ft' }, sep))
local after_ftplugin_folder = ('%s/after/ftplugin'):format(plug_dir)
mkdir_p(('%s/new-ft'):format(ftplugin_folder))
mkdir_p(('%s/new-ft'):format(after_ftplugin_folder))
exec('set rtp+=' .. plug_dir .. '/after')
exec('let g:seq = ""')
-- A .lua file is loaded after a .vim file if they only differ in extension.
-- All files in after/ftplugin/ are loaded after all files in ftplugin/.
write_file(table.concat({ ftplugin_folder, 'new-ft.vim' }, sep), [[let g:seq ..= 'A']])
write_file(('%s/new-ft.vim'):format(ftplugin_folder), [[let g:seq ..= 'A']])
write_file(('%s/new-ft.lua'):format(ftplugin_folder), [[vim.g.seq = vim.g.seq .. 'B']])
write_file(('%s/new-ft_a.vim'):format(ftplugin_folder), [[let g:seq ..= 'C']])
write_file(('%s/new-ft_a.lua'):format(ftplugin_folder), [[vim.g.seq = vim.g.seq .. 'D']])
write_file(('%s/new-ft/a.vim'):format(ftplugin_folder), [[let g:seq ..= 'E']])
write_file(('%s/new-ft/a.lua'):format(ftplugin_folder), [[vim.g.seq = vim.g.seq .. 'F']])
write_file(('%s/new-ft.vim'):format(after_ftplugin_folder), [[let g:seq ..= 'a']])
write_file(('%s/new-ft.lua'):format(after_ftplugin_folder), [[vim.g.seq = vim.g.seq .. 'b']])
write_file(('%s/new-ft_a.vim'):format(after_ftplugin_folder), [[let g:seq ..= 'c']])
write_file(
table.concat({ ftplugin_folder, 'new-ft.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'B']]
)
write_file(table.concat({ ftplugin_folder, 'new-ft_a.vim' }, sep), [[let g:seq ..= 'C']])
write_file(
table.concat({ ftplugin_folder, 'new-ft_a.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'D']]
)
write_file(table.concat({ ftplugin_folder, 'new-ft', 'a.vim' }, sep), [[let g:seq ..= 'E']])
write_file(
table.concat({ ftplugin_folder, 'new-ft', 'a.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'F']]
)
write_file(table.concat({ after_ftplugin_folder, 'new-ft.vim' }, sep), [[let g:seq ..= 'a']])
write_file(
table.concat({ after_ftplugin_folder, 'new-ft.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'b']]
)
write_file(
table.concat({ after_ftplugin_folder, 'new-ft_a.vim' }, sep),
[[let g:seq ..= 'c']]
)
write_file(
table.concat({ after_ftplugin_folder, 'new-ft_a.lua' }, sep),
('%s/new-ft_a.lua'):format(after_ftplugin_folder),
[[vim.g.seq = vim.g.seq .. 'd']]
)
write_file(('%s/new-ft/a.vim'):format(after_ftplugin_folder), [[let g:seq ..= 'e']])
write_file(
table.concat({ after_ftplugin_folder, 'new-ft', 'a.vim' }, sep),
[[let g:seq ..= 'e']]
)
write_file(
table.concat({ after_ftplugin_folder, 'new-ft', 'a.lua' }, sep),
('%s/new-ft/a.lua'):format(after_ftplugin_folder),
[[vim.g.seq = vim.g.seq .. 'f']]
)
exec('setfiletype new-ft')
@@ -232,47 +207,29 @@ describe('runtime:', function()
it("'rtp' order is respected with 'fileignorecase'", function()
exec('set fileignorecase')
local after_ftplugin_folder = table.concat({ plug_dir, 'after', 'ftplugin' }, sep)
mkdir_p(table.concat({ ftplugin_folder, 'new-ft' }, sep))
mkdir_p(table.concat({ after_ftplugin_folder, 'new-ft' }, sep))
local after_ftplugin_folder = ('%s/after/ftplugin'):format(plug_dir)
mkdir_p(('%s/new-ft'):format(ftplugin_folder))
mkdir_p(('%s/new-ft'):format(after_ftplugin_folder))
exec('set rtp+=' .. plug_dir .. '/after')
exec('let g:seq = ""')
-- A .lua file is loaded after a .vim file if they only differ in extension.
-- All files in after/ftplugin/ are loaded after all files in ftplugin/.
write_file(table.concat({ ftplugin_folder, 'new-ft.VIM' }, sep), [[let g:seq ..= 'A']])
write_file(('%s/new-ft.VIM'):format(ftplugin_folder), [[let g:seq ..= 'A']])
write_file(('%s/new-ft.LUA'):format(ftplugin_folder), [[vim.g.seq = vim.g.seq .. 'B']])
write_file(('%s/new-ft_a.vim'):format(ftplugin_folder), [[let g:seq ..= 'C']])
write_file(('%s/new-ft_a.lua'):format(ftplugin_folder), [[vim.g.seq = vim.g.seq .. 'D']])
write_file(('%s/new-ft/a.VIM'):format(ftplugin_folder), [[let g:seq ..= 'E']])
write_file(('%s/new-ft/a.LUA'):format(ftplugin_folder), [[vim.g.seq = vim.g.seq .. 'F']])
write_file(('%s/new-ft.vim'):format(after_ftplugin_folder), [[let g:seq ..= 'a']])
write_file(('%s/new-ft.lua'):format(after_ftplugin_folder), [[vim.g.seq = vim.g.seq .. 'b']])
write_file(('%s/new-ft_a.VIM'):format(after_ftplugin_folder), [[let g:seq ..= 'c']])
write_file(
table.concat({ ftplugin_folder, 'new-ft.LUA' }, sep),
[[vim.g.seq = vim.g.seq .. 'B']]
)
write_file(table.concat({ ftplugin_folder, 'new-ft_a.vim' }, sep), [[let g:seq ..= 'C']])
write_file(
table.concat({ ftplugin_folder, 'new-ft_a.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'D']]
)
write_file(table.concat({ ftplugin_folder, 'new-ft', 'a.VIM' }, sep), [[let g:seq ..= 'E']])
write_file(
table.concat({ ftplugin_folder, 'new-ft', 'a.LUA' }, sep),
[[vim.g.seq = vim.g.seq .. 'F']]
)
write_file(table.concat({ after_ftplugin_folder, 'new-ft.vim' }, sep), [[let g:seq ..= 'a']])
write_file(
table.concat({ after_ftplugin_folder, 'new-ft.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'b']]
)
write_file(
table.concat({ after_ftplugin_folder, 'new-ft_a.VIM' }, sep),
[[let g:seq ..= 'c']]
)
write_file(
table.concat({ after_ftplugin_folder, 'new-ft_a.LUA' }, sep),
('%s/new-ft_a.LUA'):format(after_ftplugin_folder),
[[vim.g.seq = vim.g.seq .. 'd']]
)
write_file(('%s/new-ft/a.vim'):format(after_ftplugin_folder), [[let g:seq ..= 'e']])
write_file(
table.concat({ after_ftplugin_folder, 'new-ft', 'a.vim' }, sep),
[[let g:seq ..= 'e']]
)
write_file(
table.concat({ after_ftplugin_folder, 'new-ft', 'a.lua' }, sep),
('%s/new-ft/a.lua'):format(after_ftplugin_folder),
[[vim.g.seq = vim.g.seq .. 'f']]
)
exec('setfiletype new-ft')
@@ -281,11 +238,11 @@ describe('runtime:', function()
end)
describe('indent', function()
local indent_folder = table.concat({ plug_dir, 'indent' }, sep)
local indent_folder = ('%s/indent'):format(plug_dir)
it('Lua indents work and are included in cmdline completion', function()
mkdir_p(indent_folder)
local indent_file = table.concat({ indent_folder, 'new-ft.lua' }, sep)
local indent_file = ('%s/new-ft.lua'):format(indent_folder)
write_file(indent_file, [[vim.b.lua_indent = 1]])
eq({ 'new-ft' }, fn.getcompletion('new-f', 'filetype'))
@@ -296,34 +253,28 @@ describe('runtime:', function()
end)
it("'rtp' order is respected", function()
local after_indent_folder = table.concat({ plug_dir, 'after', 'indent' }, sep)
mkdir_p(table.concat({ indent_folder, 'new-ft' }, sep))
mkdir_p(table.concat({ after_indent_folder, 'new-ft' }, sep))
local after_indent_folder = ('%s/after/indent'):format(plug_dir)
mkdir_p(('%s/new-ft'):format(indent_folder))
mkdir_p(('%s/new-ft'):format(after_indent_folder))
exec('set rtp+=' .. plug_dir .. '/after')
exec('let g:seq = ""')
-- A .lua file is loaded after a .vim file if they only differ in extension.
-- All files in after/indent/ are loaded after all files in indent/.
write_file(table.concat({ indent_folder, 'new-ft.vim' }, sep), [[let g:seq ..= 'A']])
write_file(
table.concat({ indent_folder, 'new-ft.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'B']]
)
write_file(table.concat({ after_indent_folder, 'new-ft.vim' }, sep), [[let g:seq ..= 'a']])
write_file(
table.concat({ after_indent_folder, 'new-ft.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'b']]
)
write_file(('%s/new-ft.vim'):format(indent_folder), [[let g:seq ..= 'A']])
write_file(('%s/new-ft.lua'):format(indent_folder), [[vim.g.seq = vim.g.seq .. 'B']])
write_file(('%s/new-ft.vim'):format(after_indent_folder), [[let g:seq ..= 'a']])
write_file(('%s/new-ft.lua'):format(after_indent_folder), [[vim.g.seq = vim.g.seq .. 'b']])
exec('setfiletype new-ft')
eq('ABab', eval('g:seq'))
end)
end)
describe('syntax', function()
local syntax_folder = table.concat({ plug_dir, 'syntax' }, sep)
local syntax_folder = ('%s/syntax'):format(plug_dir)
before_each(function()
mkdir_p(syntax_folder)
local syntax_file = table.concat({ syntax_folder, 'my-lang.lua' }, sep)
local syntax_file = ('%s/my-lang.lua'):format(syntax_folder)
write_file(syntax_file, [[vim.b.current_syntax = 'my-lang']])
exec([[let b:current_syntax = '']])
end)
@@ -351,36 +302,21 @@ describe('runtime:', function()
end)
it("'rtp' order is respected", function()
local after_syntax_folder = table.concat({ plug_dir, 'after', 'syntax' }, sep)
mkdir_p(table.concat({ syntax_folder, 'my-lang' }, sep))
mkdir_p(table.concat({ after_syntax_folder, 'my-lang' }, sep))
local after_syntax_folder = ('%s/after/syntax'):format(plug_dir)
mkdir_p(('%s/my-lang'):format(syntax_folder))
mkdir_p(('%s/my-lang'):format(after_syntax_folder))
exec('set rtp+=' .. plug_dir .. '/after')
exec('let g:seq = ""')
-- A .lua file is loaded after a .vim file if they only differ in extension.
-- All files in after/syntax/ are loaded after all files in syntax/.
write_file(table.concat({ syntax_folder, 'my-lang.vim' }, sep), [[let g:seq ..= 'A']])
write_file(
table.concat({ syntax_folder, 'my-lang.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'B']]
)
write_file(table.concat({ syntax_folder, 'my-lang', 'a.vim' }, sep), [[let g:seq ..= 'C']])
write_file(
table.concat({ syntax_folder, 'my-lang', 'a.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'D']]
)
write_file(table.concat({ after_syntax_folder, 'my-lang.vim' }, sep), [[let g:seq ..= 'a']])
write_file(
table.concat({ after_syntax_folder, 'my-lang.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'b']]
)
write_file(
table.concat({ after_syntax_folder, 'my-lang', 'a.vim' }, sep),
[[let g:seq ..= 'c']]
)
write_file(
table.concat({ after_syntax_folder, 'my-lang', 'a.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'd']]
)
write_file(('%s/my-lang.vim'):format(syntax_folder), [[let g:seq ..= 'A']])
write_file(('%s/my-lang.lua'):format(syntax_folder), [[vim.g.seq = vim.g.seq .. 'B']])
write_file(('%s/my-lang/a.vim'):format(syntax_folder), [[let g:seq ..= 'C']])
write_file(('%s/my-lang/a.lua'):format(syntax_folder), [[vim.g.seq = vim.g.seq .. 'D']])
write_file(('%s/my-lang.vim'):format(after_syntax_folder), [[let g:seq ..= 'a']])
write_file(('%s/my-lang.lua'):format(after_syntax_folder), [[vim.g.seq = vim.g.seq .. 'b']])
write_file(('%s/my-lang/a.vim'):format(after_syntax_folder), [[let g:seq ..= 'c']])
write_file(('%s/my-lang/a.lua'):format(after_syntax_folder), [[vim.g.seq = vim.g.seq .. 'd']])
exec('setfiletype my-lang')
eq('ABCDabcd', eval('g:seq'))
end)
@@ -388,21 +324,18 @@ describe('runtime:', function()
describe('spell', function()
it("loads spell/LANG.{vim,lua} respecting 'rtp' order", function()
local spell_folder = table.concat({ plug_dir, 'spell' }, sep)
local after_spell_folder = table.concat({ plug_dir, 'after', 'spell' }, sep)
mkdir_p(table.concat({ spell_folder, 'Xtest' }, sep))
mkdir_p(table.concat({ after_spell_folder, 'Xtest' }, sep))
local spell_folder = ('%s/spell'):format(plug_dir)
local after_spell_folder = ('%s/after/spell'):format(plug_dir)
mkdir_p(('%s/Xtest'):format(spell_folder))
mkdir_p(('%s/Xtest'):format(after_spell_folder))
exec('set rtp+=' .. plug_dir .. '/after')
exec('let g:seq = ""')
-- A .lua file is loaded after a .vim file if they only differ in extension.
-- All files in after/spell/ are loaded after all files in spell/.
write_file(table.concat({ spell_folder, 'Xtest.vim' }, sep), [[let g:seq ..= 'A']])
write_file(table.concat({ spell_folder, 'Xtest.lua' }, sep), [[vim.g.seq = vim.g.seq .. 'B']])
write_file(table.concat({ after_spell_folder, 'Xtest.vim' }, sep), [[let g:seq ..= 'a']])
write_file(
table.concat({ after_spell_folder, 'Xtest.lua' }, sep),
[[vim.g.seq = vim.g.seq .. 'b']]
)
write_file(('%s/Xtest.vim'):format(spell_folder), [[let g:seq ..= 'A']])
write_file(('%s/Xtest.lua'):format(spell_folder), [[vim.g.seq = vim.g.seq .. 'B']])
write_file(('%s/Xtest.vim'):format(after_spell_folder), [[let g:seq ..= 'a']])
write_file(('%s/Xtest.lua'):format(after_spell_folder), [[vim.g.seq = vim.g.seq .. 'b']])
exec('set spelllang=Xtest')
eq('ABab', eval('g:seq'))
end)
@@ -411,7 +344,7 @@ describe('runtime:', function()
it('Lua file loaded by :runtime has proper script ID #32598', function()
local test_file = 'Xtest_runtime_cmd.lua'
write_file(
table.concat({ plug_dir, test_file }, sep),
('%s/%s'):format(plug_dir, test_file),
[[
vim.g.script_id = tonumber(vim.fn.expand('<SID>'):match('<SNR>(%d+)_'))
vim.o.mouse = 'nv'
+4 -5
View File
@@ -145,7 +145,7 @@ describe(':mksession', function()
it('restores buffers with tab-local CWD', function()
local tmpfile_base = file_prefix .. '-tmpfile'
local cwd_dir = t.fix_slashes(fn.getcwd())
local cwd_dir = vim.fs.normalize(fn.getcwd())
local session_path = cwd_dir .. get_pathsep() .. session_file
command('edit ' .. tmpfile_base .. '1')
@@ -161,9 +161,9 @@ describe(':mksession', function()
-- Use :silent to avoid hit-enter prompt due to long path
command('silent source ' .. session_path)
command('tabnext 1')
eq(cwd_dir .. '/' .. tmpfile_base .. '1', fn.expand('%:p'))
eq(('%s/%s1'):format(cwd_dir, tmpfile_base), vim.fs.normalize(fn.expand('%:p')))
command('tabnext 2')
eq(cwd_dir .. '/' .. tmpfile_base .. '2', fn.expand('%:p'))
eq(('%s/%s2'):format(cwd_dir, tmpfile_base), vim.fs.normalize(fn.expand('%:p')))
end)
it('restores symlinked directory buffer names', function()
@@ -187,8 +187,7 @@ describe(':mksession', function()
end)
it('restores CWD for :terminal buffers #11288', function()
local cwd_dir = fn.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '')
cwd_dir = t.fix_slashes(cwd_dir) -- :mksession always uses unix slashes.
local cwd_dir = fn.fnamemodify('.', ':p:~'):gsub([[/*$]], '')
local session_path = cwd_dir .. '/' .. session_file
command('cd ' .. tab_dir)
+5 -5
View File
@@ -47,7 +47,7 @@ describe(':source', function()
os.remove(test_file)
end)
it("changing 'shellslash' doesn't affect the result of expand()", function()
it("changing 'shellslash' changes the result of expand()", function()
t.skip(not is_os('win'), "N/A: 'shellslash' only works on Windows")
api.nvim_set_option_value('shellslash', false, {})
@@ -66,9 +66,9 @@ describe(':source', function()
for _ = 1, 2 do
command([[source Xshellslash/Xstack.vim]])
matches([[Xshellslash/Xstack%.vim]], api.nvim_get_var('stack1'))
matches([[Xshellslash\Xstack%.vim]], api.nvim_get_var('stack1'))
matches([[Xshellslash/Xstack%.vim]], api.nvim_get_var('stack2'))
matches([[Xshellslash/Xstack%.vim]], api.nvim_get_var('stack3'))
matches([[Xshellslash\Xstack%.vim]], api.nvim_get_var('stack3'))
end
write_file(
@@ -84,9 +84,9 @@ describe(':source', function()
for _ = 1, 2 do
command([[source Xshellslash/Xstack.lua]])
matches([[Xshellslash/Xstack%.lua]], api.nvim_get_var('stack1'))
matches([[Xshellslash\Xstack%.lua]], api.nvim_get_var('stack1'))
matches([[Xshellslash/Xstack%.lua]], api.nvim_get_var('stack2'))
matches([[Xshellslash/Xstack%.lua]], api.nvim_get_var('stack3'))
matches([[Xshellslash\Xstack%.lua]], api.nvim_get_var('stack3'))
end
rmdir('Xshellslash')
+2 -2
View File
@@ -17,7 +17,7 @@ local function last_set_lua_verbose_tests(cmd, v1)
setup(function()
clear(v1 and { args = { '-V1' } } or nil)
script_file = 'test_verbose.lua'
local current_dir = assert(t.fix_slashes(fn.getcwd()))
local current_dir = fn.getcwd()
current_dir = fn.fnamemodify(current_dir, ':~')
script_location = current_dir .. '/' .. script_file
@@ -326,7 +326,7 @@ describe(':verbose when using API from Vimscript', function()
setup(function()
clear()
script_file = 'test_verbose.vim'
local current_dir = assert(t.fix_slashes(fn.getcwd()))
local current_dir = fn.getcwd()
current_dir = fn.fnamemodify(current_dir, ':~')
script_location = current_dir .. '/' .. script_file
+1 -1
View File
@@ -217,7 +217,7 @@ describe('URI methods', function()
]],
file
)
local expected_uri = 'file:///' .. t.fix_slashes(file)
local expected_uri = ('file:///%s'):format(file)
eq(expected_uri, exec_lua(test_case))
os.remove(file)
end)
+112 -281
View File
@@ -265,7 +265,7 @@ describe('startup defaults', function()
NVIM_LOG_FILE = '', -- Empty is invalid.
},
})
eq(xdgstatedir .. '/logs/nvim.log', t.fix_slashes(eval('$NVIM_LOG_FILE')))
eq(('%s/logs/nvim.log'):format(xdgstatedir), eval('$NVIM_LOG_FILE'))
end)
it('defaults to stdpath("log")/nvim.log if invalid', function()
@@ -276,7 +276,7 @@ describe('startup defaults', function()
NVIM_LOG_FILE = '.', -- Any directory is invalid.
},
})
eq(xdgstatedir .. '/logs/nvim.log', t.fix_slashes(eval('$NVIM_LOG_FILE')))
eq(('%s/logs/nvim.log'):format(xdgstatedir), eval('$NVIM_LOG_FILE'))
-- Avoid "failed to open $NVIM_LOG_FILE" noise in test output.
expect_exit(command, 'qall!')
end)
@@ -382,158 +382,48 @@ describe('XDG defaults', function()
local vimruntime, libdir = vimruntime_and_libdir()
eq(
(
t.fix_slashes(
root_path
.. ('/x'):rep(4096)
.. '/nvim'
.. ','
.. root_path
.. ('/a'):rep(2048)
.. '/nvim'
.. ','
.. root_path
.. ('/b'):rep(2048)
.. '/nvim'
.. (',' .. root_path .. '/c/nvim')
.. ','
.. root_path
.. ('/X'):rep(4096)
.. '/'
.. data_dir
.. '/site'
.. ','
.. root_path
.. ('/A'):rep(2048)
.. '/nvim/site'
.. ','
.. root_path
.. ('/B'):rep(2048)
.. '/nvim/site'
.. (',' .. root_path .. '/C/nvim/site')
.. ','
.. vimruntime
.. ','
.. libdir
.. (',' .. root_path .. '/C/nvim/site/after')
.. ','
.. root_path
.. ('/B'):rep(2048)
.. '/nvim/site/after'
.. ','
.. root_path
.. ('/A'):rep(2048)
.. '/nvim/site/after'
.. ','
.. root_path
.. ('/X'):rep(4096)
.. '/'
.. data_dir
.. '/site/after'
.. (',' .. root_path .. '/c/nvim/after')
.. ','
.. root_path
.. ('/b'):rep(2048)
.. '/nvim/after'
.. ','
.. root_path
.. ('/a'):rep(2048)
.. '/nvim/after'
.. ','
.. root_path
.. ('/x'):rep(4096)
.. '/nvim/after'
)
),
t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
)
local expected_paths = table.concat({
('%s%s/nvim'):format(root_path, ('/x'):rep(4096)),
('%s%s/nvim'):format(root_path, ('/a'):rep(2048)),
('%s%s/nvim'):format(root_path, ('/b'):rep(2048)),
('%s/c/nvim'):format(root_path),
('%s%s/%s/site'):format(root_path, ('/X'):rep(4096), data_dir),
('%s%s/nvim/site'):format(root_path, ('/A'):rep(2048)),
('%s%s/nvim/site'):format(root_path, ('/B'):rep(2048)),
('%s/C/nvim/site'):format(root_path),
vimruntime,
libdir,
('%s/C/nvim/site/after'):format(root_path),
('%s%s/nvim/site/after'):format(root_path, ('/B'):rep(2048)),
('%s%s/nvim/site/after'):format(root_path, ('/A'):rep(2048)),
('%s%s/%s/site/after'):format(root_path, ('/X'):rep(4096), data_dir),
('%s/c/nvim/after'):format(root_path),
('%s%s/nvim/after'):format(root_path, ('/b'):rep(2048)),
('%s%s/nvim/after'):format(root_path, ('/a'):rep(2048)),
('%s%s/nvim/after'):format(root_path, ('/x'):rep(4096)),
}, ',')
eq(expected_paths, api.nvim_get_option_value('runtimepath', {}))
command('set runtimepath&')
command('set backupdir&')
command('set directory&')
command('set undodir&')
command('set viewdir&')
eq(expected_paths, api.nvim_get_option_value('runtimepath', {}))
eq(
(
t.fix_slashes(
root_path
.. ('/x'):rep(4096)
.. '/nvim'
.. ','
.. root_path
.. ('/a'):rep(2048)
.. '/nvim'
.. ','
.. root_path
.. ('/b'):rep(2048)
.. '/nvim'
.. (',' .. root_path .. '/c/nvim')
.. ','
.. root_path
.. ('/X'):rep(4096)
.. '/'
.. data_dir
.. '/site'
.. ','
.. root_path
.. ('/A'):rep(2048)
.. '/nvim/site'
.. ','
.. root_path
.. ('/B'):rep(2048)
.. '/nvim/site'
.. (',' .. root_path .. '/C/nvim/site')
.. ','
.. vimruntime
.. ','
.. libdir
.. (',' .. root_path .. '/C/nvim/site/after')
.. ','
.. root_path
.. ('/B'):rep(2048)
.. '/nvim/site/after'
.. ','
.. root_path
.. ('/A'):rep(2048)
.. '/nvim/site/after'
.. ','
.. root_path
.. ('/X'):rep(4096)
.. '/'
.. data_dir
.. '/site/after'
.. (',' .. root_path .. '/c/nvim/after')
.. ','
.. root_path
.. ('/b'):rep(2048)
.. '/nvim/after'
.. ','
.. root_path
.. ('/a'):rep(2048)
.. '/nvim/after'
.. ','
.. root_path
.. ('/x'):rep(4096)
.. '/nvim/after'
)
),
t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
('.,%s%s/%s/backup//'):format(root_path, ('/X'):rep(4096), state_dir),
api.nvim_get_option_value('backupdir', {})
)
eq(
'.,' .. root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/backup//',
t.fix_slashes(api.nvim_get_option_value('backupdir', {}))
('%s%s/%s/swap//'):format(root_path, ('/X'):rep(4096), state_dir),
api.nvim_get_option_value('directory', {})
)
eq(
root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/swap//',
t.fix_slashes(api.nvim_get_option_value('directory', {}))
('%s%s/%s/undo//'):format(root_path, ('/X'):rep(4096), state_dir),
api.nvim_get_option_value('undodir', {})
)
eq(
root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/undo//',
t.fix_slashes(api.nvim_get_option_value('undodir', {}))
)
eq(
root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/view//',
t.fix_slashes(api.nvim_get_option_value('viewdir', {}))
('%s%s/%s/view//'):format(root_path, ('/X'):rep(4096), state_dir),
api.nvim_get_option_value('viewdir', {})
)
end)
end)
@@ -573,111 +463,47 @@ describe('XDG defaults', function()
end
local vimruntime, libdir = vimruntime_and_libdir()
eq(
(
t.fix_slashes(
'$XDG_DATA_HOME/nvim'
.. ',$XDG_DATA_DIRS/nvim'
.. ',$XDG_CONFIG_HOME/'
.. data_dir
.. '/site'
.. ',$XDG_CONFIG_DIRS/nvim/site'
.. ','
.. vimruntime
.. ','
.. libdir
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
.. ',$XDG_CONFIG_HOME/'
.. data_dir
.. '/site/after'
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
)
),
t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
)
local expected_paths = table.concat({
'$XDG_DATA_HOME/nvim',
'$XDG_DATA_DIRS/nvim',
('$XDG_CONFIG_HOME/%s/site'):format(data_dir),
'$XDG_CONFIG_DIRS/nvim/site',
vimruntime,
libdir,
'$XDG_CONFIG_DIRS/nvim/site/after',
('$XDG_CONFIG_HOME/%s/site/after'):format(data_dir),
'$XDG_DATA_DIRS/nvim/after',
'$XDG_DATA_HOME/nvim/after',
}, ',')
eq(expected_paths, api.nvim_get_option_value('runtimepath', {}))
command('set runtimepath&')
command('set backupdir&')
command('set directory&')
command('set undodir&')
command('set viewdir&')
eq(expected_paths, api.nvim_get_option_value('runtimepath', {}))
eq(
(
t.fix_slashes(
'$XDG_DATA_HOME/nvim'
.. ',$XDG_DATA_DIRS/nvim'
.. ',$XDG_CONFIG_HOME/'
.. data_dir
.. '/site'
.. ',$XDG_CONFIG_DIRS/nvim/site'
.. ','
.. vimruntime
.. ','
.. libdir
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
.. ',$XDG_CONFIG_HOME/'
.. data_dir
.. '/site/after'
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
)
),
t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
('.,$XDG_CONFIG_HOME/%s/backup//'):format(state_dir),
api.nvim_get_option_value('backupdir', {})
)
eq(
('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
t.fix_slashes(api.nvim_get_option_value('backupdir', {}))
)
eq(
('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
t.fix_slashes(api.nvim_get_option_value('directory', {}))
)
eq(
('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
t.fix_slashes(api.nvim_get_option_value('undodir', {}))
)
eq(
('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
t.fix_slashes(api.nvim_get_option_value('viewdir', {}))
('$XDG_CONFIG_HOME/%s/swap//'):format(state_dir),
api.nvim_get_option_value('directory', {})
)
eq(('$XDG_CONFIG_HOME/%s/undo//'):format(state_dir), api.nvim_get_option_value('undodir', {}))
eq(('$XDG_CONFIG_HOME/%s/view//'):format(state_dir), api.nvim_get_option_value('viewdir', {}))
command('set all&')
eq(expected_paths, api.nvim_get_option_value('runtimepath', {}))
eq(
t.fix_slashes(
'$XDG_DATA_HOME/nvim'
.. ',$XDG_DATA_DIRS/nvim'
.. ',$XDG_CONFIG_HOME/'
.. data_dir
.. '/site'
.. ',$XDG_CONFIG_DIRS/nvim/site'
.. ','
.. vimruntime
.. ','
.. libdir
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
.. ',$XDG_CONFIG_HOME/'
.. data_dir
.. '/site/after'
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
),
t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
('.,$XDG_CONFIG_HOME/%s/backup//'):format(state_dir),
api.nvim_get_option_value('backupdir', {})
)
eq(
('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
t.fix_slashes(api.nvim_get_option_value('backupdir', {}))
)
eq(
('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
t.fix_slashes(api.nvim_get_option_value('directory', {}))
)
eq(
('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
t.fix_slashes(api.nvim_get_option_value('undodir', {}))
)
eq(
('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
t.fix_slashes(api.nvim_get_option_value('viewdir', {}))
('$XDG_CONFIG_HOME/%s/swap//'):format(state_dir),
api.nvim_get_option_value('directory', {})
)
eq(('$XDG_CONFIG_HOME/%s/undo//'):format(state_dir), api.nvim_get_option_value('undodir', {}))
eq(('$XDG_CONFIG_HOME/%s/view//'):format(state_dir), api.nvim_get_option_value('viewdir', {}))
eq(nil, (fn.tempname()):match('XDG_RUNTIME_DIR'))
end)
end)
@@ -953,6 +779,11 @@ describe('stdpath()', function()
test_appname('..', 1)
test_appname('.', 1)
test_appname('/', 1)
test_appname('\\', 1)
if is_os('win') then
test_appname('..\\a', 1)
test_appname('a\\..', 1)
end
test_appname(is_os('win') and 'C:/a/b' or '/a/b', 1)
-- Valid appnames:
test_appname('a/b', 0)
@@ -980,10 +811,10 @@ describe('stdpath()', function()
},
})
t.matches(vim.pesc(tmpdir), t.fix_slashes(fn.tempname()))
t.matches(vim.pesc(tmpdir), fn.tempname())
t.assert_nolog('tempdir', testlog, 100)
t.assert_nolog('TMPDIR', testlog, 100)
t.matches([=[[/\\]relative%-appname.[^/\\]+]=], api.nvim_get_vvar('servername'))
t.matches([[/relative%-appname.%d+]], api.nvim_get_vvar('servername'))
end)
describe('returns a String', function()
@@ -994,16 +825,16 @@ describe('stdpath()', function()
XDG_CONFIG_HOME = '/home/docwhat/.config',
},
})
eq('/home/docwhat/.config/nvim', t.fix_slashes(fn.stdpath('config')))
eq('/home/docwhat/.config/nvim', fn.stdpath('config'))
end)
it('handles changes during runtime', function()
clear({ env = {
XDG_CONFIG_HOME = '/home/original',
} })
eq('/home/original/nvim', t.fix_slashes(fn.stdpath('config')))
eq('/home/original/nvim', fn.stdpath('config'))
command("let $XDG_CONFIG_HOME='/home/new'")
eq('/home/new/nvim', t.fix_slashes(fn.stdpath('config')))
eq('/home/new/nvim', fn.stdpath('config'))
end)
it("doesn't expand $VARIABLES", function()
@@ -1013,14 +844,14 @@ describe('stdpath()', function()
VARIABLES = 'this-should-not-happen',
},
})
eq('$VARIABLES/nvim', t.fix_slashes(fn.stdpath('config')))
eq('$VARIABLES/nvim', fn.stdpath('config'))
end)
it("doesn't expand ~/", function()
clear({ env = {
XDG_CONFIG_HOME = '~/frobnitz',
} })
eq('~/frobnitz/nvim', t.fix_slashes(fn.stdpath('config')))
eq('~/frobnitz/nvim', fn.stdpath('config'))
end)
end)
@@ -1029,16 +860,16 @@ describe('stdpath()', function()
clear({ env = {
XDG_DATA_HOME = '/home/docwhat/.local',
} })
eq('/home/docwhat/.local/' .. datadir, t.fix_slashes(fn.stdpath('data')))
eq(('/home/docwhat/.local/%s'):format(datadir), fn.stdpath('data'))
end)
it('handles changes during runtime', function()
clear({ env = {
XDG_DATA_HOME = '/home/original',
} })
eq('/home/original/' .. datadir, t.fix_slashes(fn.stdpath('data')))
eq(('/home/original/%s'):format(datadir), fn.stdpath('data'))
command("let $XDG_DATA_HOME='/home/new'")
eq('/home/new/' .. datadir, t.fix_slashes(fn.stdpath('data')))
eq(('/home/new/%s'):format(datadir), fn.stdpath('data'))
end)
it("doesn't expand $VARIABLES", function()
@@ -1048,14 +879,14 @@ describe('stdpath()', function()
VARIABLES = 'this-should-not-happen',
},
})
eq('$VARIABLES/' .. datadir, t.fix_slashes(fn.stdpath('data')))
eq(('$VARIABLES/%s'):format(datadir), fn.stdpath('data'))
end)
it("doesn't expand ~/", function()
clear({ env = {
XDG_DATA_HOME = '~/frobnitz',
} })
eq('~/frobnitz/' .. datadir, t.fix_slashes(fn.stdpath('data')))
eq(('~/frobnitz/%s'):format(datadir), fn.stdpath('data'))
end)
end)
@@ -1066,16 +897,16 @@ describe('stdpath()', function()
XDG_STATE_HOME = '/home/docwhat/.local',
},
})
eq('/home/docwhat/.local/' .. statedir, t.fix_slashes(fn.stdpath('state')))
eq(('/home/docwhat/.local/%s'):format(statedir), fn.stdpath('state'))
end)
it('handles changes during runtime', function()
clear({ env = {
XDG_STATE_HOME = '/home/original',
} })
eq('/home/original/' .. statedir, t.fix_slashes(fn.stdpath('state')))
eq(('/home/original/%s'):format(statedir), fn.stdpath('state'))
command("let $XDG_STATE_HOME='" .. '/home/new' .. "'")
eq('/home/new/' .. statedir, t.fix_slashes(fn.stdpath('state')))
eq(('/home/new/%s'):format(statedir), fn.stdpath('state'))
end)
it("doesn't expand $VARIABLES", function()
@@ -1085,14 +916,14 @@ describe('stdpath()', function()
VARIABLES = 'this-should-not-happen',
},
})
eq('$VARIABLES/' .. statedir, t.fix_slashes(fn.stdpath('state')))
eq(('$VARIABLES/%s'):format(statedir), fn.stdpath('state'))
end)
it("doesn't expand ~/", function()
clear({ env = {
XDG_STATE_HOME = '~/frobnitz',
} })
eq('~/frobnitz/' .. statedir, t.fix_slashes(fn.stdpath('state')))
eq(('~/frobnitz/%s'):format(statedir), fn.stdpath('state'))
end)
end)
@@ -1103,16 +934,16 @@ describe('stdpath()', function()
XDG_CACHE_HOME = '/home/docwhat/.cache',
},
})
eq('/home/docwhat/.cache/nvim', t.fix_slashes(fn.stdpath('cache')))
eq('/home/docwhat/.cache/nvim', fn.stdpath('cache'))
end)
it('handles changes during runtime', function()
clear({ env = {
XDG_CACHE_HOME = '/home/original',
} })
eq('/home/original/nvim', t.fix_slashes(fn.stdpath('cache')))
eq('/home/original/nvim', fn.stdpath('cache'))
command("let $XDG_CACHE_HOME='" .. '/home/new' .. "'")
eq('/home/new/nvim', t.fix_slashes(fn.stdpath('cache')))
eq('/home/new/nvim', fn.stdpath('cache'))
end)
it("doesn't expand $VARIABLES", function()
@@ -1122,14 +953,14 @@ describe('stdpath()', function()
VARIABLES = 'this-should-not-happen',
},
})
eq('$VARIABLES/nvim', t.fix_slashes(fn.stdpath('cache')))
eq('$VARIABLES/nvim', fn.stdpath('cache'))
end)
it("doesn't expand ~/", function()
clear({ env = {
XDG_CACHE_HOME = '~/frobnitz',
} })
eq('~/frobnitz/nvim', t.fix_slashes(fn.stdpath('cache')))
eq('~/frobnitz/nvim', fn.stdpath('cache'))
end)
end)
end)
@@ -1178,7 +1009,7 @@ describe('stdpath()', function()
describe(msg, function()
it('set via system', function()
set_paths_via_system(env_var_name, paths)
eq(expected_paths, t.fix_slashes(fn.stdpath(stdpath_arg)))
eq(expected_paths, fn.stdpath(stdpath_arg))
if not is_os('win') then
assert_log(
'$TMPDIR tempdir not a directory[^\n]*TMPDIR%-should%-be%-ignored',
@@ -1190,7 +1021,7 @@ describe('stdpath()', function()
it('set at runtime', function()
set_paths_at_runtime(env_var_name, paths)
eq(expected_paths, t.fix_slashes(fn.stdpath(stdpath_arg)))
eq(expected_paths, fn.stdpath(stdpath_arg))
if not is_os('win') then
assert_log(
'$TMPDIR tempdir not a directory[^\n]*TMPDIR%-should%-be%-ignored',
@@ -1208,10 +1039,10 @@ describe('stdpath()', function()
'config_dirs',
'XDG_CONFIG_DIRS',
{
t.fix_slashes('/home/docwhat/.config'),
'/home/docwhat/.config',
},
{
t.fix_slashes('/home/docwhat/.config/nvim'),
'/home/docwhat/.config/nvim',
}
)
@@ -1220,12 +1051,12 @@ describe('stdpath()', function()
'config_dirs',
'XDG_CONFIG_DIRS',
{
t.fix_slashes('/home/docwhat/.config'),
t.fix_slashes('/etc/config'),
'/home/docwhat/.config',
'/etc/config',
},
{
t.fix_slashes('/home/docwhat/.config/nvim'),
t.fix_slashes('/etc/config/nvim'),
'/home/docwhat/.config/nvim',
'/etc/config/nvim',
}
)
@@ -1235,25 +1066,25 @@ describe('stdpath()', function()
'XDG_CONFIG_DIRS',
{ '$HOME', '$TMP' },
{
t.fix_slashes('$HOME/nvim'),
t.fix_slashes('$TMP/nvim'),
'$HOME/nvim',
'$TMP/nvim',
}
)
behaves_like_dir_list_env("doesn't expand ~/", 'config_dirs', 'XDG_CONFIG_DIRS', {
t.fix_slashes('~/.oldconfig'),
t.fix_slashes('~/.olderconfig'),
'~/.oldconfig',
'~/.olderconfig',
}, {
t.fix_slashes('~/.oldconfig/nvim'),
t.fix_slashes('~/.olderconfig/nvim'),
'~/.oldconfig/nvim',
'~/.olderconfig/nvim',
})
end)
describe('with "data_dirs"', function()
behaves_like_dir_list_env('knows XDG_DATA_DIRS with one path', 'data_dirs', 'XDG_DATA_DIRS', {
t.fix_slashes('/home/docwhat/.data'),
'/home/docwhat/.data',
}, {
t.fix_slashes('/home/docwhat/.data/nvim'),
'/home/docwhat/.data/nvim',
})
behaves_like_dir_list_env(
@@ -1261,12 +1092,12 @@ describe('stdpath()', function()
'data_dirs',
'XDG_DATA_DIRS',
{
t.fix_slashes('/home/docwhat/.data'),
t.fix_slashes('/etc/local'),
'/home/docwhat/.data',
'/etc/local',
},
{
t.fix_slashes('/home/docwhat/.data/nvim'),
t.fix_slashes('/etc/local/nvim'),
'/home/docwhat/.data/nvim',
'/etc/local/nvim',
}
)
@@ -1276,17 +1107,17 @@ describe('stdpath()', function()
'XDG_DATA_DIRS',
{ '$HOME', '$TMP' },
{
t.fix_slashes('$HOME/nvim'),
t.fix_slashes('$TMP/nvim'),
'$HOME/nvim',
'$TMP/nvim',
}
)
behaves_like_dir_list_env("doesn't expand ~/", 'data_dirs', 'XDG_DATA_DIRS', {
t.fix_slashes('~/.oldconfig'),
t.fix_slashes('~/.olderconfig'),
'~/.oldconfig',
'~/.olderconfig',
}, {
t.fix_slashes('~/.oldconfig/nvim'),
t.fix_slashes('~/.olderconfig/nvim'),
'~/.oldconfig/nvim',
'~/.olderconfig/nvim',
})
end)
end)
+2 -2
View File
@@ -850,7 +850,7 @@ describe('vim.pack', function()
eq('basic feat-branch', out)
local rtp = vim.tbl_map(t.fix_slashes, api.nvim_list_runtime_paths())
local rtp = api.nvim_list_runtime_paths()
local plug_path = pack_get_plug_path('basic')
local after_dir = vim.fs.joinpath(plug_path, 'after')
eq(true, vim.tbl_contains(rtp, plug_path))
@@ -989,7 +989,7 @@ describe('vim.pack', function()
eq(ref, out)
-- Should add necessary directories to runtimepath regardless of `opts.load`
local rtp = vim.tbl_map(t.fix_slashes, api.nvim_list_runtime_paths())
local rtp = api.nvim_list_runtime_paths()
local plug_path = pack_get_plug_path('plugin % dirs')
local after_dir = vim.fs.joinpath(plug_path, 'after')
eq(true, vim.tbl_contains(rtp, plug_path))
+1 -1
View File
@@ -25,7 +25,7 @@ describe(':edit term://*', function()
command('edit term://')
local termopen_runs = api.nvim_get_var('termopen_runs')
eq(1, #termopen_runs)
local cwd = fn.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '')
local cwd = fn.fnamemodify('.', ':p:~'):gsub([[/*$]], '')
matches('^term://' .. pesc(cwd) .. '//%d+:$', termopen_runs[1])
end)
+4
View File
@@ -837,6 +837,10 @@ describe('TUI :connect', function()
tt.feed_data('iThis is server 2.\027')
screen2:expect({ any = vim.pesc('This is server 2^.') })
if is_os('win') then
-- still supports backslashes
server1 = server1:gsub('/', '\\')
end
tt.feed_data(':connect ' .. server1 .. '\013')
screen2:expect({ any = vim.pesc('This is server 1^.') })
@@ -322,7 +322,7 @@ describe('context functions', function()
filter(map(add(
getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }),
'filter(
{ "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
{ "f": expand("#".v:val.bufnr.":p:gs?\\?/?"), "l": v:val.lnum },
{ k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
]]):gsub('\n', ''))),
}
+18 -30
View File
@@ -2,7 +2,7 @@ local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local eq, clear, call, write_file, command = t.eq, n.clear, n.call, t.write_file, n.command
local eval = n.eval
local eval, fn = n.eval, n.fn
local is_os = t.is_os
local pcall_err = t.pcall_err
@@ -18,38 +18,26 @@ describe('executable()', function()
eq(1, call('executable', 'false'))
end)
if is_os('win') then
it('exepath returns consistent slashes #13787', function()
-- test/ cannot be a symlink in this test.
n.api.nvim_set_current_dir(t.paths.test_source_path)
it('exepath respects shellslash #13787', function()
t.skip(not is_os('win'), 'N/A for non-Windows')
-- test/ cannot be a symlink in this test.
n.api.nvim_set_current_dir(t.paths.test_source_path)
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
eq(
[[test/functional/fixtures/bin/null.CMD]],
call('fnamemodify', call('exepath', 'null'), ':.')
)
command('set shellslash')
eq(
'test/functional/fixtures/bin/null.CMD',
call('fnamemodify', call('exepath', 'null'), ':.')
)
end)
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
eq(([[%s\test\functional\fixtures\bin\null.CMD]]):format(fn.getcwd()), fn.exepath('null'))
command('set shellslash')
eq(('%s/test/functional/fixtures/bin/null.CMD'):format(fn.getcwd()), fn.exepath('null'))
end)
it('stdpath returns consistent slashes #13787', function()
-- Needs to check paths relative to repo root dir.
n.api.nvim_set_current_dir(t.paths.test_source_path)
it('stdpath returns consistent slashes #13787', function()
t.skip(not is_os('win'), 'N/A for non-Windows')
-- Needs to check paths relative to repo root dir.
n.api.nvim_set_current_dir(t.paths.test_source_path)
t.matches(
[[build/Xtest_xdg[%w_]*/share/nvim%-data]],
call('fnamemodify', call('stdpath', 'data'), ':.')
)
command('set shellslash')
t.matches(
'build/Xtest_xdg[%w_]*/share/nvim%-data',
call('fnamemodify', call('stdpath', 'data'), ':.')
)
end)
end
t.matches('build/Xtest_xdg[%w_]*/share/nvim%-data', fn.stdpath('data'))
command('set shellslash')
t.matches('build/Xtest_xdg[%w_]*/share/nvim%-data', fn.stdpath('data'))
end)
it('fails for invalid values', function()
for _, input in ipairs({ 'v:null', 'v:true', 'v:false', '{}', '[]' }) do
+21 -25
View File
@@ -10,10 +10,6 @@ local write_file = t.write_file
local is_os = t.is_os
local chdir = n.fn.chdir
local function eq_slashconvert(expected, got)
eq(t.fix_slashes(expected), t.fix_slashes(got))
end
describe('fnamemodify()', function()
setup(function()
write_file('Xtest-fnamemodify.txt', [[foobar]])
@@ -42,7 +38,7 @@ describe('fnamemodify()', function()
eq(root, fnamemodify([[/]], ':p'))
local letter_colon = root:sub(1, 2)
local old_dir = t.fix_slashes(getcwd()) .. '/'
local old_dir = ('%s/'):format(getcwd())
local foo_dir = old_dir .. 'foo/'
eq(old_dir, fnamemodify(letter_colon, ':p'))
eq(old_dir, fnamemodify(letter_colon .. '.', ':p'))
@@ -65,28 +61,28 @@ describe('fnamemodify()', function()
n.api.nvim_set_current_dir(t.paths.test_source_path)
local filename = 'src/version.c'
local cwd = getcwd()
local cwd = vim.fs.normalize(getcwd())
eq_slashconvert(cwd .. '/src/version.c', fnamemodify(filename, ':p'))
eq(('%s/src/version.c'):format(cwd), fnamemodify(filename, ':p'))
eq_slashconvert('src/version.c', fnamemodify(filename, ':p:.'))
eq_slashconvert(cwd .. '/src', fnamemodify(filename, ':p:h'))
eq_slashconvert(cwd .. '', fnamemodify(filename, ':p:h:h'))
eq('src/version.c', fnamemodify(filename, ':p:.'))
eq(('%s/src'):format(cwd), fnamemodify(filename, ':p:h'))
eq(cwd, fnamemodify(filename, ':p:h:h'))
eq('version.c', fnamemodify(filename, ':p:t'))
eq_slashconvert(cwd .. '/src/version', fnamemodify(filename, ':p:r'))
eq(('%s/src/version'):format(cwd), fnamemodify(filename, ':p:r'))
eq_slashconvert(cwd .. '/src/main.c', fnamemodify(filename, ':s?version?main?:p'))
eq(('%s/src/main.c'):format(cwd), fnamemodify(filename, ':s?version?main?:p'))
local converted_cwd = cwd:gsub('/', '\\')
eq(converted_cwd .. '\\src\\version.c', fnamemodify(filename, ':p:gs?/?\\\\?'))
eq('src', fnamemodify(filename, ':h'))
eq('version.c', fnamemodify(filename, ':t'))
eq_slashconvert('src/version', fnamemodify(filename, ':r'))
eq('src/version', fnamemodify(filename, ':r'))
eq('version', fnamemodify(filename, ':t:r'))
eq('c', fnamemodify(filename, ':e'))
eq_slashconvert('src/main.c', fnamemodify(filename, ':s?version?main?'))
eq('src/main.c', fnamemodify(filename, ':s?version?main?'))
end)
it('handles advanced examples from ":help filename-modifiers"', function()
@@ -98,11 +94,11 @@ describe('fnamemodify()', function()
eq('c', fnamemodify(filename, ':e:e:r'))
eq_slashconvert('src/version.c', fnamemodify(filename, ':r'))
eq('src/version.c', fnamemodify(filename, ':r'))
eq('c', fnamemodify(filename, ':r:e'))
eq_slashconvert('src/version', fnamemodify(filename, ':r:r'))
eq_slashconvert('src/version', fnamemodify(filename, ':r:r:r'))
eq('src/version', fnamemodify(filename, ':r:r'))
eq('src/version', fnamemodify(filename, ':r:r:r'))
end)
it('handles :h', function()
@@ -136,11 +132,11 @@ describe('fnamemodify()', function()
eq('//server///share', fnamemodify('//server///share', ':h'))
eq('//server/share/', fnamemodify('//server/share/foo', ':h'))
eq([[\\foo\C$]], fnamemodify([[\\foo\C$]], ':h'))
eq([[\\foo\C$\]], fnamemodify([[\\foo\C$\]], ':h'))
eq([[\\foo\C$\]], fnamemodify([[\\foo\C$\bar]], ':h'))
eq([[\\foo\C$\]], fnamemodify([[\\foo\C$\bar]], ':h:h'))
eq([[//foo\C$/]], fnamemodify([[//foo\C$/bar]], ':h'))
eq([[//foo/C$]], fnamemodify([[\\foo\C$]], ':h'))
eq([[//foo/C$/]], fnamemodify([[\\foo\C$\]], ':h'))
eq([[//foo/C$/]], fnamemodify([[\\foo\C$\bar]], ':h'))
eq([[//foo/C$/]], fnamemodify([[\\foo\C$\bar]], ':h:h'))
eq([[//foo/C$/]], fnamemodify([[//foo\C$/bar]], ':h'))
-- `C$` is a share name, not a file name
eq('', fnamemodify('//foo/C$/bar', ':h:t'))
@@ -165,17 +161,17 @@ describe('fnamemodify()', function()
it('handles :t', function()
eq('hello.txt', fnamemodify('hello.txt', ':t'))
eq_slashconvert('hello.txt', fnamemodify('path/to/hello.txt', ':t'))
eq('hello.txt', fnamemodify('path/to/hello.txt', ':t'))
end)
it('handles :r', function()
eq('hello', fnamemodify('hello.txt', ':r'))
eq_slashconvert('path/to/hello', fnamemodify('path/to/hello.txt', ':r'))
eq('path/to/hello', fnamemodify('path/to/hello.txt', ':r'))
end)
it('handles :e', function()
eq('txt', fnamemodify('hello.txt', ':e'))
eq_slashconvert('txt', fnamemodify('path/to/hello.txt', ':e'))
eq('txt', fnamemodify('path/to/hello.txt', ':e'))
end)
it('handles regex replacements', function()
+2 -2
View File
@@ -72,12 +72,12 @@ func Test_expand_sfile_and_stack()
let g:stack3 = expand('<stack>')
END
call writefile(lines, 'Xshellslash/Xstack')
" Test that changing 'shellslash' doesn't affect the result of expand()
" Test that changing 'shellslash' always affects the result of expand()
" when sourcing a script multiple times.
for i in range(2)
source Xshellslash/Xstack
call assert_match('\<Xshellslash/Xstack\[1\]$', g:stack1)
call assert_match('\<Xshellslash/Xstack\[3\]$', g:stack2)
call assert_match('\<Xshellslash\\Xstack\[3\]$', g:stack2)
call assert_match('\<Xshellslash/Xstack\[5\]$', g:stack3)
unlet g:stack1
unlet g:stack2
+7 -5
View File
@@ -443,8 +443,9 @@ endfunc
func s:netrw_filecopy(count = 1)
" setup
let marked_files = []
let source_dir = netrw#fs#PathJoin($HOME, "src")
let target_dir = netrw#fs#PathJoin($HOME, "target")
let home = expand('$HOME')
let source_dir = netrw#fs#PathJoin(home, "src")
let target_dir = netrw#fs#PathJoin(home, "target")
call mkdir(source_dir, "R")
call mkdir(target_dir, "R")
@@ -504,8 +505,9 @@ func s:netrw_dircopy(count = 1)
" setup
let marked_dirname = "test_dir"
let marked_dir = netrw#fs#PathJoin($HOME, marked_dirname)
let target_dir = netrw#fs#PathJoin($HOME, "target")
let home = expand('$HOME')
let marked_dir = netrw#fs#PathJoin(home, marked_dirname)
let target_dir = netrw#fs#PathJoin(home, "target")
call mkdir(marked_dir, "R")
call mkdir(target_dir, "R")
@@ -519,7 +521,7 @@ func s:netrw_dircopy(count = 1)
endfor
" delegate
call Test_NetrwMarkFileCopy($HOME, target_dir, [marked_dirname])
call Test_NetrwMarkFileCopy(home, target_dir, [marked_dirname])
" verify
for file in dir_content
+2 -2
View File
@@ -37,8 +37,8 @@ func CheckHomeIsInSubprocessEnvironment(exp)
endfunc
func CheckHome(exp, ...)
call assert_equal(a:exp, $HOME)
call assert_equal(substitute(a:exp, '\\', '/', 'g'), expand('~', ':p'))
call assert_equal(substitute(a:exp, '\', '/', 'g'), $HOME)
call assert_equal(a:exp, expand('~', ':p'))
if !a:0
call CheckHomeIsMissingFromSubprocessEnvironment()
else