diff options
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | config.c | 1 | ||||
-rw-r--r-- | lsp-parse.c | 46 | ||||
-rw-r--r-- | lsp-write.c | 16 | ||||
-rw-r--r-- | lsp.c | 16 | ||||
-rw-r--r-- | lsp.h | 16 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | ted.c | 2 | ||||
-rw-r--r-- | ted.cfg | 8 | ||||
-rw-r--r-- | ted.h | 1 |
10 files changed, 65 insertions, 46 deletions
@@ -70,6 +70,7 @@ to open the command palette, and select "open-config". There are several section - `[extensions]` for which file extensions should be mapped to which programming languages Comments begin with `#`, and all other lines are of the form `key = value`. +Strings can span multiple lines and can either be delimited with `"` or `\``. By default ted's settings will automatically update when you save the config file. @@ -163,7 +164,8 @@ to reset all running LSP servers. You can integrate any LSP server with ted by setting the `lsp` option in the `[core.<language>]` section of `ted.cfg` to the command which starts the server. Some defaults will already be there, and are listed below. Make sure you install the LSP(s) you want and put the executables in your PATH (or change the `lsp` variable -to include the absolute path if not). +to include the absolute path if not). You can also set configuration options with the `lsp-configuration` option. +Make sure the configuration you provide is valid JSON. ### C/C++ @@ -119,6 +119,7 @@ static SettingString const settings_string[] = { {"bg-texture", settings_zero.bg_shader_image, sizeof settings_zero.bg_shader_image, true}, {"root-identifiers", settings_zero.root_identifiers, sizeof settings_zero.root_identifiers, true}, {"lsp", settings_zero.lsp, sizeof settings_zero.lsp, true}, + {"lsp-configuration", settings_zero.lsp_configuration, sizeof settings_zero.lsp_configuration, true}, }; diff --git a/lsp-parse.c b/lsp-parse.c index 7bbcbd1..8c914fa 100644 --- a/lsp-parse.c +++ b/lsp-parse.c @@ -929,30 +929,32 @@ void process_message(LSP *lsp, JSON *json) { case LSP_REQUEST_RENAME: add_to_messages = parse_rename(lsp, json, &response); break; - case LSP_REQUEST_INITIALIZE: { - // 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; - { - // configure jdtls so it actually supports signature help - // NOTE: this won't send if the LSP isn't jdtls (because of lsp_supports_request) - LSPRequest jdtls_configuration = { - .type = LSP_REQUEST_JDTLS_CONFIGURATION + 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}}, }; - lsp_send_request(lsp, &jdtls_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; + break; default: // it's some response we don't care about break; diff --git a/lsp-write.c b/lsp-write.c index c32b8f6..56f8e7d 100644 --- a/lsp-write.c +++ b/lsp-write.c @@ -295,7 +295,7 @@ static const char *lsp_request_method(LSPRequest *request) { return "workspace/workspaceFolders"; case LSP_REQUEST_DID_CHANGE_WORKSPACE_FOLDERS: return "workspace/didChangeWorkspaceFolders"; - case LSP_REQUEST_JDTLS_CONFIGURATION: + case LSP_REQUEST_CONFIGURATION: return "workspace/didChangeConfiguration"; case LSP_REQUEST_WORKSPACE_SYMBOLS: return "workspace/symbol"; @@ -613,17 +613,13 @@ void write_request(LSP *lsp, LSPRequest *request) { write_obj_end(o); write_obj_end(o); } break; - case LSP_REQUEST_JDTLS_CONFIGURATION: + case LSP_REQUEST_CONFIGURATION: { + const LSPRequestConfiguration *config = &request->data.configuration; write_key_obj_start(o, "params"); - write_key_obj_start(o, "settings"); - write_key_obj_start(o, "java"); - write_key_obj_start(o, "signatureHelp"); - write_key_bool(o, "enabled", true); - write_obj_end(o); - write_obj_end(o); - write_obj_end(o); + write_key(o, "settings"); + str_builder_append(&o->builder, config->settings); write_obj_end(o); - break; + } break; } write_obj_end(o); @@ -57,8 +57,11 @@ void lsp_request_free(LSPRequest *r) { case LSP_REQUEST_HIGHLIGHT: case LSP_REQUEST_DID_CLOSE: case LSP_REQUEST_WORKSPACE_FOLDERS: - case LSP_REQUEST_JDTLS_CONFIGURATION: break; + case LSP_REQUEST_CONFIGURATION: { + LSPRequestConfiguration *config = &r->data.configuration; + free(config->settings); + } break; case LSP_REQUEST_DID_OPEN: { LSPRequestDidOpen *open = &r->data.open; free(open->file_contents); @@ -165,12 +168,10 @@ static bool lsp_supports_request(LSP *lsp, const LSPRequest *request) { case LSP_REQUEST_DID_OPEN: case LSP_REQUEST_DID_CLOSE: case LSP_REQUEST_DID_CHANGE: + case LSP_REQUEST_CONFIGURATION: case LSP_REQUEST_SHUTDOWN: case LSP_REQUEST_EXIT: return true; - case LSP_REQUEST_JDTLS_CONFIGURATION: - // not perfect but whatever - return strstr(lsp->command, "jdtls") != 0; case LSP_REQUEST_COMPLETION: return cap->completion_support; case LSP_REQUEST_SIGNATURE_HELP: @@ -216,7 +217,7 @@ static bool request_type_is_notification(LSPRequestType type) { case LSP_REQUEST_DID_CLOSE: case LSP_REQUEST_DID_CHANGE: case LSP_REQUEST_DID_CHANGE_WORKSPACE_FOLDERS: - case LSP_REQUEST_JDTLS_CONFIGURATION: + case LSP_REQUEST_CONFIGURATION: return true; case LSP_REQUEST_INITIALIZE: case LSP_REQUEST_SHUTDOWN: @@ -452,7 +453,7 @@ const char *lsp_document_path(LSP *lsp, LSPDocumentID document) { return path; } -LSP *lsp_create(const char *root_dir, const char *analyzer_command) { +LSP *lsp_create(const char *root_dir, const char *analyzer_command, const char *configuration) { LSP *lsp = calloc(1, sizeof *lsp); if (!lsp) return NULL; @@ -470,6 +471,8 @@ LSP *lsp_create(const char *root_dir, const char *analyzer_command) { str_hash_table_create(&lsp->document_ids, sizeof(u32)); lsp->command = str_dup(analyzer_command); + if (configuration && *configuration) + lsp->configuration_to_send = str_dup(configuration); lsp->quit_sem = SDL_CreateSemaphore(0); lsp->error_mutex = SDL_CreateMutex(); lsp->messages_mutex = SDL_CreateMutex(); @@ -574,6 +577,7 @@ void lsp_free(LSP *lsp) { arr_free(lsp->signature_help_trigger_chars); arr_free(lsp->signature_help_retrigger_chars); free(lsp->command); + free(lsp->configuration_to_send); memset(lsp, 0, sizeof *lsp); free(lsp); } @@ -61,10 +61,7 @@ typedef enum { LSP_REQUEST_INITIALIZE, // initialize LSP_REQUEST_INITIALIZED, // initialized LSP_REQUEST_CANCEL, // $/cancelRequest - // workspace/didChangeConfiguration with parameters specifically for jdtls. - // we need this because annoyingly jdtls refuses to give signature help - // unless you specifically configure it to do that - LSP_REQUEST_JDTLS_CONFIGURATION, + LSP_REQUEST_CONFIGURATION, // workspace/didChangeConfiguration LSP_REQUEST_SHUTDOWN, // shutdown LSP_REQUEST_EXIT, // exit LSP_REQUEST_DID_OPEN, // textDocument/didOpen @@ -201,6 +198,11 @@ typedef struct { } LSPRequestDidChangeWorkspaceFolders; typedef struct { + // this string should be valid JSON. will be freed. + char *settings; +} LSPRequestConfiguration; + +typedef struct { LSPRequestID id; LSPRequestType type; char *id_string; // if not NULL, this is the ID (only for server-to-client messages; we always use integer IDs) @@ -210,6 +212,7 @@ typedef struct { LSPRequestDidOpen open; LSPRequestDidClose close; LSPRequestDidChange change; + LSPRequestConfiguration configuration; LSPRequestCompletion completion; LSPRequestSignatureHelp signature_help; LSPRequestHover hover; @@ -548,6 +551,9 @@ typedef struct LSP { bool initialized; // thread-safety: only set once in lsp_create. char *command; + // this is set in lsp_create, then later set to NULL when we send over the configuration (after the initialized notification). + // thread-safety: set once in lsp_create, then only acessed once in communication thread. + char *configuration_to_send; LSPThread communication_thread; LSPSemaphore quit_sem; // thread-safety: only accessed in communication thread @@ -587,7 +593,7 @@ void lsp_cancel_request(LSP *lsp, LSPRequestID id); // don't free the contents of this response! let me handle it! void lsp_send_response(LSP *lsp, LSPResponse *response); const char *lsp_response_string(const LSPResponse *response, LSPString string); -LSP *lsp_create(const char *root_dir, const char *analyzer_command); +LSP *lsp_create(const char *root_dir, const char *analyzer_command, const char *configuration); // try to add a new "workspace folder" to the lsp. // IMPORTANT: only call this if lsp->initialized is true // (if not we don't yet know whether the server supports workspace folders) @@ -1,7 +1,6 @@ /* @TODO: - LSP configuration in ted.cfg - - remove LSP_REQUEST_JDTLS_CONFIGURATION - disable publishDiagnostics for rust-analyzer (& others)? - phantom completions - debug-lsp option (which logs LSP messages) @@ -192,7 +192,7 @@ LSP *ted_get_lsp(Ted *ted, const char *path, Language language) { if (*settings->lsp) { // start up this LSP char *root_dir = settings_get_root_dir(settings, path); - ted->lsps[i] = lsp_create(root_dir, settings->lsp); + ted->lsps[i] = lsp_create(root_dir, settings->lsp, settings->lsp_configuration); free(root_dir); // don't actually return it yet, since it's still initializing (see above) } @@ -110,6 +110,14 @@ lsp = "gopls" [Java.core] lsp = "jdtls" +# by default, jdtls doesn't give signature help +lsp-configuration = `{ + "java": { + "signatureHelp": { + "enabled": true + } + } +}` [JavaScript.core] lsp = "typescript-language-server --stdio" @@ -144,6 +144,7 @@ typedef struct { char bg_shader_image[TED_PATH_MAX]; char root_identifiers[4096]; char lsp[512]; + char lsp_configuration[4096]; char build_default_command[256]; // [i] = comma-separated string of file extensions for language i, or NULL for none char *language_extensions[LANG_COUNT]; |