diff options
| author | Albert Cervin <albert@acervin.com> | 2024-05-22 00:00:29 +0200 |
|---|---|---|
| committer | Albert Cervin <albert@acervin.com> | 2024-09-12 20:17:56 +0200 |
| commit | 405da5f84b072ea97b69359454899f45d92d24b6 (patch) | |
| tree | 20525b4bc44a5d8cbab4d62abe8413e174731db6 /src/main/search-replace.c | |
| parent | 4ab7e453e26afc6e9f4938c65f89463fbba9e267 (diff) | |
| download | dged-405da5f84b072ea97b69359454899f45d92d24b6.tar.gz dged-405da5f84b072ea97b69359454899f45d92d24b6.tar.xz dged-405da5f84b072ea97b69359454899f45d92d24b6.zip | |
WIP LSP client
This contains the start of an LSP client.
Nothing (except starting the LSP server) works
at the moment and the feature is disabled by default.
Diffstat (limited to 'src/main/search-replace.c')
| -rw-r--r-- | src/main/search-replace.c | 209 |
1 files changed, 117 insertions, 92 deletions
diff --git a/src/main/search-replace.c b/src/main/search-replace.c index 50beb1e..32c514c 100644 --- a/src/main/search-replace.c +++ b/src/main/search-replace.c @@ -45,6 +45,55 @@ static struct search { buffer_keymap_id keymap_id; } g_current_search = {0}; +static void highlight_match(struct buffer *buffer, struct region match, + bool current) { + if (current) { + buffer_add_text_property( + buffer, match.begin, match.end, + (struct text_property){.type = TextProperty_Colors, + .data.colors = (struct text_property_colors){ + .set_bg = true, + .bg = 3, + .set_fg = true, + .fg = 0, + }}); + + } else { + buffer_add_text_property( + buffer, match.begin, match.end, + (struct text_property){.type = TextProperty_Colors, + .data.colors = (struct text_property_colors){ + .set_bg = true, + .bg = 6, + .set_fg = true, + .fg = 0, + }}); + } +} + +static void search_highlight_hook(struct buffer *buffer, void *userdata) { + (void)userdata; + + for (uint32_t matchi = 0; matchi < g_current_search.nmatches; ++matchi) { + highlight_match(buffer, g_current_search.matches[matchi], + matchi == g_current_search.current_match); + } +} + +static void replace_highlight_hook(struct buffer *buffer, void *userdata) { + (void)userdata; + + for (uint32_t matchi = 0; matchi < g_current_replace.nmatches; ++matchi) { + struct match *m = &g_current_replace.matches[matchi]; + if (m->state != Todo) { + continue; + } + + highlight_match(buffer, m->region, + matchi == g_current_replace.current_match); + } +} + static void clear_replace(void) { buffer_remove_keymap(g_current_replace.keymap_id); free(g_current_replace.matches); @@ -89,6 +138,36 @@ void abort_search(void) { minibuffer_abort_prompt(); } +static void start_search(struct buffer *buffer, const char *pattern) { + if (buffer != g_current_search.buffer) { + clear_search(); + } + + g_current_search.buffer = buffer; + g_current_search.active = true; + + // if we are in a new buffer, add the update hook for it. + if (g_current_search.highlight_hook == (uint32_t)-1) { + g_current_search.highlight_hook = + buffer_add_update_hook(buffer, search_highlight_hook, NULL); + } + + // replace the pattern if needed + if (g_current_search.pattern == NULL || + !s8eq(s8(g_current_search.pattern), s8(pattern))) { + char *new_pattern = strdup(pattern); + free(g_current_search.pattern); + g_current_search.pattern = new_pattern; + } + + // clear out any old search results + if (g_current_search.matches != NULL) { + free(g_current_search.matches); + g_current_search.matches = NULL; + g_current_search.nmatches = 0; + } +} + uint64_t matchdist(struct region *match, struct location loc) { struct location begin = match->begin; @@ -98,64 +177,21 @@ uint64_t matchdist(struct region *match, struct location loc) { // into the line it is, otherwise check the distance from location int64_t coldist = begin.col; if (linedist == 0) { - int64_t coldist = (int64_t)begin.col - (int64_t)loc.col; + coldist = (int64_t)begin.col - (int64_t)loc.col; } // arbitrary row scaling, best effort to avoid counting line length + // this is not technically correct if you have lines longer than + // 1e6 but otoh, that seems excessive return (linedist * linedist) * 1e6 + coldist * coldist; } -static void highlight_match(struct buffer *buffer, struct region match, - bool current) { - if (current) { - buffer_add_text_property( - buffer, match.begin, match.end, - (struct text_property){.type = TextProperty_Colors, - .colors = (struct text_property_colors){ - .set_bg = true, - .bg = 3, - .set_fg = true, - .fg = 0, - }}); - - } else { - buffer_add_text_property( - buffer, match.begin, match.end, - (struct text_property){.type = TextProperty_Colors, - .colors = (struct text_property_colors){ - .set_bg = true, - .bg = 6, - .set_fg = true, - .fg = 0, - }}); - } -} - -static void search_highlight_hook(struct buffer *buffer, void *userdata) { - (void)userdata; - - for (uint32_t matchi = 0; matchi < g_current_search.nmatches; ++matchi) { - highlight_match(buffer, g_current_search.matches[matchi], - matchi == g_current_search.current_match); - } -} - -static void replace_highlight_hook(struct buffer *buffer, void *userdata) { - (void)userdata; - - for (uint32_t matchi = 0; matchi < g_current_replace.nmatches; ++matchi) { - struct match *m = &g_current_replace.matches[matchi]; - if (m->state != Todo) { - continue; - } - - highlight_match(buffer, m->region, - matchi == g_current_replace.current_match); - } -} - static int32_t replace_next(struct command_ctx ctx, int argc, const char *argv[]) { + (void)ctx; + (void)argc; + (void)argv; + struct replace *state = &g_current_replace; struct buffer_view *buffer_view = window_buffer_view(state->window); struct buffer *buffer = buffer_view->buffer; @@ -207,6 +243,10 @@ static int32_t replace_next(struct command_ctx ctx, int argc, } static int32_t skip_next(struct command_ctx ctx, int argc, const char *argv[]) { + (void)ctx; + (void)argc; + (void)argv; + struct replace *state = &g_current_replace; struct buffer_view *buffer_view = window_buffer_view(state->window); @@ -230,8 +270,8 @@ static int32_t skip_next(struct command_ctx ctx, int argc, const char *argv[]) { return 0; } -COMMAND_FN("replace-next", replace_next, replace_next, NULL); -COMMAND_FN("skip-next", skip_next, skip_next, NULL); +COMMAND_FN("replace-next", replace_next, replace_next, NULL) +COMMAND_FN("skip-next", skip_next, skip_next, NULL) static int cmp_matches(const void *m1, const void *m2) { struct region *match1 = (struct region *)m1; @@ -350,35 +390,9 @@ static struct region *find_closest(struct region *matches, uint32_t nmatches, return closest; } -static void do_search(struct buffer_view *view, const char *pattern, +static bool do_search(struct buffer_view *view, const char *pattern, bool reverse) { - if (view->buffer != g_current_search.buffer) { - clear_search(); - } - - g_current_search.buffer = view->buffer; - g_current_search.active = true; - - // if we are in a new buffer, add the update hook for it. - if (g_current_search.highlight_hook == (uint32_t)-1) { - g_current_search.highlight_hook = - buffer_add_update_hook(view->buffer, search_highlight_hook, NULL); - } - - // replace the pattern if needed - if (g_current_search.pattern == NULL || - !s8eq(s8(g_current_search.pattern), s8(pattern))) { - char *new_pattern = strdup(pattern); - free(g_current_search.pattern); - g_current_search.pattern = new_pattern; - } - - // clear out any old search results first - if (g_current_search.matches != NULL) { - free(g_current_search.matches); - g_current_search.matches = NULL; - g_current_search.nmatches = 0; - } + start_search(view->buffer, pattern); buffer_find(view->buffer, g_current_search.pattern, &g_current_search.matches, &g_current_search.nmatches); @@ -391,10 +405,10 @@ static void do_search(struct buffer_view *view, const char *pattern, view->dot, reverse, &closest_idx); buffer_view_goto(view, closest->begin); g_current_search.current_match = closest_idx; - } else { - abort_search(); - minibuffer_echo_timeout(4, "%s not found", pattern); + return true; } + + return false; } static const char *get_pattern() { @@ -424,12 +438,18 @@ int32_t search_interactive(struct command_ctx ctx, int argc, } minibuffer_set_prompt(search_prompt(*(bool *)ctx.userdata)); + buffer_view_goto_end(window_buffer_view(minibuffer_window())); if (pattern != NULL) { - do_search(window_buffer_view(minibuffer_target_window()), pattern, - *(bool *)ctx.userdata); + if (!do_search(window_buffer_view(minibuffer_target_window()), pattern, + *(bool *)ctx.userdata)) { + abort_search(); + minibuffer_echo_timeout(4, "%s not found", pattern); + } + free((char *)pattern); } + return 0; } @@ -437,11 +457,13 @@ static bool search_dir_backward = true; static bool search_dir_forward = false; COMMAND_FN("search-forward", search_forward, search_interactive, - &search_dir_forward); + &search_dir_forward) COMMAND_FN("search-backward", search_backward, search_interactive, - &search_dir_backward); + &search_dir_backward) int32_t find(struct command_ctx ctx, int argc, const char *argv[]) { + (void)argv; + bool reverse = *(bool *)ctx.userdata; if (argc == 0) { struct binding bindings[] = { @@ -454,17 +476,21 @@ int32_t find(struct command_ctx ctx, int argc, const char *argv[]) { return minibuffer_prompt(ctx, search_prompt(reverse)); } + // allow enter to end the interactive search if (g_current_search.active) { abort_search(); return 0; } buffer_remove_keymap(g_current_search.keymap_id); - do_search(window_buffer_view(ctx.active_window), argv[0], reverse); + bool found = + do_search(window_buffer_view(ctx.active_window), argv[0], reverse); - if (g_current_search.active) { - abort_search(); + abort_search(); + if (!found) { + minibuffer_echo_timeout(4, "%s not found", argv[0]); } + return 0; } @@ -481,11 +507,10 @@ void register_search_replace_commands(struct commands *commands) { } void cleanup_search_replace(void) { + clear_replace(); clear_search(); if (g_current_search.pattern != NULL) { free(g_current_search.pattern); g_current_search.pattern = NULL; } - - clear_replace(); } |
