diff options
-rw-r--r-- | config.c | 4 | ||||
-rw-r--r-- | lsp-json.c | 62 | ||||
-rw-r--r-- | lsp-parse.c | 5 | ||||
-rw-r--r-- | lsp-write.c | 7 | ||||
-rw-r--r-- | lsp.c | 22 | ||||
-rw-r--r-- | lsp.h | 116 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | session.c | 6 | ||||
-rw-r--r-- | ted.h | 48 |
9 files changed, 166 insertions, 107 deletions
@@ -7,7 +7,9 @@ // [section2] // asdf = 123 -// all the "control" pointers here are relative to a NULL Settings object. +#include "ted.h" + +// all the "control" pointers here are relative to `settings_zero`. typedef struct { const char *name; const bool *control; @@ -1,62 +1,9 @@ // JSON parser for LSP -// provides FAST(ish) parsing but SLOW lookup -// this is especially fast for small objects +// provides FAST(ish) parsing but SLOW lookup for large objects // this actually supports "extended json", where objects can have arbitrary values as keys. -// a string -typedef struct { - u32 pos; - u32 len; -} JSONString; - -typedef struct JSONValue JSONValue; - -typedef struct { - u32 len; - // this is an index into the values array - // values[items..items+len] store the names - // values[items+len..items+2*len] store the values - u32 items; -} JSONObject; - -typedef struct { - u32 len; - // this is an index into the values array - // values[elements..elements+len] are the elements - u32 elements; -} JSONArray; - -typedef enum { - // note: json doesn't actually include undefined. - // this is only for returning things from json_get etc. - JSON_UNDEFINED, - JSON_NULL, - JSON_FALSE, - JSON_TRUE, - JSON_NUMBER, - JSON_STRING, - JSON_OBJECT, - JSON_ARRAY -} JSONValueType; - -struct JSONValue { - JSONValueType type; - union { - double number; - JSONString string; - JSONArray array; - JSONObject object; - } val; -}; - - -typedef struct { - char error[64]; - bool is_text_copied; // if this is true, then json_free will call free on text - const char *text; - // root = values[0] - JSONValue *values; -} JSON; +#define LSP_INTERNAL 1 +#include "lsp.h" #define SKIP_WHITESPACE while (json_is_space(text[index])) ++index; @@ -401,7 +348,6 @@ void json_free(JSON *json) { json->text = NULL; } -// NOTE: text must live as long as json!!! bool json_parse(JSON *json, const char *text) { memset(json, 0, sizeof *json); json->text = text; @@ -423,7 +369,6 @@ bool json_parse(JSON *json, const char *text) { return true; } -// like json_parse, but a copy of text is made, so you can free/overwrite it immediately. bool json_parse_copy(JSON *json, const char *text) { bool success = json_parse(json, str_dup(text)); if (success) { @@ -446,7 +391,6 @@ static bool json_streq(const JSON *json, const JSONString *string, const char *n return *name == '\0'; } -// returns undefined if the property `name` does not exist. JSONValue json_object_get(const JSON *json, JSONObject object, const char *name) { const JSONValue *items = &json->values[object.items]; for (u32 i = 0; i < object.len; ++i) { diff --git a/lsp-parse.c b/lsp-parse.c index 5a1da29..17650c3 100644 --- a/lsp-parse.c +++ b/lsp-parse.c @@ -1,3 +1,6 @@ +#define LSP_INTERNAL 1 +#include "lsp.h" + static WarnUnusedResult bool lsp_expect_type(LSP *lsp, JSONValue value, JSONValueType type, const char *what) { if (value.type != type) { lsp_set_error(lsp, "Expected %s for %s, got %s", @@ -827,7 +830,7 @@ static bool parse_references(LSP *lsp, const JSON *json, LSPResponse *response) return true; } -static void process_message(LSP *lsp, JSON *json) { +void process_message(LSP *lsp, JSON *json) { #if 0 printf("\x1b[3m"); diff --git a/lsp-write.c b/lsp-write.c index 3c2c11a..1a1093c 100644 --- a/lsp-write.c +++ b/lsp-write.c @@ -1,3 +1,6 @@ +#define LSP_INTERNAL 1 +#include "lsp.h" + #define write_bool lsp_write_bool // prevent naming conflict static const char *lsp_language_id(Language lang) { @@ -363,7 +366,7 @@ static void write_symbol_kind_support(JSONWriter *o) { // NOTE: don't call lsp_request_free after calling this function. // I will do it for you. -static void write_request(LSP *lsp, LSPRequest *request) { +void write_request(LSP *lsp, LSPRequest *request) { JSONWriter writer = message_writer_new(lsp); JSONWriter *o = &writer; @@ -660,7 +663,7 @@ static void write_response(LSP *lsp, LSPResponse *response) { lsp_response_free(response); } -static void write_message(LSP *lsp, LSPMessage *message) { +void write_message(LSP *lsp, LSPMessage *message) { switch (message->type) { case LSP_REQUEST: write_request(lsp, &message->u.request); @@ -1,19 +1,5 @@ -// print server-to-client communication -#define LSP_SHOW_S2C 0 -// print client-to-server communication -#define LSP_SHOW_C2S 0 - -static void lsp_request_free(LSPRequest *r); -static void lsp_response_free(LSPResponse *r); - -#define lsp_set_error(lsp, ...) do {\ - SDL_LockMutex(lsp->error_mutex);\ - strbuf_printf(lsp->error, __VA_ARGS__);\ - SDL_UnlockMutex(lsp->error_mutex);\ - } while (0) -#include "lsp-json.c" -#include "lsp-write.c" -#include "lsp-parse.c" +#define LSP_INTERNAL 1 +#include "lsp.h" // it's nice to have request IDs be totally unique, including across LSP servers. static LSPRequestID get_request_id(void) { @@ -39,7 +25,7 @@ static void lsp_document_change_event_free(LSPDocumentChangeEvent *event) { free(event->text); } -static void lsp_request_free(LSPRequest *r) { +void lsp_request_free(LSPRequest *r) { free(r->id_string); switch (r->type) { case LSP_REQUEST_NONE: @@ -87,7 +73,7 @@ static void lsp_request_free(LSPRequest *r) { memset(r, 0, sizeof *r); } -static void lsp_response_free(LSPResponse *r) { +void lsp_response_free(LSPResponse *r) { arr_free(r->string_data); switch (r->request.type) { case LSP_REQUEST_COMPLETION: @@ -574,3 +574,119 @@ LSPDocumentPosition lsp_location_end_position(LSPLocation location); void lsp_free(LSP *lsp); #endif // LSP_H_ + +#if defined LSP_INTERNAL && !defined LSP_INTERNAL_H_ +#define LSP_INTERNAL_H_ + +#define lsp_set_error(lsp, ...) do {\ + SDL_LockMutex(lsp->error_mutex);\ + strbuf_printf(lsp->error, __VA_ARGS__);\ + SDL_UnlockMutex(lsp->error_mutex);\ + } while (0) + +// a string +typedef struct { + u32 pos; + u32 len; +} JSONString; + +typedef struct JSONValue JSONValue; + +typedef struct { + u32 len; + // this is an index into the values array + // values[items..items+len] store the names + // values[items+len..items+2*len] store the values + u32 items; +} JSONObject; + +typedef struct { + u32 len; + // this is an index into the values array + // values[elements..elements+len] are the elements + u32 elements; +} JSONArray; + +typedef enum { + // note: json doesn't actually include undefined. + // this is only for returning things from json_get etc. + JSON_UNDEFINED, + JSON_NULL, + JSON_FALSE, + JSON_TRUE, + JSON_NUMBER, + JSON_STRING, + JSON_OBJECT, + JSON_ARRAY +} JSONValueType; + +struct JSONValue { + JSONValueType type; + union { + double number; + JSONString string; + JSONArray array; + JSONObject object; + } val; +}; + + +typedef struct { + char error[64]; + bool is_text_copied; // if this is true, then json_free will call free on text + const char *text; + // root = values[0] + JSONValue *values; +} JSON; + + +void process_message(LSP *lsp, JSON *json); +void write_request(LSP *lsp, LSPRequest *request); +void write_message(LSP *lsp, LSPMessage *message); +void lsp_request_free(LSPRequest *r); +void lsp_response_free(LSPResponse *r); + +const char *json_type_to_str(JSONValueType type); +void json_debug_print_array(const JSON *json, JSONArray array); +void json_debug_print_object(const JSON *json, JSONObject obj); +void json_debug_print_string(const JSON *json, JSONString string); +void json_debug_print_value(const JSON *json, JSONValue value); +void json_free(JSON *json); +// NOTE: text must live as long as json!!! +bool json_parse(JSON *json, const char *text); +// like json_parse, but a copy of text is made, so you can free/overwrite it immediately. +bool json_parse_copy(JSON *json, const char *text); +JSONValue json_object_get(const JSON *json, JSONObject object, const char *name); +JSONValue json_array_get(const JSON *json, JSONArray array, u64 i); +JSONValue json_object_key(const JSON *json, JSONObject object, u64 i); +JSONValue json_object_value(const JSON *json, JSONObject object, u64 i); +double json_force_number(JSONValue x); +double json_object_get_number(const JSON *json, JSONObject object, const char *name); +double json_array_get_number(const JSON *json, JSONArray array, size_t i); +bool json_force_bool(JSONValue x, bool default_value); +bool json_object_get_bool(const JSON *json, JSONObject object, const char *name, bool default_value); +bool json_array_get_bool(const JSON *json, JSONArray array, size_t i, bool default_value); +JSONString json_force_string(JSONValue x); +JSONString json_object_get_string(const JSON *json, JSONObject object, const char *name); +JSONString json_array_get_string(const JSON *json, JSONArray array, size_t i); +JSONObject json_force_object(JSONValue x); +JSONObject json_object_get_object(const JSON *json, JSONObject object, const char *name); +JSONObject json_array_get_object(const JSON *json, JSONArray array, size_t i); +JSONArray json_force_array(JSONValue x); +JSONArray json_object_get_array(const JSON *json, JSONObject object, const char *name); +JSONArray json_array_get_array(const JSON *json, JSONArray array, size_t i); +JSONValue json_root(const JSON *json); +JSONValue json_get(const JSON *json, const char *path); +bool json_has(const JSON *json, const char *path); +void json_string_get(const JSON *json, JSONString string, char *buf, size_t buf_sz); +void json_debug_print(const JSON *json); +size_t json_escape_to(char *out, size_t out_sz, const char *in); +char *json_escape(const char *str); + +// print server-to-client communication +#define LSP_SHOW_S2C 0 +// print client-to-server communication +#define LSP_SHOW_C2S 0 + +#endif // LSP_INTERNAL + @@ -110,6 +110,9 @@ no_warn_end #include "config.c" #include "session.c" #include "lsp.c" +#include "lsp-json.c" +#include "lsp-write.c" +#include "lsp-parse.c" #if PROFILE #define PROFILE_TIME(var) double var = time_get_seconds(); @@ -1,3 +1,5 @@ +#include "ted.h" + #define SESSION_FILENAME "session.txt" #define SESSION_VERSION "\x7fTED0002" @@ -320,7 +322,7 @@ static void session_read_file(Ted *ted, FILE *fp) { } } -static void session_write(Ted *ted) { +void session_write(Ted *ted) { const Settings *settings = ted_active_settings(ted); if (!settings->restore_session) return; @@ -341,7 +343,7 @@ static void session_write(Ted *ted) { } } -static void session_read(Ted *ted) { +void session_read(Ted *ted) { const Settings *settings = ted_active_settings(ted); if (settings->restore_session) { char filename[TED_PATH_MAX]; @@ -778,6 +778,26 @@ Command command_from_str(const char *str); const char *command_to_str(Command c); void command_execute(Ted *ted, Command c, i64 argument); +// === config.c === +// first, we read all config files, then we parse them. +// this is because we want less specific settings (e.g. settings applied +// to all languages instead of one particular language) to be applied first, +// then more specific settings are based off of those. +// EXAMPLE: +// ---config file 1--- +// [Javascript.core] +// syntax-highlighting = off +// (inherits tab-width = 4) +// [CSS.core] +// tab-width = 2 (overrides tab-width = 4) +// ---config file 2--- +// [core] +// tab-width = 4 +void config_read(Ted *ted, ConfigPart **parts, const char *filename); +void config_parse(Ted *ted, ConfigPart **pparts); +void config_free(Ted *ted); +char *settings_get_root_dir(Settings *settings, const char *path); + // === find.c === TextBuffer *find_search_buffer(Ted *ted); float find_menu_height(Ted *ted); @@ -890,6 +910,10 @@ void node_split(Ted *ted, Node *node, bool vertical); void node_split_switch(Ted *ted); void node_split_swap(Ted *ted); +// === session.c === +void session_write(Ted *ted); +void session_read(Ted *ted); + // === syntax.c === Language language_from_str(const char *str); const char *language_to_str(Language language); @@ -959,28 +983,4 @@ PopupOption popup_update(Ted *ted, u32 options); void popup_render(Ted *ted, u32 options, const char *title, const char *body); v2 checkbox_frame(Ted *ted, bool *value, const char *label, v2 pos); - -// first, we read all config files, then we parse them. -// this is because we want less specific settings (e.g. settings applied -// to all languages instead of one particular language) to be applied first, -// then more specific settings are based off of those. -// EXAMPLE: -// ---config file 1--- -// [Javascript.core] -// syntax-highlighting = off -// (inherits tab-width = 4) -// [CSS.core] -// tab-width = 2 (overrides tab-width = 4) -// ---config file 2--- -// [core] -// tab-width = 4 -void config_read(Ted *ted, ConfigPart **parts, const char *filename); -void config_parse(Ted *ted, ConfigPart **parts); -void config_free(Ted *ted); -char *settings_get_root_dir(Settings *settings, const char *path); -void menu_open(Ted *ted, Menu menu); -void menu_close(Ted *ted); -void autocomplete_close(Ted *ted); -void signature_help_retrigger(Ted *ted); - #endif |