diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2015-10-25 22:38:23 -0400 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2015-10-25 22:38:23 -0400 |
commit | 1ca5646bb52ec5c23b28f45bb7bc5d25cffad9b0 (patch) | |
tree | 7495d3f50b897e74fc4597d061d427a4e9b1ae36 /src/nvim/os | |
parent | de4cb766ca381c09fd3f938136c1932ebf008f63 (diff) | |
parent | 42047acb4f07c689936b051864c6b4448b1b6aa1 (diff) | |
download | rneovim-1ca5646bb52ec5c23b28f45bb7bc5d25cffad9b0.tar.gz rneovim-1ca5646bb52ec5c23b28f45bb7bc5d25cffad9b0.tar.bz2 rneovim-1ca5646bb52ec5c23b28f45bb7bc5d25cffad9b0.zip |
Merge pull request #3470 from ZyX-I/pr-3198
XDG base directory specification support
Diffstat (limited to 'src/nvim/os')
-rw-r--r-- | src/nvim/os/env.c | 68 | ||||
-rw-r--r-- | src/nvim/os/fs.c | 10 | ||||
-rw-r--r-- | src/nvim/os/os.h | 2 | ||||
-rw-r--r-- | src/nvim/os/stdpaths.c | 108 | ||||
-rw-r--r-- | src/nvim/os/stdpaths_defs.h | 14 | ||||
-rw-r--r-- | src/nvim/os/unix_defs.h | 37 | ||||
-rw-r--r-- | src/nvim/os/win_defs.h | 4 |
7 files changed, 201 insertions, 42 deletions
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index 7be8a868bd..bf6db97fcf 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -415,6 +415,74 @@ static char *remove_tail(char *p, char *pend, char *name) return pend; } +/// Iterate over colon-separated list +/// +/// @note Environment variables must not be modified during iteration. +/// +/// @param[in] val Value of the environment variable to iterate over. +/// @param[in] iter Pointer used for iteration. Must be NULL on first +/// iteration. +/// @param[out] dir Location where pointer to the start of the current +/// directory name should be saved. May be set to NULL. +/// @param[out] len Location where current directory length should be saved. +/// +/// @return Next iter argument value or NULL when iteration should stop. +const void *vim_colon_env_iter(const char *const val, + const void *const iter, + const char **const dir, + size_t *const len) + FUNC_ATTR_NONNULL_ARG(1, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT +{ + const char *varval = (const char *) iter; + if (varval == NULL) { + varval = val; + } + *dir = varval; + const char *const dirend = strchr(varval, ':'); + if (dirend == NULL) { + *len = strlen(varval); + return NULL; + } else { + *len = (size_t) (dirend - varval); + return dirend + 1; + } +} + +/// Iterate over colon-separated list in reverse order +/// +/// @note Environment variables must not be modified during iteration. +/// +/// @param[in] val Value of the environment variable to iterate over. +/// @param[in] iter Pointer used for iteration. Must be NULL on first +/// iteration. +/// @param[out] dir Location where pointer to the start of the current +/// directory name should be saved. May be set to NULL. +/// @param[out] len Location where current directory length should be saved. +/// +/// @return Next iter argument value or NULL when iteration should stop. +const void *vim_colon_env_iter_rev(const char *const val, + const void *const iter, + const char **const dir, + size_t *const len) + FUNC_ATTR_NONNULL_ARG(1, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT +{ + const char *varend = (const char *) iter; + if (varend == NULL) { + varend = val + strlen(val) - 1; + } + const size_t varlen = (size_t) (varend - val) + 1; + const char *const colon = xmemrchr(val, ':', varlen); + if (colon == NULL) { + *len = varlen; + *dir = val; + return NULL; + } else { + *dir = colon + 1; + *len = (size_t) (varend - colon); + return colon - 1; + } +} + /// Vim's version of getenv(). /// Special handling of $HOME, $VIM and $VIMRUNTIME, allowing the user to /// override the vim runtime directory at runtime. Also does ACP to 'enc' diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 522e49950c..05f0f53c63 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -366,11 +366,17 @@ int os_mkdir_recurse(const char *const dir, int32_t mode, } while (e != real_end) { if (e > past_head) { - *e = '/'; + *e = PATHSEP; } else { *past_head = past_head_save; } - e += strlen(e); + const size_t component_len = strlen(e); + e += component_len; + if (e == real_end + && memcnt(e - component_len, PATHSEP, component_len) == component_len) { + // Path ends with something like "////". Ignore this. + break; + } int ret; if ((ret = os_mkdir(curdir, mode)) != 0) { *failed_dir = curdir; diff --git a/src/nvim/os/os.h b/src/nvim/os/os.h index 69bd1ff4fd..3e89e5a94a 100644 --- a/src/nvim/os/os.h +++ b/src/nvim/os/os.h @@ -5,6 +5,7 @@ #include <uv.h> #include "nvim/os/fs_defs.h" +#include "nvim/os/stdpaths_defs.h" #include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -12,6 +13,7 @@ # include "os/mem.h.generated.h" # include "os/env.h.generated.h" # include "os/users.h.generated.h" +# include "os/stdpaths.h.generated.h" #endif #endif // NVIM_OS_OS_H diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c new file mode 100644 index 0000000000..ce374828f9 --- /dev/null +++ b/src/nvim/os/stdpaths.c @@ -0,0 +1,108 @@ +#include <stdbool.h> + +#include "nvim/os/stdpaths_defs.h" +#include "nvim/os/os.h" +#include "nvim/path.h" +#include "nvim/memory.h" +#include "nvim/ascii.h" + +/// Names of the environment variables, mapped to XDGVarType values +static const char *xdg_env_vars[] = { + [kXDGConfigHome] = "XDG_CONFIG_HOME", + [kXDGDataHome] = "XDG_DATA_HOME", + [kXDGCacheHome] = "XDG_CACHE_HOME", + [kXDGRuntimeDir] = "XDG_RUNTIME_DIR", + [kXDGConfigDirs] = "XDG_CONFIG_DIRS", + [kXDGDataDirs] = "XDG_DATA_DIRS", +}; + +/// Defaults for XDGVarType values +/// +/// Used in case environment variables contain nothing. Need to be expanded. +static const char *const xdg_defaults[] = { +#ifdef WIN32 + // Windows + [kXDGConfigHome] = "$LOCALAPPDATA\\nvim\\config", + [kXDGDataHome] = "$LOCALAPPDATA\\nvim\\data", + [kXDGCacheHome] = "$LOCALAPPDATA\\nvim\\cache", + [kXDGRuntimeDir] = "", + [kXDGConfigDirs] = NULL, + [kXDGDataDirs] = NULL, +#else + // Linux, BSD, CYGWIN, Apple + [kXDGConfigHome] = "~/.config", + [kXDGDataHome] = "~/.local/share", + [kXDGCacheHome] = "~/.cache", + [kXDGRuntimeDir] = "", + [kXDGConfigDirs] = "/etc/xdg/", + [kXDGDataDirs] = "/usr/local/share/:/usr/share/", +#endif +}; + +/// Return XDG variable value +/// +/// @param[in] idx XDG variable to use. +/// +/// @return [allocated] variable value. +char *stdpaths_get_xdg_var(const XDGVarType idx) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + const char *const env = xdg_env_vars[idx]; + const char *const fallback = xdg_defaults[idx]; + + const char *const env_val = os_getenv(env); + char *ret = NULL; + if (env_val != NULL) { + ret = xstrdup(env_val); + } else if (fallback) { + ret = (char *) expand_env_save((char_u *)fallback); + } + + return ret; +} + +/// Return nvim-specific XDG directory subpath +/// +/// @param[in] idx XDG directory to use. +/// +/// @return [allocated] `{xdg_directory}/nvim` +static char *get_xdg_home(const XDGVarType idx) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + char *dir = stdpaths_get_xdg_var(idx); + if (dir) { + dir = concat_fnames_realloc(dir, "nvim", true); + } + return dir; +} + +/// Return subpath of $XDG_CONFIG_HOME +/// +/// @param[in] fname New component of the path. +/// +/// @return [allocated] `$XDG_CONFIG_HOME/nvim/{fname}` +char *stdpaths_user_conf_subpath(const char *fname) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + return concat_fnames_realloc(get_xdg_home(kXDGConfigHome), fname, true); +} + +/// Return subpath of $XDG_DATA_HOME +/// +/// @param[in] fname New component of the path. +/// @param[in] trailing_pathseps Amount of trailing path separators to add. +/// +/// @return [allocated] `$XDG_DATA_HOME/nvim/{fname}` +char *stdpaths_user_data_subpath(const char *fname, + const size_t trailing_pathseps) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL +{ + char *ret = concat_fnames_realloc(get_xdg_home(kXDGDataHome), fname, true); + if (trailing_pathseps) { + const size_t len = strlen(ret); + ret = xrealloc(ret, len + trailing_pathseps + 1); + memset(ret + len, PATHSEP, trailing_pathseps); + ret[len + trailing_pathseps] = NUL; + } + return ret; +} diff --git a/src/nvim/os/stdpaths_defs.h b/src/nvim/os/stdpaths_defs.h new file mode 100644 index 0000000000..1433e0bc62 --- /dev/null +++ b/src/nvim/os/stdpaths_defs.h @@ -0,0 +1,14 @@ +#ifndef NVIM_OS_STDPATHS_DEFS_H +#define NVIM_OS_STDPATHS_DEFS_H + +/// List of possible XDG variables +typedef enum { + kXDGConfigHome, ///< XDG_CONFIG_HOME + kXDGDataHome, ///< XDG_DATA_HOME + kXDGCacheHome, ///< XDG_CACHE_HOME + kXDGRuntimeDir, ///< XDG_RUNTIME_DIR + kXDGConfigDirs, ///< XDG_CONFIG_DIRS + kXDGDataDirs, ///< XDG_DATA_DIRS +} XDGVarType; + +#endif // NVIM_OS_STDPATHS_DEFS_H diff --git a/src/nvim/os/unix_defs.h b/src/nvim/os/unix_defs.h index 949973bf40..b1511d4b56 100644 --- a/src/nvim/os/unix_defs.h +++ b/src/nvim/os/unix_defs.h @@ -20,7 +20,7 @@ // Unix system-dependent file names #ifndef SYS_VIMRC_FILE -# define SYS_VIMRC_FILE "$VIM/nvimrc" +# define SYS_VIMRC_FILE "$VIM/sysinit.vim" #endif #ifndef DFLT_HELPFILE # define DFLT_HELPFILE "$VIMRUNTIME/doc/help.txt" @@ -28,46 +28,11 @@ #ifndef SYNTAX_FNAME # define SYNTAX_FNAME "$VIMRUNTIME/syntax/%s.vim" #endif -#ifndef USR_EXRC_FILE -# define USR_EXRC_FILE "~/.exrc" -#endif -#ifndef USR_VIMRC_FILE -# define USR_VIMRC_FILE "~/.nvimrc" -#endif -#ifndef USR_VIMRC_FILE2 -# define USR_VIMRC_FILE2 "~/.nvim/nvimrc" -#endif #ifndef EXRC_FILE # define EXRC_FILE ".exrc" #endif #ifndef VIMRC_FILE # define VIMRC_FILE ".nvimrc" #endif -#ifndef SHADA_FILE -# define SHADA_FILE "~/.nvim/shada/main.shada" -#endif - -// Default for 'backupdir'. -#ifndef DFLT_BDIR -# define DFLT_BDIR ".,~/tmp,~/" -#endif - -// Default for 'directory'. -#ifndef DFLT_DIR -# define DFLT_DIR ".,~/tmp,/var/tmp,/tmp" -#endif - -// Default for 'viewdir'. -#ifndef DFLT_VDIR -# define DFLT_VDIR "~/.nvim/view" -#endif - -#ifdef RUNTIME_GLOBAL -# define DFLT_RUNTIMEPATH "~/.nvim," RUNTIME_GLOBAL ",$VIMRUNTIME," \ - RUNTIME_GLOBAL "/after,~/.nvim/after" -#else -# define DFLT_RUNTIMEPATH \ - "~/.nvim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,~/.nvim/after" -#endif #endif // NVIM_OS_UNIX_DEFS_H diff --git a/src/nvim/os/win_defs.h b/src/nvim/os/win_defs.h index b7ec50a109..d614582250 100644 --- a/src/nvim/os/win_defs.h +++ b/src/nvim/os/win_defs.h @@ -7,13 +7,9 @@ #define TEMP_FILE_PATH_MAXLEN _MAX_PATH // Defines needed to fix the build on Windows: -// - USR_EXRC_FILE -// - USR_VIMRC_FILE -// - SHADA_FILE // - DFLT_DIR // - DFLT_BDIR // - DFLT_VDIR -// - DFLT_RUNTIMEPATH // - EXRC_FILE // - VIMRC_FILE // - SYNTAX_FNAME |