summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorAlbert Cervin <albert@acervin.com>2023-05-07 23:59:22 +0200
committerAlbert Cervin <albert@acervin.com>2023-05-08 00:00:36 +0200
commit24cff0ec31970d5d57f61ba99ba7bfdda725cf94 (patch)
tree8304f69e38ec33d663db21ee26dbee14bf8d7a2f /src/main
parent8d73eace6806bd67852189b1a16de5895c565688 (diff)
downloaddged-24cff0ec31970d5d57f61ba99ba7bfdda725cf94.tar.gz
dged-24cff0ec31970d5d57f61ba99ba7bfdda725cf94.tar.xz
dged-24cff0ec31970d5d57f61ba99ba7bfdda725cf94.zip
Implement file reloading
When for examplue using formatters or doing vc updates, it is useful if the file is reloaded from disk.
Diffstat (limited to 'src/main')
-rw-r--r--src/main/bindings.c5
-rw-r--r--src/main/cmds.c25
-rw-r--r--src/main/main.c58
3 files changed, 86 insertions, 2 deletions
diff --git a/src/main/bindings.c b/src/main/bindings.c
index 10436d6..7ea75eb 100644
--- a/src/main/bindings.c
+++ b/src/main/bindings.c
@@ -35,11 +35,14 @@ void set_default_buffer_bindings(struct keymap *keymap) {
BINDING(Ctrl, 'S', "find-next"),
BINDING(Ctrl, 'R', "find-prev"),
+ BINDING(Meta, 'g', "goto-line"),
BINDING(Meta, '<', "goto-beginning"),
BINDING(Meta, '>', "goto-end"),
BINDING(Ctrl, 'V', "scroll-down"),
BINDING(Meta, 'v', "scroll-up"),
+ BINDING(Spec, '6', "scroll-down"),
+ BINDING(Spec, '5', "scroll-up"),
BINDING(ENTER, "newline"),
BINDING(TAB, "indent"),
@@ -204,4 +207,6 @@ void destroy_keymaps() {
km->active = false;
}
}
+
+ VEC_DESTROY(&g_buffer_keymaps);
}
diff --git a/src/main/cmds.c b/src/main/cmds.c
index 27b2a77..4cbb00f 100644
--- a/src/main/cmds.c
+++ b/src/main/cmds.c
@@ -47,8 +47,16 @@ int32_t find_file(struct command_ctx ctx, int argc, const char *argv[]) {
return 1;
}
- window_set_buffer(ctx.active_window,
- buffers_add(ctx.buffers, buffer_from_file((char *)pth)));
+ const char *filename = realpath(pth, NULL);
+ struct buffer *b = buffers_find_by_filename(ctx.buffers, filename);
+ free((char *)filename);
+ if (b == NULL) {
+ b = buffers_add(ctx.buffers, buffer_from_file((char *)pth));
+ } else {
+ buffer_reload(b);
+ }
+
+ window_set_buffer(ctx.active_window, b);
minibuffer_echo_timeout(4, "buffer \"%s\" loaded",
window_buffer(ctx.active_window)->name);
@@ -317,12 +325,14 @@ BUFFER_WRAPCMD_POS(buffer_paste_older);
BUFFER_WRAPCMD_POS(buffer_goto_beginning);
BUFFER_WRAPCMD_POS(buffer_goto_end);
BUFFER_WRAPCMD_POS(buffer_undo);
+
static int32_t buffer_view_scroll_up_cmd(struct command_ctx ctx, int argc,
const char *argv[]) {
buffer_view_scroll_up(window_buffer_view(ctx.active_window),
window_height(ctx.active_window));
return 0;
};
+
static int32_t buffer_view_scroll_down_cmd(struct command_ctx ctx, int argc,
const char *argv[]) {
buffer_view_scroll_down(window_buffer_view(ctx.active_window),
@@ -330,6 +340,16 @@ static int32_t buffer_view_scroll_down_cmd(struct command_ctx ctx, int argc,
return 0;
};
+static int32_t buffer_goto_line(struct command_ctx ctx, int argc,
+ const char *argv[]) {
+ if (argc == 0) {
+ return minibuffer_prompt(ctx, "line: ");
+ }
+
+ uint32_t line = atoi(argv[0]);
+ buffer_goto(window_buffer_view(ctx.active_window), line - 1, 0);
+}
+
void register_buffer_commands(struct commands *commands) {
static struct command buffer_commands[] = {
@@ -359,6 +379,7 @@ void register_buffer_commands(struct commands *commands) {
{.name = "scroll-down", .fn = buffer_view_scroll_down_cmd},
{.name = "scroll-up", .fn = buffer_view_scroll_up_cmd},
{.name = "reload", .fn = buffer_reload_cmd},
+ {.name = "goto-line", .fn = buffer_goto_line},
};
register_commands(commands, buffer_commands,
diff --git a/src/main/main.c b/src/main/main.c
index f13e77e..cd36733 100644
--- a/src/main/main.c
+++ b/src/main/main.c
@@ -59,6 +59,59 @@ uint64_t calc_frame_time_ns(struct timespec *timers, uint32_t num_timer_pairs) {
#define TIMED_SCOPE_BEGIN(timer) clock_gettime(CLOCK_MONOTONIC, &timer##_begin)
#define TIMED_SCOPE_END(timer) clock_gettime(CLOCK_MONOTONIC, &timer##_end)
+struct watched_file {
+ uint32_t watch_id;
+ struct buffer *buffer;
+};
+
+VEC(struct watched_file) g_watched_files;
+
+void watch_file(struct buffer *buffer, void *userdata) {
+ if (buffer_is_backed(buffer)) {
+ struct reactor *reactor = (struct reactor *)userdata;
+ VEC_APPEND(&g_watched_files, struct watched_file * w);
+ w->buffer = buffer;
+ w->watch_id = reactor_watch_file(reactor, buffer->filename, FileWritten);
+ }
+}
+
+void reload_buffer(struct buffer *buffer) {
+ if (!buffer_is_modified(buffer)) {
+ buffer_reload(buffer);
+ } else {
+ minibuffer_echo("not updating buffer %s because it contains changes",
+ buffer->name);
+ }
+}
+
+void update_file_watches(struct reactor *reactor) {
+ // first, find invalid file watches and try to update them
+ VEC_FOR_EACH(&g_watched_files, struct watched_file * w) {
+ if (w->watch_id == -1) {
+ w->watch_id =
+ reactor_watch_file(reactor, w->buffer->filename, FileWritten);
+ reload_buffer(w->buffer);
+ }
+ }
+
+ // then pick up any events we might have
+ struct file_event ev;
+ while (reactor_next_file_event(reactor, &ev)) {
+ // find the buffer we need to reload
+ VEC_FOR_EACH(&g_watched_files, struct watched_file * w) {
+ if (w->watch_id == ev.id) {
+ if (ev.mask & LastEvent != 0) {
+ w->watch_id = -1;
+ continue;
+ }
+
+ reload_buffer(w->buffer);
+ break;
+ }
+ }
+ }
+}
+
void usage() { printf("TODO: print usage\n"); }
int main(int argc, char *argv[]) {
@@ -127,8 +180,11 @@ int main(int argc, char *argv[]) {
struct keymap *current_keymap = NULL;
struct keymap *global_keymap = register_bindings();
+ VEC_INIT(&g_watched_files, 32);
+
struct buffers buflist = {0};
buffers_init(&buflist, 32);
+ buffers_add_add_hook(&buflist, watch_file, (void *)reactor);
struct buffer initial_buffer = buffer_create("welcome");
if (filename != NULL) {
buffer_destroy(&initial_buffer);
@@ -270,6 +326,8 @@ int main(int argc, char *argv[]) {
}
TIMED_SCOPE_END(keyboard);
+ update_file_watches(reactor);
+
// calculate frame time
struct timespec timers[] = {buffer_begin, buffer_end, display_begin,
display_end, keyboard_begin, keyboard_end};