New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] XDG support #3198

Closed
wants to merge 9 commits into
base: master
from

Conversation

Projects
None yet
@jck
Contributor

jck commented Aug 19, 2015

This is a continuation of the discussion in #3127 .
I've addressed some of the comments in 8fc0976 but there is still quite a bit to do.

@marvim marvim added the WIP label Aug 19, 2015

Show outdated Hide outdated src/nvim/os/stdpaths.c
[cache_home] = "~/.cache",
[runtime_dir] = "",
[config_dirs] = "/etc/xdg/",
[data_dirs] = "/usr/local/share/:/usr/share/",

This comment has been minimized.

@lucc

lucc Aug 19, 2015

Contributor

Is there a reason that some of these values have a slash at the end and some don't?

@lucc

lucc Aug 19, 2015

Contributor

Is there a reason that some of these values have a slash at the end and some don't?

This comment has been minimized.

Show outdated Hide outdated src/nvim/os/stdpaths.c
[data_dirs] = "XDG_DATA_DIRS",
};
#ifdef __linux__

This comment has been minimized.

@ghost

ghost Aug 19, 2015

Is there any particular reason why this is being ifdef'd?

@ghost

ghost Aug 19, 2015

Is there any particular reason why this is being ifdef'd?

This comment has been minimized.

@jck

jck Aug 19, 2015

Contributor

So that we can provide sane defaults for Mac and Windows as well.

@jck

jck Aug 19, 2015

Contributor

So that we can provide sane defaults for Mac and Windows as well.

This comment has been minimized.

@ghost

ghost Aug 19, 2015

Ah, then how about #if !defined WIN32 && !define OSX instead (not sure if those are the correct defs)? As it is, these convenient defaults won't be defined for any BSD systems.

@ghost

ghost Aug 19, 2015

Ah, then how about #if !defined WIN32 && !define OSX instead (not sure if those are the correct defs)? As it is, these convenient defaults won't be defined for any BSD systems.

This comment has been minimized.

@jck

jck Aug 19, 2015

Contributor

Sounds good. I guess BSD systems should have the same defaults as linux?

@jck

jck Aug 19, 2015

Contributor

Sounds good. I guess BSD systems should have the same defaults as linux?

This comment has been minimized.

@ghost

ghost Aug 19, 2015

Yes, I think so.

@ghost

ghost Aug 19, 2015

Yes, I think so.

@@ -0,0 +1,88 @@
#include "nvim/os/os.h"

This comment has been minimized.

@ghost

ghost Aug 19, 2015

Perhaps a comment up here mentioning this implements the XDG specification, with a link to the spec.

@ghost

ghost Aug 19, 2015

Perhaps a comment up here mentioning this implements the XDG specification, with a link to the spec.

Show outdated Hide outdated src/nvim/os/stdpaths.c
return get_xdg_home(config_home);
}
const char *get_from_user_conf(const char * fname)

This comment has been minimized.

@ghost

ghost Aug 19, 2015

should be no space between * and fname

@ghost

ghost Aug 19, 2015

should be no space between * and fname

