diff options
| author | Albert Cervin <albert@acervin.com> | 2025-11-05 22:00:15 +0100 |
|---|---|---|
| committer | Albert Cervin <albert@acervin.com> | 2025-11-05 22:00:15 +0100 |
| commit | 2fa2d749e675cc95ad5c6e866d3257639b136df8 (patch) | |
| tree | 2b7cf36ab7fb90125425ef23df825d5f93754d12 | |
| parent | 9ed37096c4e79169ebd6a037805ff7f2754326f7 (diff) | |
| download | dged-2fa2d749e675cc95ad5c6e866d3257639b136df8.tar.gz dged-2fa2d749e675cc95ad5c6e866d3257639b136df8.tar.xz dged-2fa2d749e675cc95ad5c6e866d3257639b136df8.zip | |
Fix searching annoyances
- It now colors correctly
- Supports searching for unicode symbols
- Make search able to continue when more letters are entered
| -rw-r--r-- | src/dged/buffer.c | 64 | ||||
| -rw-r--r-- | src/main/search-replace.c | 21 |
2 files changed, 55 insertions, 30 deletions
diff --git a/src/dged/buffer.c b/src/dged/buffer.c index a45f982..e428c58 100644 --- a/src/dged/buffer.c +++ b/src/dged/buffer.c @@ -879,39 +879,56 @@ struct location buffer_undo(struct buffer *buffer, struct location dot) { struct search_data { VEC(struct region) matches; const char *pattern; + uint32_t tab_width; }; -// TODO: maybe should live in text static void search_line(struct text_chunk *chunk, void *userdata) { struct search_data *data = (struct search_data *)userdata; - size_t pattern_len = strlen(data->pattern); - uint32_t pattern_nchars = utf8_nchars((uint8_t *)data->pattern, pattern_len); + struct s8 pattern = s8(data->pattern); - char *line = malloc(chunk->nbytes + 1); - strncpy(line, (const char *)chunk->text, chunk->nbytes); - line[chunk->nbytes] = '\0'; - char *hit = NULL; - uint32_t byteidx = 0; - while ((hit = strstr(line + byteidx, data->pattern)) != NULL) { - byteidx = hit - line; - uint32_t begin = utf8_nchars(chunk->text, byteidx); - struct region match = - region_new((struct location){.col = begin, .line = chunk->line}, - (struct location){.col = begin + pattern_nchars - 1, - .line = chunk->line}); - VEC_PUSH(&data->matches, match); + struct utf8_codepoint_iterator iter = + create_utf8_codepoint_iterator(chunk->text, chunk->nbytes, 0); + struct utf8_codepoint_iterator pattern_iter = + create_utf8_codepoint_iterator(pattern.s, pattern.l, 0); + struct codepoint *codepoint, + *pattern_codepoint = utf8_next_codepoint(&pattern_iter); - // proceed to after match - byteidx += pattern_len; + if (pattern_codepoint == NULL) { + return; } - free(line); + uint32_t col = 0, start_col = 0, tab_width = data->tab_width; + bool reset = false; + while ((codepoint = utf8_next_codepoint(&iter)) != NULL) { + if (pattern_codepoint->codepoint == codepoint->codepoint) { + pattern_codepoint = utf8_next_codepoint(&pattern_iter); + if (pattern_codepoint == NULL) { + // this is a match, add and reset iterator + VEC_PUSH( + &data->matches, + region_new((struct location){.line = chunk->line, .col = start_col}, + (struct location){.line = chunk->line, .col = col})); + reset = true; + } + } else { + reset = true; + } + + col += visual_char_width(codepoint, tab_width); + if (reset) { + start_col = col; + pattern_iter = create_utf8_codepoint_iterator(pattern.s, pattern.l, 0); + pattern_codepoint = utf8_next_codepoint(&pattern_iter); + reset = false; + } + } } void buffer_find(struct buffer *buffer, const char *pattern, struct region **matches, uint32_t *nmatches) { - struct search_data data = (struct search_data){.pattern = pattern}; + struct search_data data = (struct search_data){ + .pattern = pattern, .tab_width = get_tab_width(buffer)}; VEC_INIT(&data.matches, 16); text_for_each_line(buffer->text, 0, text_num_lines(buffer->text), search_line, &data); @@ -1237,8 +1254,11 @@ void render_line(struct text_chunk *line, void *userdata) { // and re-apply current properties uint64_t new_properties_hash = properties_hash(properties, nproperties); if (new_properties_hash != prev_properties_hash) { - command_list_draw_text(cmdbuf->cmds, drawn_coli, visual_line, - line->text + drawn_bytei, bytei - drawn_bytei); + size_t nbytes = bytei - drawn_bytei; + if (nbytes > 0) { + command_list_draw_text(cmdbuf->cmds, drawn_coli, visual_line, + line->text + drawn_bytei, nbytes); + } command_list_reset_color(cmdbuf->cmds); drawn_coli = coli; diff --git a/src/main/search-replace.c b/src/main/search-replace.c index 1910a37..3893bd3 100644 --- a/src/main/search-replace.c +++ b/src/main/search-replace.c @@ -487,9 +487,20 @@ 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) { + // allow enter to end the interactive search if it is already + // what we are searching for. + struct text_chunk line = minibuffer_content(); + char *l = (char *)malloc(line.nbytes + 1); + memcpy(l, line.text, line.nbytes); + l[line.nbytes] = '\0'; + + if (g_current_search.active && strcmp(g_current_search.pattern, l) == 0) { abort_search(); + + if (line.allocated) { + free(line.text); + } + free(l); return 0; } @@ -497,13 +508,7 @@ int32_t find(struct command_ctx ctx, int argc, const char *argv[]) { * Use the full minibuffer content here, not individual * arguments. */ - struct text_chunk line = minibuffer_content(); - char *l = (char *)malloc(line.nbytes + 1); - memcpy(l, line.text, line.nbytes); - l[line.nbytes] = '\0'; - bool found = do_search(window_buffer_view(ctx.active_window), l, reverse); - if (line.allocated) { free(line.text); } |
