summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlbert Cervin <albert@acervin.com>2024-01-24 13:00:09 +0100
committerAlbert Cervin <albert@acervin.com>2024-01-24 13:00:09 +0100
commitc27f5c5ed4bce91eaa50d7d1daa5335f186dcc36 (patch)
tree93f7ecb1e7d1ebb792d767255b27c1742745204a /src
parent64d6816a36567274551dd4f067fe4d05b1445cc0 (diff)
downloaddged-c27f5c5ed4bce91eaa50d7d1daa5335f186dcc36.tar.gz
dged-c27f5c5ed4bce91eaa50d7d1daa5335f186dcc36.tar.xz
dged-c27f5c5ed4bce91eaa50d7d1daa5335f186dcc36.zip
Relative find file and small fixes
- Save text was not always displaying - Files were sometimes not reloaded properly
Diffstat (limited to 'src')
-rw-r--r--src/dged/buffer.c16
-rw-r--r--src/dged/buffer_view.c2
-rw-r--r--src/dged/minibuffer.c66
-rw-r--r--src/dged/minibuffer.h3
-rw-r--r--src/main/bindings.c1
-rw-r--r--src/main/cmds.c81
6 files changed, 132 insertions, 37 deletions
diff --git a/src/dged/buffer.c b/src/dged/buffer.c
index f1ce2ce..8e63e1f 100644
--- a/src/dged/buffer.c
+++ b/src/dged/buffer.c
@@ -356,11 +356,10 @@ void buffer_reload(struct buffer *buffer) {
return;
}
- if (sb.st_mtim.tv_sec != buffer->last_write.tv_sec) {
+ if (sb.st_mtim.tv_sec != buffer->last_write.tv_sec ||
+ sb.st_mtim.tv_nsec != buffer->last_write.tv_nsec) {
text_clear(buffer->text);
buffer_read_from_file(buffer);
- } else {
- minibuffer_echo_timeout(2, "buffer %s not changed", buffer->filename);
}
}
@@ -488,9 +487,20 @@ struct location buffer_next_line(struct buffer *buffer, struct location dot) {
struct location buffer_clamp(struct buffer *buffer, int64_t line, int64_t col) {
struct location location = {.line = 0, .col = 0};
+ if (buffer_is_empty(buffer)) {
+ return location;
+ }
+
movev(buffer, line, &location);
moveh(buffer, col, &location);
+ // when clamping we want to stay inside
+ // the actual bounds
+ if (location.line >= buffer_num_lines(buffer)) {
+ location.line = buffer_num_lines(buffer) - 1;
+ location.col = buffer_num_chars(buffer, location.line);
+ }
+
return location;
}
diff --git a/src/dged/buffer_view.c b/src/dged/buffer_view.c
index 05d3caa..aeee2f6 100644
--- a/src/dged/buffer_view.c
+++ b/src/dged/buffer_view.c
@@ -78,7 +78,7 @@ void buffer_view_add(struct buffer_view *view, uint8_t *txt, uint32_t nbytes) {
}
void buffer_view_goto_beginning(struct buffer_view *view) {
- view->dot = (struct location){.line = 1, .col = 0};
+ view->dot = (struct location){.line = 0, .col = 0};
}
void buffer_view_goto_end(struct buffer_view *view) {
diff --git a/src/dged/minibuffer.c b/src/dged/minibuffer.c
index 2105c52..eacf8da 100644
--- a/src/dged/minibuffer.c
+++ b/src/dged/minibuffer.c
@@ -91,7 +91,10 @@ void minibuffer_init(struct buffer *buffer) {
}
g_minibuffer.buffer = buffer;
+ g_minibuffer.expires.tv_sec = 0;
+ g_minibuffer.expires.tv_nsec = 0;
g_minibuffer.clear = false;
+ g_minibuffer.prompt_active = false;
buffer_add_update_hook(g_minibuffer.buffer, update, &g_minibuffer);
}
@@ -100,6 +103,10 @@ void echo(uint32_t timeout, const char *fmt, va_list args) {
return;
}
+ clock_gettime(CLOCK_MONOTONIC, &g_minibuffer.expires);
+ g_minibuffer.expires.tv_sec += timeout;
+ g_minibuffer.clear = false;
+
char buff[2048];
size_t nbytes = vsnprintf(buff, 2048, fmt, args);
@@ -107,10 +114,6 @@ void echo(uint32_t timeout, const char *fmt, va_list args) {
// of overflow
buffer_set_text(g_minibuffer.buffer, (uint8_t *)buff,
nbytes > 2048 ? 2048 : nbytes);
- g_minibuffer.clear = false;
-
- clock_gettime(CLOCK_MONOTONIC, &g_minibuffer.expires);
- g_minibuffer.expires.tv_sec += timeout;
}
void minibuffer_destroy() {
@@ -143,27 +146,59 @@ void minibuffer_set_prompt_internal(const char *fmt, va_list args) {
vsnprintf(g_minibuffer.prompt, sizeof(g_minibuffer.prompt), fmt, args);
}
-int32_t minibuffer_prompt(struct command_ctx command_ctx, const char *fmt,
- ...) {
+static void minibuffer_setup(struct command_ctx command_ctx,
+ const char *initial) {
+ g_minibuffer.prompt_active = true;
+
+ command_ctx_free(&g_minibuffer.prompt_command_ctx);
+ g_minibuffer.prompt_command_ctx = command_ctx;
+
+ if (windows_get_active() != minibuffer_window()) {
+ g_minibuffer.prev_window = windows_get_active();
+ windows_set_active(minibuffer_window());
+ }
+
+ if (initial != NULL) {
+ buffer_set_text(g_minibuffer.buffer, (uint8_t *)initial, strlen(initial));
+
+ // there might be an earlier clear request but
+ // we have sort of taken care of that here
+ g_minibuffer.clear = false;
+
+ // TODO: what to do with these
+ buffer_view_goto_end_of_line(window_buffer_view(minibuffer_window()));
+ } else {
+ minibuffer_clear();
+ }
+}
+
+int32_t minibuffer_prompt_initial(struct command_ctx command_ctx,
+ const char *initial, const char *fmt, ...) {
if (g_minibuffer.buffer == NULL) {
return 1;
}
+ minibuffer_setup(command_ctx, initial);
+
va_list args;
va_start(args, fmt);
+ minibuffer_set_prompt_internal(fmt, args);
+ va_end(args);
- minibuffer_clear();
- g_minibuffer.prompt_active = true;
+ return 0;
+}
- command_ctx_free(&g_minibuffer.prompt_command_ctx);
- g_minibuffer.prompt_command_ctx = command_ctx;
+int32_t minibuffer_prompt(struct command_ctx command_ctx, const char *fmt,
+ ...) {
+ if (g_minibuffer.buffer == NULL) {
+ return 1;
+ }
- minibuffer_set_prompt_internal(fmt, args);
+ minibuffer_setup(command_ctx, NULL);
- if (windows_get_active() != minibuffer_window()) {
- g_minibuffer.prev_window = windows_get_active();
- windows_set_active(minibuffer_window());
- }
+ va_list args;
+ va_start(args, fmt);
+ minibuffer_set_prompt_internal(fmt, args);
va_end(args);
return 0;
@@ -193,6 +228,7 @@ bool minibuffer_displaying() {
void minibuffer_clear() {
g_minibuffer.expires.tv_sec = 0;
+ g_minibuffer.expires.tv_nsec = 0;
g_minibuffer.clear = true;
}
diff --git a/src/dged/minibuffer.h b/src/dged/minibuffer.h
index 727aac5..b7c5171 100644
--- a/src/dged/minibuffer.h
+++ b/src/dged/minibuffer.h
@@ -59,6 +59,9 @@ void minibuffer_echo_timeout(uint32_t timeout, const char *fmt, ...);
*/
int32_t minibuffer_prompt(struct command_ctx command_ctx, const char *fmt, ...);
+int32_t minibuffer_prompt_initial(struct command_ctx command_ctx,
+ const char *initial, const char *fmt, ...);
+
void minibuffer_set_prompt(const char *fmt, ...);
uint32_t minibuffer_draw_prompt(struct command_list *commands);
diff --git a/src/main/bindings.c b/src/main/bindings.c
index 32dcbdb..ad63974 100644
--- a/src/main/bindings.c
+++ b/src/main/bindings.c
@@ -98,6 +98,7 @@ void init_bindings() {
BINDING(Ctrl, 'C', "exit"),
BINDING(Ctrl, 'S', "buffer-write-to-file"),
BINDING(Ctrl, 'F', "find-file"),
+ BINDING(Ctrl, 'G', "find-file-relative"),
BINDING(Ctrl, 'W', "write-file"),
BINDING(None, 'b', "switch-buffer"),
BINDING(Ctrl, 'B', "buffer-list"),
diff --git a/src/main/cmds.c b/src/main/cmds.c
index bf465ed..506054b 100644
--- a/src/main/cmds.c
+++ b/src/main/cmds.c
@@ -1,4 +1,5 @@
#include <errno.h>
+#include <libgen.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
@@ -226,20 +227,8 @@ int32_t buffer_list(struct command_ctx ctx, int argc, const char *argv[]) {
static void find_file_comp_inserted() { minibuffer_execute(); }
-int32_t find_file(struct command_ctx ctx, int argc, const char *argv[]) {
- const char *pth = NULL;
- if (argc == 0) {
- struct completion_provider providers[] = {path_provider()};
- enable_completion(minibuffer_buffer(),
- ((struct completion_trigger){
- .kind = CompletionTrigger_Input, .nchars = 0}),
- providers, 1, find_file_comp_inserted);
- return minibuffer_prompt(ctx, "find file: ");
- }
-
- disable_completion(minibuffer_buffer());
-
- pth = argv[0];
+static int32_t open_file(struct buffers *buffers, struct window *active_window,
+ const char *pth) {
struct stat sb = {0};
if (stat(pth, &sb) < 0 && errno != ENOENT) {
minibuffer_echo("stat on %s failed: %s", pth, strerror(errno));
@@ -252,19 +241,74 @@ int32_t find_file(struct command_ctx ctx, int argc, const char *argv[]) {
}
const char *filename = to_abspath(pth);
- struct buffer *b = buffers_find_by_filename(ctx.buffers, filename);
+ struct buffer *b = buffers_find_by_filename(buffers, filename);
free((char *)filename);
if (b == NULL) {
- b = buffers_add(ctx.buffers, buffer_from_file((char *)pth));
+ b = buffers_add(buffers, buffer_from_file((char *)pth));
} else {
buffer_reload(b);
}
- window_set_buffer(ctx.active_window, b);
+ window_set_buffer(active_window, b);
minibuffer_echo_timeout(4, "buffer \"%s\" loaded",
- window_buffer(ctx.active_window)->name);
+ window_buffer(active_window)->name);
+
+ return 0;
+}
+
+int32_t find_file(struct command_ctx ctx, int argc, const char *argv[]) {
+ const char *pth = NULL;
+ if (argc == 0) {
+ struct completion_provider providers[] = {path_provider()};
+ enable_completion(minibuffer_buffer(),
+ ((struct completion_trigger){
+ .kind = CompletionTrigger_Input, .nchars = 0}),
+ providers, 1, find_file_comp_inserted);
+ return minibuffer_prompt(ctx, "find file: ");
+ }
+
+ disable_completion(minibuffer_buffer());
+
+ open_file(ctx.buffers, ctx.active_window, argv[0]);
+ return 0;
+}
+
+COMMAND_FN("find-file-internal", find_file, find_file, NULL);
+int32_t find_file_relative(struct command_ctx ctx, int argc,
+ const char *argv[]) {
+ struct buffer *b = window_buffer(ctx.active_window);
+ if (b->filename == NULL) {
+ minibuffer_echo_timeout(4, "buffer %s is not backed by a file", b->name);
+ return 1;
+ }
+
+ char *filename = strdup(b->filename);
+ char *dir = dirname(filename);
+ if (argc == 0) {
+ struct completion_provider providers[] = {path_provider()};
+ enable_completion(minibuffer_buffer(),
+ ((struct completion_trigger){
+ .kind = CompletionTrigger_Input, .nchars = 0}),
+ providers, 1, find_file_comp_inserted);
+
+ ctx.self = &find_file_command;
+ minibuffer_prompt_initial(ctx, dir, "find file: ");
+ free(filename);
+ return 0;
+ }
+ disable_completion(minibuffer_buffer());
+ size_t dirlen = strlen(dir);
+ size_t plen = strlen(argv[0]);
+ char *pth = (char *)malloc(dirlen + plen + 2);
+ memcpy(pth, dir, dirlen);
+ pth[dirlen] = '/';
+ memcpy(pth + dirlen + 1, argv[0], plen);
+ pth[dirlen + plen + 1] = '\0';
+ open_file(ctx.buffers, ctx.active_window, pth);
+
+ free(filename);
return 0;
}
@@ -272,6 +316,7 @@ void register_global_commands(struct commands *commands,
void (*terminate_cb)()) {
struct command global_commands[] = {
{.name = "find-file", .fn = find_file},
+ {.name = "find-file-relative", .fn = find_file_relative},
{.name = "write-file", .fn = write_file},
{.name = "run-command-interactive", .fn = run_interactive},
{.name = "switch-buffer", .fn = switch_buffer},