{
char *failed;
if (!os_mkdir_recurse(dir, mode, &failed)) {
// TODO: Create a folder in $TMPDIR instead

This comment has been minimized.

@ghost

ghost Aug 19, 2015

I know this isn't fully implemented, but it might be better off in os/fs.c.

@ghost

ghost Aug 19, 2015

I know this isn't fully implemented, but it might be better off in os/fs.c.

This comment has been minimized.

@jck

jck Aug 19, 2015

Contributor

Maybe, but right now what I have in mind is that this function will be tailored to create data,cache and runtime dirs. Let us revisit this later.

@jck

jck Aug 19, 2015

Contributor

Maybe, but right now what I have in mind is that this function will be tailored to create data,cache and runtime dirs. Let us revisit this later.

This comment has been minimized.

@ghost

ghost Aug 19, 2015

Sounds good, I don't want to bog this down in minutiae.

@ghost

ghost Aug 19, 2015

Sounds good, I don't want to bog this down in minutiae.

{
const char *dir = get_xdg(idx);
if (dir) {
dir = (const char *)concat_fnames(dir, "nvim", true);

This comment has been minimized.

@ghost

ghost Aug 19, 2015

why not just return (const char *)concat_fnames(dir, "nvim", true);

@ghost

ghost Aug 19, 2015

why not just return (const char *)concat_fnames(dir, "nvim", true);

This comment has been minimized.

@jck

jck Aug 19, 2015

Contributor

Because xdg_runtime_dir has no default value. When we reach a consensus on how we handle that, I'll change this.

@jck

jck Aug 19, 2015

Contributor

Because xdg_runtime_dir has no default value. When we reach a consensus on how we handle that, I'll change this.

This comment has been minimized.

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

There is a leak here, according to ASAN

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

There is a leak here, according to ASAN

@@ -1835,16 +1835,9 @@ static void source_startup_scripts(mparm_T *parmp)
* - second user exrc file ($VIM/.exrc for Dos)

This comment has been minimized.

@ghost

ghost Aug 19, 2015

The above comment is pretty outdated.

@ghost

ghost Aug 19, 2015

The above comment is pretty outdated.

Show outdated Hide outdated src/nvim/os/stdpaths.c
#include "nvim/garray.h"
typedef enum {
config_home,

This comment has been minimized.

@ZyX-I

ZyX-I Aug 19, 2015

Contributor

Style guide requires naming this like kXDGConfigHome.

@ZyX-I

ZyX-I Aug 19, 2015

Contributor

Style guide requires naming this like kXDGConfigHome.

This comment has been minimized.

@jck

jck Aug 19, 2015

Contributor

WIll do. However, I want to contain all references to the XDG spec in this module and make its public interface be something general/nvim specific..

@jck

jck Aug 19, 2015

Contributor

WIll do. However, I want to contain all references to the XDG spec in this module and make its public interface be something general/nvim specific..

@ghost ghost referenced this pull request Aug 19, 2015

Closed

[WIP] XDG support #3120

Show outdated Hide outdated src/nvim/os/stdpaths.c
[kConfigDirs] = "/etc/xdg/",
[kDataDirs] = "/usr/local/share/:/usr/share/",
};
#endif

This comment has been minimized.

@jck

jck Aug 20, 2015

Contributor

@Pyrohh Does this look good?

@jck

jck Aug 20, 2015

Contributor

@Pyrohh Does this look good?

This comment has been minimized.

@Yamakaky

Yamakaky Aug 20, 2015

Contributor

I prefer explicit defines (as opposed to else), but in this case why not.
CYGWIN <-> ~ ??

@Yamakaky

Yamakaky Aug 20, 2015

Contributor

I prefer explicit defines (as opposed to else), but in this case why not.
CYGWIN <-> ~ ??

This comment has been minimized.

@ghost

ghost Aug 20, 2015

@jck Looks fine to me, no comment on the actual defines though. I'm not sure if it should instead be __WIN32__ and __APPPLE__, but we'll deal with that later.

@ghost

ghost Aug 20, 2015

@jck Looks fine to me, no comment on the actual defines though. I'm not sure if it should instead be __WIN32__ and __APPPLE__, but we'll deal with that later.

Show outdated Hide outdated src/nvim/os/stdpaths.c
[kConfigDirs] = "XDG_CONFIG_DIRS",
[kDataDirs] = "XDG_DATA_DIRS",
};

This comment has been minimized.

@jck

jck Aug 20, 2015

Contributor

@ZyX-I I changed the enum field names as per the style guide.

@jck

jck Aug 20, 2015

Contributor

@ZyX-I I changed the enum field names as per the style guide.

This comment has been minimized.

@ZyX-I

ZyX-I Aug 20, 2015

Contributor

Common prefix for all enum values is just k. I do not think this is a good idea, I would use kXDG even for local enums.

@ZyX-I

ZyX-I Aug 20, 2015

Contributor

Common prefix for all enum values is just k. I do not think this is a good idea, I would use kXDG even for local enums.

This comment has been minimized.

@justinmk

justinmk Aug 22, 2015

Member

To be clear, these should be renamed like:

typedef enum {
  kXDGConfigHome,
  kXDGDataHome,
  ...
  kXDGDataDirs,
} XDGDirType;
@justinmk

justinmk Aug 22, 2015

Member

To be clear, these should be renamed like:

typedef enum {
  kXDGConfigHome,
  kXDGDataHome,
  ...
  kXDGDataDirs,
} XDGDirType;
Show outdated Hide outdated src/nvim/os/stdpaths.c
[kCacheHome] = "~/.cache",
[kRuntimeDir] = "",
[kConfigDirs] = "/etc/xdg/",
[kDataDirs] = "/usr/local/share/:/usr/share/",

This comment has been minimized.

@lucc

lucc Aug 20, 2015

Contributor

Picking up the question about tailing slashes again.

I see what you mean about following the spec. But I think "equal" in the spec can also mean "functional equivalent" (the spec doesn't tell you which programming language or encoding to use for example). And depending on which functions in nvim use these values it might be an advantage to have all the defaults in the same style (I would prefer no tailing slash). Otherwise the code that uses these values has to decide if it will append a slash or not.

I am not sure if this concern will actually have any functional relevance. All applications that I now of can work with non normalized path (double slashes) when using files. It is only about aesthetics when the values will be displayed to the user.

@lucc

lucc Aug 20, 2015

Contributor

Picking up the question about tailing slashes again.

I see what you mean about following the spec. But I think "equal" in the spec can also mean "functional equivalent" (the spec doesn't tell you which programming language or encoding to use for example). And depending on which functions in nvim use these values it might be an advantage to have all the defaults in the same style (I would prefer no tailing slash). Otherwise the code that uses these values has to decide if it will append a slash or not.

I am not sure if this concern will actually have any functional relevance. All applications that I now of can work with non normalized path (double slashes) when using files. It is only about aesthetics when the values will be displayed to the user.

This comment has been minimized.

@Earnestly

Earnestly Aug 20, 2015

SUS doesn't care (and shouldn't) about the number of forward slashes between pathnames, only a leading // has system specific meaning to SUS, however, it means nothing on Linux and *BSD. OSX might treat // differently.

It would be nicer and more consistent to have no trailing forward slash though, I'm only making this note to point out that code would not have to check.

@Earnestly

Earnestly Aug 20, 2015

SUS doesn't care (and shouldn't) about the number of forward slashes between pathnames, only a leading // has system specific meaning to SUS, however, it means nothing on Linux and *BSD. OSX might treat // differently.

It would be nicer and more consistent to have no trailing forward slash though, I'm only making this note to point out that code would not have to check.

Show outdated Hide outdated src/nvim/version.c
version_msg(USR_VIMRC_FILE3);
version_msg("\"\n");
#endif // ifdef USR_VIMRC_FILE3
version_msg(_(" user vimrc file: $XDG_CONFIG_HOME/nvim/init.vim\n"));

This comment has been minimized.

@ZyX-I

ZyX-I Aug 20, 2015

Contributor

I think that this comment is useless. Previously “* vimrc file” was included because there could be some differences that depend on compile-time options. Now there can’t be any differences, so this sentence is not needed.

@ZyX-I

ZyX-I Aug 20, 2015

Contributor

I think that this comment is useless. Previously “* vimrc file” was included because there could be some differences that depend on compile-time options. Now there can’t be any differences, so this sentence is not needed.

This comment has been minimized.

@jck

jck Aug 20, 2015

Contributor

I thought so too. I'll remove it if no one else has objections.

@jck

jck Aug 20, 2015

Contributor

I thought so too. I'll remove it if no one else has objections.

@@ -2567,7 +2567,7 @@ return {
vi_def=true,
expand=true,
varname='p_vdir',
defaults={if_true={vi=macros('DFLT_VDIR')}}
defaults={if_true={vi=''}}

This comment has been minimized.

@ZyX-I

ZyX-I Aug 20, 2015

Contributor

I see that only viewdir is touched. Are there plans for other options from #78? Especially for &runtimepath.

Don’t forget that for default &runtimepath value you may take code from my pr-3120 branch:

diff --git a/src/nvim/option.c b/src/nvim/option.c
index 9a375c0..f9b8924 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -301,6 +301,148 @@ static char *(p_cot_values[]) = {"menu", "menuone", "longest", "preview",
 # include "option.c.generated.h"
 #endif

+/// Count commas in the given string
+static size_t count_commas(const char *const s, size_t len)
+  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+  size_t ret = 0;
+  for (size_t i = 0; i < len; i++) {
+    if (s[i] == ',') {
+      ret++;
+    }
+  }
+  return ret;
+}
+
+/// Append string with escaped commas
+static char *strcpy_comma_escaped(char *dest, const char *src, const size_t len)
+  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+  size_t shift = 0;
+  for (size_t i = 0; i < len; i++) {
+    if (src[i] == ',') {
+      dest[i + shift++] = '\\';
+    }
+    dest[i + shift] = src[i];
+  }
+  return &dest[len + shift];
+}
+
+/// Set &runtimepath to default value
+static void set_runtimepath_default(void)
+{
+  size_t rtp_size = 0;
+  char *const data_home = vim_getenv("XDG_DATA_HOME");
+  char *const config_home = vim_getenv("XDG_CONFIG_HOME");
+  char *const vimruntime = vim_getenv("VIMRUNTIME");
+  char *const data_dirs = vim_getenv("XDG_DATA_DIRS");
+  char *const config_dirs = vim_getenv("XDG_CONFIG_DIRS");
+#define NVIM_SIZE (sizeof("/nvim") - 1)
+#define SITE_SIZE (sizeof("/site") - 1)
+#define AFTER_SIZE (sizeof("/after") - 1)
+  size_t data_len;
+  size_t config_len;
+  size_t vimruntime_len;
+  if (data_home != NULL) {
+    data_len = strlen(data_home);
+    rtp_size += ((data_len + count_commas(data_home, data_len)
+                  + NVIM_SIZE + SITE_SIZE) * 2 + AFTER_SIZE) + 2;
+  }
+  if (config_home != NULL) {
+    config_len = strlen(config_home);
+    rtp_size += ((config_len + count_commas(config_home, config_len)
+                  + NVIM_SIZE) * 2 + AFTER_SIZE) + 2;
+  }
+  if (vimruntime != NULL) {
+    vimruntime_len = strlen(vimruntime);
+    rtp_size += vimruntime_len + count_commas(vimruntime, vimruntime_len) + 1;
+  }
+#define COMPUTE_COLON_LEN(rtp_size, additional_size, val) \
+  do { \
+    if (val != NULL) { \
+      const void *iter = NULL; \
+      do { \
+        size_t dir_len; \
+        const char *dir; \
+        iter = vim_colon_env_iter(val, iter, &dir, &dir_len); \
+        if (dir != NULL && dir_len > 0) { \
+          rtp_size += ((dir_len + count_commas(dir, dir_len) \
+                        + NVIM_SIZE + additional_size) * 2 \
+                       + AFTER_SIZE) + 2; \
+        } \
+      } while (iter != NULL); \
+    } \
+  } while (0)
+  COMPUTE_COLON_LEN(rtp_size, SITE_SIZE, data_dirs);
+  COMPUTE_COLON_LEN(rtp_size, 0, config_dirs);
+#undef COMPUTE_COLON_LEN
+  if (rtp_size == 0) {
+    return;
+  }
+  // All additions were including comma.
+  rtp_size--;
+  char *const rtp = xmallocz(rtp_size);
+  char *rtp_cur = rtp;
+#define ADD_STRING(tgt, src, len) \
+  tgt = strcpy_comma_escaped(tgt, src, len)
+#define ADD_STATIC_STRING(tgt, src) \
+  do { memmove(tgt, src, sizeof(src) - 1); tgt += sizeof(src) - 1; } while (0)
+#define ADD_COLON_DIRS(tgt, val, suffix, revsuffix) \
+  do { \
+    if (val != NULL) { \
+      const void *iter = NULL; \
+      do { \
+        size_t dir_len; \
+        const char *dir; \
+        iter = vim_colon_env_iter##revsuffix(val, iter, &dir, &dir_len); \
+        if (dir != NULL && dir_len > 0) { \
+          ADD_STRING(rtp_cur, dir, dir_len); \
+          ADD_STATIC_STRING(rtp_cur, "/nvim" suffix ","); \
+        } \
+      } while (iter != NULL); \
+    } \
+  } while (0)
+  if (config_home != NULL) {
+    ADD_STRING(rtp_cur, config_home, config_len);
+    ADD_STATIC_STRING(rtp_cur, "/nvim,");
+  }
+  ADD_COLON_DIRS(rtp_cur, config_dirs, "", );
+  if (data_home != NULL) {
+    ADD_STRING(rtp_cur, data_home, data_len);
+    ADD_STATIC_STRING(rtp_cur, "/nvim/site,");
+  }
+  ADD_COLON_DIRS(rtp_cur, data_dirs, "/site", );
+  if (vimruntime != NULL) {
+    ADD_STRING(rtp_cur, vimruntime, vimruntime_len);
+    *rtp_cur++ = ',';
+  }
+  ADD_COLON_DIRS(rtp_cur, data_dirs, "/site/after", _rev);
+  if (data_home != NULL) {
+    ADD_STRING(rtp_cur, data_home, data_len);
+    ADD_STATIC_STRING(rtp_cur, "/nvim/site/after,");
+  }
+  ADD_COLON_DIRS(rtp_cur, config_dirs, "/after", _rev);
+  if (config_home != NULL) {
+    ADD_STRING(rtp_cur, config_home, config_len);
+    ADD_STATIC_STRING(rtp_cur, "/nvim/after");
+  } else {
+    // Strip trailing comma.
+    rtp[rtp_size] = NUL;
+  }
+#undef ADD_COLON_DIRS
+#undef ADD_STATIC_STRING
+#undef ADD_STRING
+#undef NVIM_SIZE
+#undef SITE_SIZE
+#undef AFTER_SIZE
+  set_string_default("runtimepath", (char_u *)rtp);
+  xfree(data_dirs);
+  xfree(config_dirs);
+  xfree(data_home);
+  xfree(config_home);
+  xfree(vimruntime);
+}
+
 /*
  * Initialize the options, first part.
  *
@@ -437,6 +579,10 @@ void set_init_1(void)
       "system('lpr' . (&printdevice == '' ? '' : ' -P' . &printdevice) . ' ' . v:fname_in) . delete(v:fname_in) + v:shell_error"
       );

+  // Set default for &runtimepath. All necessary expansions are performed in 
+  // this function.
+  set_runtimepath_default();
+
   /*
    * Set all the options (except the terminal options) to their default
    * value.  Also set the global value for local options.
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 7be8a86..e47a63b 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'

, just replace vim_getenv calls.

@ZyX-I

ZyX-I Aug 20, 2015

Contributor

I see that only viewdir is touched. Are there plans for other options from #78? Especially for &runtimepath.

Don’t forget that for default &runtimepath value you may take code from my pr-3120 branch:

diff --git a/src/nvim/option.c b/src/nvim/option.c
index 9a375c0..f9b8924 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -301,6 +301,148 @@ static char *(p_cot_values[]) = {"menu", "menuone", "longest", "preview",
 # include "option.c.generated.h"
 #endif

+/// Count commas in the given string
+static size_t count_commas(const char *const s, size_t len)
+  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+  size_t ret = 0;
+  for (size_t i = 0; i < len; i++) {
+    if (s[i] == ',') {
+      ret++;
+    }
+  }
+  return ret;
+}
+
+/// Append string with escaped commas
+static char *strcpy_comma_escaped(char *dest, const char *src, const size_t len)
+  FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+  size_t shift = 0;
+  for (size_t i = 0; i < len; i++) {
+    if (src[i] == ',') {
+      dest[i + shift++] = '\\';
+    }
+    dest[i + shift] = src[i];
+  }
+  return &dest[len + shift];
+}
+
+/// Set &runtimepath to default value
+static void set_runtimepath_default(void)
+{
+  size_t rtp_size = 0;
+  char *const data_home = vim_getenv("XDG_DATA_HOME");
+  char *const config_home = vim_getenv("XDG_CONFIG_HOME");
+  char *const vimruntime = vim_getenv("VIMRUNTIME");
+  char *const data_dirs = vim_getenv("XDG_DATA_DIRS");
+  char *const config_dirs = vim_getenv("XDG_CONFIG_DIRS");
+#define NVIM_SIZE (sizeof("/nvim") - 1)
+#define SITE_SIZE (sizeof("/site") - 1)
+#define AFTER_SIZE (sizeof("/after") - 1)
+  size_t data_len;
+  size_t config_len;
+  size_t vimruntime_len;
+  if (data_home != NULL) {
+    data_len = strlen(data_home);
+    rtp_size += ((data_len + count_commas(data_home, data_len)
+                  + NVIM_SIZE + SITE_SIZE) * 2 + AFTER_SIZE) + 2;
+  }
+  if (config_home != NULL) {
+    config_len = strlen(config_home);
+    rtp_size += ((config_len + count_commas(config_home, config_len)
+                  + NVIM_SIZE) * 2 + AFTER_SIZE) + 2;
+  }
+  if (vimruntime != NULL) {
+    vimruntime_len = strlen(vimruntime);
+    rtp_size += vimruntime_len + count_commas(vimruntime, vimruntime_len) + 1;
+  }
+#define COMPUTE_COLON_LEN(rtp_size, additional_size, val) \
+  do { \
+    if (val != NULL) { \
+      const void *iter = NULL; \
+      do { \
+        size_t dir_len; \
+        const char *dir; \
+        iter = vim_colon_env_iter(val, iter, &dir, &dir_len); \
+        if (dir != NULL && dir_len > 0) { \
+          rtp_size += ((dir_len + count_commas(dir, dir_len) \
+                        + NVIM_SIZE + additional_size) * 2 \
+                       + AFTER_SIZE) + 2; \
+        } \
+      } while (iter != NULL); \
+    } \
+  } while (0)
+  COMPUTE_COLON_LEN(rtp_size, SITE_SIZE, data_dirs);
+  COMPUTE_COLON_LEN(rtp_size, 0, config_dirs);
+#undef COMPUTE_COLON_LEN
+  if (rtp_size == 0) {
+    return;
+  }
+  // All additions were including comma.
+  rtp_size--;
+  char *const rtp = xmallocz(rtp_size);
+  char *rtp_cur = rtp;
+#define ADD_STRING(tgt, src, len) \
+  tgt = strcpy_comma_escaped(tgt, src, len)
+#define ADD_STATIC_STRING(tgt, src) \
+  do { memmove(tgt, src, sizeof(src) - 1); tgt += sizeof(src) - 1; } while (0)
+#define ADD_COLON_DIRS(tgt, val, suffix, revsuffix) \
+  do { \
+    if (val != NULL) { \
+      const void *iter = NULL; \
+      do { \
+        size_t dir_len; \
+        const char *dir; \
+        iter = vim_colon_env_iter##revsuffix(val, iter, &dir, &dir_len); \
+        if (dir != NULL && dir_len > 0) { \
+          ADD_STRING(rtp_cur, dir, dir_len); \
+          ADD_STATIC_STRING(rtp_cur, "/nvim" suffix ","); \
+        } \
+      } while (iter != NULL); \
+    } \
+  } while (0)
+  if (config_home != NULL) {
+    ADD_STRING(rtp_cur, config_home, config_len);
+    ADD_STATIC_STRING(rtp_cur, "/nvim,");
+  }
+  ADD_COLON_DIRS(rtp_cur, config_dirs, "", );
+  if (data_home != NULL) {
+    ADD_STRING(rtp_cur, data_home, data_len);
+    ADD_STATIC_STRING(rtp_cur, "/nvim/site,");
+  }
+  ADD_COLON_DIRS(rtp_cur, data_dirs, "/site", );
+  if (vimruntime != NULL) {
+    ADD_STRING(rtp_cur, vimruntime, vimruntime_len);
+    *rtp_cur++ = ',';
+  }
+  ADD_COLON_DIRS(rtp_cur, data_dirs, "/site/after", _rev);
+  if (data_home != NULL) {
+    ADD_STRING(rtp_cur, data_home, data_len);
+    ADD_STATIC_STRING(rtp_cur, "/nvim/site/after,");
+  }
+  ADD_COLON_DIRS(rtp_cur, config_dirs, "/after", _rev);
+  if (config_home != NULL) {
+    ADD_STRING(rtp_cur, config_home, config_len);
+    ADD_STATIC_STRING(rtp_cur, "/nvim/after");
+  } else {
+    // Strip trailing comma.
+    rtp[rtp_size] = NUL;
+  }
+#undef ADD_COLON_DIRS
+#undef ADD_STATIC_STRING
+#undef ADD_STRING
+#undef NVIM_SIZE
+#undef SITE_SIZE
+#undef AFTER_SIZE
+  set_string_default("runtimepath", (char_u *)rtp);
+  xfree(data_dirs);
+  xfree(config_dirs);
+  xfree(data_home);
+  xfree(config_home);
+  xfree(vimruntime);
+}
+
 /*
  * Initialize the options, first part.
  *
@@ -437,6 +579,10 @@ void set_init_1(void)
       "system('lpr' . (&printdevice == '' ? '' : ' -P' . &printdevice) . ' ' . v:fname_in) . delete(v:fname_in) + v:shell_error"
       );

+  // Set default for &runtimepath. All necessary expansions are performed in 
+  // this function.
+  set_runtimepath_default();
+
   /*
    * Set all the options (except the terminal options) to their default
    * value.  Also set the global value for local options.
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 7be8a86..e47a63b 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'

, just replace vim_getenv calls.

This comment has been minimized.

@jck

jck Aug 20, 2015

Contributor

Yup, I plan to do all of it. Just want to make sure that everyone else agrees with this approach first.

@jck

jck Aug 20, 2015

Contributor

Yup, I plan to do all of it. Just want to make sure that everyone else agrees with this approach first.

@rainerborene

This comment has been minimized.

Show comment
Hide comment
@rainerborene

rainerborene Aug 21, 2015

Contributor

Make sure to update the man page as well.

Contributor

rainerborene commented Aug 21, 2015

Make sure to update the man page as well.

ret = (const char *)expand_env_save((char_u *)fallback);
}
return ret;

This comment has been minimized.

@splinterofchaos

splinterofchaos Aug 23, 2015

Member

This returns statically allocated memory when os_getenv(env) returns non-null, and heap-allocated memory when it returns null and fallback isn't null. How does the caller know whether the return value requires an xfree()? We could add a parameter, bool *must_free, but it may be simpler to always return allocated memory.

const char *ret = os_getenv(env);
if (ret) {
  ret = xstrdup(ret);
} else if (fallback) {
  // ... same as before
}
@splinterofchaos

splinterofchaos Aug 23, 2015

Member

This returns statically allocated memory when os_getenv(env) returns non-null, and heap-allocated memory when it returns null and fallback isn't null. How does the caller know whether the return value requires an xfree()? We could add a parameter, bool *must_free, but it may be simpler to always return allocated memory.

const char *ret = os_getenv(env);
if (ret) {
  ret = xstrdup(ret);
} else if (fallback) {
  // ... same as before
}

This comment has been minimized.

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

^ This. This should fix the leak ASAN is complainign about.

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

^ This. This should fix the leak ASAN is complainign about.

@justinmk

This comment has been minimized.

Show comment
Hide comment
@justinmk

justinmk Aug 26, 2015

Member

Hoping to get this in 0.1 milestone.

Member

justinmk commented Aug 26, 2015

Hoping to get this in 0.1 milestone.

@justinmk

This comment has been minimized.

Show comment
Hide comment
@justinmk

justinmk Sep 22, 2015

Member

A bit late, but in case it helps, this was mentioned in #78 as a useful reference:

https://github.com/ActiveState/appdirs/blob/master/appdirs.py

Member

justinmk commented Sep 22, 2015

A bit late, but in case it helps, this was mentioned in #78 as a useful reference:

https://github.com/ActiveState/appdirs/blob/master/appdirs.py

@tarruda

This comment has been minimized.

Show comment
Hide comment
@tarruda

tarruda Sep 24, 2015

Member

Will this PR also allow storage of undo and swap files under the cache directory?

Member

tarruda commented Sep 24, 2015

Will this PR also allow storage of undo and swap files under the cache directory?

@justinmk

This comment has been minimized.

Show comment
Hide comment
@justinmk

justinmk Sep 24, 2015

Member

@tarruda Not sure about the exact location, but it would allow us to turn those on by default, which is I think is desirable.

Member

justinmk commented Sep 24, 2015

@tarruda Not sure about the exact location, but it would allow us to turn those on by default, which is I think is desirable.

@tarruda tarruda modified the milestones: 0.2, 0.1-first-public-release Oct 2, 2015

@jck

This comment has been minimized.

Show comment
Hide comment
@jck

jck Oct 2, 2015

Contributor

@justinmk I'll finish this off this weekend. I hope that will be enough for 0.1

Contributor

jck commented Oct 2, 2015

@justinmk I'll finish this off this weekend. I hope that will be enough for 0.1

Show outdated Hide outdated src/nvim/main.c
&& do_source((char_u *)USR_VIMRC_FILE3, TRUE,
DOSO_VIMRC) == FAIL
#endif
if (do_source(user_vimrc, TRUE, DOSO_VIMRC) == FAIL

This comment has been minimized.

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

use true

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

use true

This comment has been minimized.

@jck

jck Oct 7, 2015

Contributor

Most of main.c appears to be using TRUE and FALSE. Should I just fix all of them in a new commit/different PR?

@jck

jck Oct 7, 2015

Contributor

Most of main.c appears to be using TRUE and FALSE. Should I just fix all of them in a new commit/different PR?

This comment has been minimized.

@fmoralesc

fmoralesc Oct 7, 2015

Contributor

No, just change these, the travis build won't pass until you do so. Merely stylistic PRs are not terribly important, and since the linter starts looking for issues in the surrounding lines, they can become quite unwieldy.

@fmoralesc

fmoralesc Oct 7, 2015

Contributor

No, just change these, the travis build won't pass until you do so. Merely stylistic PRs are not terribly important, and since the linter starts looking for issues in the surrounding lines, they can become quite unwieldy.

Show outdated Hide outdated src/nvim/main.c
&& do_source((char_u *)USR_VIMRC_FILE3, TRUE,
DOSO_VIMRC) == FAIL
#endif
if (do_source(user_vimrc, TRUE, DOSO_VIMRC) == FAIL
&& process_env("EXINIT", FALSE) == FAIL

This comment has been minimized.

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

true

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

true

Show outdated Hide outdated src/nvim/main.c
(char_u *)VIMRC_FILE, FALSE) != kEqualFiles
#ifdef USR_VIMRC_FILE2
&& path_full_compare((char_u *)USR_VIMRC_FILE2,
if (path_full_compare(user_vimrc,
(char_u *)VIMRC_FILE, FALSE) != kEqualFiles

This comment has been minimized.

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

false

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

false

const char *get_from_user_data(const char * fname)
{
const char *dir = (const char *)concat_fnames(get_user_data_dir(), fname, true);

This comment has been minimized.

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

clint says this line is too long

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

clint says this line is too long

This comment has been minimized.

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

Also, there is a leak here.

@fmoralesc

fmoralesc Oct 2, 2015

Contributor

Also, there is a leak here.

This comment has been minimized.

@Yamakaky

Yamakaky Oct 2, 2015

Contributor

Speaking of that, is there any static analysis planned ? It could be a nice addition.

@Yamakaky

Yamakaky Oct 2, 2015

Contributor

Speaking of that, is there any static analysis planned ? It could be a nice addition.

This comment has been minimized.

@justinmk

justinmk Oct 2, 2015

Member

We already have static analysis:

https://neovim.io/doc/reports/clang/
https://scan.coverity.com/projects/2227

However coverity has been broken for weeks.

@justinmk

justinmk Oct 2, 2015

Member

We already have static analysis:

https://neovim.io/doc/reports/clang/
https://scan.coverity.com/projects/2227

However coverity has been broken for weeks.

@fmoralesc

This comment has been minimized.

Show comment
Hide comment
@fmoralesc

fmoralesc Oct 3, 2015

Contributor

@justinmk I think this should aim for 0.1. 0.1 will probably cause quite a bunch of people to try out nvim, and I feel it's better to have them put their configuration files in the right place right away.

Contributor

fmoralesc commented Oct 3, 2015

@justinmk I think this should aim for 0.1. 0.1 will probably cause quite a bunch of people to try out nvim, and I feel it's better to have them put their configuration files in the right place right away.

@tarruda tarruda modified the milestones: 0.1-first-public-release, 0.2 Oct 3, 2015

@@ -31,12 +31,6 @@
#ifndef USR_EXRC_FILE
# define USR_EXRC_FILE "~/.exrc"
#endif
#ifndef USR_VIMRC_FILE
# define USR_VIMRC_FILE "~/.nvimrc"

This comment has been minimized.

@tarruda

tarruda Oct 3, 2015

Member

Does this mean that users will be forced to use the new location? Isn't it better to use the old files in case it is not found in the XDG dirs? cc @justinmk

@tarruda

tarruda Oct 3, 2015

Member

Does this mean that users will be forced to use the new location? Isn't it better to use the old files in case it is not found in the XDG dirs? cc @justinmk

This comment has been minimized.

@justinmk

justinmk Oct 3, 2015

Member

In #78 @ZyX-I made the case that there is no reason for us to support both old and new config locations. It bothers me because it means the default location is different on each system (this makes support more difficult, and requires extra setup to share configs across systems using GitHub etc).

I would be less bothered by it if we defaulted to ~/.config on all systems (unix, windows, osx) instead of the terrible ~/Library and %APPDATA% paths. (No one really wants their configs there, do they?)

@justinmk

justinmk Oct 3, 2015

Member

In #78 @ZyX-I made the case that there is no reason for us to support both old and new config locations. It bothers me because it means the default location is different on each system (this makes support more difficult, and requires extra setup to share configs across systems using GitHub etc).

I would be less bothered by it if we defaulted to ~/.config on all systems (unix, windows, osx) instead of the terrible ~/Library and %APPDATA% paths. (No one really wants their configs there, do they?)

This comment has been minimized.

@Earnestly

Earnestly Oct 3, 2015

It's not your place to question it really. These are the standards set forth by the operating systems you target. I'll quote some of Raymond Chen's ironic maxims about his frustration when dealing with software during the MS-DOS to Windows 95 transition:

4. Manuals are a waste of time.
9. Find a rule and break it as blatantly as possible.
19. Second-guess the specification whenever possible.

Please don't keep repeating the same mistakes. As for support, different locations is trivial to deal with, please don't use it as an excuse to do the wrong thing.

12. It is better to be lucky than good.

@tarruda This software is pre-1.0 release (assuming you're following semver), there is no reason to support legacy. Just do the right thing now instead.

@Earnestly

Earnestly Oct 3, 2015

It's not your place to question it really. These are the standards set forth by the operating systems you target. I'll quote some of Raymond Chen's ironic maxims about his frustration when dealing with software during the MS-DOS to Windows 95 transition:

4. Manuals are a waste of time.
9. Find a rule and break it as blatantly as possible.
19. Second-guess the specification whenever possible.

Please don't keep repeating the same mistakes. As for support, different locations is trivial to deal with, please don't use it as an excuse to do the wrong thing.

12. It is better to be lucky than good.

@tarruda This software is pre-1.0 release (assuming you're following semver), there is no reason to support legacy. Just do the right thing now instead.

This comment has been minimized.

@fmoralesc

fmoralesc Oct 3, 2015

Contributor

I'm with @Earnestly (and @ZyX-I) on this one.

@fmoralesc

fmoralesc Oct 3, 2015

Contributor

I'm with @Earnestly (and @ZyX-I) on this one.

This comment has been minimized.

@justinmk

justinmk Oct 3, 2015

Member

@Earnestly Where does the standard specify the default locations for OSX and Windows? So far only source examples like https://github.com/ActiveState/appdirs/blob/master/appdirs.py have been offered, which indicate "best guesses" about default locations, there is no reference to a specification.

@justinmk

justinmk Oct 3, 2015

Member

@Earnestly Where does the standard specify the default locations for OSX and Windows? So far only source examples like https://github.com/ActiveState/appdirs/blob/master/appdirs.py have been offered, which indicate "best guesses" about default locations, there is no reference to a specification.

This comment has been minimized.

@fmoralesc

fmoralesc Oct 8, 2015

Contributor

@kopischke I'm not a OSX user (never really used it, actually), so I was just being conservative ;)

@fmoralesc

fmoralesc Oct 8, 2015

Contributor

@kopischke I'm not a OSX user (never really used it, actually), so I was just being conservative ;)

This comment has been minimized.

@fmoralesc

fmoralesc Oct 8, 2015

Contributor

@justinmk Taking a look at the basedir spec again, most of the XDG_ variables are defined relative to $HOME, which has its equivalent in %UserProfile% under Windows. I guess in that sense using that should be the correct behavior as per the basedir spec. However, XDG_DATA_DIRS and XDG_CONFIG_DIRS are undefined, since they default to paths Windows doesn't have.

http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html

@fmoralesc

fmoralesc Oct 8, 2015

Contributor

@justinmk Taking a look at the basedir spec again, most of the XDG_ variables are defined relative to $HOME, which has its equivalent in %UserProfile% under Windows. I guess in that sense using that should be the correct behavior as per the basedir spec. However, XDG_DATA_DIRS and XDG_CONFIG_DIRS are undefined, since they default to paths Windows doesn't have.

http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html

This comment has been minimized.

@Earnestly

Earnestly Oct 8, 2015

@justinmk Windows is out of scope of XDG Basedir, follow Windows' standards for Windows instead. For example, Vala's Environment.get_user_config_dir() uses CSIDL_LOCAL_APPDATA for Windows.

What you want to do about Windows however is up to you,
thank you for working on this btw. ❤

@Earnestly

Earnestly Oct 8, 2015

@justinmk Windows is out of scope of XDG Basedir, follow Windows' standards for Windows instead. For example, Vala's Environment.get_user_config_dir() uses CSIDL_LOCAL_APPDATA for Windows.

What you want to do about Windows however is up to you,
thank you for working on this btw. ❤

This comment has been minimized.

@kopischke

kopischke Oct 10, 2015

@fmoralesc nothing wrong with that, especially as OS X’ “almost, but not quite, Unix” system does need special treatment in many areas. The XDG spec as applied to CLI applications is not one of them, however, so let’s count our blessings and limit special treatment to The Odd Man Out™, aka Windows :).

@kopischke

kopischke Oct 10, 2015

@fmoralesc nothing wrong with that, especially as OS X’ “almost, but not quite, Unix” system does need special treatment in many areas. The XDG spec as applied to CLI applications is not one of them, however, so let’s count our blessings and limit special treatment to The Odd Man Out™, aka Windows :).

This comment has been minimized.

@fmoralesc

fmoralesc Oct 10, 2015

Contributor

@kopischke 👍

@fmoralesc
@fmoralesc

This comment has been minimized.

Show comment
Hide comment
@fmoralesc

fmoralesc Oct 3, 2015

Contributor

I was just trying out the PR locally, and it seems to me like it still needs to handle 'runtimepath', 'undodir, etc. Also, it would be good to show the new place for the user initialization file in the output of :version. There isn't a way to query this value as far as I can tell.

Contributor

fmoralesc commented Oct 3, 2015

I was just trying out the PR locally, and it seems to me like it still needs to handle 'runtimepath', 'undodir, etc. Also, it would be good to show the new place for the user initialization file in the output of :version. There isn't a way to query this value as far as I can tell.

@ZyX-I

This comment has been minimized.

Show comment
Hide comment
@ZyX-I

ZyX-I Oct 3, 2015

Contributor

@fmoralesc Initialization file location should be stored in $MYVIMRC environment variable. If this is not true with this PR then it needs fixing.

Contributor

ZyX-I commented Oct 3, 2015

@fmoralesc Initialization file location should be stored in $MYVIMRC environment variable. If this is not true with this PR then it needs fixing.

@fmoralesc

This comment has been minimized.

Show comment
Hide comment
@fmoralesc

fmoralesc Oct 3, 2015

Contributor

@ZyX-I No, it's OK in this PR, I just missed it (I think I tried it, but I must have made a typo so I didn't see it). Still, I opened a PR in @jck's repo to add it to the output of :version.

Contributor

fmoralesc commented Oct 3, 2015

@ZyX-I No, it's OK in this PR, I just missed it (I think I tried it, but I must have made a typo so I didn't see it). Still, I opened a PR in @jck's repo to add it to the output of :version.

ga_init(&rtp_ga, (int)sizeof(const char *), 1);
GA_APPEND(const char *, &rtp_ga, get_user_conf_dir());
GA_APPEND(const char *, &rtp_ga, concat_fnames(get_user_conf_dir(), "after", true));
set_string_default("runtimepath", ga_concat_strings(&rtp_ga));

This comment has been minimized.

@splinterofchaos

splinterofchaos Oct 7, 2015

Member

The memory allocated by concat_fnames must be xfreed. Doesn't look like we gain much by using garray_T here. sprintf() (or the custom vim variant) might be more appropriate.

@splinterofchaos

splinterofchaos Oct 7, 2015

Member

The memory allocated by concat_fnames must be xfreed. Doesn't look like we gain much by using garray_T here. sprintf() (or the custom vim variant) might be more appropriate.

This comment has been minimized.

@jck

jck Oct 7, 2015

Contributor

Would you suggest that I precomute the length of the rtp string like this?
ZyX-I@b4331ac

@jck

jck Oct 7, 2015

Contributor

Would you suggest that I precomute the length of the rtp string like this?
ZyX-I@b4331ac

This comment has been minimized.

@splinterofchaos

splinterofchaos Oct 9, 2015

Member

The safest bet for allocating path names is just xmalloc(PATH_MAX). If you care about over-allocated memory, you can xrealloc(rtp strlen(rtp) + 1) later, but it's not necessary.

I just realized another issue: It looks like the resulting string will be "{get_user_conf_dir()}{get_user_conf_dir()}/after". Could just do this:

char* conf_dir = get_user_conf_dir();
set_string_default("runtimepath", concat_fnames(conf_dir, "after", true);
xfree(conf_dir);
@splinterofchaos

splinterofchaos Oct 9, 2015

Member

The safest bet for allocating path names is just xmalloc(PATH_MAX). If you care about over-allocated memory, you can xrealloc(rtp strlen(rtp) + 1) later, but it's not necessary.

I just realized another issue: It looks like the resulting string will be "{get_user_conf_dir()}{get_user_conf_dir()}/after". Could just do this:

char* conf_dir = get_user_conf_dir();
set_string_default("runtimepath", concat_fnames(conf_dir, "after", true);
xfree(conf_dir);

This comment has been minimized.

@Earnestly

Earnestly Oct 9, 2015

Relying on PATH_MAX is extremely silly and not a very well researched suggestion. Consider the implications of what you're suggesting on a portability level. No, correct handling of paths involve using calloc and snprintf. (I assume xmalloc is just a wrapper around malloc that provides overflow checking like calloc but without the guarantee of zero initialised memory.)

@Earnestly

Earnestly Oct 9, 2015

Relying on PATH_MAX is extremely silly and not a very well researched suggestion. Consider the implications of what you're suggesting on a portability level. No, correct handling of paths involve using calloc and snprintf. (I assume xmalloc is just a wrapper around malloc that provides overflow checking like calloc but without the guarantee of zero initialised memory.)

This comment has been minimized.

@splinterofchaos

splinterofchaos Oct 10, 2015

Member

Unfortunately (I guess), we have a lot of code that check paths are less than the maximum, so this convention wouldn't be easy to remove from the codebase, even if it's wrong. For the moment, I think it would be correct to just say "we don't support unreasonably large paths," and if supporting them means unleashing such inefficient code such as in the linked article, I don't see any benefit.

Also, I double checked: I should have said MAXPATHL, an os-independent variable that we define.

@splinterofchaos

splinterofchaos Oct 10, 2015

Member

Unfortunately (I guess), we have a lot of code that check paths are less than the maximum, so this convention wouldn't be easy to remove from the codebase, even if it's wrong. For the moment, I think it would be correct to just say "we don't support unreasonably large paths," and if supporting them means unleashing such inefficient code such as in the linked article, I don't see any benefit.

Also, I double checked: I should have said MAXPATHL, an os-independent variable that we define.

This comment has been minimized.

@ZyX-I

ZyX-I Oct 11, 2015

Contributor

@splinterofchaos Why not simply use my code with minimal modifications (to use different functions to get XDG_* variables)? I see that this variant uses only XDG_CONFIG_HOME which is not enough.

@ZyX-I

ZyX-I Oct 11, 2015

Contributor

@splinterofchaos Why not simply use my code with minimal modifications (to use different functions to get XDG_* variables)? I see that this variant uses only XDG_CONFIG_HOME which is not enough.

This comment has been minimized.

@ZyX-I

ZyX-I Oct 11, 2015

Contributor

(Note: do not use the commit you referenced, use the head of pr-3120 branch.)

@ZyX-I

ZyX-I Oct 11, 2015

Contributor

(Note: do not use the commit you referenced, use the head of pr-3120 branch.)

This comment has been minimized.

@Earnestly

Earnestly Oct 11, 2015

@ZyX-I “53. So many good ideas are never heard from again once they embark in a voyage on the semantic gulf.” — Alan J. Perlis

@Earnestly

Earnestly Oct 11, 2015

@ZyX-I “53. So many good ideas are never heard from again once they embark in a voyage on the semantic gulf.” — Alan J. Perlis

@fmoralesc

This comment has been minimized.

Show comment
Hide comment
@fmoralesc

fmoralesc Oct 8, 2015

Contributor

'runtimepath' needs to include the system runtime path.

Contributor

fmoralesc commented Oct 8, 2015

'runtimepath' needs to include the system runtime path.

@ZyX-I

This comment has been minimized.

Show comment
Hide comment
@ZyX-I

ZyX-I Oct 17, 2015

Contributor

@fmoralesc My variant includes system runtime path.

BTW, after #2506 is merged this PR needs rebasing or you will not be able to move shada file to XDG-compatible location. I have updated #78 to reflect changes (for some reason that issue did not talk about viminfo though).

Contributor

ZyX-I commented Oct 17, 2015

@fmoralesc My variant includes system runtime path.

BTW, after #2506 is merged this PR needs rebasing or you will not be able to move shada file to XDG-compatible location. I have updated #78 to reflect changes (for some reason that issue did not talk about viminfo though).

@fmoralesc

This comment has been minimized.

Show comment
Hide comment
@fmoralesc

fmoralesc Oct 17, 2015

Contributor

@ZyX-I Yes, I just pointed it out because the current version didn't. I hope @jck picks this up again, otherwise could you take over?

Contributor

fmoralesc commented Oct 17, 2015

@ZyX-I Yes, I just pointed it out because the current version didn't. I hope @jck picks this up again, otherwise could you take over?

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Oct 17, 2015

Closing in favor of #3470, but if I missed something please reopen.

ghost commented Oct 17, 2015

Closing in favor of #3470, but if I missed something please reopen.

@ghost ghost closed this Oct 17, 2015

@jszakmeister jszakmeister removed the WIP label Oct 17, 2015

This issue was closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment