summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-01-02 13:20:16 -0500
committerpommicket <pommicket@gmail.com>2023-01-02 13:20:16 -0500
commit1dc24e79ec7cf80e06b9c4e7cc55e18857b624c1 (patch)
tree9537660776906e08d5b4f511926bf4a1c8f4c644
parent9844c679b4a4fb42c97f80e5653dea7c73ff0edf (diff)
restructure LSP stuff
-rw-r--r--config.c4
-rw-r--r--lsp-json.c62
-rw-r--r--lsp-parse.c5
-rw-r--r--lsp-write.c7
-rw-r--r--lsp.c22
-rw-r--r--lsp.h116
-rw-r--r--main.c3
-rw-r--r--session.c6
-rw-r--r--ted.h48
9 files changed, 166 insertions, 107 deletions
diff --git a/config.c b/config.c
index 7f43b24..bc02e5c 100644
--- a/config.c
+++ b/config.c
@@ -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;
diff --git a/lsp-json.c b/lsp-json.c
index 1e77812..4d5a2c7 100644
--- a/lsp-json.c
+++ b/lsp-json.c
@@ -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);
diff --git a/lsp.c b/lsp.c
index 16e0087..35ec0d7 100644
--- a/lsp.c
+++ b/lsp.c
@@ -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:
diff --git a/lsp.h b/lsp.h
index 3948329..6623300 100644
--- a/lsp.h
+++ b/lsp.h
@@ -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
+
diff --git a/main.c b/main.c
index 2f06cdf..9433c4d 100644
--- a/main.c
+++ b/main.c
@@ -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();
diff --git a/session.c b/session.c
index 4dfbefa..6202a08 100644
--- a/session.c
+++ b/session.c
@@ -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];
diff --git a/ted.h b/ted.h
index 21e421a..7c50ac2 100644
--- a/ted.h
+++ b/ted.h
@@ -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