#ifndef EDITOR_H #define EDITOR_H #include "editor/completions.h" #include "editor/indents.h" #include "io/knot.h" #include "io/sysio.h" #include "syntax/extras.h" #include "syntax/parser.h" #include "ui/completionbox.h" #include "ui/diagnostics.h" #include "ui/hover.h" #include "utils/utils.h" #include #define CHAR 0 #define WORD 1 #define LINE 2 #define EXTRA_META 4 #define INDENT_WIDTH 2 // autocomplete lua// Bracket closing / tab on enter struct Editor { std::string filename; std::string uri; Knot *root; std::shared_mutex knot_mtx; Coord cursor; uint32_t cursor_preffered; Coord selection; bool selection_active; bool unix_eol; // false for windows int selection_type; Coord position; Coord size; Coord scroll; Language lang; uint32_t hooks[94]; bool jumper_set; std::shared_mutex v_mtx; std::vector warnings; bool warnings_dirty; VAI ai; std::shared_mutex lsp_mtx; std::shared_ptr lsp; bool hover_active; HoverBox hover; bool diagnostics_active; DiagnosticBox diagnostics; std::atomic lsp_version = 1; CompletionSession completion; IndentationEngine indents; Parser *parser; ExtraHighlighter extra_hl; bool is_css_color; }; Editor *new_editor(const char *filename_arg, Coord position, Coord size, uint8_t eol); void save_file(Editor *editor); void free_editor(Editor *editor); void render_editor(Editor *editor); void cursor_up(Editor *editor, uint32_t number); void cursor_down(Editor *editor, uint32_t number); Coord move_left(Editor *editor, Coord cursor, uint32_t number); Coord move_right(Editor *editor, Coord cursor, uint32_t number); void cursor_left(Editor *editor, uint32_t number); void cursor_right(Editor *editor, uint32_t number); void scroll_up(Editor *editor, int32_t number); void scroll_down(Editor *editor, uint32_t number); void ensure_cursor(Editor *editor); void ensure_scroll(Editor *editor); void handle_editor_event(Editor *editor, KeyEvent event); void edit_erase(Editor *editor, Coord pos, int64_t len); void edit_insert(Editor *editor, Coord pos, char *data, uint32_t len); void edit_replace(Editor *editor, Coord start, Coord end, const char *text, uint32_t len); Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y); char *get_selection(Editor *editor, uint32_t *out_len, Coord *out_start); void selection_bounds(Editor *editor, Coord *out_start, Coord *out_end); void editor_worker(Editor *editor); void move_line_down(Editor *editor); void move_line_up(Editor *editor); void word_boundaries(Editor *editor, Coord coord, uint32_t *prev_col, uint32_t *next_col, uint32_t *prev_clusters, uint32_t *next_clusters); void word_boundaries_exclusive(Editor *editor, Coord coord, uint32_t *prev_col, uint32_t *next_col); void editor_lsp_handle(Editor *editor, json msg); void apply_lsp_edits(Editor *editor, std::vector edits, bool move); void completion_resolve_doc(Editor *editor); void complete_accept(Editor *editor); void complete_next(Editor *editor); void complete_prev(Editor *editor); void complete_select(Editor *editor, uint8_t index); void handle_completion(Editor *editor, KeyEvent event); inline void apply_hook_insertion(Editor *editor, uint32_t line, uint32_t rows) { for (auto &hook : editor->hooks) if (hook > line) hook += rows; } inline void apply_hook_deletion(Editor *editor, uint32_t removal_start, uint32_t removal_end) { for (auto &hook : editor->hooks) if (hook > removal_start) hook -= removal_end - removal_start + 1; } inline static void utf8_normalize_edit(Editor *editor, TextEdit *edit) { std::shared_lock lock(editor->knot_mtx); if (edit->start.row > editor->root->line_count) { edit->start.row = editor->root->line_count; edit->start.col = UINT32_MAX; } if (edit->end.row > editor->root->line_count) { edit->end.row = editor->root->line_count; edit->end.col = UINT32_MAX; } LineIterator *it = begin_l_iter(editor->root, edit->start.row); if (!it) return; uint32_t len; char *line = next_line(it, &len); if (!line) { free(it->buffer); free(it); return; } if (edit->start.col < len) edit->start.col = utf16_offset_to_utf8(line, len, edit->start.col); else edit->start.col = len; if (edit->end.row == edit->start.row) { if (edit->end.col < len) edit->end.col = utf16_offset_to_utf8(line, len, edit->end.col); else edit->end.col = len; free(it->buffer); free(it); return; } free(it->buffer); free(it); it = begin_l_iter(editor->root, edit->end.row); if (!it) return; line = next_line(it, &len); if (!line) { free(it->buffer); free(it); return; } if (edit->end.col < len) edit->end.col = utf16_offset_to_utf8(line, len, edit->end.col); else edit->end.col = len; free(it->buffer); free(it); } #endif