summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Cervin <albert@acervin.com>2025-11-05 22:00:15 +0100
committerAlbert Cervin <albert@acervin.com>2025-11-05 22:00:15 +0100
commit2fa2d749e675cc95ad5c6e866d3257639b136df8 (patch)
tree2b7cf36ab7fb90125425ef23df825d5f93754d12
parent9ed37096c4e79169ebd6a037805ff7f2754326f7 (diff)
downloaddged-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.c64
-rw-r--r--src/main/search-replace.c21
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);
}