Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow regexes to contain ␀ byte #713

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2321,7 +2321,7 @@ int main(int argc, char *argv[]) {
}
win_created = true;
if (cmd) {
vis_prompt_cmd(vis, cmd);
vis_prompt_cmd(vis, cmd, strlen(cmd));
cmd = NULL;
}
}
Expand All @@ -2330,7 +2330,7 @@ int main(int argc, char *argv[]) {
if (!vis_window_new(vis, NULL))
vis_die(vis, "Can not create empty buffer\n");
if (cmd)
vis_prompt_cmd(vis, cmd);
vis_prompt_cmd(vis, cmd, strlen(cmd));
}

int status = vis_run(vis);
Expand Down
2 changes: 1 addition & 1 deletion sam.c
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ static Regex *parse_regex(Vis *vis, const char **s) {
char *pattern = parse_delimited(s, CMD_REGEX);
if (!pattern && *s == before)
return NULL;
Regex *regex = vis_regex(vis, pattern);
Regex *regex = vis_regex(vis, pattern, strlen(pattern));
free(pattern);
return regex;
}
Expand Down
5 changes: 3 additions & 2 deletions text-regex-tre.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,9 @@ void text_regex_free(Regex *r) {
free(r);
}

int text_regex_compile(Regex *regex, const char *string, int cflags) {
int r = tre_regcomp(&regex->regex, string, cflags);
int text_regex_compile(Regex *regex, const char *string, size_t len, int cflags) {
int r = tre_regncomp(&regex->regex, string, len, cflags);

if (r)
tre_regcomp(&regex->regex, "\0\0", 0);
return r;
Expand Down
2 changes: 1 addition & 1 deletion text-regex.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Regex *text_regex_new(void) {
return r;
}

int text_regex_compile(Regex *regex, const char *string, int cflags) {
int text_regex_compile(Regex *regex, const char *string, size_t len, int cflags) {
int r = regcomp(&regex->regex, string, cflags);
if (r)
regcomp(&regex->regex, "\0\0", 0);
Expand Down
2 changes: 1 addition & 1 deletion text-regex.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ typedef struct Regex Regex;
typedef Filerange RegexMatch;

Regex *text_regex_new(void);
int text_regex_compile(Regex*, const char *pattern, int cflags);
int text_regex_compile(Regex*, const char *pattern, size_t len, int cflags);
size_t text_regex_nsub(Regex*);
void text_regex_free(Regex*);
int text_regex_match(Regex*, const char *data, int eflags);
Expand Down
2 changes: 1 addition & 1 deletion vis-cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,7 @@ static bool cmd_help(Vis *vis, Win *win, Command *cmd, const char *argv[], Selec
view_cursors_to(vis->win->view.selection, 0);

if (argv[1])
vis_motion(vis, VIS_MOVE_SEARCH_FORWARD, argv[1]);
vis_motion(vis, VIS_MOVE_SEARCH_FORWARD, argv[1], strlen(argv[1]));
return true;
}

Expand Down
11 changes: 6 additions & 5 deletions vis-motions.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ static Regex *search_word(Vis *vis, Text *txt, size_t pos) {
if (!buf)
return NULL;
snprintf(expr, sizeof(expr), "[[:<:]]%s[[:>:]]", buf);
Regex *regex = vis_regex(vis, expr);
Regex *regex = vis_regex(vis, expr, strlen(expr));
if (!regex) {
snprintf(expr, sizeof(expr), "\\<%s\\>", buf);
regex = vis_regex(vis, expr);
regex = vis_regex(vis, expr, strlen(expr));
}
free(buf);
return regex;
Expand All @@ -46,15 +46,15 @@ static size_t search_word_backward(Vis *vis, Text *txt, size_t pos) {
}

static size_t search_forward(Vis *vis, Text *txt, size_t pos) {
Regex *regex = vis_regex(vis, NULL);
Regex *regex = vis_regex(vis, NULL, 0);
if (regex)
pos = text_search_forward(txt, pos, regex);
text_regex_free(regex);
return pos;
}

static size_t search_backward(Vis *vis, Text *txt, size_t pos) {
Regex *regex = vis_regex(vis, NULL);
Regex *regex = vis_regex(vis, NULL, 0);
if (regex)
pos = text_search_backward(txt, pos, regex);
text_regex_free(regex);
Expand Down Expand Up @@ -293,7 +293,8 @@ bool vis_motion(Vis *vis, enum VisMotion motion, ...) {
case VIS_MOVE_SEARCH_BACKWARD:
{
const char *pattern = va_arg(ap, char*);
Regex *regex = vis_regex(vis, pattern);
size_t len = va_arg(ap, size_t);
Regex *regex = vis_regex(vis, pattern, len);
if (!regex) {
vis_cancel(vis);
goto err;
Expand Down
27 changes: 15 additions & 12 deletions vis-prompt.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
#include "text-objects.h"
#include "text-util.h"

bool vis_prompt_cmd(Vis *vis, const char *cmd) {
if (!cmd || !cmd[0] || !cmd[1])
bool vis_prompt_cmd(Vis *vis, const char *cmd, size_t len) {
if (!cmd || len < 2)
return true;
switch (cmd[0]) {
case '/':
return vis_motion(vis, VIS_MOVE_SEARCH_FORWARD, cmd+1);
return vis_motion(vis, VIS_MOVE_SEARCH_FORWARD, cmd+1, len-1);
case '?':
return vis_motion(vis, VIS_MOVE_SEARCH_BACKWARD, cmd+1);
return vis_motion(vis, VIS_MOVE_SEARCH_BACKWARD, cmd+1, len-1);
case '+':
case ':':
register_put0(vis, &vis->registers[VIS_REG_COMMAND], cmd+1);
register_put(vis, &vis->registers[VIS_REG_COMMAND], cmd+1, len-1);
return vis_cmd(vis, cmd+1);
default:
return false;
Expand Down Expand Up @@ -53,6 +53,7 @@ static const char *prompt_enter(Vis *vis, const char *keys, const Arg *arg) {
Text *txt = prompt->file->text;
Win *win = prompt->parent;
char *cmd = NULL;
size_t len = 0;

Filerange range = view_selections_get(view->selection);
if (!vis->mode->visual) {
Expand All @@ -64,7 +65,7 @@ static const char *prompt_enter(Vis *vis, const char *keys, const Arg *arg) {
else if (prompt->file == vis->search_file)
pattern = "^(/|\\?)";
int cflags = REG_EXTENDED|REG_NEWLINE|(REG_ICASE*vis->ignorecase);
if (pattern && regex && text_regex_compile(regex, pattern, cflags) == 0) {
if (pattern && regex && text_regex_compile(regex, pattern, strlen(pattern), cflags) == 0) {
size_t end = text_line_end(txt, pos);
size_t prev = text_search_backward(txt, end, regex);
if (prev > pos)
Expand All @@ -76,8 +77,10 @@ static const char *prompt_enter(Vis *vis, const char *keys, const Arg *arg) {
}
text_regex_free(regex);
}
if (text_range_valid(&range))
cmd = text_bytes_alloc0(txt, range.start, text_range_size(&range));
if (text_range_valid(&range)) {
len = text_range_size(&range);
cmd = text_bytes_alloc0(txt, range.start, len);
}

if (!win || !cmd) {
if (!win)
Expand All @@ -90,14 +93,14 @@ static const char *prompt_enter(Vis *vis, const char *keys, const Arg *arg) {
return keys;
}

size_t len = strlen(cmd);
if (len > 0 && cmd[len-1] == '\n')
cmd[len-1] = '\0';
if (len > 0 && cmd[len-1] == '\n') {
cmd[--len] = '\0';
}

bool lastline = (range.end == text_size(txt));

prompt_restore(prompt);
if (vis_prompt_cmd(vis, cmd)) {
if (vis_prompt_cmd(vis, cmd, len)) {
prompt_hide(prompt);
if (!lastline) {
text_delete(txt, range.start, text_range_size(&range));
Expand Down
4 changes: 2 additions & 2 deletions vis-text-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ bool vis_textobject(Vis *vis, enum VisTextObject id) {

static Filerange search_forward(Vis *vis, Text *txt, size_t pos) {
Filerange range = text_range_empty();
Regex *regex = vis_regex(vis, NULL);
Regex *regex = vis_regex(vis, NULL, 0);
if (regex)
range = text_object_search_forward(txt, pos, regex);
text_regex_free(regex);
Expand All @@ -40,7 +40,7 @@ static Filerange search_forward(Vis *vis, Text *txt, size_t pos) {

static Filerange search_backward(Vis *vis, Text *txt, size_t pos) {
Filerange range = text_range_empty();
Regex *regex = vis_regex(vis, NULL);
Regex *regex = vis_regex(vis, NULL, 0);
if (regex)
range = text_object_search_backward(txt, pos, regex);
text_regex_free(regex);
Expand Down
8 changes: 4 additions & 4 deletions vis.c
Original file line number Diff line number Diff line change
Expand Up @@ -1578,18 +1578,18 @@ void vis_insert_nl(Vis *vis) {
vis_window_invalidate(win);
}

Regex *vis_regex(Vis *vis, const char *pattern) {
if (!pattern && !(pattern = register_get(vis, &vis->registers[VIS_REG_SEARCH], NULL)))
Regex *vis_regex(Vis *vis, const char *pattern, size_t len) {
if (!pattern && !(pattern = register_get(vis, &vis->registers[VIS_REG_SEARCH], &len)))
return NULL;
Regex *regex = text_regex_new();
if (!regex)
return NULL;
int cflags = REG_EXTENDED|REG_NEWLINE|(REG_ICASE*vis->ignorecase);
if (text_regex_compile(regex, pattern, cflags) != 0) {
if (text_regex_compile(regex, pattern, len, cflags) != 0) {
text_regex_free(regex);
return NULL;
}
register_put0(vis, &vis->registers[VIS_REG_SEARCH], pattern);
register_put(vis, &vis->registers[VIS_REG_SEARCH], pattern, len+1);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The +1 here is not very intuitive. For some reason, register_get gives us a length without the terminating null byte (which is still part of the buffer), but register_put expects a length including the null.

return regex;
}

Expand Down
4 changes: 2 additions & 2 deletions vis.h
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ bool vis_option_register(Vis*, const char *names[], enum VisOption,
bool vis_option_unregister(Vis*, const char *name);

/** Execute any kind (``:``, ``?``, ``/``) of prompt command */
bool vis_prompt_cmd(Vis*, const char *cmd);
bool vis_prompt_cmd(Vis*, const char *cmd, size_t len);

/**
* Pipe a given file range to an external process.
Expand Down Expand Up @@ -921,7 +921,7 @@ void vis_keys_feed(Vis*, const char *keys);
* .. warning:: The caller must free the regex object using `text_regex_free`.
* @endrst
*/
Regex *vis_regex(Vis*, const char *pattern);
Regex *vis_regex(Vis*, const char *pattern, size_t len);

/**
* Take an undo snapshot to which we can later revert.
Expand Down