summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-08-06 22:48:10 -0400
committerpommicket <pommicket@gmail.com>2023-08-06 22:48:10 -0400
commit81354f84a463ef782f53358a3a3f9b359ece9a64 (patch)
treef60ab47ac87d2f7195f19aefef1fa03d69e71e1d
parent419d5b17f27b8d3dda1e59c6193f1ad9c3d218f8 (diff)
rework edit notify
-rw-r--r--buffer.c57
-rw-r--r--find.c17
-rw-r--r--main.c9
-rw-r--r--ted-internal.h14
-rw-r--r--ted.c20
-rw-r--r--ted.h32
6 files changed, 102 insertions, 47 deletions
diff --git a/buffer.c b/buffer.c
index efed7fe..2c8e8e2 100644
--- a/buffer.c
+++ b/buffer.c
@@ -24,12 +24,6 @@ struct BufferEdit {
double time; // time at start of edit (i.e. the time just before the edit), in seconds since epoch
};
-struct EditNotifyInfo {
- EditNotify fn;
- void *context;
- EditNotifyID id;
-};
-
// this is a macro so we get -Wformat warnings
#define buffer_error(buffer, ...) \
snprintf(buffer->error, sizeof buffer->error - 1, __VA_ARGS__)
@@ -791,7 +785,6 @@ void buffer_free(TextBuffer *buffer) {
arr_free(buffer->undo_history);
arr_free(buffer->redo_history);
- arr_free(buffer->edit_notifys);
memset(buffer, 0, sizeof *buffer);
}
@@ -1739,9 +1732,17 @@ BufferPos buffer_insert_text_at_pos(TextBuffer *buffer, BufferPos pos, String32
BufferPos b = {.line = line_idx, .index = index};
free(str_alloc);
+ const EditInfo info = {
+ .pos = pos,
+ .chars_deleted = 0,
+ .newlines_deleted = 0,
+ .chars_inserted = insertion_len,
+ .newlines_inserted = n_added_lines,
+ };
+
signature_help_retrigger(buffer->ted);
- arr_foreach_ptr(buffer->edit_notifys, EditNotifyInfo, n) {
- n->fn(buffer, n->context, pos, 0, insertion_len);
+ arr_foreach_ptr(buffer->ted->edit_notifys, EditNotifyInfo, n) {
+ n->fn(n->context, buffer, &info);
}
return b;
@@ -2209,6 +2210,8 @@ void buffer_delete_chars_at_pos(TextBuffer *buffer, BufferPos pos, i64 nchars_)
u32 line_idx = pos.line;
u32 index = pos.index;
Line *line = &buffer->lines[line_idx], *lines_end = &buffer->lines[buffer->nlines];
+ u32 newlines_deleted = 0;
+
if (nchars + index > line->len) {
// delete rest of line
nchars -= line->len - index + 1; // +1 for the newline that got deleted
@@ -2223,6 +2226,7 @@ void buffer_delete_chars_at_pos(TextBuffer *buffer, BufferPos pos, i64 nchars_)
// delete everything to the end of the file
for (u32 idx = line_idx + 1; idx < buffer->nlines; ++idx) {
buffer_line_free(&buffer->lines[idx]);
+ ++newlines_deleted;
}
buffer_shorten(buffer, line_idx + 1);
} else {
@@ -2235,8 +2239,8 @@ void buffer_delete_chars_at_pos(TextBuffer *buffer, BufferPos pos, i64 nchars_)
// remove all lines between line + 1 and last_line (inclusive).
buffer_delete_lines(buffer, line_idx + 1, (u32)(last_line - line));
- u32 lines_removed = (u32)(last_line - line);
- buffer_shorten(buffer, buffer->nlines - lines_removed);
+ newlines_deleted = (u32)(last_line - line);
+ buffer_shorten(buffer, buffer->nlines - newlines_deleted);
}
} else {
// just delete characters from this line
@@ -2254,8 +2258,15 @@ void buffer_delete_chars_at_pos(TextBuffer *buffer, BufferPos pos, i64 nchars_)
buffer_lines_modified(buffer, line_idx, line_idx);
signature_help_retrigger(buffer->ted);
- arr_foreach_ptr(buffer->edit_notifys, EditNotifyInfo, info) {
- info->fn(buffer, info->context, pos, deletion_len, 0);
+ const EditInfo info = {
+ .pos = pos,
+ .chars_inserted = 0,
+ .newlines_inserted = 0,
+ .chars_deleted = deletion_len,
+ .newlines_deleted = newlines_deleted,
+ };
+ arr_foreach_ptr(buffer->ted->edit_notifys, EditNotifyInfo, n) {
+ n->fn(n->context, buffer, &info);
}
}
@@ -3519,23 +3530,3 @@ void buffer_highlight_lsp_range(TextBuffer *buffer, LSPRange range, ColorSetting
gl_geometry_rect(r2, colors[COLOR_HOVER_HL]);
}
}
-
-u64 buffer_add_edit_notify(TextBuffer *buffer, EditNotify notify, void *context) {
- EditNotifyInfo info = {
- .fn = notify,
- .context = context,
- .id = ++buffer->edit_notify_id,
- };
- arr_add(buffer->edit_notifys, info);
- return info.id;
-}
-
-void buffer_remove_edit_notify(TextBuffer *buffer, EditNotifyID id) {
- u32 i;
- for (i = 0; i < arr_len(buffer->edit_notifys); ++i) {
- if (buffer->edit_notifys[i].id == id) {
- arr_remove(buffer->edit_notifys, i);
- break;
- }
- }
-}
diff --git a/find.c b/find.c
index de5ec15..046cef1 100644
--- a/find.c
+++ b/find.c
@@ -25,6 +25,23 @@ TextBuffer *find_search_buffer(Ted *ted) {
return ted->prev_active_buffer;
}
+static void find_edit_notify(void *context, TextBuffer *buffer, const EditInfo *info) {
+ (void)context;
+ Ted *ted = buffer->ted;
+ if (!ted->find) {
+ return;
+ }
+ if (buffer != find_search_buffer(ted))
+ return;
+
+ // TODO: update find result locations
+// printf("%s %u\n",buffer_get_path(buffer),info->newlines_inserted);
+}
+
+void find_init(Ted *ted) {
+ ted_add_edit_notify(ted, find_edit_notify, NULL);
+}
+
static void ted_error_from_pcre2_error(Ted *ted, int err) {
char32_t buf[256] = {0};
diff --git a/main.c b/main.c
index 19d4b6c..3dd4fe5 100644
--- a/main.c
+++ b/main.c
@@ -1,9 +1,11 @@
/*
+TODO:
+- robust find (results shouldn't move around when you type things)
+
FUTURE FEATURES:
- autodetect indentation (tabs vs spaces)
-- robust find (results shouldn't move around when you type things)
- config variables
-- bind key to multiple commands
+- bind key to series of commands
- convert macro to command list
- plugins?
- built-in plugins
@@ -501,6 +503,7 @@ int main(int argc, char **argv) {
hover_init(ted);
rename_symbol_init(ted);
document_link_init(ted);
+ find_init(ted);
PROFILE_TIME(gl_end)
@@ -1193,6 +1196,8 @@ int main(int argc, char **argv) {
rename_symbol_quit(ted);
document_link_quit(ted);
menu_quit(ted);
+ arr_free(ted->edit_notifys);
+
for (int i = 0; i < TED_LSP_MAX; ++i) {
if (!ted->lsps[i]) break;
diff --git a/ted-internal.h b/ted-internal.h
index fdd46ef..3f5481a 100644
--- a/ted-internal.h
+++ b/ted-internal.h
@@ -167,7 +167,11 @@ typedef struct ConfigPart ConfigPart;
/// A single undoable edit to a buffer
typedef struct BufferEdit BufferEdit;
-typedef struct EditNotifyInfo EditNotifyInfo;
+typedef struct EditNotifyInfo {
+ EditNotify fn;
+ void *context;
+ EditNotifyID id;
+} EditNotifyInfo;
struct TextBuffer {
/// NULL if this buffer is untitled or doesn't correspond to a file (e.g. line buffers)
@@ -250,9 +254,6 @@ struct TextBuffer {
BufferEdit *undo_history;
/// dynamic array of redo history
BufferEdit *redo_history;
-
- u64 edit_notify_id;
- EditNotifyInfo *edit_notifys;
};
/// an entry in a selector menu (e.g. the "open" menu)
@@ -588,6 +589,10 @@ struct Ted {
MessageType message_type;
MessageType message_shown_type;
char message_shown[512];
+
+
+ u64 edit_notify_id;
+ EditNotifyInfo *edit_notifys;
};
// === buffer.c ===
@@ -661,6 +666,7 @@ void config_free(Ted *ted);
long context_score(const char *path, Language lang, const SettingsContext *context);
// === find.c ===
+void find_init(Ted *ted);
/// height of the find/find+replace menu in pixels
float find_menu_height(Ted *ted);
void find_menu_frame(Ted *ted, Rect menu_bounds);
diff --git a/ted.c b/ted.c
index 175e905..14cc440 100644
--- a/ted.c
+++ b/ted.c
@@ -859,3 +859,23 @@ void ted_color_settings_for_message_type(MessageType type, ColorSetting *bg_colo
}
}
+
+u64 ted_add_edit_notify(Ted *ted, EditNotify notify, void *context) {
+ EditNotifyInfo info = {
+ .fn = notify,
+ .context = context,
+ .id = ++ted->edit_notify_id,
+ };
+ arr_add(ted->edit_notifys, info);
+ return info.id;
+}
+
+void ted_remove_edit_notify(Ted *ted, EditNotifyID id) {
+ u32 i;
+ for (i = 0; i < arr_len(ted->edit_notifys); ++i) {
+ if (ted->edit_notifys[i].id == id) {
+ arr_remove(ted->edit_notifys, i);
+ break;
+ }
+ }
+}
diff --git a/ted.h b/ted.h
index 1b9338a..66e8c04 100644
--- a/ted.h
+++ b/ted.h
@@ -281,12 +281,28 @@ typedef struct {
char reserved[128];
} MenuInfo;
+/// information about an edit provided to \ref EditNotify.
+///
+/// NOTE: more members may be added in the future (this does not affect backwards compatibility)
+typedef struct {
+ /// position where the edit took place
+ BufferPos pos;
+ /// number of characters (unicode codepoints, including newlines) deleted
+ u32 chars_deleted;
+ /// number of characters (unicode codepoints, including newlines) inserted
+ u32 chars_inserted;
+ /// number of newlines deleted
+ u32 newlines_deleted;
+ /// number of newlines inserted
+ u32 newlines_inserted;
+} EditInfo;
+
/// this type of callback is called right after an edit is made to the buffer.
///
/// you will be given the number of characters deleted at the position, the number
/// of characters inserted after the position, and the context pointer
-/// which was passed to \ref buffer_add_edit_notify.
-typedef void (*EditNotify)(TextBuffer *buffer, void *context, BufferPos pos, u32 chars_deleted, u32 chars_inserted);
+/// which was passed to \ref ted_add_edit_notify.
+typedef void (*EditNotify)(void *context, TextBuffer *buffer, const EditInfo *info);
typedef u64 EditNotifyID;
@@ -642,12 +658,6 @@ int buffer_pos_cmp(BufferPos p1, BufferPos p2);
/// returns "`p2 - p1`", that is, the number of characters between `p1` and `p2`,
/// but negative if `p1` comes after `p2`.
i64 buffer_pos_diff(TextBuffer *buffer, BufferPos p1, BufferPos p2);
-/// add a \ref EditNotify callback which will be called whenever `buffer` is edited.
-///
-/// returns an ID which can be used with \ref buffer_remove_edit_notify
-EditNotifyID buffer_add_edit_notify(TextBuffer *buffer, EditNotify notify, void *context);
-/// remove edit notify callback. if `id` is zero or invalid, no action is taken.
-void buffer_remove_edit_notify(TextBuffer *buffer, EditNotifyID id);
// === build.c ===
/// clear build errors and stop
@@ -1021,6 +1031,12 @@ Status ted_get_mouse_buffer_pos(Ted *ted, TextBuffer **pbuffer, BufferPos *ppos)
void ted_flash_error_cursor(Ted *ted);
/// how tall is a line buffer?
float ted_line_buffer_height(Ted *ted);
+/// add a \ref EditNotify callback which will be called whenever `buffer` is edited.
+///
+/// returns an ID which can be used with \ref ted_remove_edit_notify
+EditNotifyID ted_add_edit_notify(Ted *ted, EditNotify notify, void *context);
+/// remove edit notify callback. if `id` is zero or invalid, no action is taken.
+void ted_remove_edit_notify(Ted *ted, EditNotifyID id);
// === ui.c ===
/// move selector cursor up by `n` entries