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 3 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
@@ -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;
}
}
@@ -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);
2 changes: 1 addition & 1 deletion sam.c
Original file line number Diff line number Diff line change
@@ -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;
}
4 changes: 1 addition & 3 deletions text-regex-tre.c
Original file line number Diff line number Diff line change
@@ -121,9 +121,7 @@ void text_regex_free(Regex *r) {
}

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

if (r)
tre_regcomp(&regex->regex, "\0\0", 0);
2 changes: 1 addition & 1 deletion vis-cmds.c
Original file line number Diff line number Diff line change
@@ -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;
}

11 changes: 6 additions & 5 deletions vis-motions.c
Original file line number Diff line number Diff line change
@@ -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));
Copy link
Collaborator

@rnpnr rnpnr Jul 2, 2024

Choose a reason for hiding this comment

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

These strlens can be avoided by saving the return value from snprintf.
Edit: Check line 18 for the other snprintf; github messed up my response.

Copy link
Author

Choose a reason for hiding this comment

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

I did that now by removing the ~500 character limit on the word search. That seemed to be better than handling the case where snprintf truncates its output.

}
free(buf);
return regex;
@@ -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);
@@ -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;
27 changes: 15 additions & 12 deletions vis-prompt.c
Original file line number Diff line number Diff line change
@@ -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;
@@ -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) {
@@ -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, 0, 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)
@@ -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)
@@ -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));
4 changes: 2 additions & 2 deletions vis-text-objects.c
Original file line number Diff line number Diff line change
@@ -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);
@@ -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);
6 changes: 2 additions & 4 deletions vis.c
Original file line number Diff line number Diff line change
@@ -1578,8 +1578,7 @@ void vis_insert_nl(Vis *vis) {
vis_window_invalidate(win);
}

Regex *vis_regex(Vis *vis, const char *pattern) {
size_t len = 0;
Regex *vis_regex(Vis *vis, const char *pattern, size_t len) {
if (!pattern && !(pattern = register_get(vis, &vis->registers[VIS_REG_SEARCH], &len)))
rnpnr marked this conversation as resolved.
Show resolved Hide resolved
return NULL;
Regex *regex = text_regex_new();
@@ -1590,8 +1589,7 @@ Regex *vis_regex(Vis *vis, const char *pattern) {
text_regex_free(regex);
return NULL;
}
if (len == 0)
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;
}

4 changes: 2 additions & 2 deletions vis.h
Original file line number Diff line number Diff line change
@@ -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.
@@ -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.