diff options
| author | Mitja Felicijan <mitja.felicijan@gmail.com> | 2026-01-21 22:52:54 +0100 |
|---|---|---|
| committer | Mitja Felicijan <mitja.felicijan@gmail.com> | 2026-01-21 22:52:54 +0100 |
| commit | dcacc00e3750300617ba6e16eb346713f91a783a (patch) | |
| tree | 38e2d4fb5ed9d119711d4295c6eda4b014af73fd /examples/dte/search.c | |
| parent | 58dac10aeb8f5a041c46bddbeaf4c7966a99b998 (diff) | |
| download | crep-dcacc00e3750300617ba6e16eb346713f91a783a.tar.gz | |
Remove testing data
Diffstat (limited to 'examples/dte/search.c')
| -rw-r--r-- | examples/dte/search.c | 244 |
1 files changed, 0 insertions, 244 deletions
diff --git a/examples/dte/search.c b/examples/dte/search.c deleted file mode 100644 index 80ad5c3..0000000 --- a/examples/dte/search.c +++ /dev/null | |||
| @@ -1,244 +0,0 @@ | |||
| 1 | #include <stdlib.h> | ||
| 2 | #include "search.h" | ||
| 3 | #include "block-iter.h" | ||
| 4 | #include "buffer.h" | ||
| 5 | #include "error.h" | ||
| 6 | #include "regexp.h" | ||
| 7 | #include "util/ascii.h" | ||
| 8 | #include "util/xmalloc.h" | ||
| 9 | |||
| 10 | static bool do_search_fwd(View *view, regex_t *regex, BlockIter *bi, bool skip) | ||
| 11 | { | ||
| 12 | int flags = block_iter_is_bol(bi) ? 0 : REG_NOTBOL; | ||
| 13 | |||
| 14 | do { | ||
| 15 | if (block_iter_is_eof(bi)) { | ||
| 16 | return false; | ||
| 17 | } | ||
| 18 | |||
| 19 | regmatch_t match; | ||
| 20 | StringView line; | ||
| 21 | fill_line_ref(bi, &line); | ||
| 22 | |||
| 23 | // NOTE: If this is the first iteration then line.data contains | ||
| 24 | // partial line (text starting from the cursor position) and | ||
| 25 | // if match.rm_so is 0 then match is at beginning of the text | ||
| 26 | // which is same as the cursor position. | ||
| 27 | if (regexp_exec(regex, line.data, line.length, 1, &match, flags)) { | ||
| 28 | if (skip && match.rm_so == 0) { | ||
| 29 | // Ignore match at current cursor position | ||
| 30 | regoff_t count = match.rm_eo; | ||
| 31 | if (count == 0) { | ||
| 32 | // It is safe to skip one byte because every line | ||
| 33 | // has one extra byte (newline) that is not in line.data | ||
| 34 | count = 1; | ||
| 35 | } | ||
| 36 | block_iter_skip_bytes(bi, (size_t)count); | ||
| 37 | return do_search_fwd(view, regex, bi, false); | ||
| 38 | } | ||
| 39 | |||
| 40 | block_iter_skip_bytes(bi, match.rm_so); | ||
| 41 | view->cursor = *bi; | ||
| 42 | view->center_on_scroll = true; | ||
| 43 | view_reset_preferred_x(view); | ||
| 44 | return true; | ||
| 45 | } | ||
| 46 | |||
| 47 | skip = false; // Not at cursor position any more | ||
| 48 | flags = 0; | ||
| 49 | } while (block_iter_next_line(bi)); | ||
| 50 | |||
| 51 | return false; | ||
| 52 | } | ||
| 53 | |||
| 54 | static bool do_search_bwd(View *view, regex_t *regex, BlockIter *bi, ssize_t cx, bool skip) | ||
| 55 | { | ||
| 56 | if (block_iter_is_eof(bi)) { | ||
| 57 | goto next; | ||
| 58 | } | ||
| 59 | |||
| 60 | do { | ||
| 61 | regmatch_t match; | ||
| 62 | StringView line; | ||
| 63 | int flags = 0; | ||
| 64 | regoff_t offset = -1; | ||
| 65 | regoff_t pos = 0; | ||
| 66 | |||
| 67 | fill_line_ref(bi, &line); | ||
| 68 | while ( | ||
| 69 | pos <= line.length | ||
| 70 | && regexp_exec(regex, line.data + pos, line.length - pos, 1, &match, flags) | ||
| 71 | ) { | ||
| 72 | flags = REG_NOTBOL; | ||
| 73 | if (cx >= 0) { | ||
| 74 | if (pos + match.rm_so >= cx) { | ||
| 75 | // Ignore match at or after cursor | ||
| 76 | break; | ||
| 77 | } | ||
| 78 | if (skip && pos + match.rm_eo > cx) { | ||
| 79 | // Search -rw should not find word under cursor | ||
| 80 | break; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | // This might be what we want (last match before cursor) | ||
| 85 | offset = pos + match.rm_so; | ||
| 86 | pos += match.rm_eo; | ||
| 87 | |||
| 88 | if (match.rm_so == match.rm_eo) { | ||
| 89 | // Zero length match | ||
| 90 | break; | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | if (offset >= 0) { | ||
| 95 | block_iter_skip_bytes(bi, offset); | ||
| 96 | view->cursor = *bi; | ||
| 97 | view->center_on_scroll = true; | ||
| 98 | view_reset_preferred_x(view); | ||
| 99 | return true; | ||
| 100 | } | ||
| 101 | |||
| 102 | next: | ||
| 103 | cx = -1; | ||
| 104 | } while (block_iter_prev_line(bi)); | ||
| 105 | |||
| 106 | return false; | ||
| 107 | } | ||
| 108 | |||
| 109 | bool search_tag(View *view, const char *pattern) | ||
| 110 | { | ||
| 111 | regex_t regex; | ||
| 112 | if (!regexp_compile_basic(®ex, pattern, REG_NEWLINE)) { | ||
| 113 | return false; | ||
| 114 | } | ||
| 115 | |||
| 116 | BlockIter bi = block_iter(view->buffer); | ||
| 117 | bool found = do_search_fwd(view, ®ex, &bi, false); | ||
| 118 | regfree(®ex); | ||
| 119 | |||
| 120 | if (!found) { | ||
| 121 | // Don't center view to cursor unnecessarily | ||
| 122 | view->force_center = false; | ||
| 123 | return error_msg("Tag not found"); | ||
| 124 | } | ||
| 125 | |||
| 126 | view->center_on_scroll = true; | ||
| 127 | return true; | ||
| 128 | } | ||
| 129 | |||
| 130 | static void free_regex(SearchState *search) | ||
| 131 | { | ||
| 132 | if (search->re_flags) { | ||
| 133 | regfree(&search->regex); | ||
| 134 | search->re_flags = 0; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | static bool has_upper(const char *str) | ||
| 139 | { | ||
| 140 | for (size_t i = 0; str[i]; i++) { | ||
| 141 | if (ascii_isupper(str[i])) { | ||
| 142 | return true; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | return false; | ||
| 146 | } | ||
| 147 | |||
| 148 | static bool update_regex(SearchState *search, SearchCaseSensitivity cs) | ||
| 149 | { | ||
| 150 | int re_flags = REG_NEWLINE; | ||
| 151 | switch (cs) { | ||
| 152 | case CSS_TRUE: | ||
| 153 | break; | ||
| 154 | case CSS_FALSE: | ||
| 155 | re_flags |= REG_ICASE; | ||
| 156 | break; | ||
| 157 | case CSS_AUTO: | ||
| 158 | if (!has_upper(search->pattern)) { | ||
| 159 | re_flags |= REG_ICASE; | ||
| 160 | } | ||
| 161 | break; | ||
| 162 | default: | ||
| 163 | BUG("unhandled case sensitivity value"); | ||
| 164 | } | ||
| 165 | |||
| 166 | if (re_flags == search->re_flags) { | ||
| 167 | return true; | ||
| 168 | } | ||
| 169 | |||
| 170 | free_regex(search); | ||
| 171 | |||
| 172 | search->re_flags = re_flags; | ||
| 173 | if (regexp_compile(&search->regex, search->pattern, search->re_flags)) { | ||
| 174 | return true; | ||
| 175 | } | ||
| 176 | |||
| 177 | free_regex(search); | ||
| 178 | return false; | ||
| 179 | } | ||
| 180 | |||
| 181 | void search_free_regexp(SearchState *search) | ||
| 182 | { | ||
| 183 | free_regex(search); | ||
| 184 | free(search->pattern); | ||
| 185 | } | ||
| 186 | |||
| 187 | void search_set_regexp(SearchState *search, const char *pattern) | ||
| 188 | { | ||
| 189 | search_free_regexp(search); | ||
| 190 | search->pattern = xstrdup(pattern); | ||
| 191 | } | ||
| 192 | |||
| 193 | static bool do_search_next(View *view, SearchState *search, SearchCaseSensitivity cs, bool skip) | ||
| 194 | { | ||
| 195 | if (!search->pattern) { | ||
| 196 | return error_msg("No previous search pattern"); | ||
| 197 | } | ||
| 198 | if (!update_regex(search, cs)) { | ||
| 199 | return false; | ||
| 200 | } | ||
| 201 | |||
| 202 | BlockIter bi = view->cursor; | ||
| 203 | regex_t *regex = &search->regex; | ||
| 204 | if (!search->reverse) { | ||
| 205 | if (do_search_fwd(view, regex, &bi, true)) { | ||
| 206 | return true; | ||
| 207 | } | ||
| 208 | block_iter_bof(&bi); | ||
| 209 | if (do_search_fwd(view, regex, &bi, false)) { | ||
| 210 | info_msg("Continuing at top"); | ||
| 211 | return true; | ||
| 212 | } | ||
| 213 | } else { | ||
| 214 | size_t cursor_x = block_iter_bol(&bi); | ||
| 215 | if (do_search_bwd(view, regex, &bi, cursor_x, skip)) { | ||
| 216 | return true; | ||
| 217 | } | ||
| 218 | block_iter_eof(&bi); | ||
| 219 | if (do_search_bwd(view, regex, &bi, -1, false)) { | ||
| 220 | info_msg("Continuing at bottom"); | ||
| 221 | return true; | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | return error_msg("Pattern '%s' not found", search->pattern); | ||
| 226 | } | ||
| 227 | |||
| 228 | bool search_prev(View *view, SearchState *search, SearchCaseSensitivity cs) | ||
| 229 | { | ||
| 230 | toggle_search_direction(search); | ||
| 231 | bool r = search_next(view, search, cs); | ||
| 232 | toggle_search_direction(search); | ||
| 233 | return r; | ||
| 234 | } | ||
| 235 | |||
| 236 | bool search_next(View *view, SearchState *search, SearchCaseSensitivity cs) | ||
| 237 | { | ||
| 238 | return do_search_next(view, search, cs, false); | ||
| 239 | } | ||
| 240 | |||
| 241 | bool search_next_word(View *view, SearchState *search, SearchCaseSensitivity cs) | ||
| 242 | { | ||
| 243 | return do_search_next(view, search, cs, true); | ||
| 244 | } | ||
