summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-12-09 22:43:45 -0500
committerpommicket <pommicket@gmail.com>2022-12-09 22:43:45 -0500
commit8362c840c3c3afefa56ecaef68d1c926c9ee118b (patch)
tree96052e88741b1884cca3a84a4eae7aa3655860f7
parent78c3046bdd2c9db044a6178536e274cdc0b20120 (diff)
more completion, not working yet
-rw-r--r--lsp.c35
-rw-r--r--main.c14
-rw-r--r--util.c32
3 files changed, 65 insertions, 16 deletions
diff --git a/lsp.c b/lsp.c
index 8cd06d8..61ba014 100644
--- a/lsp.c
+++ b/lsp.c
@@ -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;
}
diff --git a/main.c b/main.c
index 28fb1d6..c388b63 100644
--- a/main.c
+++ b/main.c
@@ -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) {
diff --git a/util.c b/util.c
index 32411a7..76229af 100644
--- a/util.c
+++ b/util.c
@@ -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.