summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorAlbert Cervin <albert@acervin.com>2023-07-12 16:20:50 +0200
committerAlbert Cervin <albert@acervin.com>2023-10-19 22:41:33 +0200
commit54c9b4b533210b77be998f458ff96bdc54272f64 (patch)
treeeb434343bb1083172af50b7372d1e2745af00f8f /src/main
parent3a8ae83aa13636679c151027cace905fa87ebd8e (diff)
downloaddged-54c9b4b533210b77be998f458ff96bdc54272f64.tar.gz
dged-54c9b4b533210b77be998f458ff96bdc54272f64.tar.xz
dged-54c9b4b533210b77be998f458ff96bdc54272f64.zip
big buffer/buffer_view rework
A buffer is only the text and the corresponding operation. A buffer view holds information about scroll, dot and mark positions. One way to think about it is that a buffer is stateless whereas a buffer view is stateful.
Diffstat (limited to 'src/main')
-rw-r--r--src/main/cmds.c241
-rw-r--r--src/main/main.c26
-rw-r--r--src/main/search-replace.c105
3 files changed, 178 insertions, 194 deletions
diff --git a/src/main/cmds.c b/src/main/cmds.c
index ecce343..26e2628 100644
--- a/src/main/cmds.c
+++ b/src/main/cmds.c
@@ -9,6 +9,7 @@
#include "dged/binding.h"
#include "dged/buffer.h"
+#include "dged/buffer_view.h"
#include "dged/buffers.h"
#include "dged/command.h"
#include "dged/display.h"
@@ -25,7 +26,7 @@ int32_t _abort(struct command_ctx ctx, int argc, const char *argv[]) {
abort_replace();
abort_completion();
minibuffer_abort_prompt();
- buffer_clear_mark(window_buffer_view(ctx.active_window));
+ buffer_view_clear_mark(window_buffer_view(ctx.active_window));
reset_minibuffer_keys(minibuffer_buffer());
minibuffer_echo_timeout(4, "💣 aborted");
return 0;
@@ -52,11 +53,7 @@ uint32_t g_ncompletions = 0;
struct completion g_completions[50] = {0};
static void abort_completion() {
- if (!minibuffer_focused()) {
- reset_buffer_keys(window_buffer(windows_get_active()));
- } else {
- reset_minibuffer_keys(minibuffer_buffer());
- }
+ reset_minibuffer_keys(minibuffer_buffer());
windows_close_popup();
for (uint32_t compi = 0; compi < g_ncompletions; ++compi) {
@@ -83,6 +80,8 @@ static void complete_path(const char *path, struct completion results[],
size_t len = strlen(p1);
char *p2 = strdup(p1);
+ size_t inlen = strlen(path);
+
if (len == 0) {
goto done;
}
@@ -94,7 +93,9 @@ static void complete_path(const char *path, struct completion results[],
const char *dir = p1;
const char *file = "";
- if (dir[len - 1] != '/') {
+ // check the input path here since
+ // to_abspath removes trailing slashes
+ if (path[inlen - 1] != '/') {
dir = dirname(p1);
file = basename(p2);
}
@@ -143,20 +144,13 @@ done:
*nresults = n;
}
-void render_completion_line(struct text_chunk *line_data, uint32_t line,
- struct command_list *commands, void *userdata) {
- command_list_set_show_whitespace(commands, false);
- command_list_draw_repeated(commands, 0, line, ' ', 1);
-}
-
-struct update_hook_result
-update_completion_buffer(struct buffer_view *view,
- struct command_list *commands, uint32_t width,
- uint32_t height, uint64_t frame_time, void *userdata) {
- struct text_chunk line = buffer_get_line(view->buffer, view->dot.line);
+void update_completion_buffer(struct buffer *buffer, uint32_t width,
+ uint32_t height, void *userdata) {
+ struct buffer_view *view = (struct buffer_view *)userdata;
+ struct text_chunk line = buffer_line(buffer, view->dot.line);
buffer_add_text_property(
- view->buffer, (struct buffer_location){.line = view->dot.line, .col = 0},
- (struct buffer_location){.line = view->dot.line, .col = line.nchars},
+ view->buffer, (struct location){.line = view->dot.line, .col = 0},
+ (struct location){.line = view->dot.line, .col = line.nchars},
(struct text_property){.type = TextProperty_Colors,
.colors = (struct text_property_colors){
.set_bg = false,
@@ -168,17 +162,6 @@ update_completion_buffer(struct buffer_view *view,
if (line.allocated) {
free(line.text);
}
-
- struct update_hook_result res = {0};
- res.margins.left = 1;
- res.margins.right = 1;
- res.line_render_hook = (struct line_render_hook){
- .callback = render_completion_line,
- .empty_callback = NULL,
- .userdata = NULL,
- };
-
- return res;
}
static int32_t goto_completion(struct command_ctx ctx, int argc,
@@ -193,7 +176,7 @@ static int32_t goto_completion(struct command_ctx ctx, int argc,
movement_fn(v);
if (v->dot.line >= text_num_lines(b->text)) {
- buffer_backward_line(v);
+ buffer_view_backward_line(v);
}
}
@@ -211,15 +194,13 @@ static int32_t insert_completion(struct command_ctx ctx, int argc,
char *ins = (char *)g_completions[cv->dot.line].insert;
bool complete = g_completions[cv->dot.line].complete;
size_t inslen = strlen(ins);
- if (minibuffer_focused()) {
- buffer_add_text(window_buffer_view(minibuffer_window()), ins, inslen);
- } else {
- buffer_add_text(window_buffer_view(windows_get_active()), ins, inslen);
- }
+ buffer_view_add(window_buffer_view(windows_get_active()), ins, inslen);
- if (complete) {
+ if (minibuffer_focused() && complete) {
minibuffer_execute();
}
+
+ abort_completion();
}
}
@@ -227,9 +208,9 @@ static int32_t insert_completion(struct command_ctx ctx, int argc,
}
COMMAND_FN("next-completion", next_completion, goto_completion,
- buffer_forward_line);
+ buffer_view_forward_line);
COMMAND_FN("prev-completion", prev_completion, goto_completion,
- buffer_backward_line);
+ buffer_view_backward_line);
COMMAND_FN("insert-completion", insert_completion, insert_completion, NULL);
static void on_find_file_input(void *userdata) {
@@ -237,12 +218,14 @@ static void on_find_file_input(void *userdata) {
struct text_chunk txt = minibuffer_content();
struct window *mb = minibuffer_window();
- struct buffer_location mb_dot = window_absolute_cursor_location(mb);
+ struct location mb_dot = window_buffer_view(mb)->dot;
+ struct window_position mbpos = window_position(mb);
struct buffer *b = buffers_find(buffers, "*completions*");
if (b == NULL) {
b = buffers_add(buffers, buffer_create("*completions*"));
- buffer_add_update_hook(b, update_completion_buffer, NULL);
+ buffer_add_update_hook(b, update_completion_buffer,
+ (void *)window_buffer_view(popup_window()));
window_set_buffer_e(popup_window(), b, false, false);
}
@@ -261,9 +244,10 @@ static void on_find_file_input(void *userdata) {
complete_path(path, g_completions, 50, &g_ncompletions);
size_t max_width = 0;
- struct buffer_location prev_dot = v->dot;
+ struct location prev_dot = v->dot;
- buffer_clear(v);
+ buffer_clear(v->buffer);
+ buffer_view_goto(v, (struct location){.line = 0, .col = 0});
if (g_ncompletions > 0) {
for (uint32_t compi = 0; compi < g_ncompletions; ++compi) {
const char *disp = g_completions[compi].display;
@@ -271,17 +255,18 @@ static void on_find_file_input(void *userdata) {
if (width > max_width) {
max_width = width;
}
- buffer_add_text(v, (uint8_t *)disp, width);
+ buffer_view_add(v, (uint8_t *)disp, width);
// the extra newline feels weird in navigation
if (compi != g_ncompletions - 1) {
- buffer_add_text(v, (uint8_t *)"\n", 1);
+ buffer_view_add(v, (uint8_t *)"\n", 1);
}
}
- buffer_goto(v, prev_dot.line, prev_dot.col);
+ buffer_view_goto(
+ v, (struct location){.line = prev_dot.line, .col = prev_dot.col});
if (prev_dot.line >= text_num_lines(b->text)) {
- buffer_backward_line(v);
+ buffer_view_backward_line(v);
}
if (!popup_window_visible()) {
@@ -294,11 +279,12 @@ static void on_find_file_input(void *userdata) {
sizeof(bindings) / sizeof(bindings[0]));
}
- uint32_t width = max_width > 2 ? max_width + 2 : 4,
+ uint32_t width = max_width > 2 ? max_width : 4,
height = g_ncompletions > 10 ? 10 : g_ncompletions;
- windows_show_popup(mb_dot.line - height, mb_dot.col, width, height);
+ windows_show_popup(mbpos.y + mb_dot.line - height, mbpos.x + mb_dot.col,
+ width, height);
} else {
- windows_close_popup();
+ abort_completion();
}
if (txt.allocated) {
@@ -313,8 +299,6 @@ int32_t find_file(struct command_ctx ctx, int argc, const char *argv[]) {
"find file: ");
}
- abort_completion();
-
pth = argv[0];
struct stat sb = {0};
if (stat(pth, &sb) < 0 && errno != ENOENT) {
@@ -351,7 +335,8 @@ int32_t write_file(struct command_ctx ctx, int argc, const char *argv[]) {
}
pth = argv[0];
- buffer_write_to(window_buffer(ctx.active_window), pth);
+ buffer_set_filename(window_buffer(ctx.active_window), pth);
+ buffer_to_file(window_buffer(ctx.active_window));
return 0;
}
@@ -432,7 +417,7 @@ void buffer_to_list_line(struct buffer *buffer, void *userdata) {
buffer->filename != NULL ? buffer->filename : "<no-file>");
if (written > 0) {
- buffer_add_text(listbuf, (uint8_t *)buf, written);
+ buffer_view_add(listbuf, (uint8_t *)buf, written);
}
}
@@ -441,7 +426,7 @@ int32_t buflist_visit_cmd(struct command_ctx ctx, int argc,
struct window *w = ctx.active_window;
struct buffer_view *bv = window_buffer_view(w);
- struct text_chunk text = buffer_get_line(bv->buffer, bv->dot.line);
+ struct text_chunk text = buffer_line(bv->buffer, bv->dot.line);
char *end = (char *)memchr(text.text, ' ', text.nbytes);
@@ -468,9 +453,9 @@ int32_t buflist_close_cmd(struct command_ctx ctx, int argc,
void buflist_refresh(struct buffers *buffers, struct buffer_view *target) {
buffer_set_readonly(target->buffer, false);
- buffer_clear(target);
+ buffer_clear(target->buffer);
buffers_for_each(buffers, buffer_to_list_line, target);
- buffer_goto_beginning(target);
+ buffer_view_goto_beginning(target);
buffer_set_readonly(target->buffer, true);
}
@@ -535,102 +520,102 @@ void register_global_commands(struct commands *commands,
register_search_replace_commands(commands);
}
-#define BUFFER_WRAPCMD_POS(fn) \
+#define BUFFER_VIEW_WRAPCMD(fn) \
static int32_t fn##_cmd(struct command_ctx ctx, int argc, \
const char *argv[]) { \
- fn(window_buffer_view(ctx.active_window)); \
+ buffer_view_##fn(window_buffer_view(ctx.active_window)); \
return 0; \
}
#define BUFFER_WRAPCMD(fn) \
static int32_t fn##_cmd(struct command_ctx ctx, int argc, \
const char *argv[]) { \
- fn(window_buffer(ctx.active_window)); \
+ buffer_##fn(window_buffer(ctx.active_window)); \
return 0; \
}
-BUFFER_WRAPCMD_POS(buffer_kill_line);
-BUFFER_WRAPCMD_POS(buffer_forward_delete_char);
-BUFFER_WRAPCMD_POS(buffer_backward_delete_char);
-BUFFER_WRAPCMD_POS(buffer_forward_delete_word);
-BUFFER_WRAPCMD_POS(buffer_backward_delete_word);
-BUFFER_WRAPCMD_POS(buffer_backward_char);
-BUFFER_WRAPCMD_POS(buffer_backward_word);
-BUFFER_WRAPCMD_POS(buffer_forward_char);
-BUFFER_WRAPCMD_POS(buffer_forward_word);
-BUFFER_WRAPCMD_POS(buffer_backward_line);
-BUFFER_WRAPCMD_POS(buffer_forward_line);
-BUFFER_WRAPCMD_POS(buffer_end_of_line);
-BUFFER_WRAPCMD_POS(buffer_beginning_of_line);
-BUFFER_WRAPCMD_POS(buffer_newline);
-BUFFER_WRAPCMD_POS(buffer_indent);
-BUFFER_WRAPCMD(buffer_to_file);
-BUFFER_WRAPCMD(buffer_reload);
-BUFFER_WRAPCMD_POS(buffer_set_mark);
-BUFFER_WRAPCMD_POS(buffer_clear_mark);
-BUFFER_WRAPCMD_POS(buffer_copy);
-BUFFER_WRAPCMD_POS(buffer_cut);
-BUFFER_WRAPCMD_POS(buffer_paste);
-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));
+BUFFER_WRAPCMD(to_file);
+BUFFER_WRAPCMD(reload);
+BUFFER_VIEW_WRAPCMD(kill_line);
+BUFFER_VIEW_WRAPCMD(forward_delete_char);
+BUFFER_VIEW_WRAPCMD(backward_delete_char);
+BUFFER_VIEW_WRAPCMD(forward_delete_word);
+BUFFER_VIEW_WRAPCMD(backward_delete_word);
+BUFFER_VIEW_WRAPCMD(backward_char);
+BUFFER_VIEW_WRAPCMD(backward_word);
+BUFFER_VIEW_WRAPCMD(forward_char);
+BUFFER_VIEW_WRAPCMD(forward_word);
+BUFFER_VIEW_WRAPCMD(backward_line);
+BUFFER_VIEW_WRAPCMD(forward_line);
+BUFFER_VIEW_WRAPCMD(goto_end_of_line);
+BUFFER_VIEW_WRAPCMD(goto_beginning_of_line);
+BUFFER_VIEW_WRAPCMD(newline);
+BUFFER_VIEW_WRAPCMD(indent);
+BUFFER_VIEW_WRAPCMD(set_mark);
+BUFFER_VIEW_WRAPCMD(clear_mark);
+BUFFER_VIEW_WRAPCMD(copy);
+BUFFER_VIEW_WRAPCMD(cut);
+BUFFER_VIEW_WRAPCMD(paste);
+BUFFER_VIEW_WRAPCMD(paste_older);
+BUFFER_VIEW_WRAPCMD(goto_beginning);
+BUFFER_VIEW_WRAPCMD(goto_end);
+BUFFER_VIEW_WRAPCMD(undo);
+
+static int32_t scroll_up_cmd(struct command_ctx ctx, int argc,
+ const char *argv[]) {
+ buffer_view_backward_nlines(window_buffer_view(ctx.active_window),
+ window_height(ctx.active_window) - 1);
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),
- window_height(ctx.active_window));
+static int32_t scroll_down_cmd(struct command_ctx ctx, int argc,
+ const char *argv[]) {
+ buffer_view_forward_nlines(window_buffer_view(ctx.active_window),
+ window_height(ctx.active_window) - 1);
return 0;
};
-static int32_t buffer_goto_line(struct command_ctx ctx, int argc,
- const char *argv[]) {
+static int32_t 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);
+ buffer_view_goto(window_buffer_view(ctx.active_window),
+ (struct location){.line = line, .col = 0});
}
void register_buffer_commands(struct commands *commands) {
static struct command buffer_commands[] = {
- {.name = "kill-line", .fn = buffer_kill_line_cmd},
- {.name = "delete-word", .fn = buffer_forward_delete_word_cmd},
- {.name = "backward-delete-word", .fn = buffer_backward_delete_word_cmd},
- {.name = "delete-char", .fn = buffer_forward_delete_char_cmd},
- {.name = "backward-delete-char", .fn = buffer_backward_delete_char_cmd},
- {.name = "backward-char", .fn = buffer_backward_char_cmd},
- {.name = "backward-word", .fn = buffer_backward_word_cmd},
- {.name = "forward-char", .fn = buffer_forward_char_cmd},
- {.name = "forward-word", .fn = buffer_forward_word_cmd},
- {.name = "backward-line", .fn = buffer_backward_line_cmd},
- {.name = "forward-line", .fn = buffer_forward_line_cmd},
- {.name = "end-of-line", .fn = buffer_end_of_line_cmd},
- {.name = "beginning-of-line", .fn = buffer_beginning_of_line_cmd},
- {.name = "newline", .fn = buffer_newline_cmd},
- {.name = "indent", .fn = buffer_indent_cmd},
- {.name = "buffer-write-to-file", .fn = buffer_to_file_cmd},
- {.name = "set-mark", .fn = buffer_set_mark_cmd},
- {.name = "clear-mark", .fn = buffer_clear_mark_cmd},
- {.name = "copy", .fn = buffer_copy_cmd},
- {.name = "cut", .fn = buffer_cut_cmd},
- {.name = "paste", .fn = buffer_paste_cmd},
- {.name = "paste-older", .fn = buffer_paste_older_cmd},
- {.name = "goto-beginning", .fn = buffer_goto_beginning_cmd},
- {.name = "goto-end", .fn = buffer_goto_end_cmd},
- {.name = "undo", .fn = buffer_undo_cmd},
- {.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},
+ {.name = "kill-line", .fn = kill_line_cmd},
+ {.name = "delete-word", .fn = forward_delete_word_cmd},
+ {.name = "backward-delete-word", .fn = backward_delete_word_cmd},
+ {.name = "delete-char", .fn = forward_delete_char_cmd},
+ {.name = "backward-delete-char", .fn = backward_delete_char_cmd},
+ {.name = "backward-char", .fn = backward_char_cmd},
+ {.name = "backward-word", .fn = backward_word_cmd},
+ {.name = "forward-char", .fn = forward_char_cmd},
+ {.name = "forward-word", .fn = forward_word_cmd},
+ {.name = "backward-line", .fn = backward_line_cmd},
+ {.name = "forward-line", .fn = forward_line_cmd},
+ {.name = "end-of-line", .fn = goto_end_of_line_cmd},
+ {.name = "beginning-of-line", .fn = goto_beginning_of_line_cmd},
+ {.name = "newline", .fn = newline_cmd},
+ {.name = "indent", .fn = indent_cmd},
+ {.name = "buffer-write-to-file", .fn = to_file_cmd},
+ {.name = "set-mark", .fn = set_mark_cmd},
+ {.name = "clear-mark", .fn = clear_mark_cmd},
+ {.name = "copy", .fn = copy_cmd},
+ {.name = "cut", .fn = cut_cmd},
+ {.name = "paste", .fn = paste_cmd},
+ {.name = "paste-older", .fn = paste_older_cmd},
+ {.name = "goto-beginning", .fn = goto_beginning_cmd},
+ {.name = "goto-end", .fn = goto_end_cmd},
+ {.name = "undo", .fn = undo_cmd},
+ {.name = "scroll-down", .fn = scroll_down_cmd},
+ {.name = "scroll-up", .fn = scroll_up_cmd},
+ {.name = "reload", .fn = reload_cmd},
+ {.name = "goto-line", .fn = goto_line},
};
register_commands(commands, buffer_commands,
diff --git a/src/main/main.c b/src/main/main.c
index b6ee3c0..fd69cff 100644
--- a/src/main/main.c
+++ b/src/main/main.c
@@ -11,6 +11,7 @@
#include "dged/allocator.h"
#include "dged/binding.h"
#include "dged/buffer.h"
+#include "dged/buffer_view.h"
#include "dged/buffers.h"
#include "dged/display.h"
#include "dged/lang.h"
@@ -127,7 +128,7 @@ int main(int argc, char *argv[]) {
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}};
- char *filename = NULL;
+ const char *filename = NULL;
uint32_t jumpline = 1;
bool goto_end = false;
char ch;
@@ -239,9 +240,13 @@ int main(int argc, char *argv[]) {
&minibuffer);
struct window *active = windows_get_active();
if (goto_end) {
- buffer_goto_end(window_buffer_view(active));
+ buffer_view_goto_end(window_buffer_view(active));
} else {
- buffer_goto(window_buffer_view(active), jumpline > 0 ? jumpline - 1 : 0, 0);
+ struct location to = {
+ .line = jumpline > 0 ? jumpline - 1 : 0,
+ .col = 0,
+ };
+ buffer_view_goto(window_buffer_view(active), to);
}
DECLARE_TIMER(buffer);
@@ -253,7 +258,6 @@ int main(int argc, char *argv[]) {
static uint32_t nkeychars = 0;
while (running) {
-
if (display_resized) {
windows_resize(display_height(display), display_width(display));
display_resized = false;
@@ -265,9 +269,6 @@ int main(int argc, char *argv[]) {
TIMED_SCOPE_END(buffer);
struct window *active_window = windows_get_active();
- if (minibuffer_focused()) {
- active_window = minibuffer_window();
- }
/* Update the screen by flushing command lists collected from updating the
* buffers.
@@ -275,14 +276,15 @@ int main(int argc, char *argv[]) {
TIMED_SCOPE_BEGIN(display);
display_begin_render(display);
windows_render(display);
- struct buffer_location cursor =
- window_absolute_cursor_location(active_window);
- display_move_cursor(display, cursor.line, cursor.col);
+ struct buffer_view *view = window_buffer_view(active_window);
+ struct location cursor = buffer_view_dot_to_relative(view);
+ struct window_position winpos = window_position(active_window);
+ display_move_cursor(display, winpos.y + cursor.line, winpos.x + cursor.col);
display_end_render(display);
TIMED_SCOPE_END(display);
/* This blocks for events, so if nothing has happened we block here and let
- * the CPU do something more useful than updating this narcissistic editor.
+ * the CPU do something more useful than updating this editor for no reason.
* This is also the reason that there is no timed scope around this, it
* simply makes no sense.
*/
@@ -343,7 +345,7 @@ int main(int argc, char *argv[]) {
}
}
} else if (k->mod == 0) {
- buffer_add_text(window_buffer_view(active_window),
+ buffer_view_add(window_buffer_view(active_window),
&kbd_upd.raw[k->start], k->end - k->start);
} else {
char keyname[16];
diff --git a/src/main/search-replace.c b/src/main/search-replace.c
index 828ce32..cd12d5d 100644
--- a/src/main/search-replace.c
+++ b/src/main/search-replace.c
@@ -4,6 +4,7 @@
#include "dged/binding.h"
#include "dged/buffer.h"
+#include "dged/buffer_view.h"
#include "dged/command.h"
#include "dged/minibuffer.h"
#include "dged/window.h"
@@ -13,7 +14,7 @@
static struct replace {
char *replace;
- struct match *matches;
+ struct region *matches;
uint32_t nmatches;
uint32_t current_match;
} g_current_replace = {0};
@@ -28,8 +29,8 @@ void abort_replace() {
minibuffer_abort_prompt();
}
-uint64_t matchdist(struct match *match, struct buffer_location loc) {
- struct buffer_location begin = match->begin;
+uint64_t matchdist(struct region *match, struct location loc) {
+ struct location begin = match->begin;
int64_t linedist = (int64_t)begin.line - (int64_t)loc.line;
int64_t coldist = (int64_t)begin.col - (int64_t)loc.col;
@@ -38,26 +39,10 @@ uint64_t matchdist(struct match *match, struct buffer_location loc) {
return (linedist * linedist) * 1e6 + coldist * coldist;
}
-int buffer_loc_cmp(struct buffer_location loc1, struct buffer_location loc2) {
- if (loc1.line < loc2.line) {
- return -1;
- } else if (loc1.line > loc2.line) {
- return 1;
- } else {
- if (loc1.col < loc2.col) {
- return -1;
- } else if (loc1.col > loc2.col) {
- return 1;
- } else {
- return 0;
- }
- }
-}
-
-static void highlight_matches(struct buffer *buffer, struct match *matches,
+static void highlight_matches(struct buffer *buffer, struct region *matches,
uint32_t nmatches, uint32_t current) {
for (uint32_t matchi = 0; matchi < nmatches; ++matchi) {
- struct match *m = &matches[matchi];
+ struct region *m = &matches[matchi];
if (matchi == current) {
buffer_add_text_property(
buffer, m->begin, m->end,
@@ -88,10 +73,12 @@ static int32_t replace_next(struct command_ctx ctx, int argc,
struct replace *state = &g_current_replace;
struct buffer_view *buffer_view = window_buffer_view(windows_get_active());
- struct match *m = &state->matches[state->current_match];
- buffer_set_mark_at(buffer_view, m->begin.line, m->begin.col);
- buffer_goto(buffer_view, m->end.line, m->end.col + 1);
- buffer_add_text(buffer_view, state->replace, strlen(state->replace));
+ struct region *m = &state->matches[state->current_match];
+ buffer_view_set_mark_at(buffer_view, (struct location){.line = m->begin.line,
+ .col = m->begin.col});
+ buffer_view_goto(buffer_view, (struct location){.line = m->end.line,
+ .col = m->end.col + 1});
+ buffer_view_add(buffer_view, state->replace, strlen(state->replace));
++state->current_match;
@@ -99,7 +86,8 @@ static int32_t replace_next(struct command_ctx ctx, int argc,
abort_replace();
} else {
m = &state->matches[state->current_match];
- buffer_goto(buffer_view, m->begin.line, m->begin.col);
+ buffer_view_goto(buffer_view, (struct location){.line = m->begin.line,
+ .col = m->begin.col});
highlight_matches(buffer_view->buffer, state->matches, state->nmatches,
state->current_match);
}
@@ -111,8 +99,9 @@ static int32_t skip_next(struct command_ctx ctx, int argc, const char *argv[]) {
struct replace *state = &g_current_replace;
struct buffer_view *buffer_view = window_buffer_view(windows_get_active());
- struct match *m = &state->matches[state->current_match];
- buffer_goto(buffer_view, m->end.line, m->end.col + 1);
+ struct region *m = &state->matches[state->current_match];
+ buffer_view_goto(buffer_view, (struct location){.line = m->end.line,
+ .col = m->end.col + 1});
++state->current_match;
@@ -120,7 +109,8 @@ static int32_t skip_next(struct command_ctx ctx, int argc, const char *argv[]) {
abort_replace();
} else {
m = &state->matches[state->current_match];
- buffer_goto(buffer_view, m->begin.line, m->begin.col);
+ buffer_view_goto(buffer_view, (struct location){.line = m->begin.line,
+ .col = m->begin.col});
highlight_matches(buffer_view->buffer, state->matches, state->nmatches,
state->current_match);
}
@@ -132,14 +122,14 @@ COMMAND_FN("replace-next", replace_next, replace_next, NULL);
COMMAND_FN("skip-next", skip_next, skip_next, NULL);
static int cmp_matches(const void *m1, const void *m2) {
- struct match *match1 = (struct match *)m1;
- struct match *match2 = (struct match *)m2;
- struct buffer_location dot = window_buffer_view(windows_get_active())->dot;
+ struct region *match1 = (struct region *)m1;
+ struct region *match2 = (struct region *)m2;
+ struct location dot = window_buffer_view(windows_get_active())->dot;
uint64_t dist1 = matchdist(match1, dot);
uint64_t dist2 = matchdist(match2, dot);
- int loc1 = buffer_loc_cmp(match1->begin, dot);
- int loc2 = buffer_loc_cmp(match2->begin, dot);
+ int loc1 = location_compare(match1->begin, dot);
+ int loc2 = location_compare(match2->begin, dot);
int64_t score1 = dist1 * loc1;
int64_t score2 = dist2 * loc2;
@@ -166,7 +156,7 @@ static int32_t replace(struct command_ctx ctx, int argc, const char *argv[]) {
}
struct buffer_view *buffer_view = window_buffer_view(windows_get_active());
- struct match *matches = NULL;
+ struct region *matches = NULL;
uint32_t nmatches = 0;
buffer_find(buffer_view->buffer, argv[0], &matches, &nmatches);
@@ -177,7 +167,7 @@ static int32_t replace(struct command_ctx ctx, int argc, const char *argv[]) {
}
// sort matches
- qsort(matches, nmatches, sizeof(struct match), cmp_matches);
+ qsort(matches, nmatches, sizeof(struct region), cmp_matches);
g_current_replace = (struct replace){
.replace = strdup(argv[1]),
@@ -186,8 +176,9 @@ static int32_t replace(struct command_ctx ctx, int argc, const char *argv[]) {
.current_match = 0,
};
- struct match *m = &g_current_replace.matches[0];
- buffer_goto(buffer_view, m->begin.line, m->begin.col);
+ struct region *m = &g_current_replace.matches[0];
+ buffer_view_goto(buffer_view, (struct location){.line = m->begin.line,
+ .col = m->begin.col});
highlight_matches(buffer_view->buffer, g_current_replace.matches,
g_current_replace.nmatches, 0);
@@ -203,6 +194,7 @@ static int32_t replace(struct command_ctx ctx, int argc, const char *argv[]) {
}
static char *g_last_search = NULL;
+static bool g_last_search_interactive = false;
const char *search_prompt(bool reverse) {
const char *txt = "search (down): ";
@@ -215,13 +207,13 @@ const char *search_prompt(bool reverse) {
struct closest_match {
bool found;
- struct match closest;
+ struct region closest;
};
static struct closest_match find_closest(struct buffer_view *view,
const char *pattern, bool highlight,
bool reverse) {
- struct match *matches = NULL;
+ struct region *matches = NULL;
uint32_t nmatches = 0;
struct closest_match res = {
.found = false,
@@ -233,10 +225,10 @@ static struct closest_match find_closest(struct buffer_view *view,
// find the "nearest" match
if (nmatches > 0) {
res.found = true;
- struct match *closest = &matches[0];
+ struct region *closest = &matches[0];
int64_t closest_dist = INT64_MAX;
for (uint32_t matchi = 0; matchi < nmatches; ++matchi) {
- struct match *m = &matches[matchi];
+ struct region *m = &matches[matchi];
if (highlight) {
buffer_add_text_property(
@@ -249,7 +241,7 @@ static struct closest_match find_closest(struct buffer_view *view,
.fg = 0,
}});
}
- int res = buffer_loc_cmp(m->begin, view->dot);
+ int res = location_compare(m->begin, view->dot);
uint64_t dist = matchdist(m, view->dot);
if (((res < 0 && reverse) || (res > 0 && !reverse)) &&
dist < closest_dist) {
@@ -279,12 +271,13 @@ static struct closest_match find_closest(struct buffer_view *view,
void do_search(struct buffer_view *view, const char *pattern, bool reverse) {
g_last_search = strdup(pattern);
- struct buffer_view *buffer_view = window_buffer_view(windows_get_active());
- struct closest_match m = find_closest(buffer_view, pattern, true, reverse);
+ struct closest_match m = find_closest(view, pattern, true, reverse);
// find the "nearest" match
if (m.found) {
- buffer_goto(buffer_view, m.closest.begin.line, m.closest.begin.col);
+ buffer_view_goto(view,
+ (struct location){.line = m.closest.begin.line,
+ .col = m.closest.begin.col});
} else {
minibuffer_echo_timeout(4, "%s not found", pattern);
}
@@ -292,13 +285,13 @@ void do_search(struct buffer_view *view, const char *pattern, bool reverse) {
int32_t search_interactive(struct command_ctx ctx, int argc,
const char *argv[]) {
+ g_last_search_interactive = true;
const char *pattern = NULL;
if (minibuffer_content().nbytes == 0) {
// recall the last search, if any
if (g_last_search != NULL) {
struct buffer_view *view = window_buffer_view(minibuffer_window());
- buffer_clear(view);
- buffer_add_text(view, (uint8_t *)g_last_search, strlen(g_last_search));
+ buffer_set_text(view->buffer, (uint8_t *)g_last_search, strlen(g_last_search));
pattern = g_last_search;
}
} else {
@@ -309,11 +302,10 @@ int32_t search_interactive(struct command_ctx ctx, int argc,
pattern = p;
}
- minibuffer_set_prompt(search_prompt(*(bool *)ctx.userdata));
+ minibuffer_set_prompt(search_prompt(*(bool*)ctx.userdata));
if (pattern != NULL) {
- // ctx.active_window would be the minibuffer window
- do_search(window_buffer_view(windows_get_active()), pattern,
+ do_search(window_buffer_view(minibuffer_target_window()), pattern,
*(bool *)ctx.userdata);
free((char *)pattern);
}
@@ -329,7 +321,7 @@ COMMAND_FN("search-backward", search_backward, search_interactive,
&search_dir_backward);
int32_t find(struct command_ctx ctx, int argc, const char *argv[]) {
- bool reverse = strcmp((char *)ctx.userdata, "backward") == 0;
+ bool reverse = *(bool *)ctx.userdata;
if (argc == 0) {
struct binding bindings[] = {
ANONYMOUS_BINDING(Ctrl, 'S', &search_forward_command),
@@ -341,6 +333,11 @@ int32_t find(struct command_ctx ctx, int argc, const char *argv[]) {
}
reset_minibuffer_keys(minibuffer_buffer());
+ if (g_last_search_interactive) {
+ g_last_search_interactive = false;
+ return 0;
+ }
+
struct text_chunk content = minibuffer_content();
char *pattern = malloc(content.nbytes + 1);
strncpy(pattern, content.text, content.nbytes);
@@ -354,8 +351,8 @@ int32_t find(struct command_ctx ctx, int argc, const char *argv[]) {
void register_search_replace_commands(struct commands *commands) {
struct command search_replace_commands[] = {
- {.name = "find-next", .fn = find, .userdata = "forward"},
- {.name = "find-prev", .fn = find, .userdata = "backward"},
+ {.name = "find-next", .fn = find, .userdata = &search_dir_forward},
+ {.name = "find-prev", .fn = find, .userdata = &search_dir_backward},
{.name = "replace", .fn = replace},
};