From 632a3cf4ddba6fd843633a8f7fe49d27a19f488c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Wed, 12 Apr 2017 18:25:58 +0200 Subject: sam: add support for negative count specifier --- sam.c | 52 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 10 deletions(-) (limited to 'sam.c') diff --git a/sam.c b/sam.c index f607721..b0e1ac6 100644 --- a/sam.c +++ b/sam.c @@ -1112,11 +1112,28 @@ static enum SamError command_validate(Command *cmd) { return validate(cmd, false, false); } -static void count_init(Command *cmd) { +static bool count_negative(Command *cmd) { + if (cmd->count.start < 0 || cmd->count.end < 0) + return true; + for (Command *c = cmd->cmd; c; c = c->next) { + if (c->cmddef->func != cmd_extract) { + if (count_negative(c)) + return true; + } + } + return false; +} + +static void count_init(Command *cmd, int max) { + Count *count = &cmd->count; cmd->iteration = 0; + if (count->start < 0) + count->start += max; + if (count->end < 0) + count->end += max; for (Command *c = cmd->cmd; c; c = c->next) { if (c->cmddef->func != cmd_extract) - count_init(c); + count_init(c, max); } } @@ -1308,12 +1325,10 @@ static bool cmd_guard(Vis *vis, Win *win, Command *cmd, const char *argv[], Curs return true; } -static bool cmd_extract(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor *cur, Filerange *range) { - if (!win) - return false; +static int extract(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor *cur, Filerange *range, bool simulate) { bool ret = true; + int count = 0; Text *txt = win->file->text; - count_init(cmd->cmd); if (cmd->regex) { bool trailing_match = false; @@ -1362,7 +1377,10 @@ static bool cmd_extract(Vis *vis, Win *win, Command *cmd, const char *argv[], Cu register_put_range(vis, reg, txt, &match[i]); } } - ret &= sam_execute(vis, win, cmd->cmd, NULL, &r); + if (simulate) + count++; + else + ret &= sam_execute(vis, win, cmd->cmd, NULL, &r); last_start = start; } } @@ -1375,13 +1393,27 @@ static bool cmd_extract(Vis *vis, Win *win, Command *cmd, const char *argv[], Cu Filerange r = text_range_new(start, next); if (start == next || !text_range_valid(&r)) break; - ret &= sam_execute(vis, win, cmd->cmd, NULL, &r); + if (simulate) + count++; + else + ret &= sam_execute(vis, win, cmd->cmd, NULL, &r); start = next; } } - view_cursors_dispose_force(cur); - return ret; + if (!simulate) + view_cursors_dispose_force(cur); + return simulate ? count : ret; +} + +static bool cmd_extract(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor *cur, Filerange *range) { + if (!win) + return false; + int matches = 0; + if (count_negative(cmd->cmd)) + matches = extract(vis, win, cmd, argv, cur, range, true); + count_init(cmd->cmd, matches+1); + return extract(vis, win, cmd, argv, cur, range, false); } static bool cmd_select(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor *cur, Filerange *range) { -- cgit v1.2.3