diff options
-rw-r--r-- | ide-definitions.c | 2 | ||||
-rw-r--r-- | lsp-parse.c | 166 | ||||
-rw-r--r-- | main.c | 54 |
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 @@ -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); |