summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-12-29 23:13:23 -0500
committerpommicket <pommicket@gmail.com>2022-12-29 23:13:23 -0500
commita0f8332da674d452f7ae4f84f01d4682d464c9b2 (patch)
treed003832a43f92b8b466815dc3f1354e5b69da11d
parentadbfd5f248d390ae73eb9da636a457ce770c9ac0 (diff)
show the wait cursor when waiting for go to definition
-rw-r--r--command.c1
-rw-r--r--ide-definitions.c30
-rw-r--r--lsp-write.c38
-rw-r--r--lsp.c40
-rw-r--r--lsp.h9
-rw-r--r--main.c4
-rw-r--r--ted.h15
7 files changed, 84 insertions, 53 deletions
diff --git a/command.c b/command.c
index 47dabef..4f2d643 100644
--- a/command.c
+++ b/command.c
@@ -394,6 +394,7 @@ void command_execute(Ted *ted, Command c, i64 argument) {
break;
case CMD_ESCAPE:
+ definition_cancel_lookup(ted);
if (*ted->error_shown) {
// dismiss error box
*ted->error_shown = '\0';
diff --git a/ide-definitions.c b/ide-definitions.c
index 3a36a96..8648325 100644
--- a/ide-definitions.c
+++ b/ide-definitions.c
@@ -1,15 +1,25 @@
void definition_goto(Ted *ted, LSP *lsp, const char *name, LSPDocumentPosition position) {
+ Definitions *defs = &ted->definitions;
if (lsp) {
// send that request
LSPRequest request = {.type = LSP_REQUEST_DEFINITION};
request.data.definition.position = position;
- lsp_send_request(lsp, &request);
+ LSPRequestID id = lsp_send_request(lsp, &request);
+ defs->last_request_lsp = lsp->id;
+ defs->last_request_id = id;
+ defs->last_request_time = ted->frame_time;
} else {
// just go to the tag
tag_goto(ted, name);
}
}
+void definition_cancel_lookup(Ted *ted) {
+ Definitions *defs = &ted->definitions;
+ defs->last_request_lsp = 0;
+ defs->last_request_id = 0;
+}
+
void definitions_process_lsp_response(Ted *ted, LSP *lsp, const LSPResponse *response) {
if (response->request.type != LSP_REQUEST_DEFINITION)
return;
@@ -17,13 +27,14 @@ void definitions_process_lsp_response(Ted *ted, LSP *lsp, const LSPResponse *res
const LSPResponseDefinition *response_def = &response->data.definition;
Definitions *defs = &ted->definitions;
- if (defs->last_response_lsp == lsp->id
- && response->request.id < defs->last_response_id) {
- // we just processed a later response, so let's ignore this
+ if (defs->last_request_lsp != lsp->id
+ || response->request.id != defs->last_request_id) {
+ // response to an old request
return;
}
- defs->last_response_lsp = lsp->id;
- defs->last_response_id = response->request.id;
+
+ defs->last_request_lsp = 0;
+ defs->last_request_id = 0;
if (!arr_len(response_def->locations)) {
// no definition. do the error cursor.
@@ -39,3 +50,10 @@ void definitions_process_lsp_response(Ted *ted, LSP *lsp, const LSPResponse *res
LSPDocumentPosition position = lsp_location_start_position(location);
ted_go_to_lsp_document_position(ted, lsp, position);
}
+
+void definitions_frame(Ted *ted) {
+ Definitions *defs = &ted->definitions;
+ if (defs->last_request_lsp && timespec_sub(ted->frame_time, defs->last_request_time) > 0.2) {
+ ted->cursor = ted->cursor_wait;
+ }
+}
diff --git a/lsp-write.c b/lsp-write.c
index 9d7c2b1..82ba5b4 100644
--- a/lsp-write.c
+++ b/lsp-write.c
@@ -282,31 +282,6 @@ static const char *lsp_request_method(LSPRequest *request) {
return "$/ignore";
}
-static bool request_type_is_notification(LSPRequestType type) {
- switch (type) {
- case LSP_REQUEST_NONE: break;
- case LSP_REQUEST_INITIALIZED:
- case LSP_REQUEST_EXIT:
- case LSP_REQUEST_DID_OPEN:
- case LSP_REQUEST_DID_CLOSE:
- case LSP_REQUEST_DID_CHANGE:
- case LSP_REQUEST_DID_CHANGE_WORKSPACE_FOLDERS:
- case LSP_REQUEST_JDTLS_CONFIGURATION:
- return true;
- case LSP_REQUEST_INITIALIZE:
- case LSP_REQUEST_SHUTDOWN:
- case LSP_REQUEST_SHOW_MESSAGE:
- case LSP_REQUEST_LOG_MESSAGE:
- case LSP_REQUEST_COMPLETION:
- case LSP_REQUEST_SIGNATURE_HELP:
- case LSP_REQUEST_HOVER:
- case LSP_REQUEST_DEFINITION:
- case LSP_REQUEST_WORKSPACE_FOLDERS:
- return false;
- }
- assert(0);
- return false;
-}
static const size_t max_header_size = 64;
@@ -352,11 +327,8 @@ static void write_request(LSP *lsp, LSPRequest *request) {
write_obj_start(o);
write_key_string(o, "jsonrpc", "2.0");
- bool is_notification = request_type_is_notification(request->type);
- if (!is_notification) {
- u32 id = lsp->request_id++;
- request->id = id;
- write_key_number(o, "id", id);
+ if (request->id) { // i.e. if this is a request as opposed to a notification
+ write_key_number(o, "id", request->id);
}
write_key_string(o, "method", lsp_request_method(request));
@@ -564,12 +536,12 @@ static void write_request(LSP *lsp, LSPRequest *request) {
message_writer_write_and_free(lsp, o);
- if (is_notification) {
- lsp_request_free(request);
- } else {
+ if (request->id) {
SDL_LockMutex(lsp->messages_mutex);
arr_add(lsp->requests_sent, *request);
SDL_UnlockMutex(lsp->messages_mutex);
+ } else {
+ lsp_request_free(request);
}
}
diff --git a/lsp.c b/lsp.c
index e1fdd16..8b147b2 100644
--- a/lsp.c
+++ b/lsp.c
@@ -162,15 +162,48 @@ void lsp_send_message(LSP *lsp, LSPMessage *message) {
SDL_UnlockMutex(lsp->messages_mutex);
}
-bool lsp_send_request(LSP *lsp, LSPRequest *request) {
+static bool request_type_is_notification(LSPRequestType type) {
+ switch (type) {
+ case LSP_REQUEST_NONE: break;
+ case LSP_REQUEST_INITIALIZED:
+ case LSP_REQUEST_EXIT:
+ case LSP_REQUEST_DID_OPEN:
+ case LSP_REQUEST_DID_CLOSE:
+ case LSP_REQUEST_DID_CHANGE:
+ case LSP_REQUEST_DID_CHANGE_WORKSPACE_FOLDERS:
+ case LSP_REQUEST_JDTLS_CONFIGURATION:
+ return true;
+ case LSP_REQUEST_INITIALIZE:
+ case LSP_REQUEST_SHUTDOWN:
+ case LSP_REQUEST_SHOW_MESSAGE:
+ case LSP_REQUEST_LOG_MESSAGE:
+ case LSP_REQUEST_COMPLETION:
+ case LSP_REQUEST_SIGNATURE_HELP:
+ case LSP_REQUEST_HOVER:
+ case LSP_REQUEST_DEFINITION:
+ case LSP_REQUEST_WORKSPACE_FOLDERS:
+ return false;
+ }
+ assert(0);
+ return false;
+}
+
+LSPRequestID lsp_send_request(LSP *lsp, LSPRequest *request) {
if (!lsp_supports_request(lsp, request)) {
lsp_request_free(request);
- return false;
+ return 0;
+ }
+
+ bool is_notification = request_type_is_notification(request->type);
+ LSPRequestID id = 0;
+ if (!is_notification) {
+ id = ++lsp->request_id;
+ request->id = id;
}
LSPMessage message = {.type = LSP_REQUEST};
message.u.request = *request;
lsp_send_message(lsp, &message);
- return true;
+ return id;
}
void lsp_send_response(LSP *lsp, LSPResponse *response) {
@@ -395,6 +428,7 @@ LSP *lsp_create(const char *root_dir, Language language, const char *analyzer_co
LSPRequest initialize = {
.type = LSP_REQUEST_INITIALIZE
};
+ initialize.id = ++lsp->request_id;
// immediately send the request rather than queueing it.
// this is a small request, so it shouldn't be a problem.
write_request(lsp, &initialize);
diff --git a/lsp.h b/lsp.h
index 7d45f5b..a5120cd 100644
--- a/lsp.h
+++ b/lsp.h
@@ -1,5 +1,6 @@
typedef u32 LSPDocumentID;
typedef u32 LSPID;
+typedef u32 LSPRequestID;
typedef struct {
u32 line;
@@ -350,8 +351,8 @@ typedef struct LSP {
Process process;
// Which ID number the next request will get
- // thread-safety: only accessed in communication thread
- u32 request_id;
+ // thread-safety: atomic, all that matters is `LSPRequestID id = ++lsp->request_id;` works
+ _Atomic LSPRequestID request_id;
SDL_mutex *document_mutex;
// for our purposes, folders are "documents"
@@ -402,9 +403,9 @@ void lsp_message_free(LSPMessage *message);
u32 lsp_document_id(LSP *lsp, const char *path);
// returned pointer lives exactly as long as lsp.
const char *lsp_document_path(LSP *lsp, LSPDocumentID id);
-// returns false if the request is not supported by the LSP
+// returns the ID of the sent request, or 0 if the request is not supported by the LSP
// don't free the contents of this request (even on failure)! let me handle it!
-bool lsp_send_request(LSP *lsp, LSPRequest *request);
+LSPRequestID lsp_send_request(LSP *lsp, LSPRequest *request);
// 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);
diff --git a/main.c b/main.c
index 2162577..172a415 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,5 @@
/*
@TODO:
-- some way of showing that we're currently loading the definition location (different cursor color?)
- more LSP stuff:
- go to definition using LSP
- find usages
@@ -587,6 +586,7 @@ int main(int argc, char **argv) {
ted->cursor_ibeam = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
+ ted->cursor_wait = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT);
ted->cursor_arrow = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
ted->cursor_resize_h = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
ted->cursor_resize_v = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
@@ -1009,6 +1009,7 @@ int main(int argc, char **argv) {
autocomplete_frame(ted);
signature_help_frame(ted);
hover_frame(ted, frame_dt);
+ definitions_frame(ted);
} else {
autocomplete_close(ted);
text_utf8_anchored(font, "Press Ctrl+O to open a file or Ctrl+N to create a new one.",
@@ -1161,6 +1162,7 @@ int main(int argc, char **argv) {
SDL_FreeCursor(ted->cursor_arrow);
SDL_FreeCursor(ted->cursor_ibeam);
+ SDL_FreeCursor(ted->cursor_wait);
SDL_FreeCursor(ted->cursor_resize_h);
SDL_FreeCursor(ted->cursor_resize_v);
SDL_FreeCursor(ted->cursor_hand);
diff --git a/ted.h b/ted.h
index be8fcb0..fd2cf9f 100644
--- a/ted.h
+++ b/ted.h
@@ -414,11 +414,13 @@ typedef struct {
} Hover;
typedef struct {
-
- // LSPID and ID of the last response which was processed.
- // used to process responses in chronological order (= ID order)
- LSPID last_response_lsp;
- u32 last_response_id;
+ // LSPID and ID of the last request which was sent out.
+ // used to process responses in chronological order (= ID order).
+ // if we got a response for the last request, or no requests have been made,
+ // last_request_lsp is set to 0.
+ LSPID last_request_lsp;
+ u32 last_request_id;
+ struct timespec last_request_time;
} Definitions;
@@ -488,7 +490,8 @@ typedef struct Ted {
// used by menus to keep track of the scroll position so we can return to it.
v2d prev_active_buffer_scroll;
- SDL_Cursor *cursor_arrow, *cursor_ibeam, *cursor_resize_h, *cursor_resize_v, *cursor_hand, *cursor_move;
+ SDL_Cursor *cursor_arrow, *cursor_ibeam, *cursor_wait,
+ *cursor_resize_h, *cursor_resize_v, *cursor_hand, *cursor_move;
SDL_Cursor *cursor; // which cursor to use this frame (NULL for no cursor)
// node containing tab user is dragging around, NULL if user is not dragging a tab