summaryrefslogtreecommitdiff
path: root/ted.c
diff options
context:
space:
mode:
Diffstat (limited to 'ted.c')
-rw-r--r--ted.c90
1 files changed, 84 insertions, 6 deletions
diff --git a/ted.c b/ted.c
index b5403c6..4c96e86 100644
--- a/ted.c
+++ b/ted.c
@@ -982,16 +982,96 @@ void ted_test(Ted *ted) {
printf("all good as far as i know :3\n");
}
+void ted_perform_workspace_edit(Ted *ted, LSP *lsp, const LSPResponse *response, const LSPWorkspaceEdit *edit) {
+ TextBuffer *const start_buffer = ted_active_buffer(ted);
+ arr_foreach_ptr(edit->changes, const LSPWorkspaceChange, change) {
+ if (change->type == LSP_CHANGE_DELETE && change->data.delete.recursive) {
+ ted_error(ted, "refusing to perform edit because it involves a recursive deletion\n"
+ "I'm too scared to go through with this");
+ return;
+ }
+ }
+
+ arr_foreach_ptr(edit->changes, const LSPWorkspaceChange, change) {
+ switch (change->type) {
+ case LSP_CHANGE_EDITS: {
+ const LSPWorkspaceChangeEdit *change_data = &change->data.edit;
+ const char *path = lsp_document_path(lsp, change_data->document);
+ if (!ted_open_file(ted, path)) goto done;
+
+ TextBuffer *buffer = ted_get_buffer_with_file(ted, path);
+ // chain all edits together so they can be undone with one ctrl+z
+ buffer_start_edit_chain(buffer);
+
+ if (!buffer) {
+ // this should never happen since we just
+ // successfully opened it
+ assert(0);
+ goto done;
+ }
+
+ buffer_apply_lsp_text_edits(buffer, response, change_data->edits, arr_len(change_data->edits));
+ }
+ break;
+ case LSP_CHANGE_RENAME: {
+ const LSPWorkspaceChangeRename *rename = &change->data.rename;
+ const char *old = lsp_document_path(lsp, rename->old);
+ const char *new = lsp_document_path(lsp, rename->new);
+ FsType new_type = fs_path_type(new);
+ if (new_type == FS_DIRECTORY) {
+ ted_error(ted, "Aborting rename since it's asking to overwrite a directory.");
+ goto done;
+ }
+
+ if (rename->ignore_if_exists && new_type != FS_NON_EXISTENT) {
+ break;
+ }
+ if (!rename->overwrite && new_type != FS_NON_EXISTENT) {
+ ted_error(ted, "Aborting rename since it would overwrite a file.");
+ goto done;
+ }
+ os_rename_overwrite(old, new);
+ if (ted_close_buffer_with_file(ted, old))
+ ted_open_file(ted, new);
+ } break;
+ case LSP_CHANGE_DELETE: {
+ const LSPWorkspaceChangeDelete *delete = &change->data.delete;
+ const char *path = lsp_document_path(lsp, delete->document);
+ remove(path);
+ ted_close_buffer_with_file(ted, path);
+ } break;
+ case LSP_CHANGE_CREATE: {
+ const LSPWorkspaceChangeCreate *create = &change->data.create;
+ const char *path = lsp_document_path(lsp, create->document);
+ FILE *fp = fopen(path, create->overwrite ? "wb" : "ab");
+ if (fp) fclose(fp);
+ ted_open_file(ted, path);
+ } break;
+ }
+ }
+ done:
+
+ {
+ // end all edit chains in all buffers
+ // they're almost definitely all created by us
+ arr_foreach_ptr(ted->buffers, TextBufferPtr, pbuffer) {
+ buffer_end_edit_chain(*pbuffer);
+ }
+
+ ted_save_all(ted);
+ }
+ ted_switch_to_buffer(ted, start_buffer);
+}
+
#if HAS_INOTIFY
void ted_check_inotify(Ted *ted) {
// see buffer_externally_changed definition for why this exists
if (ted->inotify_fd == -1) return;
int *watches_modified = NULL;
- char events[16384 * sizeof(struct inotify_event)];
- ssize_t bytes = read(ted->inotify_fd, events, sizeof events);
+ ssize_t bytes = read(ted->inotify_fd, ted->inotify_event_buf, sizeof ted->inotify_event_buf);
for (int i = 0; i + (int)sizeof(struct inotify_event) <= bytes; i += (int)sizeof(struct inotify_event)) {
struct inotify_event event;
- memcpy(&event, &events[i * (int)sizeof event], sizeof event);
+ memcpy(&event, &ted->inotify_event_buf[i], sizeof event);
if (event.mask & INOTIFY_MASK) {
bool new = true;
arr_foreach_ptr(watches_modified, int, w) {
@@ -1002,12 +1082,10 @@ void ted_check_inotify(Ted *ted) {
}
if (new) arr_add(watches_modified, event.wd);
}
- i += (int)event.len; // should always be 0 in theory...
+ i += (int)event.len; // should always be 0 in theory given our event types...
}
// ideally we'd read more events in a loop here but then we'd hang if someone is constantly
// changing the file. probably no good way of dealing with that though.
- // for what it's worth, 16384 is the default max inotify queue size, so we should always
- // read all the events with that one read call.
arr_foreach_ptr(ted->buffers, TextBufferPtr, pbuffer) {
int watch = buffer_inotify_watch(*pbuffer);
arr_foreach_ptr(watches_modified, int, w) {