summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autocomplete.c21
-rw-r--r--json.c87
-rw-r--r--lsp-parse.c19
-rw-r--r--lsp-write.c1
-rw-r--r--lsp.h2
-rw-r--r--ted.h1
6 files changed, 91 insertions, 40 deletions
diff --git a/autocomplete.c b/autocomplete.c
index 514c9a5..f6c6ff6 100644
--- a/autocomplete.c
+++ b/autocomplete.c
@@ -147,6 +147,7 @@ static void autocomplete_process_lsp_response(Ted *ted, const LSPResponse *respo
const char *detail = lsp_response_string(response, lsp_completion->detail);
ted_completion->detail = *detail ? str_dup(detail) : NULL;
ted_completion->kind = lsp_completion_kind_to_ted(lsp_completion->kind);
+ ted_completion->deprecated = lsp_completion->deprecated;
}
}
autocomplete_update_suggested(ted);
@@ -293,13 +294,14 @@ static void autocomplete_frame(Ted *ted) {
state.min_x = x + padding; state.min_y = y; state.max_x = x + menu_width - padding; state.max_y = y + menu_height;
rgba_u32_to_floats(colors[COLOR_TEXT], state.color);
- u8 border_thickness = settings->border_thickness;
+ float border_thickness = settings->border_thickness;
if (ac->waiting_for_lsp) {
state.x = x + padding; state.y = y;
text_utf8_with_state(font, &state, "Loading...");
} else {
for (size_t i = 0; i < ncompletions; ++i) {
+ const Autocompletion *completion = &completions[i];
state.x = x; state.y = y;
if (i != ncompletions-1) {
@@ -308,14 +310,14 @@ static void autocomplete_frame(Ted *ted) {
colors[COLOR_AUTOCOMPLETE_BORDER]);
}
- ColorSetting label_color = color_for_symbol_kind(completions[i].kind);
+ ColorSetting label_color = color_for_symbol_kind(completion->kind);
if (!settings->syntax_highlighting)
label_color = COLOR_TEXT;
rgba_u32_to_floats(colors[label_color], state.color);
// draw icon
- char icon_text[2] = {symbol_kind_icon(completions[i].kind), 0};
+ char icon_text[2] = {symbol_kind_icon(completion->kind), 0};
state.x += padding;
text_utf8_with_state(font, &state, icon_text);
state.x += padding;
@@ -323,10 +325,10 @@ static void autocomplete_frame(Ted *ted) {
colors[COLOR_AUTOCOMPLETE_BORDER]);
state.x += padding;
+ float label_x = (float)state.x;
+ text_utf8_with_state(font, &state, completion->label);
- text_utf8_with_state(font, &state, completions[i].label);
-
- const char *detail = completions[i].detail;
+ const char *detail = completion->detail;
if (detail) {
double label_end_x = state.x;
@@ -355,6 +357,13 @@ static void autocomplete_frame(Ted *ted) {
colors[COLOR_COMMENT], ANCHOR_TOP_RIGHT);
}
}
+
+ if (completion->deprecated) {
+ gl_geometry_rect(rect(V2(label_x, y + (char_height - border_thickness) * 0.5f),
+ V2((float)state.x - label_x, 1)),
+ colors[COLOR_TEXT]);
+ }
+
y += char_height;
}
}
diff --git a/json.c b/json.c
index e07b0ec..61c8103 100644
--- a/json.c
+++ b/json.c
@@ -444,54 +444,79 @@ JSONValue json_object_get(const JSON *json, JSONObject object, const char *name)
return (JSONValue){0};
}
-// returns (JSONString){0} (which is interpreted as an empty string) if `name` does
-// not exist or is not a string.
-JSONString json_object_get_string(const JSON *json, JSONObject object, const char *name) {
- JSONValue value = json_object_get(json, object, name);
- if (value.type == JSON_STRING) {
- return value.val.string;
+JSONValue json_array_get(const JSON *json, JSONArray array, u64 i) {
+ if (i < array.len) {
+ return json->values[array.elements + i];
+ }
+ return (JSONValue){0};
+}
+
+// returns NaN if `x` is not a number (ha ha).
+double json_force_number(JSONValue x) {
+ if (x.type == JSON_NUMBER) {
+ return x.val.number;
+ } else {
+ return NAN;
+ }
+}
+
+double json_object_get_number(const JSON *json, JSONObject object, const char *name) {
+ return json_force_number(json_object_get(json, object, name));
+}
+
+double json_array_get_number(const JSON *json, JSONArray array, size_t i) {
+ return json_force_number(json_array_get(json, array, i));
+}
+
+// returns (JSONString){0} (which is interpreted as an empty string) if `x` is not a string
+JSONString json_force_string(JSONValue x) {
+ if (x.type == JSON_STRING) {
+ return x.val.string;
} else {
return (JSONString){0};
}
}
-// returns (JSONObject){0} (which is interpreted as an empty object) if `name` does
-// not exist or is not an object.
-JSONObject json_object_get_object(const JSON *json, JSONObject object, const char *name) {
- JSONValue value = json_object_get(json, object, name);
- if (value.type == JSON_OBJECT) {
- return value.val.object;
+JSONString json_object_get_string(const JSON *json, JSONObject object, const char *name) {
+ return json_force_string(json_object_get(json, object, name));
+}
+
+JSONString json_array_get_string(const JSON *json, JSONArray array, size_t i) {
+ return json_force_string(json_array_get(json, array, i));
+}
+
+// returns (JSONObject){0} (which is interpreted as an empty object) if `x` is not an object
+JSONObject json_force_object(JSONValue x) {
+ if (x.type == JSON_OBJECT) {
+ return x.val.object;
} else {
return (JSONObject){0};
}
}
-// returns (JSONArray){0} (which is interpreted as an empty array) if `name` does
-// not exist or is not an array.
-JSONArray json_object_get_array(const JSON *json, JSONObject object, const char *name) {
- JSONValue value = json_object_get(json, object, name);
- if (value.type == JSON_ARRAY) {
- return value.val.array;
+JSONObject json_object_get_object(const JSON *json, JSONObject object, const char *name) {
+ return json_force_object(json_object_get(json, object, name));
+}
+
+JSONObject json_array_get_object(const JSON *json, JSONArray array, size_t i) {
+ return json_force_object(json_array_get(json, array, i));
+}
+
+// returns (JSONArray){0} (which is interpreted as an empty array) if `x` is not an array
+JSONArray json_force_array(JSONValue x) {
+ if (x.type == JSON_ARRAY) {
+ return x.val.array;
} else {
return (JSONArray){0};
}
}
-// returns NaN if `name` does not exist or is not a number.
-double json_object_get_number(const JSON *json, JSONObject object, const char *name) {
- JSONValue value = json_object_get(json, object, name);
- if (value.type == JSON_NUMBER) {
- return value.val.number;
- } else {
- return NAN;
- }
+JSONArray json_object_get_array(const JSON *json, JSONObject object, const char *name) {
+ return json_force_array(json_object_get(json, object, name));
}
-JSONValue json_array_get(const JSON *json, JSONArray array, u64 i) {
- if (i < array.len) {
- return json->values[array.elements + i];
- }
- return (JSONValue){0};
+JSONArray json_array_get_array(const JSON *json, JSONArray array, size_t i) {
+ return json_force_array(json_array_get(json, array, i));
}
// e.g. if json is { "a" : { "b": 3 }}, then json_get(json, "a.b") = 3.
diff --git a/lsp-parse.c b/lsp-parse.c
index 947feb9..6b4dc46 100644
--- a/lsp-parse.c
+++ b/lsp-parse.c
@@ -106,10 +106,10 @@ static bool parse_completion(LSP *lsp, const JSON *json, LSPResponse *response)
arr_set_len(completion->items, items.len);
- for (u32 i = 0; i < items.len; ++i) {
- LSPCompletionItem *item = &completion->items[i];
+ for (u32 item_idx = 0; item_idx < items.len; ++item_idx) {
+ LSPCompletionItem *item = &completion->items[item_idx];
- JSONValue item_value = json_array_get(json, items, i);
+ JSONValue item_value = json_array_get(json, items, item_idx);
if (!lsp_expect_object(lsp, item_value, "completion list"))
return false;
JSONObject item_object = item_value.val.object;
@@ -141,6 +141,19 @@ static bool parse_completion(LSP *lsp, const JSON *json, LSPResponse *response)
item->sort_text = lsp_response_add_json_string(response, json, sort_text);
}
+ JSONValue deprecated = json_object_get(json, item_object, "deprecated");
+ if (deprecated.type == JSON_TRUE) {
+ item->deprecated = true;
+ }
+
+ JSONArray tags = json_object_get_array(json, item_object, "tags");
+ for (u32 i = 0; i < tags.len; ++i) {
+ double tag = json_array_get_number(json, tags, i);
+ if (tag == 1 /* deprecated */) {
+ item->deprecated = true;
+ }
+ }
+
JSONString filter_text = json_object_get_string(json, item_object, "filterText");
if (filter_text.pos) {
// LSP allows using a different string for filtering.
diff --git a/lsp-write.c b/lsp-write.c
index 51f638f..9922862 100644
--- a/lsp-write.c
+++ b/lsp-write.c
@@ -291,6 +291,7 @@ static void write_request(LSP *lsp, LSPRequest *request) {
// completion capabilities
write_key_obj_start(o, "completionItem");
write_key_bool(o, "snippetSupport", false);
+ write_key_bool(o, "deprecatedSupport", true);
write_obj_end(o);
// "completion item kinds" supported by ted
// (these are the little icons displayed for function/variable/etc.)
diff --git a/lsp.h b/lsp.h
index 0aa8628..612b370 100644
--- a/lsp.h
+++ b/lsp.h
@@ -207,6 +207,8 @@ typedef struct {
// note: the items are sorted here in this file,
// so you probably don't need to access this.
LSPString sort_text;
+ // is this function/type/whatever deprecated?
+ bool deprecated;
// type of completion
LSPCompletionKind kind;
} LSPCompletionItem;
diff --git a/ted.h b/ted.h
index 7d23088..6f10bfb 100644
--- a/ted.h
+++ b/ted.h
@@ -368,6 +368,7 @@ typedef struct {
char *filter;
char *text;
char *detail; // this can be NULL!
+ bool deprecated;
SymbolKind kind;
} Autocompletion;