summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-01-06 11:52:30 -0500
committerpommicket <pommicket@gmail.com>2023-01-06 11:52:30 -0500
commitd69fb12c055e1e17c765ca9714c508552a027384 (patch)
tree41073af13fdf014cc7d630c6aa4b5593fea16a42
parent268aba5dde93b67df5f5bd137141eeb177485685 (diff)
phantom completions
-rw-r--r--ide-autocomplete.c57
-rw-r--r--main.c1
-rw-r--r--menu.c6
-rw-r--r--ted.cfg2
-rw-r--r--text.c6
-rw-r--r--text.h2
-rw-r--r--ui.c6
7 files changed, 56 insertions, 24 deletions
diff --git a/ide-autocomplete.c b/ide-autocomplete.c
index 033841f..1046364 100644
--- a/ide-autocomplete.c
+++ b/ide-autocomplete.c
@@ -96,9 +96,7 @@ void autocomplete_close(Ted *ted) {
static void autocomplete_update_suggested(Ted *ted) {
Autocomplete *ac = &ted->autocomplete;
arr_clear(ac->suggested);
- char *word = str32_to_utf8_cstr(
- buffer_word_at_cursor(ted->active_buffer)
- );
+ char *word = buffer_word_at_cursor_utf8(ted->active_buffer);
for (u32 i = 0; i < arr_len(ac->completions); ++i) {
Autocompletion *completion = &ac->completions[i];
if (str_has_prefix(completion->filter, word))
@@ -282,14 +280,42 @@ void autocomplete_process_lsp_response(Ted *ted, const LSPResponse *response) {
return;
}
+ TextBuffer *buffer = ted->active_buffer;
+ if (!buffer)
+ return;
+
const LSPResponseCompletion *completion = &response->data.completion;
size_t ncompletions = arr_len(completion->items);
- printf("got %zu\n",ncompletions);
- if (ac->last_request_phantom && ncompletions != 1) {
- // only show phantom completion if there's exactly 1 completion.
- autocomplete_clear_phantom(ac);
+ if (ac->last_request_phantom) {
+ // check for phantom completion
+ // ideally we would just check if ncompletions == 1,
+ // but some completions might not start with the word at the cursor,
+ // and it's best to filter those out.
+ char *word_at_cursor = buffer_word_at_cursor_utf8(buffer);
+ if (*word_at_cursor) {
+ int ncandidates = 0;
+ const char *candidate = NULL;
+ for (size_t i = 0; i < ncompletions; ++i) {
+ const LSPCompletionItem *lsp_completion = &completion->items[i];
+ const char *new_text = lsp_response_string(response, lsp_completion->text_edit.new_text);
+ if (str_has_prefix(new_text, word_at_cursor)) {
+ candidate = new_text;
+ ++ncandidates;
+ if (ncandidates >= 2) break;
+ }
+ }
+
+ // only show phantom if there is exactly 1 possible completion.
+ if (ncandidates == 1) {
+ ac->phantom = str_dup(candidate);
+ } else {
+ autocomplete_clear_phantom(ac);
+ }
+ }
+ free(word_at_cursor);
return;
}
+
arr_set_len(ac->completions, ncompletions);
for (size_t i = 0; i < ncompletions; ++i) {
const LSPCompletionItem *lsp_completion = &completion->items[i];
@@ -412,10 +438,17 @@ void autocomplete_frame(Ted *ted) {
char *word_at_cursor = buffer_word_at_cursor_utf8(buffer);
if (*word_at_cursor && str_has_prefix(ac->phantom, word_at_cursor)) {
const char *completion = ac->phantom + strlen(word_at_cursor);
- vec2 pos = buffer_pos_to_pixels(buffer, buffer->cursor_pos);
- text_utf8(font, completion, pos.x, pos.y,
- colors[COLOR_TEXT] & 0xffffff7f);
- text_render(font);
+ if (*completion) {
+ vec2 pos = buffer_pos_to_pixels(buffer, buffer->cursor_pos);
+ //vec2 size = text_get_size_vec2(font, completion);
+ //Rect r = rect(pos, size);
+ //gl_geometry_rect(r, colors[COLOR_CURSOR_BG] & 0xffffff7f);
+
+ text_utf8(font, completion, pos.x, pos.y,
+ colors[COLOR_TEXT] & 0xffffff7f);
+ text_render(font);
+ gl_geometry_draw();
+ }
} else {
// this phantom is no longer relevant
autocomplete_clear_phantom(ac);
@@ -595,7 +628,7 @@ void autocomplete_frame(Ted *ted) {
char text[128] = {0};
strbuf_printf(text, "%.*s%s", amount_detail, detail,
(size_t)amount_detail == strlen(detail) ? "" : "...");
- double width = text_get_size_v2(font, text).x;
+ double width = text_get_size_vec2(font, text).x;
if (label_end_x + width + 2 * padding < state.max_x) {
strbuf_cpy(show_text, text);
}
diff --git a/main.c b/main.c
index 18276d2..3975adc 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,5 @@
/*
@TODO:
-- phantom completions
- debug-lsp option (which logs LSP messages)
- check LSP process status (TEST: what happens if LSP server is not installed)
- make tags_dir the root folder
diff --git a/menu.c b/menu.c
index ae024b2..b894c35 100644
--- a/menu.c
+++ b/menu.c
@@ -400,7 +400,7 @@ void menu_render(Ted *ted) {
gl_geometry_rect(r, colors[COLOR_MENU_BG]);
gl_geometry_rect_border(r, settings->border_thickness, colors[COLOR_BORDER]);
const char *text = "Go to line...";
- vec2 text_size = text_get_size_v2(font_bold, text);
+ vec2 text_size = text_get_size_vec2(font_bold, text);
rect_coords(r, &x1, &y1, &x2, &y2);
x1 += padding;
y1 += padding;
@@ -419,7 +419,7 @@ void menu_render(Ted *ted) {
// argument field
const char *text = "Argument";
text_utf8(font_bold, text, x1, y1, colors[COLOR_TEXT]);
- float x = x1 + text_get_size_v2(font_bold, text).x + padding;
+ float x = x1 + text_get_size_vec2(font_bold, text).x + padding;
buffer_render(&ted->argument_buffer, rect4(x, y1, x2, y1 + line_buffer_height));
y1 += line_buffer_height + padding;
@@ -445,7 +445,7 @@ void menu_render(Ted *ted) {
const char *text = "Run";
text_utf8(font_bold, text, x1, y1, colors[COLOR_TEXT]);
- x1 += text_get_size_v2(font_bold, text).x + padding;
+ x1 += text_get_size_vec2(font_bold, text).x + padding;
text_render(font_bold);
buffer_render(&ted->line_buffer, rect4(x1, y1, x2, y2));
diff --git a/ted.cfg b/ted.cfg
index 7648d12..220de0a 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -34,7 +34,7 @@ trigger-characters = on
# should all identifier characters (e.g. a-z) be treated as trigger characters?
identifier-trigger-characters = off
# display "phantom completions"? (if there is only one completion, display it next to the cursor)
-phantom-completions = yes
+phantom-completions = on
# enable LSP support (for autocompletion, etc.)
# you can also set `lsp = ""` but this is a quick way to disable LSP servers for all langauges
lsp-enabled = yes
diff --git a/text.c b/text.c
index bd1f3a8..398bb3f 100644
--- a/text.c
+++ b/text.c
@@ -395,8 +395,8 @@ static vec2 text_render_utf8_internal(Font *font, const char *text, double x, do
rgba_u32_to_floats(color, render_state.color);
text_utf8_with_state(font, &render_state, text);
return Vec2(
- (float)(render_state.x_largest - x),
- (float)(render_state.y_largest - y)
+ maxf(0.0f, (float)(render_state.x_largest - x)),
+ maxf(0.0f, (float)(render_state.y_largest - y))
);
}
@@ -429,7 +429,7 @@ void text_get_size(Font *font, const char *text, float *width, float *height) {
if (height) *height = size.y + font->char_height;
}
-vec2 text_get_size_v2(Font *font, const char *text) {
+vec2 text_get_size_vec2(Font *font, const char *text) {
vec2 v;
text_get_size(font, text, &v.x, &v.y);
return v;
diff --git a/text.h b/text.h
index e5e5e61..2d7429d 100644
--- a/text.h
+++ b/text.h
@@ -60,7 +60,7 @@ float text_font_char_width(Font *font);
void text_font_set_force_monospace(Font *font, bool force);
// Get the dimensions of some text.
void text_get_size(Font *font, const char *text, float *width, float *height);
-vec2 text_get_size_v2(Font *font, const char *text);
+vec2 text_get_size_vec2(Font *font, const char *text);
void text_get_size32(Font *font, const char32_t *text, u64 len, float *width, float *height);
void text_utf8(Font *font, const char *text, double x, double y, u32 color);
void text_utf8_anchored(Font *font, const char *text, double x, double y, u32 color, Anchor anchor);
diff --git a/ui.c b/ui.c
index 56e89db..0c398b3 100644
--- a/ui.c
+++ b/ui.c
@@ -164,7 +164,7 @@ void selector_render(Ted *ted, Selector *s) {
if (entry->detail) {
// draw detail
- float detail_size = text_get_size_v2(font, entry->detail).x;
+ float detail_size = text_get_size_vec2(font, entry->detail).x;
TextRenderState detail_state = text_state;
detail_state.x = maxd(text_state.x + 2 * padding, x2 - detail_size);
@@ -530,7 +530,7 @@ void file_selector_render(Ted *ted, FileSelector *fs) {
vec2 button_get_size(Ted *ted, const char *text) {
float border_thickness = ted_active_settings(ted)->border_thickness;
- return vec2_add_const(text_get_size_v2(ted->font, text), 2 * border_thickness);
+ return vec2_add_const(text_get_size_vec2(ted->font, text), 2 * border_thickness);
}
void button_render(Ted *ted, Rect button, const char *text, u32 color) {
@@ -668,7 +668,7 @@ vec2 checkbox_frame(Ted *ted, bool *value, const char *label, vec2 pos) {
}
vec2 text_pos = vec2_add(pos, Vec2(checkbox_size + padding * 0.5f, 0));
- vec2 size = text_get_size_v2(font, label);
+ vec2 size = text_get_size_vec2(font, label);
text_utf8(font, label, text_pos.x, text_pos.y, colors[COLOR_TEXT]);
gl_geometry_draw();