From fb342182983ffdb0aae0497f5cbcb71b0b291023 Mon Sep 17 00:00:00 2001 From: pommicket Date: Fri, 3 Mar 2023 18:01:34 -0500 Subject: different read/write colors for ide-highlights --- buffer.c | 4 ++-- colors.c | 1 + colors.h | 1 + ide-highlights.c | 5 ++++- ide-hover.c | 2 +- lsp-parse.c | 39 ++++++++++++++++++++++++++++++--------- lsp.c | 20 ++++++++++++++++++++ lsp.h | 5 +++++ main.c | 2 ++ ted.cfg | 7 +++++-- ted.h | 4 +++- 11 files changed, 74 insertions(+), 16 deletions(-) diff --git a/buffer.c b/buffer.c index aa9e165..bb7fabf 100644 --- a/buffer.c +++ b/buffer.c @@ -3152,7 +3152,7 @@ void buffer_toggle_comment_selection(TextBuffer *buffer) { } -void buffer_highlight_lsp_range(TextBuffer *buffer, LSPRange range) { +void buffer_highlight_lsp_range(TextBuffer *buffer, LSPRange range, ColorSetting color) { Font *font = buffer_font(buffer); const u32 *colors = buffer_settings(buffer)->colors; const float char_height = text_font_char_height(font); @@ -3164,7 +3164,7 @@ void buffer_highlight_lsp_range(TextBuffer *buffer, LSPRange range) { vec2 b = buffer_pos_to_pixels(buffer, range_end); b.y += char_height; Rect r = rect_endpoints(a, b); buffer_clip_rect(buffer, &r); - gl_geometry_rect(r, colors[COLOR_HOVER_HL]); + gl_geometry_rect(r, colors[color]); } else if (range_end.line - range_start.line < 1000) { // prevent gigantic highlights from slowing things down // multiple lines. vec2 a = buffer_pos_to_pixels(buffer, range_start); diff --git a/colors.c b/colors.c index 9d2cfa1..3b4793f 100644 --- a/colors.c +++ b/colors.c @@ -52,6 +52,7 @@ static ColorName color_names[] = { {COLOR_HOVER_BG, "hover-bg"}, {COLOR_HOVER_TEXT, "hover-text"}, {COLOR_HOVER_HL, "hover-hl"}, + {COLOR_HL_WRITE, "hl-write"}, {COLOR_YES, "yes"}, {COLOR_NO, "no"}, {COLOR_CANCEL, "cancel"}, diff --git a/colors.h b/colors.h index 9d82602..66a4c75 100644 --- a/colors.h +++ b/colors.h @@ -48,6 +48,7 @@ typedef enum { COLOR_HOVER_BORDER, COLOR_HOVER_TEXT, COLOR_HOVER_HL, + COLOR_HL_WRITE, COLOR_YES, COLOR_NO, diff --git a/ide-highlights.c b/ide-highlights.c index fee01d4..4188f4e 100644 --- a/ide-highlights.c +++ b/ide-highlights.c @@ -66,7 +66,10 @@ void highlights_frame(Ted *ted) { } arr_foreach_ptr(hls->highlights, LSPHighlight, hl) { - buffer_highlight_lsp_range(buffer, hl->range); + ColorSetting color = COLOR_HOVER_HL; + if (hl->kind == LSP_HIGHLIGHT_WRITE) + color = COLOR_HL_WRITE; + buffer_highlight_lsp_range(buffer, hl->range, color); } gl_geometry_draw(); } diff --git a/ide-hover.c b/ide-hover.c index aed7ed1..b88a960 100644 --- a/ide-hover.c +++ b/ide-hover.c @@ -133,7 +133,7 @@ void hover_frame(Ted *ted, double dt) { float char_height = text_font_char_height(font); float x = ted->mouse_pos.x, y = ted->mouse_pos.y + char_height; - buffer_highlight_lsp_range(buffer, hover->range); + buffer_highlight_lsp_range(buffer, hover->range, COLOR_HOVER_HL); if (hover->text) { float max_width = 400; diff --git a/lsp-parse.c b/lsp-parse.c index 094fc81..6c5ccec 100644 --- a/lsp-parse.c +++ b/lsp-parse.c @@ -855,16 +855,37 @@ static bool parse_highlight(LSP *lsp, const JSON *json, LSPResponse *response) { JSONArray result = json_force_array(json_get(json, "result")); for (u32 h = 0; h < result.len; ++h) { JSONObject highlight_in = json_array_get_object(json, result, h); - LSPHighlight *highlight_out = arr_addp(hl->highlights); - double kind = json_object_get_number(json, highlight_in, "kind"); - if (isfinite(kind) && kind >= LSP_HIGHLIGHT_MAX && kind <= LSP_HIGHLIGHT_MAX) { - highlight_out->kind = (LSPHighlightKind)kind; - } else { - highlight_out->kind = LSP_HIGHLIGHT_TEXT; - } - JSONValue range = json_object_get(json, highlight_in, "range"); - if (!parse_range(lsp, json, range, &highlight_out->range)) + JSONValue range_value = json_object_get(json, highlight_in, "range"); + LSPRange range = {0}; + if (!parse_range(lsp, json, range_value, &range)) return false; + double lsp_kind = json_object_get_number(json, highlight_in, "kind"); + LSPHighlightKind kind = LSP_HIGHLIGHT_TEXT; + if (isfinite(lsp_kind) && lsp_kind >= LSP_HIGHLIGHT_MAX && lsp_kind <= LSP_HIGHLIGHT_MAX) { + kind = (LSPHighlightKind)lsp_kind; + } + + + bool already_highlighted = false; + arr_foreach_ptr(hl->highlights, LSPHighlight, h2) { + if (lsp_ranges_overlap(range, h2->range)) { + if (kind > h2->kind) { + // replace the old range with this one since it has higher kind (e.g. prefer writes over reads) + // technically this is slightly wrong since the new range might overlap with new stuff but whatever idc + h2->range = range; + h2->kind = kind; + } + already_highlighted = true; + } + } + if (already_highlighted) { + // don't show overlapping highlights + continue; + } + + LSPHighlight *highlight_out = arr_addp(hl->highlights); + highlight_out->range = range; + highlight_out->kind = kind; } return true; } diff --git a/lsp.c b/lsp.c index 9761049..c50ecc1 100644 --- a/lsp.c +++ b/lsp.c @@ -654,10 +654,30 @@ void lsp_document_changed(LSP *lsp, const char *document, LSPDocumentChangeEvent lsp_send_request(lsp, &request); } +int lsp_position_cmp(LSPPosition a, LSPPosition b) { + if (a.line < b.line) + return -1; + if (a.line > b.line) + return 1; + if (a.character < b.character) + return -1; + if (a.character > b.character) + return 1; + return 0; +} + bool lsp_position_eq(LSPPosition a, LSPPosition b) { return a.line == b.line && a.character == b.character; } +bool lsp_ranges_overlap(LSPRange a, LSPRange b) { + if (lsp_position_cmp(a.end, b.start) <= 0) + return false; + if (lsp_position_cmp(b.end, a.start) <= 0) + return false; + return true; +} + bool lsp_document_position_eq(LSPDocumentPosition a, LSPDocumentPosition b) { return a.document == b.document && lsp_position_eq(a.pos, b.pos); } diff --git a/lsp.h b/lsp.h index 2ebcce4..2f1720d 100644 --- a/lsp.h +++ b/lsp.h @@ -623,7 +623,12 @@ void lsp_document_changed(LSP *lsp, const char *document, LSPDocumentChangeEvent bool lsp_covers_path(LSP *lsp, const char *path); // get next message from server bool lsp_next_message(LSP *lsp, LSPMessage *message); +/// returns `-1` if `a` comes before `b`, 0 if `a` and `b` are equal, and `1` if `a` comes after `b` +int lsp_position_cmp(LSPPosition a, LSPPosition b); +/// returns `true` if `a` and `b` are equal bool lsp_position_eq(LSPPosition a, LSPPosition b); +/// returns `true` if `a` and `b` overlap +bool lsp_ranges_overlap(LSPRange a, LSPRange b); bool lsp_document_position_eq(LSPDocumentPosition a, LSPDocumentPosition b); // get the start of location's range as a LSPDocumentPosition LSPDocumentPosition lsp_location_start_position(LSPLocation location); diff --git a/main.c b/main.c index 8d720c5..b16a867 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,6 @@ /* +@TODO +- what's wrong with session FUTURE FEATURES: - option for separate colors for read/write highlights - styles ([color] sections) diff --git a/ted.cfg b/ted.cfg index 6bf60d3..dbcc9d7 100644 --- a/ted.cfg +++ b/ted.cfg @@ -397,11 +397,14 @@ cancel = #ffa autocomplete-bg = #000 autocomplete-border = #999 autocomplete-hl = #f6a3 -# hover (press shift while hovering over an identifier with an LSP server running) +# hover (press F1 while hovering over an identifier with an LSP server running) hover-bg = #000a hover-border = #fffa hover-text = #fff -hover-hl = #ffc4 +hover-hl = #fff4 +# highlight color for F2 key (LSP "document highlights") for write accesses to a variable +# (hover-hl is used for read accesses) +hl-write = #fca4 # these control the text color for various kinds of completions autocomplete-variable = #bfb autocomplete-function = #fec diff --git a/ted.h b/ted.h index 5990a58..12dfcb5 100644 --- a/ted.h +++ b/ted.h @@ -1164,8 +1164,10 @@ void buffer_uncomment_lines(TextBuffer *buffer, u32 first_line, u32 last_line); void buffer_toggle_comment_lines(TextBuffer *buffer, u32 first_line, u32 last_line); /// comment the selected lines, or uncomment them if they're all commented void buffer_toggle_comment_selection(TextBuffer *buffer); +/// highlight an \ref LSPRange in this buffer. +/// /// make sure to call \ref gl_geometry_draw after this -void buffer_highlight_lsp_range(TextBuffer *buffer, LSPRange range); +void buffer_highlight_lsp_range(TextBuffer *buffer, LSPRange range, ColorSetting color); /// returns true if `p1` and `p2` are equal bool buffer_pos_eq(BufferPos p1, BufferPos p2); /// returns `-1` if `p1` comes before `p2` -- cgit v1.2.3