summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autocomplete.c5
-rw-r--r--colors.c70
-rw-r--r--colors.h57
-rw-r--r--lsp-parse.c11
-rw-r--r--lsp.c88
-rw-r--r--lsp.h70
-rw-r--r--main.c4
-rw-r--r--ted.h12
8 files changed, 259 insertions, 58 deletions
diff --git a/autocomplete.c b/autocomplete.c
index eb5993f..24ca71b 100644
--- a/autocomplete.c
+++ b/autocomplete.c
@@ -144,6 +144,7 @@ static void autocomplete_process_lsp_response(Ted *ted, const LSPResponse *respo
ted_completion->text = str_dup(lsp_response_string(response, lsp_completion->text_edit.new_text));
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);
}
}
autocomplete_update_suggested(ted);
@@ -282,7 +283,11 @@ static void autocomplete_frame(Ted *ted) {
} else {
for (size_t i = 0; i < ncompletions; ++i) {
state.x = x + padding; state.y = y;
+
+ ColorSetting label_color = color_for_symbol_kind(completions[i].kind);
+ rgba_u32_to_floats(colors[label_color], state.color);
text_utf8_with_state(font, &state, completions[i].label);
+
const char *detail = completions[i].detail;
if (detail) {
double label_end_x = state.x;
diff --git a/colors.c b/colors.c
new file mode 100644
index 0000000..aac5e00
--- /dev/null
+++ b/colors.c
@@ -0,0 +1,70 @@
+
+static ColorSetting color_setting_from_str(char const *str) {
+ // @OPTIMIZE: sort color_names, binary search
+ for (int i = 0; i < COLOR_COUNT; ++i) {
+ ColorName const *n = &color_names[i];
+ if (streq(n->name, str))
+ return n->setting;
+ }
+ return COLOR_UNKNOWN;
+}
+
+static char const *color_setting_to_str(ColorSetting s) {
+ for (int i = 0; i < COLOR_COUNT; ++i) {
+ ColorName const *n = &color_names[i];
+ if (n->setting == s)
+ return n->name;
+ }
+ return "???";
+}
+
+// converts #rrggbb/#rrggbbaa to a color. returns false if it's not in the right format.
+static Status color_from_str(char const *str, u32 *color) {
+ uint r = 0, g = 0, b = 0, a = 0xff;
+ bool success = false;
+ switch (strlen(str)) {
+ case 4:
+ success = sscanf(str, "#%01x%01x%01x", &r, &g, &b) == 3;
+ // extend single hex digit to double hex digit
+ r |= r << 4;
+ g |= g << 4;
+ b |= b << 4;
+ break;
+ case 5:
+ success = sscanf(str, "#%01x%01x%01x%01x", &r, &g, &b, &a) == 4;
+ r |= r << 4;
+ g |= g << 4;
+ b |= b << 4;
+ a |= a << 4;
+ break;
+ case 7:
+ success = sscanf(str, "#%02x%02x%02x", &r, &g, &b) == 3;
+ break;
+ case 9:
+ success = sscanf(str, "#%02x%02x%02x%02x", &r, &g, &b, &a) == 4;
+ break;
+ }
+ if (!success || r > 0xff || g > 0xff || b > 0xff || a > 0xff)
+ return false;
+ if (color)
+ *color = (u32)r << 24 | (u32)g << 16 | (u32)b << 8 | (u32)a;
+ return true;
+}
+
+
+static ColorSetting color_for_symbol_kind(SymbolKind kind) {
+ switch (kind) {
+ case SYMBOL_CONSTANT:
+ return COLOR_CONSTANT;
+ case SYMBOL_TYPE:
+ case SYMBOL_FUNCTION:
+ case SYMBOL_FIELD:
+ return COLOR_BUILTIN;
+ case SYMBOL_VARIABLE:
+ case SYMBOL_OTHER:
+ return COLOR_TEXT;
+ case SYMBOL_KEYWORD:
+ return COLOR_KEYWORD;
+ }
+ return COLOR_TEXT;
+}
diff --git a/colors.h b/colors.h
index f45ed01..5f9f330 100644
--- a/colors.h
+++ b/colors.h
@@ -1,4 +1,4 @@
-ENUM_U16 {
+typedef enum {
COLOR_UNKNOWN,
COLOR_TEXT,
@@ -43,7 +43,7 @@ ENUM_U16 {
COLOR_COUNT
-} ENUM_U16_END(ColorSetting);
+} ColorSetting;
typedef struct {
ColorSetting setting;
@@ -91,56 +91,3 @@ static ColorName const color_names[] = {
};
static_assert_if_possible(arr_count(color_names) == COLOR_COUNT)
-
-static ColorSetting color_setting_from_str(char const *str) {
- // @OPTIMIZE: sort color_names, binary search
- for (int i = 0; i < COLOR_COUNT; ++i) {
- ColorName const *n = &color_names[i];
- if (streq(n->name, str))
- return n->setting;
- }
- return COLOR_UNKNOWN;
-}
-
-static char const *color_setting_to_str(ColorSetting s) {
- for (int i = 0; i < COLOR_COUNT; ++i) {
- ColorName const *n = &color_names[i];
- if (n->setting == s)
- return n->name;
- }
- return "???";
-}
-
-// converts #rrggbb/#rrggbbaa to a color. returns false if it's not in the right format.
-static Status color_from_str(char const *str, u32 *color) {
- uint r = 0, g = 0, b = 0, a = 0xff;
- bool success = false;
- switch (strlen(str)) {
- case 4:
- success = sscanf(str, "#%01x%01x%01x", &r, &g, &b) == 3;
- // extend single hex digit to double hex digit
- r |= r << 4;
- g |= g << 4;
- b |= b << 4;
- break;
- case 5:
- success = sscanf(str, "#%01x%01x%01x%01x", &r, &g, &b, &a) == 4;
- r |= r << 4;
- g |= g << 4;
- b |= b << 4;
- a |= a << 4;
- break;
- case 7:
- success = sscanf(str, "#%02x%02x%02x", &r, &g, &b) == 3;
- break;
- case 9:
- success = sscanf(str, "#%02x%02x%02x%02x", &r, &g, &b, &a) == 4;
- break;
- }
- if (!success || r > 0xff || g > 0xff || b > 0xff || a > 0xff)
- return false;
- if (color)
- *color = (u32)r << 24 | (u32)g << 16 | (u32)b << 8 | (u32)a;
- return true;
-}
-
diff --git a/lsp-parse.c b/lsp-parse.c
index 8afca07..947feb9 100644
--- a/lsp-parse.c
+++ b/lsp-parse.c
@@ -130,6 +130,11 @@ static bool parse_completion(LSP *lsp, const JSON *json, LSPResponse *response)
.new_text = item->label
};
+ double kind = json_object_get_number(json, item_object, "kind");
+ if (isnormal(kind) && kind >= LSP_COMPLETION_KIND_MIN && kind <= LSP_COMPLETION_KIND_MAX) {
+ item->kind = (LSPCompletionKind)kind;
+ }
+
JSONString sort_text = json_object_get_string(json, item_object, "sortText");
if (sort_text.pos) {
// LSP allows using a different string for sorting.
@@ -145,8 +150,10 @@ static bool parse_completion(LSP *lsp, const JSON *json, LSPResponse *response)
double edit_type = json_object_get_number(json, item_object, "insertTextFormat");
if (!isnan(edit_type)) {
if (edit_type != LSP_TEXT_EDIT_PLAIN && edit_type != LSP_TEXT_EDIT_SNIPPET) {
- lsp_set_error(lsp, "Bad InsertTextFormat: %g", edit_type);
- return false;
+ // maybe in the future more edit types will be added.
+ // probably they'll have associated capabilities, but I think it's best to just ignore unrecognized types
+ debug_println("Bad InsertTextFormat: %g", edit_type);
+ edit_type = LSP_TEXT_EDIT_PLAIN;
}
item->text_edit.type = (LSPTextEditType)edit_type;
}
diff --git a/lsp.c b/lsp.c
index 281ec17..9d02d34 100644
--- a/lsp.c
+++ b/lsp.c
@@ -323,3 +323,91 @@ void lsp_document_changed(LSP *lsp, const char *document, LSPDocumentChangeEvent
arr_add(c->changes, change);
lsp_send_request(lsp, &request);
}
+
+SymbolKind lsp_symbol_kind_to_ted(LSPSymbolKind kind) {
+ switch (kind) {
+ case LSP_SYMBOL_OTHER:
+ case LSP_SYMBOL_FILE:
+ case LSP_SYMBOL_MODULE:
+ case LSB_SYMBOL_NAMESPACE:
+ case LSP_SYMBOL_PACKAGE:
+ return SYMBOL_OTHER;
+
+ case LSP_SYMBOL_CLASS:
+ case LSP_SYMBOL_TYPEPARAMETER:
+ case LSP_SYMBOL_ENUM:
+ case LSP_SYMBOL_INTERFACE:
+ case LSP_SYMBOL_STRUCT:
+ case LSP_SYMBOL_EVENT: // i have no clue what this is. let's say it's a type.
+ return SYMBOL_TYPE;
+
+ case LSP_SYMBOL_PROPERTY:
+ case LSP_SYMBOL_FIELD:
+ case LSP_SYMBOL_KEY:
+ return SYMBOL_FIELD;
+
+ case LSP_SYMBOL_CONSTRUCTOR:
+ case LSP_SYMBOL_FUNCTION:
+ case LSP_SYMBOL_OPERATOR:
+ case LSP_SYMBOL_METHOD:
+ return SYMBOL_FUNCTION;
+
+ case LSP_SYMBOL_VARIABLE:
+ return SYMBOL_VARIABLE;
+
+ case LSP_SYMBOL_CONSTANT:
+ case LSP_SYMBOL_STRING:
+ case LSP_SYMBOL_NUMBER:
+ case LSP_SYMBOL_BOOLEAN:
+ case LSP_SYMBOL_ARRAY:
+ case LSP_SYMBOL_OBJECT:
+ case LSP_SYMBOL_ENUMMEMBER:
+ case LSP_SYMBOL_NULL:
+ return SYMBOL_CONSTANT;
+ }
+
+ return SYMBOL_OTHER;
+}
+
+SymbolKind lsp_completion_kind_to_ted(LSPCompletionKind kind) {
+ switch (kind) {
+ case LSP_COMPLETION_TEXT:
+ case LSP_COMPLETION_MODULE:
+ case LSP_COMPLETION_UNIT:
+ case LSP_COMPLETION_COLOR:
+ case LSP_COMPLETION_FILE:
+ case LSP_COMPLETION_REFERENCE:
+ case LSP_COMPLETION_FOLDER:
+ case LSP_COMPLETION_OPERATOR:
+ return SYMBOL_OTHER;
+
+ case LSP_COMPLETION_METHOD:
+ case LSP_COMPLETION_FUNCTION:
+ case LSP_COMPLETION_CONSTRUCTOR:
+ return SYMBOL_FUNCTION;
+
+ case LSP_COMPLETION_FIELD:
+ case LSP_COMPLETION_PROPERTY:
+ return SYMBOL_FIELD;
+
+ case LSP_COMPLETION_VARIABLE:
+ return SYMBOL_VARIABLE;
+
+ case LSP_COMPLETION_CLASS:
+ case LSP_COMPLETION_INTERFACE:
+ case LSP_COMPLETION_ENUM:
+ case LSP_COMPLETION_STRUCT:
+ case LSP_COMPLETION_EVENT:
+ case LSP_COMPLETION_TYPEPARAMETER:
+ return SYMBOL_TYPE;
+
+ case LSP_COMPLETION_VALUE:
+ case LSP_COMPLETION_ENUMMEMBER:
+ case LSP_COMPLETION_CONSTANT:
+ return SYMBOL_CONSTANT;
+
+ case LSP_COMPLETION_KEYWORD:
+ case LSP_COMPLETION_SNIPPET:
+ return SYMBOL_KEYWORD;
+ }
+}
diff --git a/lsp.h b/lsp.h
index d965cf6..0aa8628 100644
--- a/lsp.h
+++ b/lsp.h
@@ -44,7 +44,7 @@ typedef enum {
// server-to-client
LSP_REQUEST_SHOW_MESSAGE,
- LSP_REQUEST_LOG_MESSAGE
+ LSP_REQUEST_LOG_MESSAGE,
} LSPRequestType;
typedef struct {
@@ -106,6 +106,70 @@ typedef struct {
} data;
} LSPRequest;
+typedef enum {
+ // LSP doesn't actually define this but this will be used for unrecognized values
+ // (in case they add more symbol kinds in the future)
+ LSP_SYMBOL_OTHER = 0,
+
+ #define LSP_SYMBOL_KIND_MIN 1
+ LSP_SYMBOL_FILE = 1,
+ LSP_SYMBOL_MODULE = 2,
+ LSB_SYMBOL_NAMESPACE = 3,
+ LSP_SYMBOL_PACKAGE = 4,
+ LSP_SYMBOL_CLASS = 5,
+ LSP_SYMBOL_METHOD = 6,
+ LSP_SYMBOL_PROPERTY = 7,
+ LSP_SYMBOL_FIELD = 8,
+ LSP_SYMBOL_CONSTRUCTOR = 9,
+ LSP_SYMBOL_ENUM = 10,
+ LSP_SYMBOL_INTERFACE = 11,
+ LSP_SYMBOL_FUNCTION = 12,
+ LSP_SYMBOL_VARIABLE = 13,
+ LSP_SYMBOL_CONSTANT = 14,
+ LSP_SYMBOL_STRING = 15,
+ LSP_SYMBOL_NUMBER = 16,
+ LSP_SYMBOL_BOOLEAN = 17,
+ LSP_SYMBOL_ARRAY = 18,
+ LSP_SYMBOL_OBJECT = 19,
+ LSP_SYMBOL_KEY = 20,
+ LSP_SYMBOL_NULL = 21,
+ LSP_SYMBOL_ENUMMEMBER = 22,
+ LSP_SYMBOL_STRUCT = 23,
+ LSP_SYMBOL_EVENT = 24,
+ LSP_SYMBOL_OPERATOR = 25,
+ LSP_SYMBOL_TYPEPARAMETER = 26,
+ #define LSP_SYMBOL_KIND_MAX 26
+} LSPSymbolKind;
+
+typedef enum {
+ #define LSP_COMPLETION_KIND_MIN 1
+ LSP_COMPLETION_TEXT = 1,
+ LSP_COMPLETION_METHOD = 2,
+ LSP_COMPLETION_FUNCTION = 3,
+ LSP_COMPLETION_CONSTRUCTOR = 4,
+ LSP_COMPLETION_FIELD = 5,
+ LSP_COMPLETION_VARIABLE = 6,
+ LSP_COMPLETION_CLASS = 7,
+ LSP_COMPLETION_INTERFACE = 8,
+ LSP_COMPLETION_MODULE = 9,
+ LSP_COMPLETION_PROPERTY = 10,
+ LSP_COMPLETION_UNIT = 11,
+ LSP_COMPLETION_VALUE = 12,
+ LSP_COMPLETION_ENUM = 13,
+ LSP_COMPLETION_KEYWORD = 14,
+ LSP_COMPLETION_SNIPPET = 15,
+ LSP_COMPLETION_COLOR = 16,
+ LSP_COMPLETION_FILE = 17,
+ LSP_COMPLETION_REFERENCE = 18,
+ LSP_COMPLETION_FOLDER = 19,
+ LSP_COMPLETION_ENUMMEMBER = 20,
+ LSP_COMPLETION_CONSTANT = 21,
+ LSP_COMPLETION_STRUCT = 22,
+ LSP_COMPLETION_EVENT = 23,
+ LSP_COMPLETION_OPERATOR = 24,
+ LSP_COMPLETION_TYPEPARAMETER = 25,
+ #define LSP_COMPLETION_KIND_MAX 25
+} LSPCompletionKind;
// see InsertTextFormat in the LSP spec.
@@ -143,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;
+ // type of completion
+ LSPCompletionKind kind;
} LSPCompletionItem;
typedef struct {
@@ -212,3 +278,5 @@ bool lsp_create(LSP *lsp, const char *analyzer_command);
bool lsp_next_message(LSP *lsp, LSPMessage *message);
void lsp_document_changed(LSP *lsp, const char *document, LSPDocumentChangeEvent change);
void lsp_free(LSP *lsp);
+SymbolKind lsp_symbol_kind_to_ted(LSPSymbolKind kind);
+SymbolKind lsp_completion_kind_to_ted(LSPCompletionKind kind);
diff --git a/main.c b/main.c
index 364e7e3..ce40db1 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,8 @@
/*
@TODO:
+- kind (icon/color)
+ - improve color_for_symbol_kind
+- send textDocument.completion.completionItemKind capability
- only show "Loading..." if it's taking some time (prevent flash)
- LSP setting
- scroll through completions
@@ -111,6 +114,7 @@ static void die(char const *fmt, ...) {
#include "lsp.h"
#include "string32.c"
+#include "colors.c"
#include "syntax.c"
bool tag_goto(Ted *ted, char const *tag);
#include "buffer.c"
diff --git a/ted.h b/ted.h
index d56f3ab..7d23088 100644
--- a/ted.h
+++ b/ted.h
@@ -352,11 +352,23 @@ typedef struct {
u32 build_output_line; // which line in the build output corresponds to this error
} BuildError;
+// LSPSymbolKinds are translated to these. this is a much coarser categorization
+typedef enum {
+ SYMBOL_OTHER,
+ SYMBOL_FUNCTION,
+ SYMBOL_FIELD,
+ SYMBOL_TYPE,
+ SYMBOL_VARIABLE,
+ SYMBOL_CONSTANT,
+ SYMBOL_KEYWORD
+} SymbolKind;
+
typedef struct {
char *label;
char *filter;
char *text;
char *detail; // this can be NULL!
+ SymbolKind kind;
} Autocompletion;
typedef struct {