diff options
Diffstat (limited to 'ted.c')
-rw-r--r-- | ted.c | 90 |
1 files changed, 84 insertions, 6 deletions
@@ -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) { |