diff options
author | pommicket <pommicket@gmail.com> | 2022-12-09 22:43:45 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-12-09 22:43:45 -0500 |
commit | 8362c840c3c3afefa56ecaef68d1c926c9ee118b (patch) | |
tree | 96052e88741b1884cca3a84a4eae7aa3655860f7 | |
parent | 78c3046bdd2c9db044a6178536e274cdc0b20120 (diff) |
more completion, not working yet
-rw-r--r-- | lsp.c | 35 | ||||
-rw-r--r-- | main.c | 14 | ||||
-rw-r--r-- | util.c | 32 |
3 files changed, 65 insertions, 16 deletions
@@ -81,8 +81,9 @@ typedef struct { typedef struct { LSPResponseString label; - // note: the items are sorted here in this file. - LSPResponseString sort_by; + // note: the items are sorted here in this file, + // so you probably don't need to access this. + LSPResponseString sort_text; } LSPCompletionItem; typedef struct { @@ -450,6 +451,22 @@ static LSPResponseString lsp_response_add_json_string(LSPResponse *response, con }; } +static int completion_qsort_cmp(void *context, const void *av, const void *bv) { + const LSPResponse *response = context; + const LSPCompletionItem *a = av, *b = bv; + const char *a_sort_text = lsp_response_string(response, a->sort_text); + const char *b_sort_text = lsp_response_string(response, b->sort_text); + int sort_text_cmp = strcmp(a_sort_text, b_sort_text); + if (sort_text_cmp != 0) + return sort_text_cmp; + // for some reason, rust-analyzer outputs identical sortTexts + // i have no clue what that means. + // the LSP "specification" is not very specific. + // we'll sort by label in this case. + const char *a_label = lsp_response_string(response, a->label); + const char *b_label = lsp_response_string(response, b->label); + return strcmp(a_label, b_label); +} static bool parse_completion(LSP *lsp, const JSON *json, LSPResponse *response) { // deal with textDocument/completion response. @@ -492,12 +509,22 @@ static bool parse_completion(LSP *lsp, const JSON *json, LSPResponse *response) JSONValue label_value = json_object_get(json, &item_object, "label"); if (!lsp_expect_string(lsp, label_value, "completion label")) return false; - JSONString label = label_value.val.string; + + JSONString sort_text = label; + JSONValue sort_text_value = json_object_get(json, &item_object, "sortText"); + if (sort_text_value.type == JSON_STRING) { + // LSP allows using a different string for sorting. + sort_text = sort_text_value.val.string; + } + item->label = lsp_response_add_json_string(response, json, label); - printf("%s\n",lsp_response_string(response,item->label));//@TODO + item->sort_text = lsp_response_add_json_string(response, json, sort_text); } + qsort_with_context(completion->items, items.len, sizeof *completion->items, + completion_qsort_cmp, response); + return true; } @@ -308,7 +308,19 @@ int main(int argc, char **argv) { LSPMessage message = {0}; while (lsp_next_message(&lsp, &message)) { if (message.type == LSP_RESPONSE) { - printf("response type %u\n",message.u.response.type); + const LSPResponse *response = &message.u.response; + switch (response->type) { + case LSP_COMPLETION: { + const LSPResponseCompletion *completion = &response->data.completion; + arr_foreach_ptr(completion->items, LSPCompletionItem, item) { + printf("%s:%s\n", + lsp_response_string(response, item->sort_text), + lsp_response_string(response, item->label)); + } + } break; + default: + break; + } } else if (message.type == LSP_REQUEST) { const LSPRequest *request = &message.u.request; switch (request->type) { @@ -241,18 +241,28 @@ static int str_qsort_case_insensitive_cmp(const void *av, const void *bv) { return strcmp_case_insensitive(*a, *b); } -static void *qsort_ctx_arg; -static int (*qsort_ctx_cmp)(void *, const void *, const void *); -static int qsort_with_context_cmp(const void *a, const void *b) { - return qsort_ctx_cmp(qsort_ctx_arg, a, b); -} - -static void qsort_with_context(void *base, size_t nmemb, size_t size, int (*compar)(void *, const void *, const void *), void *arg) { - // just use global variables. hopefully we don't try to run this in something multithreaded! - qsort_ctx_arg = arg; - qsort_ctx_cmp = compar; - qsort(base, nmemb, size, qsort_with_context_cmp); +// imo windows has the argument order right here +#if _WIN32 +#define qsort_with_context qsort_s +#else +typedef struct { + int (*compar)(void *, const void *, const void *); + void *context; +} QSortWithContext; +static int qsort_with_context_cmp(const void *a, const void *b, void *context) { + QSortWithContext *c = context; + return c->compar(context, a, b); +} +static void qsort_with_context(void *base, size_t nmemb, size_t size, + int (*compar)(void *, const void *, const void *), + void *arg) { + QSortWithContext ctx = { + .compar = compar, + .context = arg + }; + qsort_r(base, nmemb, size, qsort_with_context_cmp, &ctx); } +#endif // the actual file name part of the path; get rid of the containing directory. // NOTE: the returned string is part of path, so you don't need to free it or anything. |