diff options
author | pommicket <pommicket@gmail.com> | 2022-12-23 14:48:32 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-12-23 14:48:32 -0500 |
commit | dbab768e4d0be378e65399f32f26edb4756533ce (patch) | |
tree | 7cd92c46903df99c1c3ad084d2eab0013f67c4ab | |
parent | 002215c37f6a1ced083c78b7c9b6f86f472b23cd (diff) |
completion context + don't flash cursor if trigger character
-rw-r--r-- | autocomplete.c | 19 | ||||
-rw-r--r-- | command.c | 2 | ||||
-rw-r--r-- | lsp-write.c | 10 | ||||
-rw-r--r-- | lsp.h | 13 | ||||
-rw-r--r-- | main.c | 8 | ||||
-rw-r--r-- | ted.h | 3 |
6 files changed, 44 insertions, 11 deletions
diff --git a/autocomplete.c b/autocomplete.c index 335a502..020a2e3 100644 --- a/autocomplete.c +++ b/autocomplete.c @@ -74,16 +74,19 @@ static bool autocomplete_using_lsp(Ted *ted) { } static void autocomplete_no_suggestions(Ted *ted) { - ted->cursor_error_time = time_get_seconds(); + Autocomplete *ac = &ted->autocomplete; + if (ac->trigger_char == 0) + ted->cursor_error_time = time_get_seconds(); autocomplete_close(ted); } -static void autocomplete_find_completions(Ted *ted) { +static void autocomplete_find_completions(Ted *ted, char32_t trigger_char) { Autocomplete *ac = &ted->autocomplete; TextBuffer *buffer = ted->active_buffer; BufferPos pos = buffer->cursor_pos; if (buffer_pos_eq(pos, ac->last_pos)) return; // no need to update completions. + ac->trigger_char = trigger_char; ac->last_pos = pos; LSP *lsp = buffer_lsp(buffer); @@ -91,12 +94,18 @@ static void autocomplete_find_completions(Ted *ted) { LSPRequest request = { .type = LSP_REQUEST_COMPLETION }; + bool invoked = ac->trigger_char == 0 || is_word(ac->trigger_char); request.data.completion = (LSPRequestCompletion) { .position = { .document = lsp_document_id(lsp, buffer->filename), .pos = buffer_pos_to_lsp(buffer, pos) + }, + .context = { + .trigger_kind = invoked ? LSP_TRIGGER_INVOKED : LSP_TRIGGER_CHARACTER, + .trigger_character = {0}, } }; + unicode_utf32_to_utf8(request.data.completion.context.trigger_character, ac->trigger_char); lsp_send_request(lsp, &request); if (!ac->completions) ac->waiting_for_lsp = true; @@ -169,7 +178,7 @@ static void autocomplete_process_lsp_response(Ted *ted, const LSPResponse *respo } // open autocomplete, or just do the completion if there's only one suggestion -static void autocomplete_open(Ted *ted) { +static void autocomplete_open(Ted *ted, char32_t trigger_character) { Autocomplete *ac = &ted->autocomplete; if (ac->open) return; if (!ted->active_buffer) return; @@ -180,7 +189,7 @@ static void autocomplete_open(Ted *ted) { ted->cursor_error_time = 0; ac->last_pos = (BufferPos){0,0}; ac->cursor = 0; - autocomplete_find_completions(ted); + autocomplete_find_completions(ted, trigger_character); switch (arr_len(ac->completions)) { case 0: @@ -228,7 +237,7 @@ static void autocomplete_frame(Ted *ted) { u32 const *colors = settings->colors; float const padding = settings->padding; - autocomplete_find_completions(ted); + autocomplete_find_completions(ted, 0); Autocompletion completions[AUTOCOMPLETE_NCOMPLETIONS_VISIBLE] = {0}; size_t ncompletions = 0; @@ -287,7 +287,7 @@ void command_execute(Ted *ted, Command c, i64 argument) { if (ted->autocomplete.open) autocomplete_next(ted); else - autocomplete_open(ted); + autocomplete_open(ted, 0); break; case CMD_AUTOCOMPLETE_BACK: if (ted->autocomplete.open) diff --git a/lsp-write.c b/lsp-write.c index 87cb238..808f479 100644 --- a/lsp-write.c +++ b/lsp-write.c @@ -323,6 +323,7 @@ static void write_request(LSP *lsp, LSPRequest *request) { } write_arr_end(o); write_obj_end(o); + write_key_bool(o, "contextSupport", true); write_obj_end(o); write_obj_end(o); write_obj_end(o); @@ -383,6 +384,15 @@ static void write_request(LSP *lsp, LSPRequest *request) { write_key_file_uri(o, "uri", completion->position.document); write_obj_end(o); write_key_position(o, "position", completion->position.pos); + const LSPCompletionContext *context = &completion->context; + LSPCompletionTriggerKind trigger_kind = context->trigger_kind; + if (trigger_kind != LSP_TRIGGER_NONE) { + write_key_obj_start(o, "context"); + write_key_number(o, "triggerKind", trigger_kind); + if (trigger_kind == LSP_TRIGGER_CHARACTER) + write_key_string(o, "triggerCharacter", context->trigger_character); + write_obj_end(o); + } write_obj_end(o); } break; } @@ -88,8 +88,21 @@ typedef struct { LSPPosition pos; } LSPDocumentPosition; +typedef enum { + LSP_TRIGGER_NONE = 0, // not actually defined in LSP spec + LSP_TRIGGER_INVOKED = 1, + LSP_TRIGGER_CHARACTER = 2, + LSP_TRIGGER_INCOMPLETE = 3 +} LSPCompletionTriggerKind; + +typedef struct { + LSPCompletionTriggerKind trigger_kind; + char trigger_character[5]; +} LSPCompletionContext; + typedef struct { LSPDocumentPosition position; + LSPCompletionContext context; } LSPRequestCompletion; typedef struct { @@ -1,10 +1,8 @@ /* @TODO: -- fix unicode_utf8_to_utf32 to handle bad UTF-8 (i.e. continuation bytes which aren't actually continuation bytes) -- provide completion context + don't flash cursor for triggers with no completions +- only show "Loading..." if it's taking some time (prevent flash) - dont do completion if provides_completion = false - scroll through completions -- only show "Loading..." if it's taking some time (prevent flash) - LSP setting - figure out workspace - make sure "save as" works @@ -832,14 +830,14 @@ int main(int argc, char **argv) { strlen(text) - last_code_point); arr_foreach_ptr(lsp->trigger_chars, char32_t, c) { if (*c == last_char) { - autocomplete_open(ted); + autocomplete_open(ted, last_char); break; } } if (settings->identifier_trigger_characters && is_word(last_char) && !is_digit(last_char)) - autocomplete_open(ted); + autocomplete_open(ted, last_char); } } @@ -379,6 +379,9 @@ typedef struct { bool open; // is the autocomplete window open? bool waiting_for_lsp; + // which trigger character invoked this (0 if autocomplete was manually invoked) + char32_t trigger_char; + Autocompletion *completions; // dynamic array of all completions u32 *suggested; // dynamic array of completions to be suggested (indices into completions) BufferPos last_pos; // position of cursor last time completions were generated. if this changes, we need to recompute completions. |