From aba45a64364457f20e84de4189500f4426e11d53 Mon Sep 17 00:00:00 2001 From: David Moc Date: Wed, 3 Jun 2026 04:14:59 +0200 Subject: Added ffap and fixed an eval memory leak --- src/path.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) (limited to 'src/path.c') diff --git a/src/path.c b/src/path.c index be2b347..930fbb7 100644 --- a/src/path.c +++ b/src/path.c @@ -114,6 +114,92 @@ char *ecex_path_normalize(const char *path) { return joined; } +static int ecex_project_root_has_marker(const char *dir) { + static const char *const markers[] = { + ".git", + "compile_commands.json", + "compile_flags.txt", + ".ecex-project", + }; + + for (size_t i = 0; i < sizeof(markers) / sizeof(markers[0]); i++) { + char *path = ecex_path_join(dir, markers[i]); + if (!path) continue; + int found = ecex_path_exists(path); + free(path); + if (found) return 1; + } + + return 0; +} + +static char *ecex_path_parent_dup(const char *path) { + if (!path || !path[0]) return NULL; + + char *parent = ecex_strdup(path); + if (!parent) return NULL; + + size_t len = strlen(parent); + while (len > 1 && parent[len - 1] == '/') parent[--len] = '\0'; + if (strcmp(parent, "/") == 0) return parent; + + char *slash = strrchr(parent, '/'); + if (!slash) { + free(parent); + return NULL; + } + + if (slash == parent) parent[1] = '\0'; + else *slash = '\0'; + return parent; +} + +char *ecex_project_root_for_file(const char *path) { + char *start = NULL; + + if (path && path[0]) { + if (ecex_path_is_dir(path)) { + start = ecex_path_normalize(path); + } else { + char *dir = ecex_path_dirname(path); + if (dir) { + start = ecex_path_normalize(dir); + free(dir); + } + } + } else { + char cwd[4096]; + if (ecex_path_cwd(cwd, sizeof(cwd)) == 0) start = ecex_path_normalize(cwd); + } + + if (!start) return NULL; + char *fallback = ecex_strdup(start); + if (!fallback) { + free(start); + return NULL; + } + + char *dir = start; + while (dir && dir[0]) { + if (ecex_project_root_has_marker(dir)) { + free(fallback); + return dir; + } + + char *parent = ecex_path_parent_dup(dir); + if (!parent || strcmp(parent, dir) == 0) { + free(parent); + break; + } + + free(dir); + dir = parent; + } + + free(dir); + return fallback; +} + int ecex_path_exists(const char *path) { if (!path) return 0; char *expanded = ecex_path_expand_user(path); -- cgit v1.2.3