summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dged/buffer.c41
-rw-r--r--src/dged/buffer.h2
-rw-r--r--src/dged/lang.c61
-rw-r--r--src/dged/lang.h6
-rw-r--r--src/dged/path.h38
-rw-r--r--src/dged/window.c11
-rw-r--r--src/main/cmds.c11
7 files changed, 101 insertions, 69 deletions
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(&regex, val, REG_EXTENDED) == 0 &&
+ regexec(&regex, filename, 0, NULL, 0) == 0) {
+ regfree(&regex);
+ char lang_path[128] = {0};
+ strncpy(lang_path, setting->path, setting_name - setting->path);
+ return lang_from_settings(lang_path);
}
+ regfree(&regex);
}
}
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));