aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/news.txt4
-rw-r--r--runtime/doc/starting.txt12
-rw-r--r--src/nvim/eval.c3
-rw-r--r--src/nvim/fileio.c5
-rw-r--r--src/nvim/msgpack_rpc/server.c5
-rw-r--r--src/nvim/os/stdpaths.c39
-rw-r--r--src/nvim/runtime.c41
-rw-r--r--test/functional/options/defaults_spec.lua26
8 files changed, 99 insertions, 36 deletions
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 2afb22bb43..ae21bc47ca 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -55,6 +55,10 @@ NEW FEATURES *news-features*
The following new APIs or features were added.
+• A new environment variable named NVIM_APPNAME enables configuring the
+ directories where Neovim should find its configuration and state files. See
+ `:help $NVIM_APPNAME` .
+
• |nvim_open_win()| now accepts a relative `mouse` option to open a floating win
relative to the mouse. Note that the mouse doesn't update frequently without
setting `vim.o.mousemoveevent = true`
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index 5e0718c3bb..67a88913fb 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -1385,6 +1385,18 @@ STATE DIRECTORY (DEFAULT) ~
Note: Throughout the user manual these defaults are used as placeholders, e.g.
"~/.config" is understood to mean "$XDG_CONFIG_HOME or ~/.config".
+NVIM_APPNAME *$NVIM_APPNAME*
+The XDG directories used by Nvim can be further configured by setting the
+`$NVIM_APPNAME` environment variable. This variable controls the directory
+Neovim will look for (and auto-create) in the various XDG parent directories.
+For example, setting `$NVIM_APPNAME` to "neovim" before running Neovim will
+result in Neovim looking for configuration files in `$XDG_CONFIG_HOME/neovim`
+instead of `$XDG_CONFIG_HOME/nvim`.
+
+Note: Similarly to the $XDG environment variables, when
+`$XDG_CONFIG_HOME/nvim` is mentionned, it should be understood as
+`$XDG_CONFIG_HOME/$NVIM_APPNAME`.
+
LOG FILE *$NVIM_LOG_FILE* *E5430*
Besides 'debug' and 'verbose', Nvim keeps a general log file for internal
debugging, plugins and RPC clients. >
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 92a8ffd646..ccea4f4951 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -5368,13 +5368,14 @@ void get_xdg_var_list(const XDGVarType xdg, typval_T *rettv)
return;
}
const void *iter = NULL;
+ const char *appname = get_appname();
do {
size_t dir_len;
const char *dir;
iter = vim_env_iter(ENV_SEPCHAR, dirs, iter, &dir, &dir_len);
if (dir != NULL && dir_len > 0) {
char *dir_with_nvim = xmemdupz(dir, dir_len);
- dir_with_nvim = concat_fnames_realloc(dir_with_nvim, "nvim", true);
+ dir_with_nvim = concat_fnames_realloc(dir_with_nvim, appname, true);
tv_list_append_string(list, dir_with_nvim, (ssize_t)strlen(dir_with_nvim));
xfree(dir_with_nvim);
}
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index a3cdd2bb23..755b8e0834 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -5181,7 +5181,10 @@ static void vim_mktempdir(void)
// "/tmp/" exists, now try to create "/tmp/nvim.<user>/".
add_pathsep(tmp);
- xstrlcat(tmp, "nvim.", sizeof(tmp));
+
+ const char *appname = get_appname();
+ xstrlcat(tmp, appname, sizeof(tmp));
+ xstrlcat(tmp, ".", sizeof(tmp));
xstrlcat(tmp, user, sizeof(tmp));
(void)os_mkdir(tmp, 0700); // Always create, to avoid a race.
bool owned = os_file_owned(tmp);
diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c
index 1d75c208be..c6a0a4d8cc 100644
--- a/src/nvim/msgpack_rpc/server.c
+++ b/src/nvim/msgpack_rpc/server.c
@@ -91,13 +91,14 @@ char *server_address_new(const char *name)
{
static uint32_t count = 0;
char fmt[ADDRESS_MAX_SIZE];
+ const char *appname = get_appname();
#ifdef MSWIN
int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32,
- name ? name : "nvim", os_get_pid(), count++);
+ name ? name : appname, os_get_pid(), count++);
#else
char *dir = stdpaths_get_xdg_var(kXDGRuntimeDir);
int r = snprintf(fmt, sizeof(fmt), "%s/%s.%" PRIu64 ".%" PRIu32,
- dir, name ? name : "nvim", os_get_pid(), count++);
+ dir, name ? name : appname, os_get_pid(), count++);
xfree(dir);
#endif
if ((size_t)r >= sizeof(fmt)) {
diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c
index 6b07b6ef70..5235828f7a 100644
--- a/src/nvim/os/stdpaths.c
+++ b/src/nvim/os/stdpaths.c
@@ -57,6 +57,18 @@ static const char *const xdg_defaults[] = {
#endif
};
+/// Get the value of $NVIM_APPNAME or "nvim" if not set.
+///
+/// @return $NVIM_APPNAME value
+const char *get_appname(void)
+{
+ const char *env_val = os_getenv("NVIM_APPNAME");
+ if (env_val == NULL || *env_val == '\0') {
+ env_val = "nvim";
+ }
+ return env_val;
+}
+
/// Return XDG variable value
///
/// @param[in] idx XDG variable to use.
@@ -100,25 +112,28 @@ char *stdpaths_get_xdg_var(const XDGVarType idx)
/// Return Nvim-specific XDG directory subpath.
///
-/// Windows: Uses "…/nvim-data" for kXDGDataHome to avoid storing
+/// Windows: Uses "…/$NVIM_APPNAME-data" for kXDGDataHome to avoid storing
/// configuration and data files in the same path. #4403
///
/// @param[in] idx XDG directory to use.
///
-/// @return [allocated] "{xdg_directory}/nvim"
+/// @return [allocated] "{xdg_directory}/$NVIM_APPNAME"
char *get_xdg_home(const XDGVarType idx)
FUNC_ATTR_WARN_UNUSED_RESULT
{
char *dir = stdpaths_get_xdg_var(idx);
+ const char *appname = get_appname();
+ size_t appname_len = strlen(appname);
+ assert(appname_len < (IOSIZE - sizeof("-data")));
+
if (dir) {
+ xstrlcpy(IObuff, appname, appname_len + 1);
#if defined(MSWIN)
- dir = concat_fnames_realloc(dir,
- ((idx == kXDGDataHome
- || idx == kXDGStateHome) ? "nvim-data" : "nvim"),
- true);
-#else
- dir = concat_fnames_realloc(dir, "nvim", true);
+ if (idx == kXDGDataHome || idx == kXDGStateHome) {
+ STRCAT(IObuff, "-data");
+ }
#endif
+ dir = concat_fnames_realloc(dir, IObuff, true);
#ifdef BACKSLASH_IN_FILENAME
slash_adjust(dir);
@@ -131,7 +146,7 @@ char *get_xdg_home(const XDGVarType idx)
///
/// @param[in] fname New component of the path.
///
-/// @return [allocated] `$XDG_CACHE_HOME/nvim/{fname}`
+/// @return [allocated] `$XDG_CACHE_HOME/$NVIM_APPNAME/{fname}`
char *stdpaths_user_cache_subpath(const char *fname)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
@@ -142,7 +157,7 @@ char *stdpaths_user_cache_subpath(const char *fname)
///
/// @param[in] fname New component of the path.
///
-/// @return [allocated] `$XDG_CONFIG_HOME/nvim/{fname}`
+/// @return [allocated] `$XDG_CONFIG_HOME/$NVIM_APPNAME/{fname}`
char *stdpaths_user_conf_subpath(const char *fname)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
@@ -153,7 +168,7 @@ char *stdpaths_user_conf_subpath(const char *fname)
///
/// @param[in] fname New component of the path.
///
-/// @return [allocated] `$XDG_DATA_HOME/nvim/{fname}`
+/// @return [allocated] `$XDG_DATA_HOME/$NVIM_APPNAME/{fname}`
char *stdpaths_user_data_subpath(const char *fname)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
@@ -166,7 +181,7 @@ char *stdpaths_user_data_subpath(const char *fname)
/// @param[in] trailing_pathseps Amount of trailing path separators to add.
/// @param[in] escape_commas If true, all commas will be escaped.
///
-/// @return [allocated] `$XDG_STATE_HOME/nvim/{fname}`.
+/// @return [allocated] `$XDG_STATE_HOME/$NVIM_APPNAME/{fname}`.
char *stdpaths_user_state_subpath(const char *fname, const size_t trailing_pathseps,
const bool escape_commas)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index 9dc213d718..3487a8d7a2 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -1435,7 +1435,6 @@ static inline size_t compute_double_env_sep_len(const char *const val, const siz
return ret;
}
-#define NVIM_SIZE (sizeof("nvim") - 1)
/// Add directories to a ENV_SEPCHAR-separated array from a colon-separated one
///
/// Commas are escaped in process. To each item PATHSEP "nvim" is appended in
@@ -1464,6 +1463,8 @@ static inline char *add_env_sep_dirs(char *dest, const char *const val, const ch
return dest;
}
const void *iter = NULL;
+ const char *appname = get_appname();
+ const size_t appname_len = strlen(appname);
do {
size_t dir_len;
const char *dir;
@@ -1474,8 +1475,8 @@ static inline char *add_env_sep_dirs(char *dest, const char *const val, const ch
if (!after_pathsep(dest - 1, dest)) {
*dest++ = PATHSEP;
}
- memmove(dest, "nvim", NVIM_SIZE);
- dest += NVIM_SIZE;
+ memmove(dest, appname, appname_len);
+ dest += appname_len;
if (suf1 != NULL) {
*dest++ = PATHSEP;
memmove(dest, suf1, len1);
@@ -1529,14 +1530,18 @@ static inline char *add_dir(char *dest, const char *const dir, const size_t dir_
if (!after_pathsep(dest - 1, dest)) {
*dest++ = PATHSEP;
}
+ const char *appname = get_appname();
+ size_t appname_len = strlen(appname);
+ assert(appname_len < (IOSIZE - sizeof("-data")));
+ xstrlcpy(IObuff, appname, appname_len + 1);
#if defined(MSWIN)
- size_t size = (type == kXDGDataHome ? sizeof("nvim-data") - 1 : NVIM_SIZE);
- memmove(dest, (type == kXDGDataHome ? "nvim-data" : "nvim"), size);
- dest += size;
-#else
- memmove(dest, "nvim", NVIM_SIZE);
- dest += NVIM_SIZE;
+ if (type == kXDGDataHome || type == kXDGStateHome) {
+ STRCAT(IObuff, "-data");
+ appname_len += 5;
+ }
#endif
+ xstrlcpy(dest, IObuff, appname_len + 1);
+ dest += appname_len;
if (suf1 != NULL) {
*dest++ = PATHSEP;
memmove(dest, suf1, len1);
@@ -1596,16 +1601,17 @@ char *runtimepath_default(bool clean_arg)
size_t config_len = 0;
size_t vimruntime_len = 0;
size_t libdir_len = 0;
+ const char *appname = get_appname();
+ size_t appname_len = strlen(appname);
if (data_home != NULL) {
data_len = strlen(data_home);
- if (data_len != 0) {
+ size_t nvim_data_size = appname_len;
#if defined(MSWIN)
- size_t nvim_size = (sizeof("nvim-data") - 1);
-#else
- size_t nvim_size = NVIM_SIZE;
+ nvim_data_size += sizeof("-data");
#endif
+ if (data_len != 0) {
rtp_size += ((data_len + memcnt(data_home, ',', data_len)
- + nvim_size + 1 + SITE_SIZE + 1
+ + nvim_data_size + 1 + SITE_SIZE + 1
+ !after_pathsep(data_home, data_home + data_len)) * 2
+ AFTER_SIZE + 1);
}
@@ -1614,7 +1620,7 @@ char *runtimepath_default(bool clean_arg)
config_len = strlen(config_home);
if (config_len != 0) {
rtp_size += ((config_len + memcnt(config_home, ',', config_len)
- + NVIM_SIZE + 1
+ + appname_len + 1
+ !after_pathsep(config_home, config_home + config_len)) * 2
+ AFTER_SIZE + 1);
}
@@ -1632,9 +1638,9 @@ char *runtimepath_default(bool clean_arg)
}
}
rtp_size += compute_double_env_sep_len(data_dirs,
- NVIM_SIZE + 1 + SITE_SIZE + 1,
+ appname_len + 1 + SITE_SIZE + 1,
AFTER_SIZE + 1);
- rtp_size += compute_double_env_sep_len(config_dirs, NVIM_SIZE + 1,
+ rtp_size += compute_double_env_sep_len(config_dirs, appname_len + 1,
AFTER_SIZE + 1);
char *rtp = NULL;
if (rtp_size == 0) {
@@ -1675,7 +1681,6 @@ freeall:
return rtp;
}
-#undef NVIM_SIZE
static void cmd_source(char *fname, exarg_T *eap)
{
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index 84ec43f4cb..4242b6e493 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -566,8 +566,12 @@ end)
describe('stdpath()', function()
-- Windows appends 'nvim-data' instead of just 'nvim' to prevent collisions
-- due to XDG_CONFIG_HOME, XDG_DATA_HOME and XDG_STATE_HOME being the same.
- local datadir = is_os('win') and 'nvim-data' or 'nvim'
- local statedir = is_os('win') and 'nvim-data' or 'nvim'
+ local function maybe_data(name)
+ return is_os('win') and name .. '-data' or name
+ end
+
+ local datadir = maybe_data('nvim')
+ local statedir = maybe_data('nvim')
local env_sep = is_os('win') and ';' or ':'
it('acceptance', function()
@@ -583,6 +587,24 @@ describe('stdpath()', function()
assert_alive() -- Check for crash. #8393
end)
+ it('reacts to #NVIM_APPNAME', function()
+ local appname = "NVIM_APPNAME_TEST____________________________________" ..
+ "______________________________________________________________________"
+ clear({env={ NVIM_APPNAME=appname }})
+ eq(appname, funcs.fnamemodify(funcs.stdpath('config'), ':t'))
+ eq(appname, funcs.fnamemodify(funcs.stdpath('cache'), ':t'))
+ eq(maybe_data(appname), funcs.fnamemodify(funcs.stdpath('log'), ':t'))
+ eq(maybe_data(appname), funcs.fnamemodify(funcs.stdpath('data'), ':t'))
+ eq(maybe_data(appname), funcs.fnamemodify(funcs.stdpath('state'), ':t'))
+ -- config_dirs and data_dirs are empty on windows, so don't check them on
+ -- that platform
+ if not is_os('win') then
+ eq(appname, funcs.fnamemodify(funcs.stdpath('config_dirs')[1], ':t'))
+ eq(appname, funcs.fnamemodify(funcs.stdpath('data_dirs')[1], ':t'))
+ end
+ assert_alive() -- Check for crash. #8393
+ end)
+
context('returns a String', function()
describe('with "config"' , function ()