aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/os
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/os')
-rw-r--r--src/nvim/os/env.c35
-rw-r--r--src/nvim/os/fs.c21
-rw-r--r--src/nvim/os/input.c2
-rw-r--r--src/nvim/os/lang.c2
-rw-r--r--src/nvim/os/shell.c48
-rw-r--r--src/nvim/os/time.c4
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);