diff options
| author | Albert Cervin <albert@acervin.com> | 2023-05-11 22:09:49 +0200 |
|---|---|---|
| committer | Albert Cervin <albert@acervin.com> | 2023-05-11 22:09:49 +0200 |
| commit | ea849862a85e1751206c20254e9126cf3e8096b5 (patch) | |
| tree | 249bbd4630a156983ea77bc4d43c186e03f6ed0e | |
| parent | 67276833f9ede96dbc549c508f182c913240ac2c (diff) | |
| download | dged-ea849862a85e1751206c20254e9126cf3e8096b5.tar.gz dged-ea849862a85e1751206c20254e9126cf3e8096b5.tar.xz dged-ea849862a85e1751206c20254e9126cf3e8096b5.zip | |
Fix languages
- Enumerate windows on screen.
- Build with optimizations.
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | dged.nix | 4 | ||||
| -rw-r--r-- | src/dged/buffer.c | 41 | ||||
| -rw-r--r-- | src/dged/buffer.h | 2 | ||||
| -rw-r--r-- | src/dged/lang.c | 61 | ||||
| -rw-r--r-- | src/dged/lang.h | 6 | ||||
| -rw-r--r-- | src/dged/path.h | 38 | ||||
| -rw-r--r-- | src/dged/window.c | 11 | ||||
| -rw-r--r-- | src/main/cmds.c | 11 | ||||
| -rw-r--r-- | test/keyboard.c | 5 | ||||
| -rw-r--r-- | test/minibuffer.c | 4 |
11 files changed, 109 insertions, 76 deletions
@@ -23,7 +23,7 @@ prefix ?= "/usr" .SUFFIXES: .SUFFIXES: .c .o .d -CFLAGS = -Werror -g -std=c99 -I $(.CURDIR)/src -I $(.CURDIR)/src/main +CFLAGS += -Werror -g -std=c99 -I $(.CURDIR)/src -I $(.CURDIR)/src/main UNAME_S != uname -s | tr '[:upper:]' '[:lower:]' .sinclude "$(UNAME_S).mk" @@ -23,7 +23,7 @@ stdenv.mkDerivation { buildPhase = '' bmake build - bmake dged + CFLAGS=-O2 bmake dged bmake docs ''; @@ -34,6 +34,4 @@ stdenv.mkDerivation { buildInputs = [ tree-sitter ]; - - hardeningDisable = [ "fortify" ]; } diff --git a/src/dged/buffer.c b/src/dged/buffer.c index e40281f..c34d314 100644 --- a/src/dged/buffer.c +++ b/src/dged/buffer.c @@ -5,6 +5,7 @@ #include "errno.h" #include "lang.h" #include "minibuffer.h" +#include "path.h" #include "reactor.h" #include "settings.h" #include "utf8.h" @@ -510,8 +511,10 @@ void buffer_beginning_of_line(struct buffer_view *view) { view->dot.col = 0; } void buffer_read_from_file(struct buffer *b) { struct stat sb; - if (stat(b->filename, &sb) == 0) { - FILE *file = fopen(b->filename, "r"); + char *fullname = expanduser(b->filename); + if (stat(fullname, &sb) == 0) { + FILE *file = fopen(fullname, "r"); + free(fullname); if (file == NULL) { minibuffer_echo("Error opening %s: %s", b->filename, strerror(errno)); @@ -538,21 +541,16 @@ void buffer_read_from_file(struct buffer *b) { b->last_write = sb.st_mtim; } else { minibuffer_echo("Error opening %s: %s", b->filename, strerror(errno)); + free(fullname); return; } - const char *ext = strrchr(b->filename, '.'); - if (ext != NULL) { - b->lang = lang_from_extension(ext + 1); - } + b->lang = lang_from_filename(b->filename); undo_push_boundary(&b->undo, (struct undo_boundary){.save_point = true}); } struct buffer buffer_from_file(char *filename) { - char *full_filename = realpath(filename, NULL); - if (full_filename == NULL) { - full_filename = strdup(filename); - } + char *full_filename = to_abspath(filename); struct buffer b = create_internal(basename((char *)filename), full_filename); buffer_read_from_file(&b); @@ -583,7 +581,9 @@ void buffer_to_file(struct buffer *buffer) { return; } - FILE *file = fopen(buffer->filename, "w"); + char *fullname = expanduser(buffer->filename); + FILE *file = fopen(fullname, "w"); + free(fullname); if (file == NULL) { minibuffer_echo("failed to open file %s for writing: %s", buffer->filename, strerror(errno)); @@ -605,7 +605,7 @@ void buffer_to_file(struct buffer *buffer) { } void buffer_write_to(struct buffer *buffer, const char *filename) { - buffer->filename = strdup(filename); + buffer->filename = to_abspath(filename); buffer_to_file(buffer); } @@ -978,8 +978,8 @@ uint32_t visual_dot_col(struct buffer_view *view, uint32_t dot_col) { } void render_modeline(struct modeline *modeline, struct buffer_view *view, - struct command_list *commands, uint32_t width, - uint32_t height, uint64_t frame_time) { + struct command_list *commands, uint32_t window_id, + uint32_t width, uint32_t height, uint64_t frame_time) { char buf[width * 4]; static uint64_t samples[10] = {0}; @@ -996,9 +996,9 @@ void render_modeline(struct modeline *modeline, struct buffer_view *view, struct tm *lt = localtime(&now); char left[128], right[128]; - snprintf(left, 128, " %c%c %-16s (%d, %d) (%s)", + snprintf(left, 128, " %c%c %d:%-16s (%d, %d) (%s)", view->buffer->modified ? '*' : '-', - view->buffer->readonly ? '%' : '-', view->buffer->name, + view->buffer->readonly ? '%' : '-', window_id, view->buffer->name, view->dot.line + 1, visual_dot_col(view, view->dot.col), view->buffer->lang.name); snprintf(right, 128, "(%.2f ms) %02d:%02d", frame_time / 1e6, lt->tm_hour, @@ -1072,9 +1072,9 @@ uint32_t longest_linenum(struct buffer *buffer) { return longest_nchars; } -void buffer_update(struct buffer_view *view, uint32_t width, uint32_t height, - struct command_list *commands, uint64_t frame_time, - uint32_t *relline, uint32_t *relcol) { +void buffer_update(struct buffer_view *view, uint32_t window_id, uint32_t width, + uint32_t height, struct command_list *commands, + uint64_t frame_time, uint32_t *relline, uint32_t *relcol) { if (width == 0 || height == 0) { return; } @@ -1114,7 +1114,8 @@ void buffer_update(struct buffer_view *view, uint32_t width, uint32_t height, } if (view->modeline != NULL) { - render_modeline(view->modeline, view, commands, width, height, frame_time); + render_modeline(view->modeline, view, commands, window_id, width, height, + frame_time); total_margins.bottom += 1; } diff --git a/src/dged/buffer.h b/src/dged/buffer.h index e33733b..417ca03 100644 --- a/src/dged/buffer.h +++ b/src/dged/buffer.h @@ -221,6 +221,6 @@ void buffer_to_file(struct buffer *buffer); void buffer_write_to(struct buffer *buffer, const char *filename); void buffer_reload(struct buffer *buffer); -void buffer_update(struct buffer_view *view, uint32_t width, uint32_t height, +void buffer_update(struct buffer_view *view, uint32_t window_id, uint32_t width, uint32_t height, struct command_list *commands, uint64_t frame_time, uint32_t *relline, uint32_t *relcol); diff --git a/src/dged/lang.c b/src/dged/lang.c index 6919780..6b02c72 100644 --- a/src/dged/lang.c +++ b/src/dged/lang.c @@ -2,31 +2,34 @@ #include "minibuffer.h" #include "settings.h" +#include <regex.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -void define_lang(const char *name, const char *id, const char *extensions, +void define_lang(const char *name, const char *id, const char *pattern, uint32_t tab_width, const char *lang_srv) { char namebuf[128] = {0}; size_t offs = snprintf(namebuf, 128, "languages.%s.", id); char *b = namebuf + offs; - snprintf(b, 128 - offs, "%s", "extensions"); + snprintf(b, 128 - offs, "%s", "pattern"); settings_register_setting( namebuf, (struct setting_value){.type = Setting_String, - .string_value = (char *)extensions}); + .string_value = (char *)pattern}); snprintf(b, 128 - offs, "%s", "tab-width"); settings_register_setting(namebuf, (struct setting_value){.type = Setting_Number, .number_value = tab_width}); - snprintf(b, 128 - offs, "%s", "lang-srv"); - settings_register_setting( - namebuf, (struct setting_value){.type = Setting_String, - .string_value = (char *)lang_srv}); + if (lang_srv != NULL) { + snprintf(b, 128 - offs, "%s", "lang-srv"); + settings_register_setting( + namebuf, (struct setting_value){.type = Setting_String, + .string_value = (char *)lang_srv}); + } snprintf(b, 128 - offs, "%s", "name"); settings_register_setting( @@ -42,10 +45,11 @@ static struct language g_fundamental = { void languages_init(bool register_default) { if (register_default) { - define_lang("C", "c", "c h", 2, "clangd"); - define_lang("C++", "cxx", "cpp cxx cc c++ hh h", 2, "clangd"); - define_lang("Rust", "rs", "rs", 4, "rust-analyzer"); - define_lang("Nix", "nix", "nix", 4, "rnix-lsp"); + define_lang("C", "c", ".*\\.(c|h)", 2, "clangd"); + define_lang("C++", "cxx", ".*\\.(cpp|cxx|cc|c++|hh|h)", 2, "clangd"); + define_lang("Rust", "rs", ".*\\.rs", 4, "rust-analyzer"); + define_lang("Nix", "nix", ".*\\.nix", 4, "rnix-lsp"); + define_lang("Makefile", "make", ".*(Makefile|\\.mk)", 4, NULL); } } @@ -71,7 +75,7 @@ struct language lang_from_settings(const char *lang_path) { snprintf(b, 128 - offs, "%s", "lang-srv"); struct setting *lang_srv = settings_get(setting_name_buf); - l.lang_srv = lang_srv->value.string_value; + l.lang_srv = lang_srv != NULL ? lang_srv->value.string_value : NULL; return l; } @@ -91,10 +95,9 @@ void next_ext(const char *curr, const char **nxt, const char **end) { } } -struct language lang_from_extension(const char *ext) { +struct language lang_from_filename(const char *filename) { - uint32_t extlen = strlen(ext); - if (extlen == 0) { + if (strlen(filename) == 0) { return g_fundamental; } @@ -103,29 +106,21 @@ struct language lang_from_extension(const char *ext) { uint32_t nsettings = 0; settings_get_prefix("languages.", &settings, &nsettings); - // find the first one with a matching extension list + // find the first one with a matching regex for (uint32_t i = 0; i < nsettings; ++i) { struct setting *setting = settings[i]; char *setting_name = strrchr(setting->path, '.'); - if (setting_name != NULL && - strncmp(setting_name + 1, "extensions", 10) == 0) { + if (setting_name != NULL && strncmp(setting_name + 1, "pattern", 5) == 0) { const char *val = setting->value.string_value; - - // go over extensions - const char *cext = val, *nxt = NULL, *end = NULL; - next_ext(cext, &nxt, &end); - while (nxt != end) { - if (extlen == (end - nxt) && strncmp(ext, nxt, (end - nxt)) == 0) { - char lang_path[128] = {0}; - strncpy(lang_path, setting->path, setting_name - setting->path); - - free(settings); - return lang_from_settings(lang_path); - } - - cext = end + 1; - next_ext(cext, &nxt, &end); + regex_t regex; + if (regcomp(®ex, val, REG_EXTENDED) == 0 && + regexec(®ex, filename, 0, NULL, 0) == 0) { + regfree(®ex); + char lang_path[128] = {0}; + strncpy(lang_path, setting->path, setting_name - setting->path); + return lang_from_settings(lang_path); } + regfree(®ex); } } diff --git a/src/dged/lang.h b/src/dged/lang.h index 984e207..5aff52c 100644 --- a/src/dged/lang.h +++ b/src/dged/lang.h @@ -27,12 +27,12 @@ struct language { void languages_init(bool register_default); /** - * Get a language config by file name extension. + * Get a language config by file name. * - * @param[in] ext File extension + * @param[in] filename File name. * @returns A language config instance or the default language if not found. */ -struct language lang_from_extension(const char *ext); +struct language lang_from_filename(const char *filename); /** * Get a language config by id. The language id is a short (all-lowercase) diff --git a/src/dged/path.h b/src/dged/path.h new file mode 100644 index 0000000..d74f723 --- /dev/null +++ b/src/dged/path.h @@ -0,0 +1,38 @@ +#include <limits.h> +#include <stdlib.h> +#include <string.h> + +static char *expanduser(const char *path) { + // replace tilde + char *res = NULL; + char *tilde_pos = strchr(path, '~'); + if (tilde_pos != NULL) { + char *home = getenv("HOME"); + if (home != NULL) { + // allocate a new string based with the new len + size_t home_len = strlen(home); + size_t path_len = strlen(path); + size_t total_len = path_len + home_len; + res = malloc(total_len); + size_t initial_len = tilde_pos - path; + strncpy(res, path, initial_len); + + strncpy(res + initial_len, home, home_len); + + size_t rest_len = path_len - initial_len - 1; + strncpy(res + initial_len + home_len, path + initial_len + 1, rest_len); + res[total_len-1] = '\0'; + } + } + + return res != NULL ? res : strdup(path); +} + +static char *to_abspath(const char *path) { + char *p = realpath(path, NULL); + if (p != NULL) { + return p; + } else { + return strdup(path); + } +} diff --git a/src/dged/window.c b/src/dged/window.c index 33659a7..5ea4085 100644 --- a/src/dged/window.c +++ b/src/dged/window.c @@ -147,14 +147,17 @@ void windows_resize(uint32_t height, uint32_t width) { void windows_update(void *(*frame_alloc)(size_t), uint64_t frame_time) { struct window_node *n = BINTREE_ROOT(&g_windows.windows); BINTREE_FIRST(n); + uint32_t window_id = 0; while (n != NULL) { struct window *w = &BINTREE_VALUE(n); if (w->type == Window_Buffer) { w->commands = command_list_create(w->height * w->width, frame_alloc, w->x, w->y, w->buffer_view.buffer->name); - buffer_update(&w->buffer_view, w->width, w->height, w->commands, - frame_time, &w->relline, &w->relcol); + buffer_update(&w->buffer_view, window_id, w->width, w->height, + w->commands, frame_time, &w->relline, &w->relcol); + + ++window_id; } BINTREE_NEXT(n); @@ -163,8 +166,8 @@ void windows_update(void *(*frame_alloc)(size_t), uint64_t frame_time) { struct window *w = &g_minibuffer_window; w->commands = command_list_create(w->height * w->width, frame_alloc, w->x, w->y, w->buffer_view.buffer->name); - buffer_update(&w->buffer_view, w->width, w->height, w->commands, frame_time, - &w->relline, &w->relcol); + buffer_update(&w->buffer_view, -1, w->width, w->height, w->commands, + frame_time, &w->relline, &w->relcol); } void windows_render(struct display *display) { diff --git a/src/main/cmds.c b/src/main/cmds.c index 48088b1..b7f7011 100644 --- a/src/main/cmds.c +++ b/src/main/cmds.c @@ -8,6 +8,7 @@ #include "dged/buffers.h" #include "dged/command.h" #include "dged/minibuffer.h" +#include "dged/path.h" #include "dged/settings.h" #include "bindings.h" @@ -48,15 +49,9 @@ int32_t find_file(struct command_ctx ctx, int argc, const char *argv[]) { return 1; } - const char *filename = realpath(pth, NULL); - if (filename == NULL) { - filename = pth; - } + const char *filename = to_abspath(pth); struct buffer *b = buffers_find_by_filename(ctx.buffers, filename); - - if (filename != pth) { - free((char *)filename); - } + free((char *)filename); if (b == NULL) { b = buffers_add(ctx.buffers, buffer_from_file((char *)pth)); diff --git a/test/keyboard.c b/test/keyboard.c index 1ddbba5..64419ec 100644 --- a/test/keyboard.c +++ b/test/keyboard.c @@ -1,3 +1,4 @@ +#include <errno.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -60,7 +61,9 @@ struct fake_keyboard create_fake_keyboard(struct fake_reactor_impl *reactor) { } void fake_keyboard_write(struct fake_keyboard *kbd, const char *s) { - write(kbd->writefd, s, strlen(s)); + if (write(kbd->writefd, s, strlen(s)) < 0) { + printf("write to kbd fd failed: %s\n", strerror(errno)); + } } void fake_keyboard_close_write(struct fake_keyboard *kbd) { diff --git a/test/minibuffer.c b/test/minibuffer.c index a6c7f96..5c5ae63 100644 --- a/test/minibuffer.c +++ b/test/minibuffer.c @@ -50,13 +50,13 @@ void test_minibuffer_echo() { ASSERT(minibuffer_displaying(), "Minibuffer should now have text to display"); minibuffer_clear(); - buffer_update(&view, 100, 1, list, 0, &relline, &relcol); + buffer_update(&view, -1, 100, 1, list, 0, &relline, &relcol); ASSERT(!minibuffer_displaying(), "Minibuffer should have nothing to display after clearing"); minibuffer_echo_timeout(0, "You will not see me"); - buffer_update(&view, 100, 1, list, 0, &relline, &relcol); + buffer_update(&view, -1, 100, 1, list, 0, &relline, &relcol); ASSERT(!minibuffer_displaying(), "A zero timeout echo should be cleared after first update"); |
