summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buffer.c4
-rw-r--r--colors.c1
-rw-r--r--colors.h1
-rw-r--r--ide-highlights.c5
-rw-r--r--ide-hover.c2
-rw-r--r--lsp-parse.c39
-rw-r--r--lsp.c20
-rw-r--r--lsp.h5
-rw-r--r--main.c2
-rw-r--r--ted.cfg7
-rw-r--r--ted.h4
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`