Skip to content

Commit

Permalink
sam: allow input text to refer to search registers
Browse files Browse the repository at this point in the history
& refers to the most recent complete match and \1 - \9
refer to the last sub-expression matches.
  • Loading branch information
martanne committed Jan 13, 2017
1 parent 4600b76 commit 104df30
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 6 deletions.
13 changes: 11 additions & 2 deletions man/vis.1
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,10 @@ and hence
It is an error for a compound address to represent a malformed substring.
.
.Ss Commands
In the following, text demarcated by slashes represents text delimited by any printable ASCII character except alphanumerics.
Any number of trailing delimiters may be elided, with multiple elisions then representing null strings, but the first delimiter must always be present.
In the following, text demarcated by slashes represents text delimited
by any printable ASCII character except alphanumerics. Any number
of trailing delimiters may be elided, with multiple elisions then
representing null strings, but the first delimiter must always be present.
In any delimited text, newline may not appear literally;
.Li \[rs]n
and
Expand All @@ -369,6 +371,13 @@ may be typed for newline and tab;
.Li \[rs]/
quotes the delimiter, here
.Li / .
An ampersand
.Li &
and
.Sy \[rs]n ,
where
.Sy n
is a digit (1-9) are replaced by the corresponding register.
Backslash is otherwise interpreted literally.
.Pp
Most commands may be prefixed with an address to indicate their range
Expand Down
58 changes: 54 additions & 4 deletions sam.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ static char *parse_until(const char **s, const char *until, const char *escchars
c = '\n';
} else if (c == 't') {
c = '\t';
} else if (type != CMD_REGEX && c == '\\') {
} else if (type != CMD_REGEX && type != CMD_TEXT && c == '\\') {
// ignore one of the back slashes
} else {
bool delim = memchr(until, c, len);
Expand Down Expand Up @@ -1145,16 +1145,66 @@ enum SamError sam_cmd(Vis *vis, const char *s) {
return err;
}

/* process text input, substitute register content for backreferences etc. */
Buffer text(Vis *vis, const char *text) {
Buffer buf;
buffer_init(&buf);
for (size_t len = strcspn(text, "\\&"); *text; len = strcspn(++text, "\\&")) {
buffer_append(&buf, text, len);
text += len;
enum VisRegister regid = VIS_REG_INVALID;
switch (text[0]) {
case '&':
regid = VIS_REG_AMPERSAND;
break;
case '\\':
if ('1' <= text[1] && text[1] <= '9') {
regid = VIS_REG_1 + text[1] - '1';
text++;
} else if (text[1] == '\\' || text[1] == '&') {
text++;
}
break;
case '\0':
goto out;
}

const char *data;
size_t reglen = 0;
if (regid != VIS_REG_INVALID) {
data = register_get(vis, &vis->registers[regid], &reglen);
} else {
data = text;
reglen = 1;
}
buffer_append(&buf, data, reglen);
}
out:
return buf;
}

static bool cmd_insert(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor *cur, Filerange *range) {
return win && sam_insert(win, cur, range->start, strdup(argv[1]), strlen(argv[1]));
if (!win)
return false;
Buffer buf = text(vis, argv[1]);
size_t len = buffer_length(&buf);
return sam_insert(win, cur, range->start, buffer_move(&buf), len);
}

static bool cmd_append(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor *cur, Filerange *range) {
return win && sam_insert(win, cur, range->end, strdup(argv[1]), strlen(argv[1]));
if (!win)
return false;
Buffer buf = text(vis, argv[1]);
size_t len = buffer_length(&buf);
return sam_insert(win, cur, range->end, buffer_move(&buf), len);
}

static bool cmd_change(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor *cur, Filerange *range) {
return win && sam_change(win, cur, range, strdup(argv[1]), strlen(argv[1]));
if (!win)
return false;
Buffer buf = text(vis, argv[1]);
size_t len = buffer_length(&buf);
return sam_change(win, cur, range, buffer_move(&buf), len);
}

static bool cmd_delete(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor *cur, Filerange *range) {
Expand Down

0 comments on commit 104df30

Please sign in to comment.