From 4b59f95bccf66dcf7338d7180871df85d4269cf3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Wed, 12 Feb 2020 15:22:49 +0100 Subject: [PATCH] sam: support optional count for text commands The text given for the a, i and c commands can be prefixed with an optional count indicating how often the text should be inserted, defaults to 1. --- man/vis.1 | 7 +++++-- sam.c | 33 +++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/man/vis.1 b/man/vis.1 index f1af19d..a60d4fb 100644 --- a/man/vis.1 +++ b/man/vis.1 @@ -512,8 +512,11 @@ refinements of ranges. .Ss Text commands . .Bl -tag -width indent -.It Ic a/ Ns Ar text Ns Ic / -Insert the text into the file after the range. +.It Ic a Ns [ Ar count ] Ns / Ns Ar text Ns Ic / +Insert the +.Ar text +.Ar count +times into the file after the range. .\" Set dot. .Pp May also be written as diff --git a/sam.c b/sam.c index 8d3ab1f..38bbad8 100644 --- a/sam.c +++ b/sam.c @@ -50,6 +50,7 @@ struct Change { const char *data; /* will be free(3)-ed after transcript has been processed */ size_t len; /* size in bytes of the chunk pointed to by data */ Change *next; /* modification position increase monotonically */ + int count; /* how often should data be inserted? */ }; struct Address { @@ -486,12 +487,13 @@ static void sam_transcript_free(Transcript *t) { } } -static bool sam_insert(Win *win, Selection *sel, size_t pos, const char *data, size_t len) { +static bool sam_insert(Win *win, Selection *sel, size_t pos, const char *data, size_t len, int count) { Filerange range = text_range_new(pos, pos); Change *c = change_new(&win->file->transcript, TRANSCRIPT_INSERT, &range, win, sel); if (c) { c->data = data; c->len = len; + c->count = count; } return c; } @@ -500,11 +502,12 @@ static bool sam_delete(Win *win, Selection *sel, Filerange *range) { return change_new(&win->file->transcript, TRANSCRIPT_DELETE, range, win, sel); } -static bool sam_change(Win *win, Selection *sel, Filerange *range, const char *data, size_t len) { +static bool sam_change(Win *win, Selection *sel, Filerange *range, const char *data, size_t len, int count) { Change *c = change_new(&win->file->transcript, TRANSCRIPT_CHANGE, range, win, sel); if (c) { c->data = data; c->len = len; + c->count = count; } return c; } @@ -593,10 +596,14 @@ static int parse_number(const char **s) { return number; } -static char *parse_text(const char **s) { +static char *parse_text(const char **s, Count *count) { skip_spaces(s); + const char *before = *s; + count->start = parse_number(s); + if (*s == before) + count->start = 1; if (**s != '\n') { - const char *before = *s; + before = *s; char *text = parse_delimited(s, CMD_TEXT); return (!text && *s != before) ? strdup("") : text; } @@ -930,7 +937,7 @@ static Command *command_parse(Vis *vis, const char **s, enum SamError *err) { goto fail; } - if (cmddef->flags & CMD_TEXT && !(cmd->argv[1] = parse_text(s))) { + if (cmddef->flags & CMD_TEXT && !(cmd->argv[1] = parse_text(s, &cmd->count))) { *err = SAM_ERR_TEXT; goto fail; } @@ -1229,10 +1236,12 @@ enum SamError sam_cmd(Vis *vis, const char *s) { } } if (c->type & TRANSCRIPT_INSERT) { - text_insert(file->text, c->range.start, c->data, c->len); - delta += c->len; + for (int i = 0; i < c->count; i++) { + text_insert(file->text, c->range.start, c->data, c->len); + delta += c->len; + } Filerange r = text_range_new(c->range.start, - c->range.start+c->len); + c->range.start + c->len * c->count); if (c->sel) { if (visual) { view_selections_set(c->sel, &r); @@ -1321,7 +1330,7 @@ static bool cmd_insert(Vis *vis, Win *win, Command *cmd, const char *argv[], Sel Buffer buf = text(vis, argv[1]); size_t len = buffer_length(&buf); char *data = buffer_move(&buf); - bool ret = sam_insert(win, sel, range->start, data, len); + bool ret = sam_insert(win, sel, range->start, data, len, cmd->count.start); if (!ret) free(data); return ret; @@ -1333,7 +1342,7 @@ static bool cmd_append(Vis *vis, Win *win, Command *cmd, const char *argv[], Sel Buffer buf = text(vis, argv[1]); size_t len = buffer_length(&buf); char *data = buffer_move(&buf); - bool ret = sam_insert(win, sel, range->end, data, len); + bool ret = sam_insert(win, sel, range->end, data, len, cmd->count.start); if (!ret) free(data); return ret; @@ -1345,7 +1354,7 @@ static bool cmd_change(Vis *vis, Win *win, Command *cmd, const char *argv[], Sel Buffer buf = text(vis, argv[1]); size_t len = buffer_length(&buf); char *data = buffer_move(&buf); - bool ret = sam_change(win, sel, range, data, len); + bool ret = sam_change(win, sel, range, data, len, cmd->count.start); if (!ret) free(data); return ret; @@ -1703,7 +1712,7 @@ static bool cmd_filter(Vis *vis, Win *win, Command *cmd, const char *argv[], Sel } else if (status == 0) { size_t len = buffer_length(&bufout); char *data = buffer_move(&bufout); - if (!sam_change(win, sel, range, data, len)) + if (!sam_change(win, sel, range, data, len, 1)) free(data); } else { vis_info_show(vis, "Command failed %s", buffer_content0(&buferr)); -- 2.11.4.GIT