diff options
author | pommicket <pommicket@gmail.com> | 2025-09-30 12:41:46 -0400 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2025-09-30 12:41:46 -0400 |
commit | f7993d24a0dfd4762f84378722bd39b07c0fe405 (patch) | |
tree | 0bedeb9afcd54c8c5b09f5cd64c46148626b3845 | |
parent | 13143e9d1a78c8e0135336bbfcc922ef28c0196a (diff) |
Use a cursor for code actions
-rw-r--r-- | command.c | 17 | ||||
-rw-r--r-- | command.h | 1 | ||||
-rw-r--r-- | ide-code-action.c | 41 | ||||
-rw-r--r-- | lsp-parse.c | 2 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | ted.cfg | 3 | ||||
-rw-r--r-- | ted.h | 8 |
7 files changed, 49 insertions, 24 deletions
@@ -112,6 +112,7 @@ static CommandName command_names[] = { {"set-tab-width", CMD_SET_TAB_WIDTH}, {"debug-print-undo-history", CMD_DEBUG_PRINT_UNDO_HISTORY}, {"code-action", CMD_CODE_ACTION}, + {"code-action-prev", CMD_CODE_ACTION_PREV}, }; static_assert_if_possible(arr_count(command_names) == CMD_COUNT) @@ -345,6 +346,8 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen buffer_select_all(buffer); } else if (autocomplete_is_open(ted) || autocomplete_has_phantom(ted)) { autocomplete_select_completion(ted); + } else if (code_action_is_open(ted)) { + code_action_select(ted); } else if (buffer) { if (buffer_has_selection(buffer)) buffer_indent_selection(buffer); @@ -369,9 +372,7 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen break; case CMD_NEWLINE: case CMD_NEWLINE_BACK: - if (code_action_is_open(ted)) { - code_action_select_best(ted); - } else if (ted->find) { + if (ted->find) { if (buffer == ted->find_buffer || buffer == ted->replace_buffer) { if (c == CMD_NEWLINE) find_next(ted); @@ -380,6 +381,8 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen } else if (buffer) { buffer_newline(buffer); } + } else if (code_action_is_open(ted)) { + code_action_select(ted); } else if (buffer) { buffer_newline(buffer); } @@ -746,7 +749,13 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen buffer_print_undo_history(buffer); break; case CMD_CODE_ACTION: - code_action_open(ted); + if (code_action_is_open(ted)) + code_action_next(ted); + else + code_action_open(ted); + break; + case CMD_CODE_ACTION_PREV: + code_action_prev(ted); break; } } @@ -108,6 +108,7 @@ typedef enum { CMD_FIND_USAGES, CMD_RENAME_SYMBOL, CMD_CODE_ACTION, + CMD_CODE_ACTION_PREV, /// "go to definition of..." menu CMD_GOTO_DEFINITION, diff --git a/ide-code-action.c b/ide-code-action.c index 6244756..4eef1ef 100644 --- a/ide-code-action.c +++ b/ide-code-action.c @@ -13,6 +13,7 @@ struct CodeAction { BufferPos cursor_pos; LSPResponse response; Action *actions; + u32 cursor; }; static bool ranges_touch(BufferPos p1, BufferPos p2, BufferPos q1, BufferPos q2) { @@ -41,6 +42,7 @@ void code_action_open(Ted *ted) { LSP *lsp = buffer_lsp(buffer); if (!lsp) return; autocomplete_close(ted); + c->cursor = 0; c->which_buffer = buffer_lsp_document_id(buffer); c->cursor_pos = buffer_cursor_pos(buffer); BufferPos range_start = {0}, range_end = {0}; @@ -72,6 +74,20 @@ void code_action_open(Ted *ted) { c->last_request = lsp_send_request(lsp, &req); } +void code_action_next(Ted *ted) { + CodeAction *c = ted->code_action; + u32 actions_count = arr_len(c->actions); + if (actions_count) + c->cursor = (c->cursor + 1) % actions_count; +} + +void code_action_prev(Ted *ted) { + CodeAction *c = ted->code_action; + u32 actions_count = arr_len(c->actions); + if (actions_count) + c->cursor = c->cursor ? c->cursor - 1 : actions_count - 1; +} + bool code_action_is_open(Ted *ted) { CodeAction *c = ted->code_action; return arr_len(c->response.data.code_action.actions) != 0; @@ -151,10 +167,10 @@ static void code_action_perform(Ted *ted, const LSPCodeAction *action) { code_action_close(ted); } -void code_action_select_best(Ted *ted) { +void code_action_select(Ted *ted) { CodeAction *c = ted->code_action; - if (arr_len(c->actions)) - code_action_perform(ted, c->actions[0].lsp); + if (c->cursor < arr_len(c->actions)) + code_action_perform(ted, c->actions[c->cursor].lsp); } void code_action_frame(Ted *ted) { @@ -183,7 +199,7 @@ void code_action_frame(Ted *ted) { return; } const Settings *settings = ted_active_settings(ted); - Font *font = ted->font, *font_bold = ted->font_bold; + Font *font = ted->font; float char_height = text_font_char_height(font); float padding = settings->padding; float border_thickness = settings->border_thickness; @@ -214,8 +230,9 @@ void code_action_frame(Ted *ted) { const Action *selected_action = NULL; arr_foreach_ptr(c->actions, const Action, action) { Rect entry_rect = {{x, y}, {panel_width, char_height}}; - if (rect_contains_point(entry_rect, ted->mouse_pos)) { - // hovering over this entry + if (rect_contains_point(entry_rect, ted->mouse_pos) + || c->cursor == (u32)(action - c->actions)) { + // hovering/cursoring over this entry ted->cursor = ted->cursor_hand; gl_geometry_rect(entry_rect, settings_color(settings, COLOR_AUTOCOMPLETE_HL)); } @@ -228,20 +245,12 @@ void code_action_frame(Ted *ted) { gl_geometry_rect(border, settings_color(settings, COLOR_AUTOCOMPLETE_BORDER)); y += border_thickness; }; - text_utf8(action == c->actions ? font_bold : font, - action->name, x + padding, y, settings_color(settings, COLOR_TEXT)); - if (action == c->actions) { - // action we think is best - text_utf8_anchored(font, "(Enter)", - panel_rect.pos.x + panel_rect.size.x - padding, y, - settings_color(settings, COLOR_COMMENT), - ANCHOR_TOP_RIGHT); - } + text_utf8(font, action->name, x + padding, y, + settings_color(settings, COLOR_TEXT)); y += char_height; } gl_geometry_draw(); text_render(font); - text_render(font_bold); if (selected_action) { code_action_perform(ted, selected_action->lsp); } else { diff --git a/lsp-parse.c b/lsp-parse.c index bb4a10d..3c956e9 100644 --- a/lsp-parse.c +++ b/lsp-parse.c @@ -1109,7 +1109,7 @@ static bool parse_command(LSP *lsp, LSPResponse *response, const JSON *json, JSO command_out->kind = LSP_COMMAND_WORKSPACE_EDIT; return true; } - lsp_set_error(lsp, "Unrecognized command: %s\n", command); + fprintf(stderr, "Unrecognized command: %s\n", command); (void)command_out; return false; } @@ -1,6 +1,5 @@ /* FUTURE FEATURES: -- LSP "actions" - wrap-text command - path-specific extensions - more tests @@ -346,7 +346,10 @@ Ctrl+Space = :autocomplete Ctrl+Shift+Space = :autocomplete-back Ctrl+u = :find-usages Ctrl+r = :rename-symbol +# Show "code action" suggestions (refactoring, quick fixes, etc.) / move code action cursor forwards Alt+Space = :code-action +# Move code action cursor backwards +Alt+Shift+Space = :code-action-prev Ctrl+z = :undo Ctrl+Shift+z = :redo @@ -935,8 +935,12 @@ void code_action_open(Ted *ted); void code_action_close(Ted *ted); /// Are code actions being shown? bool code_action_is_open(Ted *ted); -/// Select best code action -void code_action_select_best(Ted *ted); +/// Select current code action +void code_action_select(Ted *ted); +/// Move code action cursor forwards +void code_action_next(Ted *ted); +/// Move code action cursor backwards +void code_action_prev(Ted *ted); // === ide-definitions.c === /// cancel the last go-to-definition / find symbols request. |