summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-01-24 12:39:45 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2021-01-24 12:39:45 -0500
commit33b951f3b5d89c0ba7e7c7d821a9eafb37088872 (patch)
treea5de2f26fe044f44f5b39fae9adac51395dae893
parent68b77c7a1cde7344702cf1d162e0124498a6b616 (diff)
auto-cd: check if actually directory, ~
-rw-r--r--main.c7
-rw-r--r--ted-base.c10
-rw-r--r--ted.h13
-rw-r--r--ui.c70
4 files changed, 70 insertions, 30 deletions
diff --git a/main.c b/main.c
index f04f984..ca8c991 100644
--- a/main.c
+++ b/main.c
@@ -95,8 +95,15 @@ int main(int argc, char **argv) {
strbuf_printf(ted_local_data_dir, "%ls" PATH_SEPARATOR_STR "ted", appdata);
CoTaskMemFree(appdata);
}
+ id = FOLDERID_Profile;
+ wchar_t *home = NULL;
+ if (SHGetKnownFolderPath(&id, 0, NULL, &home) == S_OK) {
+ strbuf_printf(ted_home, "%ls", home);
+ CoTaskMemFree(home);
+ }
#else
char *home = getenv("HOME");
+ strbuf_printf(ted_home, "%s", home);
strbuf_printf(ted_local_data_dir, "%s/.local/share/ted", home);
#endif
}
diff --git a/ted-base.c b/ted-base.c
index d8acf0c..80d14e3 100644
--- a/ted-base.c
+++ b/ted-base.c
@@ -38,16 +38,6 @@ static void *ted_realloc(Ted *ted, void *p, size_t new_size) {
return ret;
}
-// should the working directory be searched for files? set to true if the executable isn't "installed"
-static bool ted_search_cwd = false;
-static char const ted_global_data_dir[] =
-#if _WIN32
- "C:\\Program Files\\ted";
-#else
- "/usr/share/ted";
-#endif
-static char ted_local_data_dir[TED_PATH_MAX]; // filled out in main()
-
// Check the various places a file could be, and return the full path.
static Status ted_get_file(char const *name, char *out, size_t outsz) {
if (ted_search_cwd && fs_file_exists(name)) {
diff --git a/ted.h b/ted.h
index d33c460..077d32d 100644
--- a/ted.h
+++ b/ted.h
@@ -114,3 +114,16 @@ typedef struct Ted {
char cwd[TED_PATH_MAX]; // current working directory
char error[256];
} Ted;
+
+// should the working directory be searched for files? set to true if the executable isn't "installed"
+static bool ted_search_cwd = false;
+static char const ted_global_data_dir[] =
+#if _WIN32
+ "C:\\Program Files\\ted";
+#else
+ "/usr/share/ted";
+#endif
+
+// filled out in main()
+static char ted_local_data_dir[TED_PATH_MAX];
+static char ted_home[TED_PATH_MAX]; // home directory -- this is what ~ expands to
diff --git a/ui.c b/ui.c
index 1e6702c..87f2175 100644
--- a/ui.c
+++ b/ui.c
@@ -46,15 +46,25 @@ static int qsort_file_entry_cmp(void const *av, void const *bv) {
return strcmp_case_insensitive(a->name, b->name);
}
-static void file_selector_cd_(FileSelector *fs, char const *path, int symlink_depth);
+static Status file_selector_cd_(FileSelector *fs, char const *path, int symlink_depth);
// cd to the directory `name`. `name` cannot include any path separators.
-static void file_selector_cd1(FileSelector *fs, char const *name, size_t name_len, int symlink_depth) {
+static Status file_selector_cd1(FileSelector *fs, char const *name, size_t name_len, int symlink_depth) {
char *const cwd = fs->cwd;
if (name_len == 0 || (name_len == 1 && name[0] == '.')) {
// no name, or .
- return;
+ return true;
+ }
+
+ if (name_len == 1 && name[0] == '~') {
+ // just in case the user's HOME happens to be accidentally set to, e.g. '/foo/~', make
+ // sure we don't recurse infinitely
+ if (symlink_depth < 32) {
+ return file_selector_cd_(fs, ted_home, symlink_depth + 1);
+ } else {
+ return false;
+ }
}
if (name_len == 2 && name[0] == '.' && name[1] == '.') {
@@ -72,37 +82,46 @@ static void file_selector_cd1(FileSelector *fs, char const *name, size_t name_le
}
}
} else {
- #if __unix__
- if (symlink_depth < 32) { // on my system, MAXSYMLINKS is 20, so this should be plenty
- char path[TED_PATH_MAX], link_to[TED_PATH_MAX];
- // join fs->cwd with name to get full path
- str_printf(path, TED_PATH_MAX, "%s%s%*s", cwd,
+ char path[TED_PATH_MAX];
+ // join fs->cwd with name to get full path
+ str_printf(path, TED_PATH_MAX, "%s%s%*s", cwd,
cwd[strlen(cwd) - 1] == PATH_SEPARATOR ?
"" : PATH_SEPARATOR_STR,
(int)name_len, name);
+ if (fs_path_type(path) != FS_DIRECTORY) {
+ // trying to cd to something that's not a directory!
+ return false;
+ }
+
+ #if __unix__
+ if (symlink_depth < 32) { // on my system, MAXSYMLINKS is 20, so this should be plenty
+ char link_to[TED_PATH_MAX];
ssize_t bytes = readlink(path, link_to, sizeof link_to);
if (bytes != -1) {
// this is a symlink
link_to[bytes] = '\0';
- file_selector_cd_(fs, link_to, symlink_depth + 1);
- return;
+ return file_selector_cd_(fs, link_to, symlink_depth + 1);
}
+ } else {
+ return false;
}
#else
(void)symlink_depth;
#endif
+
// add path separator to end if not already there (which could happen in the case of /)
if (cwd[strlen(cwd) - 1] != PATH_SEPARATOR)
str_cat(cwd, sizeof fs->cwd, PATH_SEPARATOR_STR);
// add name itself
strn_cat(cwd, sizeof fs->cwd, name, name_len);
}
+ return true;
}
-static void file_selector_cd_(FileSelector *fs, char const *path, int symlink_depth) {
+static Status file_selector_cd_(FileSelector *fs, char const *path, int symlink_depth) {
char *const cwd = fs->cwd;
- if (path[0] == '\0') return;
+ if (path[0] == '\0') return true;
if (path[0] == PATH_SEPARATOR
#if _WIN32
@@ -128,16 +147,19 @@ static void file_selector_cd_(FileSelector *fs, char const *path, int symlink_de
while (*p) {
size_t len = strcspn(p, PATH_SEPARATOR_STR);
- file_selector_cd1(fs, p, len, symlink_depth);
+ if (!file_selector_cd1(fs, p, len, symlink_depth))
+ return false;
p += len;
p += strspn(p, PATH_SEPARATOR_STR);
}
+ return true;
}
// go to the directory `path`. make sure `path` only contains path separators like PATH_SEPARATOR, not any
// other members of ALL_PATH_SEPARATORS
-static void file_selector_cd(FileSelector *fs, char const *path) {
- file_selector_cd_(fs, path, 0);
+// returns false if this path doesn't exist or isn't a directory
+static bool file_selector_cd(FileSelector *fs, char const *path) {
+ return file_selector_cd_(fs, path, 0);
}
// returns the name of the selected file, or NULL
@@ -154,11 +176,14 @@ static char *file_selector_update(Ted *ted, FileSelector *fs) {
// check if the search term contains a path separator. if so, cd to the dirname.
- u32 last_path_sep = U32_MAX;
+ u32 first_path_sep = U32_MAX, last_path_sep = U32_MAX;
for (u32 i = 0; i < search_term32.len; ++i) {
char32_t c = search_term32.str[i];
- if (c < CHAR_MAX && strchr(ALL_PATH_SEPARATORS, (char)c))
+ if (c < CHAR_MAX && strchr(ALL_PATH_SEPARATORS, (char)c)) {
last_path_sep = i;
+ if (first_path_sep == U32_MAX)
+ first_path_sep = i;
+ }
}
if (last_path_sep != U32_MAX) {
@@ -171,9 +196,14 @@ static char *file_selector_update(Ted *ted, FileSelector *fs) {
if (strchr(ALL_PATH_SEPARATORS, *p))
*p = PATH_SEPARATOR;
- file_selector_cd(fs, dir_name);
- buffer_delete_chars_at_pos(line_buffer, buffer_start_of_file(line_buffer), last_path_sep + 1); // delete up to and including the last path separator
- buffer_clear_undo_redo(line_buffer);
+ if (file_selector_cd(fs, dir_name)) {
+ buffer_delete_chars_at_pos(line_buffer, buffer_start_of_file(line_buffer), last_path_sep + 1); // delete up to and including the last path separator
+ buffer_clear_undo_redo(line_buffer);
+ } else {
+ BufferPos pos = {.line = 0, .index = first_path_sep};
+ size_t nchars = search_term32.len - first_path_sep;
+ buffer_delete_chars_at_pos(line_buffer, pos, (i64)nchars);
+ }
}
}