From da5a197ea3d6ac8333cb020080205cfd1af530c1 Mon Sep 17 00:00:00 2001 From: pommicket Date: Sat, 7 Jan 2023 11:39:29 -0500 Subject: clean up phantom code --- colors.c | 19 ++++++++++++ ide-autocomplete.c | 89 ++++++++++++++++++++++++++++-------------------------- ted.h | 4 +++ 3 files changed, 70 insertions(+), 42 deletions(-) diff --git a/colors.c b/colors.c index 896f0e3..9d2cfa1 100644 --- a/colors.c +++ b/colors.c @@ -149,3 +149,22 @@ ColorSetting color_for_symbol_kind(SymbolKind kind) { } return COLOR_TEXT; } + +u32 color_blend(u32 bg, u32 fg) { + u32 r1 = bg >> 24; + u32 g1 = (bg >> 16) & 0xff; + u32 b1 = (bg >> 8) & 0xff; + u32 r2 = fg >> 24; + u32 g2 = (fg >> 16) & 0xff; + u32 b2 = (fg >> 8) & 0xff; + u32 a2 = fg & 0xff; + u32 r = (r1 * (255 - a2) + r2 * a2 + 127) / 255; + u32 g = (g1 * (255 - a2) + g2 * a2 + 127) / 255; + u32 b = (b1 * (255 - a2) + b2 * a2 + 127) / 255; + return r << 24 | g << 16 | b << 8 | 0xff; +} + +u32 color_apply_opacity(u32 color, float opacity) { + opacity = clampf(opacity, 0.0f, 1.0f); + return (color & 0xffffff00) | (u32)((color & 0xff) * opacity); +} diff --git a/ide-autocomplete.c b/ide-autocomplete.c index bee99bf..9420387 100644 --- a/ide-autocomplete.c +++ b/ide-autocomplete.c @@ -5,6 +5,7 @@ #define TAGS_MAX_COMPLETIONS 200 // max # of tag completions to scroll through #define AUTOCOMPLETE_NCOMPLETIONS_VISIBLE 10 // max # of completions to show at once + static void autocomplete_clear_completions(Autocomplete *ac) { arr_foreach_ptr(ac->completions, Autocompletion, completion) { free(completion->label); @@ -22,6 +23,22 @@ static void autocomplete_clear_phantom(Autocomplete *ac) { ac->phantom = NULL; } +// should a phantom completion be displayed? +static bool autocomplete_should_display_phantom(Ted *ted) { + Autocomplete *ac = &ted->autocomplete; + TextBuffer *buffer = ted->active_buffer; + bool show = !ac->open + && buffer + && !buffer->view_only + && !buffer->is_line_buffer + && buffer_settings(buffer)->phantom_completions + && is32_word(buffer_char_before_cursor(buffer)) + && !is32_word(buffer_char_after_cursor(buffer)); + if (!show) + autocomplete_clear_phantom(ac); + return show; +} + // do the actual completion static void autocomplete_complete(Ted *ted, Autocompletion completion) { TextBuffer *buffer = ted->active_buffer; @@ -187,14 +204,16 @@ static void autocomplete_find_completions(Ted *ted, uint32_t trigger, bool phant char *word_at_cursor = str32_to_utf8_cstr(buffer_word_at_cursor(buffer)); if (phantom) { - char *completions[2] = {NULL, NULL}; - if (tags_beginning_with(ted, word_at_cursor, completions, 2, false) == 1) { - // show phantom - ac->phantom = completions[0]; - free(completions[1]); - } else { - free(completions[0]); - free(completions[1]); + if (autocomplete_should_display_phantom(ted)) { + char *completions[2] = {NULL, NULL}; + if (tags_beginning_with(ted, word_at_cursor, completions, 2, false) == 1) { + // show phantom + ac->phantom = completions[0]; + free(completions[1]); + } else { + free(completions[0]); + free(completions[1]); + } } } else { char **completions = calloc(TAGS_MAX_COMPLETIONS, sizeof *completions); @@ -279,7 +298,8 @@ void autocomplete_process_lsp_response(Ted *ted, const LSPResponse *response) { return; } if (ac->open && ac->last_request_phantom) { - // i'm not sure if this is possible, but just in case, + // shouldn't be possible, since we should never request phantom completions while autocomplete is open + assert(0); return; } @@ -290,6 +310,9 @@ void autocomplete_process_lsp_response(Ted *ted, const LSPResponse *response) { const LSPResponseCompletion *completion = &response->data.completion; size_t ncompletions = arr_len(completion->items); if (ac->last_request_phantom) { + if (!autocomplete_should_display_phantom(ted)) + return; + // check for phantom completion // ideally we would just check if ncompletions == 1, // but some completions might not start with the word at the cursor, @@ -393,29 +416,8 @@ void autocomplete_open(Ted *ted, uint32_t trigger) { } static void autocomplete_find_phantom(Ted *ted) { - Autocomplete *ac = &ted->autocomplete; - if (ac->open) { - autocomplete_clear_phantom(ac); - return; - } - if (!ted->active_buffer) { - autocomplete_clear_phantom(ac); + if (!autocomplete_should_display_phantom(ted)) return; - } - TextBuffer *buffer = ted->active_buffer; - if (!buffer->path) { - autocomplete_clear_phantom(ac); - return; - } - if (buffer->view_only) { - autocomplete_clear_phantom(ac); - return; - } - char32_t after_cursor = buffer_char_after_cursor(buffer); - if (is32_word(after_cursor)) { - autocomplete_clear_phantom(ac); - return; - } autocomplete_find_completions(ted, TRIGGER_INVOKED, true); } @@ -447,26 +449,29 @@ void autocomplete_frame(Ted *ted) { const Settings *settings = buffer_settings(buffer); const u32 *colors = settings->colors; const float padding = settings->padding; - if (settings->phantom_completions) { - autocomplete_find_phantom(ted); - } + + autocomplete_find_phantom(ted); Autocomplete *ac = &ted->autocomplete; - if (!ac->open && ac->phantom) { + if (autocomplete_should_display_phantom(ted) && ac->phantom) { // display phantom completion 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); 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); + vec2 size = text_get_size_vec2(font, completion); + #if 0 + // this makes the text below the phantom less visible. + // doesn't look very good, so I'm not doing it. + Rect r = rect(pos, size); + u32 bg_color = color_apply_opacity(color_blend(colors[COLOR_BG], colors[COLOR_CURSOR_LINE_BG]), 0.8f); + gl_geometry_rect(r, bg_color); + #endif + u32 text_color = color_apply_opacity(colors[COLOR_TEXT], 0.5); + text_utf8(font, completion, pos.x, pos.y, text_color); gl_geometry_draw(); + text_render(font); } else { // this phantom is no longer relevant autocomplete_clear_phantom(ac); diff --git a/ted.h b/ted.h index bc99123..a17fb23 100644 --- a/ted.h +++ b/ted.h @@ -966,6 +966,10 @@ Status color_from_str(const char *str, u32 *color); // which color setting should be used for the given symbol kind. // this is the color used in the autocomplete selector, for example. ColorSetting color_for_symbol_kind(SymbolKind kind); +// perform SRC_ALPHA, ONE_MINUS_SRC_ALPHA blending with `bg` and `fg`. +u32 color_blend(u32 bg, u32 fg); +// multiply color's alpha value by `opacity`. +u32 color_apply_opacity(u32 color, float opacity); // === command.c === void command_init(void); -- cgit v1.2.3