diff options
Diffstat (limited to 'src/nvim/os')
-rw-r--r-- | src/nvim/os/env.c | 35 | ||||
-rw-r--r-- | src/nvim/os/fs.c | 21 | ||||
-rw-r--r-- | src/nvim/os/input.c | 2 | ||||
-rw-r--r-- | src/nvim/os/lang.c | 2 | ||||
-rw-r--r-- | src/nvim/os/shell.c | 48 | ||||
-rw-r--r-- | src/nvim/os/time.c | 4 |
6 files changed, 92 insertions, 20 deletions
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index 0df857352b..2f90d0bc9e 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -196,16 +196,19 @@ void init_homedir(void) const char *homedrive = os_getenv("HOMEDRIVE"); const char *homepath = os_getenv("HOMEPATH"); if (homepath == NULL) { - homepath = "\\"; + homepath = "\\"; } - if (homedrive != NULL && strlen(homedrive) + strlen(homepath) < MAXPATHL) { + if (homedrive != NULL + && strlen(homedrive) + strlen(homepath) < MAXPATHL) { snprintf(os_buf, MAXPATHL, "%s%s", homedrive, homepath); if (os_buf[0] != NUL) { var = os_buf; - vim_setenv("HOME", os_buf); } } } + if (var == NULL) { + var = os_getenv("USERPROFILE"); + } #endif if (var != NULL) { @@ -454,12 +457,15 @@ void expand_env_esc(char_u *restrict srcp, } else if ((src[0] == ' ' || src[0] == ',') && !one) { at_start = true; } - *dst++ = *src++; - --dstlen; + if (dstlen > 0) { + *dst++ = *src++; + dstlen--; - if (prefix != NULL && src - prefix_len >= srcp - && STRNCMP(src - prefix_len, prefix, prefix_len) == 0) { - at_start = true; + if (prefix != NULL + && src - prefix_len >= srcp + && STRNCMP(src - prefix_len, prefix, prefix_len) == 0) { + at_start = true; + } } } } @@ -608,6 +614,12 @@ char *vim_getenv(const char *name) return xstrdup(kos_env_path); } +#ifdef WIN32 + if (strcmp(name, "HOME") == 0) { + return xstrdup(homedir); + } +#endif + bool vimruntime = (strcmp(name, "VIMRUNTIME") == 0); if (!vimruntime && strcmp(name, "VIM") != 0) { return NULL; @@ -758,7 +770,12 @@ size_t home_replace(const buf_T *const buf, const char_u *src, dirlen = strlen(homedir); } - const char *const homedir_env = os_getenv("HOME"); + const char *homedir_env = os_getenv("HOME"); +#ifdef WIN32 + if (homedir_env == NULL) { + homedir_env = os_getenv("USERPROFILE"); + } +#endif char *homedir_env_mod = (char *)homedir_env; bool must_free = false; diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index cf00fd4f82..9a4391a0ae 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -110,7 +110,7 @@ bool os_isrealdir(const char *name) /// Check if the given path is a directory or not. /// -/// @return `true` if `fname` is a directory. +/// @return `true` if `name` is a directory. bool os_isdir(const char_u *name) FUNC_ATTR_NONNULL_ALL { @@ -126,6 +126,25 @@ bool os_isdir(const char_u *name) return true; } +/// Check if the given path is a directory and is executable. +/// Gives the same results as `os_isdir()` on Windows. +/// +/// @return `true` if `name` is a directory and executable. +bool os_isdir_executable(const char *name) + FUNC_ATTR_NONNULL_ALL +{ + int32_t mode = os_getperm((const char *)name); + if (mode < 0) { + return false; + } + +#ifdef WIN32 + return (S_ISDIR(mode)); +#else + return (S_ISDIR(mode) && (S_IXUSR & mode)); +#endif +} + /// Check what `name` is: /// @return NODE_NORMAL: file or directory (or doesn't exist) /// NODE_WRITABLE: writable device, socket, fifo, etc. diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index 599487c345..f62253cbce 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -351,6 +351,8 @@ static bool input_poll(int ms) blocking = true; multiqueue_process_events(ch_before_blocking_events); } + DLOG("blocking... events_enabled=%d events_pending=%d", events_enabled, + !multiqueue_empty(main_loop.events)); LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, ms, input_ready() || input_eof); blocking = false; diff --git a/src/nvim/os/lang.c b/src/nvim/os/lang.c index 47c278ee97..6b2a54ddbe 100644 --- a/src/nvim/os/lang.c +++ b/src/nvim/os/lang.c @@ -31,7 +31,7 @@ void lang_init(void) char buf[20] = { 0 }; if (CFStringGetCString(cf_lang_region, buf, 20, kCFStringEncodingUTF8)) { - os_setenv("LANG", lang_region, true); + os_setenv("LANG", buf, true); } } CFRelease(cf_lang_region); diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 04f59d7522..19d199f4d5 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -80,27 +80,61 @@ char **shell_build_argv(const char *cmd, const char *extra_args) void shell_free_argv(char **argv) { char **p = argv; - if (p == NULL) { // Nothing was allocated, return return; } - while (*p != NULL) { // Free each argument xfree(*p); p++; } - xfree(argv); } +/// Joins shell arguments from `argv` into a new string. +/// If the result is too long it is truncated with ellipsis ("..."). +/// +/// @returns[allocated] `argv` joined to a string. +char *shell_argv_to_str(char **const argv) + FUNC_ATTR_NONNULL_ALL +{ + size_t n = 0; + char **p = argv; + char *rv = xcalloc(256, sizeof(*rv)); + const size_t maxsize = (256 * sizeof(*rv)); + if (*p == NULL) { + return rv; + } + while (*p != NULL) { + xstrlcat(rv, "'", maxsize); + xstrlcat(rv, *p, maxsize); + n = xstrlcat(rv, "' ", maxsize); + if (n >= maxsize) { + break; + } + p++; + } + if (n < maxsize) { + rv[n - 1] = '\0'; + } else { + // Command too long, show ellipsis: "/bin/bash 'foo' 'bar'..." + rv[maxsize - 4] = '.'; + rv[maxsize - 3] = '.'; + rv[maxsize - 2] = '.'; + rv[maxsize - 1] = '\0'; + } + return rv; +} + /// Calls the user-configured 'shell' (p_sh) for running a command or wildcard /// expansion. /// /// @param cmd The command to execute, or NULL to run an interactive shell. /// @param opts Options that control how the shell will work. /// @param extra_args Extra arguments to the shell, or NULL. +/// +/// @return shell command exit code int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) { DynamicBuffer input = DYNAMIC_BUFFER_INIT; @@ -450,8 +484,8 @@ static void out_data_ring(char *output, size_t size) /// @param output Data to append to screen lines. /// @param remaining Size of data. /// @param new_line If true, next data output will be on a new line. -static void out_data_append_to_screen(char *output, size_t *count, - bool eof) +static void out_data_append_to_screen(char *output, size_t *count, bool eof) + FUNC_ATTR_NONNULL_ALL { char *p = output, *end = output + *count; while (p < end) { @@ -466,7 +500,7 @@ static void out_data_append_to_screen(char *output, size_t *count, // incomplete UTF-8 sequence that could be composing with the last // complete sequence. // This will be corrected when we switch to vterm based implementation - int i = *p ? mb_ptr2len_len((char_u *)p, (int)(end-p)) : 1; + int i = *p ? utfc_ptr2len_len((char_u *)p, (int)(end-p)) : 1; if (!eof && i == 1 && utf8len_tab_zero[*(uint8_t *)p] > (end-p)) { *count = (size_t)(p - output); goto end; @@ -491,7 +525,7 @@ static void out_data_cb(Stream *stream, RBuffer *buf, size_t count, void *data, && out_data_decide_throttle(cnt)) { // Skip output above a threshold. // Save the skipped output. If it is the final chunk, we display it later. out_data_ring(ptr, cnt); - } else { + } else if (ptr != NULL) { out_data_append_to_screen(ptr, &cnt, eof); } diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c index 290d421acc..31ef1a0cd6 100644 --- a/src/nvim/os/time.c +++ b/src/nvim/os/time.c @@ -114,12 +114,12 @@ struct tm *os_localtime_r(const time_t *restrict clock, #endif } -/// Obtains the current Unix timestamp and adjusts it to local time. +/// Gets the current Unix timestamp and adjusts it to local time. /// /// @param result Pointer to a 'struct tm' where the result should be placed /// @return A pointer to a 'struct tm' in the current time zone (the 'result' /// argument) or NULL in case of error -struct tm *os_get_localtime(struct tm *result) FUNC_ATTR_NONNULL_ALL +struct tm *os_localtime(struct tm *result) FUNC_ATTR_NONNULL_ALL { time_t rawtime = time(NULL); return os_localtime_r(&rawtime, result); |