summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ide-definitions.c2
-rw-r--r--lsp-parse.c166
-rw-r--r--main.c54
3 files changed, 119 insertions, 103 deletions
diff --git a/ide-definitions.c b/ide-definitions.c
index e956f5b..103d8c4 100644
--- a/ide-definitions.c
+++ b/ide-definitions.c
@@ -221,7 +221,7 @@ void definitions_process_lsp_response(Ted *ted, LSP *lsp, const LSPResponse *res
} break;
default:
- debug_println("?? bad request type in %s", __func__);
+ debug_println("?? bad request type in %s : %u:%u", __func__, response->request.id, response->request.type);
break;
}
}
diff --git a/lsp-parse.c b/lsp-parse.c
index 6cb7cd4..094fc81 100644
--- a/lsp-parse.c
+++ b/lsp-parse.c
@@ -911,6 +911,7 @@ void process_message(LSP *lsp, JSON *json) {
LSPRequest response_to = {0};
if (id_value.type == JSON_NUMBER) {
u64 id = (u64)id_value.val.number;
+ SDL_LockMutex(lsp->messages_mutex);
arr_foreach_ptr(lsp->requests_sent, LSPRequest, req) {
if (req->id == id) {
response_to = *req;
@@ -918,6 +919,7 @@ void process_message(LSP *lsp, JSON *json) {
break;
}
}
+ SDL_UnlockMutex(lsp->messages_mutex);
}
double error_code = json_force_number(json_get(json, "error.code"));
@@ -925,89 +927,93 @@ void process_message(LSP *lsp, JSON *json) {
JSONValue result = json_get(json, "result");
if (result.type != JSON_UNDEFINED || error.type == JSON_STRING) {
// server-to-client response
- LSPResponse response = {0};
- bool add_to_messages = false;
- response.request = response_to;
- // now response_to is response's responsibility
- memset(&response_to, 0, sizeof response_to);
-
- // make sure (LSPString){0} gets treated as an empty string
- arr_add(response.string_data, '\0');
-
- if (error.type == JSON_STRING) {
- response.error = json_string_get_alloc(json, error.val.string);
- }
-
- if (response.error) {
- if (error_code != LSP_ERROR_REQUEST_CANCELLED)
- add_to_messages = true;
- } else switch (response.request.type) {
- case LSP_REQUEST_COMPLETION:
- add_to_messages = parse_completion(lsp, json, &response);
- break;
- case LSP_REQUEST_SIGNATURE_HELP:
- add_to_messages = parse_signature_help(lsp, json, &response);
- break;
- case LSP_REQUEST_HOVER:
- add_to_messages = parse_hover(lsp, json, &response);
- break;
- case LSP_REQUEST_DEFINITION:
- case LSP_REQUEST_DECLARATION:
- case LSP_REQUEST_TYPE_DEFINITION:
- case LSP_REQUEST_IMPLEMENTATION:
- add_to_messages = parse_definition(lsp, json, &response);
- break;
- case LSP_REQUEST_HIGHLIGHT:
- add_to_messages = parse_highlight(lsp, json, &response);
- break;
- case LSP_REQUEST_REFERENCES:
- add_to_messages = parse_references(lsp, json, &response);
- break;
- case LSP_REQUEST_WORKSPACE_SYMBOLS:
- add_to_messages = parse_workspace_symbols(lsp, json, &response);
- break;
- case LSP_REQUEST_RENAME:
- add_to_messages = parse_rename(lsp, json, &response);
- break;
- case LSP_REQUEST_INITIALIZE:
- if (!lsp->initialized) {
- // it's the response to our initialize request!
- if (result.type == JSON_OBJECT) {
- // read server capabilities
- JSONObject capabilities = json_object_get_object(json, result.val.object, "capabilities");
- parse_capabilities(lsp, json, capabilities);
- }
-
- LSPRequest initialized = {
- .type = LSP_REQUEST_INITIALIZED,
- .data = {{0}},
- };
- write_request(lsp, &initialized);
- // we can now send requests which have nothing to do with initialization
- lsp->initialized = true;
- if (lsp->configuration_to_send) {
- LSPRequest configuration = {
- .type = LSP_REQUEST_CONFIGURATION
+ if (!response_to.type) {
+ // response to cancelled request (or invalid response from server)
+ } else {
+ LSPResponse response = {0};
+ bool add_to_messages = false;
+ response.request = response_to;
+ // now response_to is response's responsibility
+ memset(&response_to, 0, sizeof response_to);
+
+ // make sure (LSPString){0} gets treated as an empty string
+ arr_add(response.string_data, '\0');
+
+ if (error.type == JSON_STRING) {
+ response.error = json_string_get_alloc(json, error.val.string);
+ }
+
+ if (response.error) {
+ if (error_code != LSP_ERROR_REQUEST_CANCELLED)
+ add_to_messages = true;
+ } else switch (response.request.type) {
+ case LSP_REQUEST_COMPLETION:
+ add_to_messages = parse_completion(lsp, json, &response);
+ break;
+ case LSP_REQUEST_SIGNATURE_HELP:
+ add_to_messages = parse_signature_help(lsp, json, &response);
+ break;
+ case LSP_REQUEST_HOVER:
+ add_to_messages = parse_hover(lsp, json, &response);
+ break;
+ case LSP_REQUEST_DEFINITION:
+ case LSP_REQUEST_DECLARATION:
+ case LSP_REQUEST_TYPE_DEFINITION:
+ case LSP_REQUEST_IMPLEMENTATION:
+ add_to_messages = parse_definition(lsp, json, &response);
+ break;
+ case LSP_REQUEST_HIGHLIGHT:
+ add_to_messages = parse_highlight(lsp, json, &response);
+ break;
+ case LSP_REQUEST_REFERENCES:
+ add_to_messages = parse_references(lsp, json, &response);
+ break;
+ case LSP_REQUEST_WORKSPACE_SYMBOLS:
+ add_to_messages = parse_workspace_symbols(lsp, json, &response);
+ break;
+ case LSP_REQUEST_RENAME:
+ add_to_messages = parse_rename(lsp, json, &response);
+ break;
+ case LSP_REQUEST_INITIALIZE:
+ if (!lsp->initialized) {
+ // it's the response to our initialize request!
+ if (result.type == JSON_OBJECT) {
+ // read server capabilities
+ JSONObject capabilities = json_object_get_object(json, result.val.object, "capabilities");
+ parse_capabilities(lsp, json, capabilities);
+ }
+
+ LSPRequest initialized = {
+ .type = LSP_REQUEST_INITIALIZED,
+ .data = {{0}},
};
- configuration.data.configuration.settings = lsp->configuration_to_send;
- lsp->configuration_to_send = NULL;
- lsp_send_request(lsp, &configuration);
+ write_request(lsp, &initialized);
+ // we can now send requests which have nothing to do with initialization
+ lsp->initialized = true;
+ if (lsp->configuration_to_send) {
+ LSPRequest configuration = {
+ .type = LSP_REQUEST_CONFIGURATION
+ };
+ configuration.data.configuration.settings = lsp->configuration_to_send;
+ lsp->configuration_to_send = NULL;
+ lsp_send_request(lsp, &configuration);
+ }
}
+ break;
+ default:
+ // it's some response we don't care about
+ break;
+ }
+
+ if (add_to_messages) {
+ SDL_LockMutex(lsp->messages_mutex);
+ LSPMessage *message = arr_addp(lsp->messages_server2client);
+ message->type = LSP_RESPONSE;
+ message->u.response = response;
+ SDL_UnlockMutex(lsp->messages_mutex);
+ } else {
+ lsp_response_free(&response);
}
- break;
- default:
- // it's some response we don't care about
- break;
- }
-
- if (add_to_messages) {
- SDL_LockMutex(lsp->messages_mutex);
- LSPMessage *message = arr_addp(lsp->messages_server2client);
- message->type = LSP_RESPONSE;
- message->u.response = response;
- SDL_UnlockMutex(lsp->messages_mutex);
- } else {
- lsp_response_free(&response);
}
} else if (json_has(json, "method")) {
// server-to-client request
diff --git a/main.c b/main.c
index 6b5615e..8d720c5 100644
--- a/main.c
+++ b/main.c
@@ -3,7 +3,6 @@ FUTURE FEATURES:
- option for separate colors for read/write highlights
- styles ([color] sections)
- for this, it would be nice to have #include in ted.cfg
-- open multiple files with command line arguments
- better undo chaining (dechain on backspace?)
- manual.md
- regenerate tags for completion too if there are no results
@@ -316,27 +315,36 @@ int main(int argc, char **argv) {
syntax_register_builtin_languages();
// read command-line arguments
- const char *starting_filename = NULL;
- switch (argc) {
- case 0: case 1: break;
- case 2:
- if (streq(argv[1], "--help")) {
+ int dash_dash = argc;
+ for (int i = 1; i < argc; ++i) {
+ if (streq(argv[i], "--")) {
+ dash_dash = i;
+ break;
+ }
+ }
+
+ const char **starting_files = NULL;
+ for (int i = 1; i < dash_dash; ++i) {
+ if (streq(argv[i], "--help")) {
printf("%s\n", TED_VERSION_FULL);
- printf("Usage: ted [file name]\n");
+ printf("A text editor by pommicket.\n");
+ printf("For more information see https://github.com/pommicket/ted\n");
+ printf("\n");
+ printf("Usage: ted [--help] [--version] [--] [file names]\n");
exit(0);
- } else if (streq(argv[1], "--version")) {
+ } else if (streq(argv[i], "--version")) {
printf("%s\n", TED_VERSION_FULL);
exit(0);
+ } else if (argv[i][0] == '-') {
+ fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+ exit(EXIT_FAILURE);
+ } else {
+ arr_add(starting_files, argv[i]);
}
- // essentially, replace / with \ on windows.
- for (char *p = argv[1]; *p; ++p)
- if (strchr(ALL_PATH_SEPARATORS, *p))
- *p = PATH_SEPARATOR;
- starting_filename = argv[1];
- break;
- default:
- fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
- return EXIT_FAILURE;
+ }
+
+ for (int i = dash_dash + 1; i < argc; ++i) {
+ arr_add(starting_files, argv[i]);
}
PROFILE_TIME(basic_init_end)
@@ -527,17 +535,19 @@ int main(int argc, char **argv) {
line_buffer_create(&ted->argument_buffer, ted);
buffer_create(&ted->build_buffer, ted);
- {
- if (starting_filename) {
- if (fs_file_exists(starting_filename)) {
- ted_open_file(ted, starting_filename);
+ for (u32 i = 0; i < arr_len(starting_files); ++i) {
+ const char *filename = starting_files[i];
+ if (filename) {
+ if (fs_file_exists(filename)) {
+ ted_open_file(ted, filename);
} else {
- ted_new_file(ted, starting_filename);
+ ted_new_file(ted, filename);
}
} else {
session_read(ted);
}
}
+ arr_free(starting_files);