summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-10-19 11:14:39 -0400
committerpommicket <pommicket@gmail.com>2023-10-19 11:14:39 -0400
commit94c2b5a926cd7273272fb9fe268dd61c50426c59 (patch)
treed3a396ddf0e99d7ab1b2b3f955a4b51e5ff0df4e
parent69d702f2076930b8cc88c73420fc849eb4b807ce (diff)
local .ted.cfg
-rw-r--r--README.md7
-rw-r--r--config.c30
-rw-r--r--main.c2
-rw-r--r--ted.c16
-rw-r--r--ted.cfg4
-rw-r--r--test/editorconfig/.ted.cfg5
-rw-r--r--test/editorconfig/subdir/.ted.cfg5
-rw-r--r--util.c4
-rw-r--r--util.h2
9 files changed, 64 insertions, 11 deletions
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\<your user name>\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.