summaryrefslogtreecommitdiff
path: root/examples/dte/replace.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/dte/replace.c')
-rw-r--r--examples/dte/replace.c256
1 files changed, 0 insertions, 256 deletions
diff --git a/examples/dte/replace.c b/examples/dte/replace.c
deleted file mode 100644
index 028d474..0000000
--- a/examples/dte/replace.c
+++ /dev/null
@@ -1,256 +0,0 @@
-#include <stdlib.h>
-#include "replace.h"
-#include "buffer.h"
-#include "change.h"
-#include "editor.h"
-#include "error.h"
-#include "regexp.h"
-#include "screen.h"
-#include "selection.h"
-#include "util/debug.h"
-#include "util/string.h"
-#include "util/xmalloc.h"
-#include "view.h"
-#include "window.h"
-
-static void build_replacement (
- String *buf,
- const char *line,
- const char *format,
- const regmatch_t *matches
-) {
- for (size_t i = 0; format[i]; ) {
- char ch = format[i++];
- size_t match_idx;
- if (ch == '\\') {
- if (unlikely(format[i] == '\0')) {
- break;
- }
- ch = format[i++];
- if (ch < '1' || ch > '9') {
- string_append_byte(buf, ch);
- continue;
- }
- match_idx = ch - '0';
- } else if (ch == '&') {
- match_idx = 0;
- } else {
- string_append_byte(buf, ch);
- continue;
- }
- const regmatch_t *match = &matches[match_idx];
- regoff_t len = match->rm_eo - match->rm_so;
- if (len > 0) {
- string_append_buf(buf, line + match->rm_so, (size_t)len);
- }
- }
-}
-
-/*
- * s/abc/x
- *
- * string to match against
- * -------------------------------------------
- * "foo abc bar abc baz" "foo abc bar abc baz"
- * "foo x bar abc baz" " bar abc baz"
- */
-static unsigned int replace_on_line (
- View *view,
- StringView *line,
- regex_t *re,
- const char *format,
- BlockIter *bi,
- ReplaceFlags *flagsp
-) {
- const unsigned char *buf = line->data;
- unsigned char *alloc = NULL;
- EditorState *e = view->window->editor;
- ReplaceFlags flags = *flagsp;
- regmatch_t matches[32];
- size_t pos = 0;
- int eflags = 0;
- unsigned int nr = 0;
-
- while (regexp_exec (
- re,
- buf + pos,
- line->length - pos,
- ARRAYLEN(matches),
- matches,
- eflags
- )) {
- regoff_t match_len = matches[0].rm_eo - matches[0].rm_so;
- bool skip = false;
-
- // Move cursor to beginning of the text to replace
- block_iter_skip_bytes(bi, matches[0].rm_so);
- view->cursor = *bi;
-
- if (flags & REPLACE_CONFIRM) {
- switch (status_prompt(e, "Replace? [Y/n/a/q]", "ynaq")) {
- case 'y':
- break;
- case 'n':
- skip = true;
- break;
- case 'a':
- flags &= ~REPLACE_CONFIRM;
- *flagsp = flags;
-
- // Record rest of the changes as one chain
- begin_change_chain();
- break;
- case 'q':
- case 0:
- *flagsp = flags | REPLACE_CANCEL;
- goto out;
- }
- }
-
- if (skip) {
- // Move cursor after the matched text
- block_iter_skip_bytes(&view->cursor, match_len);
- } else {
- String b = STRING_INIT;
- build_replacement(&b, buf + pos, format, matches);
-
- // line ref is invalidated by modification
- if (buf == line->data && line->length != 0) {
- BUG_ON(alloc);
- alloc = xmemdup(buf, line->length);
- buf = alloc;
- }
-
- buffer_replace_bytes(view, match_len, b.buffer, b.len);
- nr++;
-
- // Update selection length
- if (view->selection) {
- view->sel_eo += b.len;
- view->sel_eo -= match_len;
- }
-
- // Move cursor after the replaced text
- block_iter_skip_bytes(&view->cursor, b.len);
- string_free(&b);
- }
- *bi = view->cursor;
-
- if (!match_len) {
- break;
- }
-
- if (!(flags & REPLACE_GLOBAL)) {
- break;
- }
-
- pos += matches[0].rm_so + match_len;
-
- // Don't match beginning of line again
- eflags = REG_NOTBOL;
- }
-
-out:
- free(alloc);
- return nr;
-}
-
-bool reg_replace(View *view, const char *pattern, const char *format, ReplaceFlags flags)
-{
- if (unlikely(pattern[0] == '\0')) {
- return error_msg("Search pattern must contain at least 1 character");
- }
-
- int re_flags = REG_NEWLINE;
- re_flags |= (flags & REPLACE_IGNORE_CASE) ? REG_ICASE : 0;
- re_flags |= (flags & REPLACE_BASIC) ? 0 : DEFAULT_REGEX_FLAGS;
-
- regex_t re;
- if (unlikely(!regexp_compile_internal(&re, pattern, re_flags))) {
- return false;
- }
-
- BlockIter bi = block_iter(view->buffer);
- size_t nr_bytes;
- bool swapped = false;
- if (view->selection) {
- SelectionInfo info;
- init_selection(view, &info);
- view->cursor = info.si;
- view->sel_so = info.so;
- view->sel_eo = info.eo;
- swapped = info.swapped;
- bi = view->cursor;
- nr_bytes = info.eo - info.so;
- } else {
- BlockIter eof = bi;
- block_iter_eof(&eof);
- nr_bytes = block_iter_get_offset(&eof);
- }
-
- // Record multiple changes as one chain only when replacing all
- if (!(flags & REPLACE_CONFIRM)) {
- begin_change_chain();
- }
-
- unsigned int nr_substitutions = 0;
- size_t nr_lines = 0;
- while (1) {
- StringView line;
- fill_line_ref(&bi, &line);
-
- // Number of bytes to process
- size_t count = line.length;
- if (line.length > nr_bytes) {
- // End of selection is not full line
- line.length = nr_bytes;
- }
-
- unsigned int nr = replace_on_line(view, &line, &re, format, &bi, &flags);
- if (nr) {
- nr_substitutions += nr;
- nr_lines++;
- }
-
- if (flags & REPLACE_CANCEL || count + 1 >= nr_bytes) {
- break;
- }
-
- nr_bytes -= count + 1;
- block_iter_next_line(&bi);
- }
-
- if (!(flags & REPLACE_CONFIRM)) {
- end_change_chain(view);
- }
-
- regfree(&re);
-
- if (nr_substitutions) {
- info_msg (
- "%u substitution%s on %zu line%s",
- nr_substitutions,
- (nr_substitutions > 1) ? "s" : "",
- nr_lines,
- (nr_lines > 1) ? "s" : ""
- );
- } else if (!(flags & REPLACE_CANCEL)) {
- error_msg("Pattern '%s' not found", pattern);
- }
-
- if (view->selection) {
- // Undo what init_selection() did
- if (view->sel_eo) {
- view->sel_eo--;
- }
- if (swapped) {
- ssize_t tmp = view->sel_so;
- view->sel_so = view->sel_eo;
- view->sel_eo = tmp;
- }
- block_iter_goto_offset(&view->cursor, view->sel_eo);
- view->sel_eo = SEL_EO_RECALC;
- }
-
- return (nr_substitutions > 0);
-}