diff options
author | pommicket <pommicket@gmail.com> | 2022-12-24 00:28:50 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-12-24 00:28:50 -0500 |
commit | 1c346f2aba30fcb581f20f2b67bd5e6adcb4a7e6 (patch) | |
tree | 863b8ebbd37c67cb4dd0015d5c72a436dd89bc7e /config.c | |
parent | 8d96a4b0f0ebb059a63cc4c3193e0169ccf4f5b5 (diff) |
find build directory in a much better way
this will be useful for LSPs
Diffstat (limited to 'config.c')
-rw-r--r-- | config.c | 67 |
1 files changed, 67 insertions, 0 deletions
@@ -274,6 +274,7 @@ static OptionString const options_string[] = { {"build-default-command", options_zero.build_default_command, sizeof options_zero.build_default_command, true}, {"bg-shader", options_zero.bg_shader_text, sizeof options_zero.bg_shader_text, true}, {"bg-texture", options_zero.bg_shader_image, sizeof options_zero.bg_shader_image, true}, + {"root-identifiers", options_zero.root_identifiers, sizeof options_zero.root_identifiers, true}, }; static void option_bool_set(Settings *settings, const OptionBool *opt, bool value) { @@ -993,3 +994,69 @@ void config_free(Ted *ted) { ted->nstrings = 0; ted->default_settings = NULL; } + + +static char *last_separator(char *path) { + for (int i = (int)strlen(path) - 1; i >= 0; --i) + if (strchr(ALL_PATH_SEPARATORS, path[i])) + return &path[i]; + return NULL; +} + +// returns the best guess for the root directory of the project containing `path` (which should be an absolute path) +// the return value should be freed. +char *settings_get_root_dir(Settings *settings, const char *path) { + char best_path[TED_PATH_MAX]; + *best_path = '\0'; + u32 best_path_score = 0; + char pathbuf[TED_PATH_MAX]; + strbuf_cpy(pathbuf, path); + + while (1) { + FsDirectoryEntry **entries = fs_list_directory(pathbuf); + if (entries) { // note: this may actually be NULL on the first iteration if `path` is a file + for (int e = 0; entries[e]; ++e) { + const char *entry_name = entries[e]->name; + const char *ident_name = settings->root_identifiers; + while (*ident_name) { + const char *separators = ", \t\n\r\v"; + size_t ident_len = strcspn(ident_name, separators); + if (strlen(entry_name) == ident_len && strncmp(entry_name, ident_name, ident_len) == 0) { + // we found an identifier! + u32 score = U32_MAX - (u32)(ident_name - settings->root_identifiers); + if (score > best_path_score) { + best_path_score = score; + strbuf_cpy(best_path, pathbuf); + } + } + ident_name += ident_len; + ident_name += strspn(ident_name, separators); + } + } + fs_dir_entries_free(entries); + } + + char *p = last_separator(pathbuf); + if (!p) + break; + *p = '\0'; + if (!last_separator(pathbuf)) + break; // we made it all the way to / (or c:\ or whatever) + } + + if (*best_path) { + return str_dup(best_path); + } else { + // didn't find any identifiers. + // just return + // - `path` if it's a directory + // - the directory containing path if it's a file + if (fs_path_type(path) == FS_DIRECTORY) { + return str_dup(path); + } + strbuf_cpy(pathbuf, path); + char *sep = last_separator(pathbuf); + *sep = '\0'; + return str_dup(pathbuf); + } +} |