summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-12-23 00:18:07 -0500
committerpommicket <pommicket@gmail.com>2022-12-23 00:18:07 -0500
commit7f98e047cb791b84cc955f534a7e94395fed1ae0 (patch)
treeb295b9bdbd8ad4bcd88e7e73f025109d5b63af93
parentdaee4283b56603e172aac547c20c5534e588f60d (diff)
show documentation!
-rw-r--r--autocomplete.c54
-rw-r--r--lsp-parse.c10
-rw-r--r--lsp.h2
-rw-r--r--main.c2
-rw-r--r--ted.h1
-rw-r--r--text.c9
6 files changed, 70 insertions, 8 deletions
diff --git a/autocomplete.c b/autocomplete.c
index 67da65a..e0de9fd 100644
--- a/autocomplete.c
+++ b/autocomplete.c
@@ -7,6 +7,8 @@ static void autocomplete_clear_completions(Ted *ted) {
free(completion->label);
free(completion->text);
free(completion->filter);
+ free(completion->detail);
+ free(completion->documentation);
}
arr_clear(ac->completions);
arr_clear(ac->suggested);
@@ -148,6 +150,9 @@ static void autocomplete_process_lsp_response(Ted *ted, const LSPResponse *respo
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;
+ const char *documentation = lsp_response_string(response, lsp_completion->documentation);
+ ted_completion->documentation = documentation ? str_dup(documentation) : NULL;
+
}
}
autocomplete_update_suggested(ted);
@@ -265,18 +270,57 @@ static void autocomplete_frame(Ted *ted) {
}
u16 cursor_entry = (u16)((ted->mouse_pos.y - start_y) / char_height);
+
+ Autocompletion *document = NULL;
if (cursor_entry < ncompletions) {
// highlight moused over entry
Rect r = rect(V2(x, start_y + cursor_entry * char_height), V2(menu_width, char_height));
gl_geometry_rect(r, colors[COLOR_AUTOCOMPLETE_HL]);
- ted->cursor = ted->cursor_hand;
- }
-
- if (!ac->waiting_for_lsp) {
+ ted->cursor = ted->cursor_hand;
+ document = &completions[cursor_entry];
+ } else if (ncompletions) {
// highlight cursor entry
Rect r = rect(V2(x, start_y + (float)ac->cursor * char_height), V2(menu_width, char_height));
gl_geometry_rect(r, colors[COLOR_AUTOCOMPLETE_HL]);
+ document = &completions[ac->cursor];
+ }
+
+ float border_thickness = settings->border_thickness;
+
+
+ if (document) {
+ // document that entry!!
+
+ // we've go tsome wacky calculations to figure out the
+ // bounding rect for the documentation
+ float doc_width = open_left ? ac->rect.pos.x - 2*padding
+ : buffer->x2 - (ac->rect.pos.x + ac->rect.size.x + 2*padding);
+ if (doc_width > 800) doc_width = 800;
+ float doc_height = buffer->y2 - (ac->rect.pos.y + 2*padding);
+ if (doc_height > char_height * 20) doc_height = char_height * 20;
+
+ // if the rect is too small, there's no point in showing it
+ if (doc_width >= 200) {
+ float doc_x = open_left ? ac->rect.pos.x - doc_width - padding
+ : ac->rect.pos.x + ac->rect.size.x + padding;
+ float doc_y = ac->rect.pos.y;
+ Rect r = rect(V2(doc_x, doc_y), V2(doc_width, doc_height));
+ gl_geometry_rect(r, colors[COLOR_AUTOCOMPLETE_BG]);
+ gl_geometry_rect_border(r, border_thickness, colors[COLOR_AUTOCOMPLETE_BORDER]);
+
+ // draw the text!
+ TextRenderState text_state = text_render_state_default;
+ text_state.min_x = doc_x + padding;
+ text_state.max_x = doc_x + doc_width - padding;
+ text_state.max_y = doc_y + doc_height;
+ text_state.x = doc_x + padding;
+ text_state.y = doc_y + padding;
+ text_state.wrap = true;
+ rgba_u32_to_floats(colors[COLOR_TEXT], text_state.color);
+ text_utf8_with_state(font, &text_state, document->documentation);
+ }
}
+
for (uint i = 0; i < ted->nmouse_clicks[SDL_BUTTON_LEFT]; ++i) {
v2 click = ted->mouse_clicks[SDL_BUTTON_LEFT][i];
@@ -294,8 +338,6 @@ 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);
- 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...");
diff --git a/lsp-parse.c b/lsp-parse.c
index 9d02782..05fc898 100644
--- a/lsp-parse.c
+++ b/lsp-parse.c
@@ -181,6 +181,16 @@ static bool parse_completion(LSP *lsp, const JSON *json, LSPResponse *response)
documentation = json_object_get_string(json, documentation_value.val.object,
"value");
}
+ if (documentation.len) {
+ if (documentation.len > 1000) {
+ // rust has some docs which are *20,000* bytes long
+ // that's more than i'm ever gonna show on-screen!
+ documentation.len = 1000;
+ // okay this could break mid-code-point but whatever it would probably
+ // just display ⌷.
+ }
+ item->documentation = lsp_response_add_json_string(response, json, documentation);
+ }
JSONString detail_text = json_object_get_string(json, item_object, "detail");
diff --git a/lsp.h b/lsp.h
index 612b370..72e621e 100644
--- a/lsp.h
+++ b/lsp.h
@@ -202,6 +202,8 @@ typedef struct {
LSPString filter_text;
// more detail for this item, e.g. the signature of a function
LSPString detail;
+ // documentation for this item (typically from a doc comment)
+ LSPString documentation;
// the edit to be applied when this completion is selected.
LSPTextEdit text_edit;
// note: the items are sorted here in this file,
diff --git a/main.c b/main.c
index c86d3b1..5274922 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,5 @@
/*
@TODO:
-- show documentation
-- finish up capabilities
- trigger characters (with setting)
- only show "Loading..." if it's taking some time (prevent flash)
- LSP setting
diff --git a/ted.h b/ted.h
index 6f10bfb..a7974dd 100644
--- a/ted.h
+++ b/ted.h
@@ -368,6 +368,7 @@ typedef struct {
char *filter;
char *text;
char *detail; // this can be NULL!
+ char *documentation; // this can be NULL!
bool deprecated;
SymbolKind kind;
} Autocompletion;
diff --git a/text.c b/text.c
index 6d40cc5..6df77ff 100644
--- a/text.c
+++ b/text.c
@@ -276,6 +276,8 @@ top:
c = UNICODE_BOX_CHARACTER;
}
if (c >= UNICODE_CODE_POINTS) c = UNICODE_BOX_CHARACTER; // code points this big should never appear in valid Unicode
+
+
uint page = c / CHAR_PAGE_SIZE;
uint index = c % CHAR_PAGE_SIZE;
if (state->render) {
@@ -286,9 +288,16 @@ top:
stbtt_bakedchar *char_data = font->char_pages[page];
float const char_height = font->char_height;
float const char_width = font->char_width;
+
if (char_data) { // if page was successfully loaded
stbtt_aligned_quad q = {0};
+ if (state->wrap && c == '\n') {
+ state->x = state->min_x;
+ state->y += char_height;
+ return;
+ }
+
{
float x, y;
x = (float)(state->x - floor(state->x));