summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autocomplete.c19
-rw-r--r--command.c2
-rw-r--r--lsp-write.c10
-rw-r--r--lsp.h13
-rw-r--r--main.c8
-rw-r--r--ted.h3
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;
diff --git a/command.c b/command.c
index b330f54..82b096b 100644
--- a/command.c
+++ b/command.c
@@ -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;
}
diff --git a/lsp.h b/lsp.h
index 1c6076a..b4a4aa3 100644
--- a/lsp.h
+++ b/lsp.h
@@ -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 {
diff --git a/main.c b/main.c
index edb8b11..7460e2b 100644
--- a/main.c
+++ b/main.c
@@ -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);
}
}
diff --git a/ted.h b/ted.h
index f7d79ae..cbcc466 100644
--- a/ted.h
+++ b/ted.h
@@ -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.