From 94c2b5a926cd7273272fb9fe268dd61c50426c59 Mon Sep 17 00:00:00 2001 From: pommicket Date: Thu, 19 Oct 2023 11:14:39 -0400 Subject: local .ted.cfg --- README.md | 7 ++++++- config.c | 30 ++++++++++++++++++++++++++++-- main.c | 2 -- ted.c | 16 ++++++++++++---- ted.cfg | 4 ++-- test/editorconfig/.ted.cfg | 5 +++++ test/editorconfig/subdir/.ted.cfg | 5 +++++ util.c | 4 ++++ util.h | 2 ++ 9 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 test/editorconfig/.ted.cfg create mode 100644 test/editorconfig/subdir/.ted.cfg diff --git a/README.md b/README.md index e6379ab..3d32f41 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ You can also include files with `%include` (note: the included file must start w By default ted's settings will automatically update when you save the config file. The `core` section's settings should be pretty familiar (font size, etc.) or should have comments on the previous line -explaining what they do. +explaining what they do. `yes`, `on`, and `true` are all synonyms, as are `no`, `off`, and `false`. Keyboard shortcuts are of the form `key combo = action`, where `action` is an argument (number or string), followed by a command. The commands match the things in the command palette (Ctrl+Shift+p), but `:` is added to the beginning to make @@ -110,6 +110,11 @@ tab-width = 17 tab-width = 9 ``` +or put a file called `.ted.cfg` in any directory to have settings apply to files in that directory. + +ted reads [.editorconfig](https://editorconfig.org) files automatically. you can override them by putting `.ted.cfg` +with the settings you want in the same directory. + To reset your ted configuration to the default settings, delete your ted.cfg file (`~/.local/share/ted/ted.cfg` on Linux, `C:\Users\\AppData\Local\ted\ted.cfg` on Windows) or move it somewhere else. diff --git a/config.c b/config.c index abb6e34..1da3dec 100644 --- a/config.c +++ b/config.c @@ -967,8 +967,14 @@ static void config_compile_regex(Config *cfg, ConfigReader *reader) { } } +static bool regex_char_needs_escaping(char c) { + return strchr("\\^.$|()[]*+?{}-", c); +} + static void config_read_ted_cfg(Ted *ted, RcStr *cfg_path_rc, const char ***include_stack) { const char *const cfg_path = rc_str(cfg_path_rc, ""); + const bool is_local = str_has_suffix(cfg_path, ".ted.cfg") + && is_path_separator(cfg_path[strlen(cfg_path) - 9]); // check for, e.g. %include ted.cfg inside ted.cfg arr_foreach_ptr(*include_stack, const char *, p_include) { if (streq(cfg_path, *p_include)) { @@ -1014,6 +1020,19 @@ static void config_read_ted_cfg(Ted *ted, RcStr *cfg_path_rc, const char ***incl char header[256]; config_read_to_eol(reader, header, sizeof header); char path[TED_PATH_MAX]; path[0] = '\0'; + if (is_local) { + // prepend directory + char dirname[TED_PATH_MAX]; + strbuf_cpy(dirname, cfg_path); + path_dirname(dirname); + for (size_t i = 0, out = 0; dirname[i] && out < sizeof path - 3; i++) { + if (regex_char_needs_escaping(dirname[i])) { + path[out++] = '\\'; + } + path[out++] = dirname[i]; + path[out] = '\0'; + } + } Language language = 0; if (strlen(header) == 0 || header[strlen(header) - 1] != ']') { config_err(reader, "Section header doesn't end with ]\n" SECTION_HEADER_HELP); @@ -1023,6 +1042,14 @@ static void config_read_ted_cfg(Ted *ted, RcStr *cfg_path_rc, const char ***incl char *p = header; char *path_end = strstr(p, "//"); if (path_end) { + if (is_local) { + // important we do this here and not above so that + // if we have /foo/.ted.cfg + // [colors] + // bg = #f00 + // ^^ this should apply to the path "/foo" (not just "/foo/something") + strbuf_catf(path, "%c", PATH_SEPARATOR); + } size_t path_len = (size_t)(path_end - header); path[0] = '\0'; // expand ~ @@ -1122,8 +1149,7 @@ static void config_read_ted_cfg(Ted *ted, RcStr *cfg_path_rc, const char ***incl } static void regex_append_literal_char(StrBuilder *b, char c) { - static const char pcre_metacharacters[] = "\\^.$|()[]*+?{}-"; - if (strchr(pcre_metacharacters, c)) + if (regex_char_needs_escaping(c)) str_builder_appendf(b, "\\%c", c); else str_builder_appendf(b, "%c", c); diff --git a/main.c b/main.c index 9fb732d..723b748 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,4 @@ /* -TODO: -- local .ted.cfg FUTURE FEATURES: - more tests - prepare rename support diff --git a/ted.c b/ted.c index 2d09574..83e542f 100644 --- a/ted.c +++ b/ted.c @@ -240,14 +240,22 @@ void ted_compute_settings(Ted *ted, const char *path, Language language, Setting u32 root_editorconfig = 0; if (path && *path) { - // check for .editorconfig - char editorconfig[2048]; - for (size_t i = 0; path[i] && i < sizeof editorconfig - 16; i++) { + // check for .editorconfig and local .ted.cfg + char editorconfig[2048], ted_cfg[2048]; + for (size_t i = 0; (i == 0 || path[i - 1]) && i < sizeof editorconfig - 16; i++) { editorconfig[i] = path[i]; editorconfig[i+1] = 0; - if (strchr(ALL_PATH_SEPARATORS, path[i])) { + ted_cfg[i] = path[i]; + ted_cfg[i+1] = 0; + if (path[i] == 0 || strchr(ALL_PATH_SEPARATORS, path[i])) { + if (path[i] == 0) { // for the case where `path` is a directory + strbuf_catf(editorconfig, "%c", PATH_SEPARATOR); + strbuf_catf(ted_cfg, "%c", PATH_SEPARATOR); + } strbuf_cat(editorconfig, ".editorconfig"); config_read(ted, editorconfig, CONFIG_EDITORCONFIG); + strbuf_cat(ted_cfg, ".ted.cfg"); + config_read(ted, ted_cfg, CONFIG_TED_CFG); } } diff --git a/ted.cfg b/ted.cfg index 9d3b864..702284b 100644 --- a/ted.cfg +++ b/ted.cfg @@ -109,7 +109,7 @@ framerate-cap = 60 # if set to 0, tag generation/regeneration will do nothing tags-max-depth = 2 # regenerate tags if an identifier is not found (with Ctrl+click)? -regenerate-tags-if-not-found = yes +regenerate-tags-if-not-found = no # this variable determines how ted finds the "root directory" of a project for # running build commands and because LSP servers need to know # FOR EXAMPLE: If you have the file /a/b/c/d.txt open, @@ -125,7 +125,7 @@ root-identifiers = .ted-root, .ted-root.out, Cargo.toml, make.bat, CMakeLists.tx # writing to the file (prevents loss of data if power goes out mid-write or something). # the backups are deleted immediately after writing. save-backup = yes -# whether to default to \r\n line endings. +# whether to save files with \r\n line endings. crlf = no # same as crlf setting, but ignored on non-Windows operating system. crlf-windows = no diff --git a/test/editorconfig/.ted.cfg b/test/editorconfig/.ted.cfg new file mode 100644 index 0000000..e3bd6ec --- /dev/null +++ b/test/editorconfig/.ted.cfg @@ -0,0 +1,5 @@ +[colors] +# blue +bg = #035 +comment = #f70 +builtin = #0f0 diff --git a/test/editorconfig/subdir/.ted.cfg b/test/editorconfig/subdir/.ted.cfg new file mode 100644 index 0000000..c09121b --- /dev/null +++ b/test/editorconfig/subdir/.ted.cfg @@ -0,0 +1,5 @@ +[colors] +# aahh beautiful +bg = #030 +comment = #0f0 +builtin = #f0f diff --git a/util.c b/util.c index 98c7dbc..de73f0e 100644 --- a/util.c +++ b/util.c @@ -463,6 +463,10 @@ void qsort_with_context(void *base, size_t nmemb, size_t size, } #endif +bool is_path_separator(char c) { + return strchr(ALL_PATH_SEPARATORS, c) != NULL; +} + const char *path_filename(const char *path) { for (int i = (int)strlen(path) - 1; i >= 0; --i) { if (strchr(ALL_PATH_SEPARATORS, path[i])) diff --git a/util.h b/util.h index 479ea03..2bbb5e7 100644 --- a/util.h +++ b/util.h @@ -146,6 +146,8 @@ int strcmp_case_insensitive(const char *a, const char *b); bool streq_case_insensitive(const char *a, const char *b); /// function to be passed into qsort for case insensitive sorting int str_qsort_case_insensitive_cmp(const void *av, const void *bv); +/// is c a path separator? +bool is_path_separator(char c); /// the actual file name part of the path; get rid of the containing directory. /// /// NOTE: the returned string is part of path, so you don't need to free it or anything. -- cgit v1.2.3