mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Add regular expression support for the format search, match and
substitute modifiers.
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -32,7 +32,6 @@ SRCS=	alerts.c \
 | 
			
		||||
	cmd-list-panes.c \
 | 
			
		||||
	cmd-list-sessions.c \
 | 
			
		||||
	cmd-list-windows.c \
 | 
			
		||||
	cmd-list.c \
 | 
			
		||||
	cmd-load-buffer.c \
 | 
			
		||||
	cmd-lock-server.c \
 | 
			
		||||
	cmd-move-window.c \
 | 
			
		||||
@@ -96,6 +95,7 @@ SRCS=	alerts.c \
 | 
			
		||||
	paste.c \
 | 
			
		||||
	proc.c \
 | 
			
		||||
	procname.c \
 | 
			
		||||
	regsub.c \
 | 
			
		||||
	resize.c \
 | 
			
		||||
	screen-redraw.c \
 | 
			
		||||
	screen-write.c \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										110
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								format.c
									
									
									
									
									
								
							@@ -23,6 +23,7 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fnmatch.h>
 | 
			
		||||
#include <libgen.h>
 | 
			
		||||
#include <regex.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
@@ -1247,7 +1248,7 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count)
 | 
			
		||||
			cp++;
 | 
			
		||||
 | 
			
		||||
		/* Check single character modifiers with no arguments. */
 | 
			
		||||
		if (strchr("lmCbdtqETSWP<>", cp[0]) != NULL &&
 | 
			
		||||
		if (strchr("lbdtqETSWP<>", cp[0]) != NULL &&
 | 
			
		||||
		    format_is_end(cp[1])) {
 | 
			
		||||
			format_add_modifier(&list, count, cp, 1, NULL, 0);
 | 
			
		||||
			cp++;
 | 
			
		||||
@@ -1268,7 +1269,7 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Now try single character with arguments. */
 | 
			
		||||
		if (strchr("s=", cp[0]) == NULL)
 | 
			
		||||
		if (strchr("mCs=", cp[0]) == NULL)
 | 
			
		||||
			break;
 | 
			
		||||
		c = cp[0];
 | 
			
		||||
 | 
			
		||||
@@ -1329,39 +1330,67 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count)
 | 
			
		||||
	return list;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Match against an fnmatch(3) pattern or regular expression. */
 | 
			
		||||
static char *
 | 
			
		||||
format_match(struct format_modifier *fm, const char *pattern, const char *text)
 | 
			
		||||
{
 | 
			
		||||
	const char	*s = "";
 | 
			
		||||
	regex_t		 r;
 | 
			
		||||
	int		 flags = 0;
 | 
			
		||||
 | 
			
		||||
	if (fm->argc >= 1)
 | 
			
		||||
		s = fm->argv[0];
 | 
			
		||||
	if (strchr(s, 'r') == NULL) {
 | 
			
		||||
		if (strchr(s, 'i') != NULL)
 | 
			
		||||
			flags |= FNM_CASEFOLD;
 | 
			
		||||
		if (fnmatch(pattern, text, flags) != 0)
 | 
			
		||||
			return (xstrdup("0"));
 | 
			
		||||
	} else {
 | 
			
		||||
		flags = REG_EXTENDED|REG_NOSUB;
 | 
			
		||||
		if (strchr(s, 'i') != NULL)
 | 
			
		||||
			flags |= REG_ICASE;
 | 
			
		||||
		if (regcomp(&r, pattern, flags) != 0)
 | 
			
		||||
			return (xstrdup("0"));
 | 
			
		||||
		if (regexec(&r, text, 0, NULL, 0) != 0) {
 | 
			
		||||
			regfree(&r);
 | 
			
		||||
			return (xstrdup("0"));
 | 
			
		||||
		}
 | 
			
		||||
		regfree(&r);
 | 
			
		||||
	}
 | 
			
		||||
	return (xstrdup("1"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Perform substitution in string. */
 | 
			
		||||
static char *
 | 
			
		||||
format_substitute(const char *source, const char *from, const char *to)
 | 
			
		||||
format_sub(struct format_modifier *fm, const char *text, const char *pattern,
 | 
			
		||||
    const char *with)
 | 
			
		||||
{
 | 
			
		||||
	char		*copy, *new;
 | 
			
		||||
	const char	*cp;
 | 
			
		||||
	size_t		 fromlen, tolen, newlen, used;
 | 
			
		||||
	char	*value;
 | 
			
		||||
	int	 flags = REG_EXTENDED;
 | 
			
		||||
 | 
			
		||||
	fromlen = strlen(from);
 | 
			
		||||
	tolen = strlen(to);
 | 
			
		||||
 | 
			
		||||
	newlen = strlen(source) + 1;
 | 
			
		||||
	copy = new = xmalloc(newlen);
 | 
			
		||||
 | 
			
		||||
	for (cp = source; *cp != '\0'; /* nothing */) {
 | 
			
		||||
		if (strncmp(cp, from, fromlen) != 0) {
 | 
			
		||||
			*new++ = *cp++;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		used = new - copy;
 | 
			
		||||
 | 
			
		||||
		newlen += tolen;
 | 
			
		||||
		copy = xrealloc(copy, newlen);
 | 
			
		||||
 | 
			
		||||
		new = copy + used;
 | 
			
		||||
		memcpy(new, to, tolen);
 | 
			
		||||
 | 
			
		||||
		new += tolen;
 | 
			
		||||
		cp += fromlen;
 | 
			
		||||
	if (fm->argc >= 3 && strchr(fm->argv[2], 'i') != NULL)
 | 
			
		||||
		flags |= REG_ICASE;
 | 
			
		||||
	value = regsub(pattern, with, text, flags);
 | 
			
		||||
	if (value == NULL)
 | 
			
		||||
		return (xstrdup(text));
 | 
			
		||||
	return (value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	*new = '\0';
 | 
			
		||||
	return (copy);
 | 
			
		||||
/* Search inside pane. */
 | 
			
		||||
static char *
 | 
			
		||||
format_search(struct format_modifier *fm, struct window_pane *wp, const char *s)
 | 
			
		||||
{
 | 
			
		||||
	int	 ignore = 0, regex = 0;
 | 
			
		||||
	char	*value;
 | 
			
		||||
 | 
			
		||||
	if (fm->argc >= 1) {
 | 
			
		||||
		if (strchr(fm->argv[0], 'i') != NULL)
 | 
			
		||||
			ignore = 1;
 | 
			
		||||
		if (strchr(fm->argv[0], 'r') != NULL)
 | 
			
		||||
			regex = 1;
 | 
			
		||||
	}
 | 
			
		||||
	xasprintf(&value, "%u", window_pane_search(wp, s, regex, ignore));
 | 
			
		||||
	return (value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Loop over sessions. */
 | 
			
		||||
@@ -1506,11 +1535,10 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
	char			*copy0, *condition, *found, *new;
 | 
			
		||||
	char			*value, *left, *right;
 | 
			
		||||
	size_t			 valuelen;
 | 
			
		||||
	int			 modifiers = 0, limit = 0;
 | 
			
		||||
	int			 modifiers = 0, limit = 0, j;
 | 
			
		||||
	struct format_modifier  *list, *fm, *cmp = NULL, *search = NULL;
 | 
			
		||||
	struct format_modifier  *sub = NULL;
 | 
			
		||||
	u_int			 i, count;
 | 
			
		||||
	int			 j;
 | 
			
		||||
 | 
			
		||||
	/* Make a copy of the key. */
 | 
			
		||||
	copy = copy0 = xstrndup(key, keylen);
 | 
			
		||||
@@ -1537,18 +1565,18 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
				search = fm;
 | 
			
		||||
				break;
 | 
			
		||||
			case 's':
 | 
			
		||||
				if (fm->argc != 2)
 | 
			
		||||
				if (fm->argc < 2)
 | 
			
		||||
					break;
 | 
			
		||||
				sub = fm;
 | 
			
		||||
				break;
 | 
			
		||||
			case '=':
 | 
			
		||||
				if (fm->argc != 1 && fm->argc != 2)
 | 
			
		||||
				if (fm->argc < 1)
 | 
			
		||||
					break;
 | 
			
		||||
				limit = strtonum(fm->argv[0], INT_MIN, INT_MAX,
 | 
			
		||||
				    &errptr);
 | 
			
		||||
				if (errptr != NULL)
 | 
			
		||||
					limit = 0;
 | 
			
		||||
				if (fm->argc == 2 && fm->argv[1] != NULL)
 | 
			
		||||
				if (fm->argc >= 2 && fm->argv[1] != NULL)
 | 
			
		||||
					marker = fm->argv[1];
 | 
			
		||||
				break;
 | 
			
		||||
			case 'l':
 | 
			
		||||
@@ -1619,7 +1647,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
			value = xstrdup("0");
 | 
			
		||||
		} else {
 | 
			
		||||
			format_log(ft, "search '%s' pane %%%u", copy,  wp->id);
 | 
			
		||||
			xasprintf(&value, "%u", window_pane_search(wp, copy));
 | 
			
		||||
			value = format_search(fm, wp, copy);
 | 
			
		||||
		}
 | 
			
		||||
	} else if (cmp != NULL) {
 | 
			
		||||
		/* Comparison of left and right. */
 | 
			
		||||
@@ -1671,12 +1699,8 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
				value = xstrdup("1");
 | 
			
		||||
			else
 | 
			
		||||
				value = xstrdup("0");
 | 
			
		||||
		} else if (strcmp(cmp->modifier, "m") == 0) {
 | 
			
		||||
			if (fnmatch(left, right, 0) == 0)
 | 
			
		||||
				value = xstrdup("1");
 | 
			
		||||
			else
 | 
			
		||||
				value = xstrdup("0");
 | 
			
		||||
		}
 | 
			
		||||
		} else if (strcmp(cmp->modifier, "m") == 0)
 | 
			
		||||
			value = format_match(fm, left, right);
 | 
			
		||||
 | 
			
		||||
		free(right);
 | 
			
		||||
		free(left);
 | 
			
		||||
@@ -1754,8 +1778,8 @@ done:
 | 
			
		||||
 | 
			
		||||
	/* Perform substitution if any. */
 | 
			
		||||
	if (sub != NULL) {
 | 
			
		||||
		new = format_substitute(value, sub->argv[0], sub->argv[1]);
 | 
			
		||||
		format_log(ft, "substituted '%s' to '%s: %s", sub->argv[0],
 | 
			
		||||
		new = format_sub(sub, value, sub->argv[0], sub->argv[1]);
 | 
			
		||||
		format_log(ft, "substituted '%s' to '%s': %s", sub->argv[0],
 | 
			
		||||
		    sub->argv[1], new);
 | 
			
		||||
		free(value);
 | 
			
		||||
		value = new;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										98
									
								
								regsub.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								regsub.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
/* $OpenBSD$ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
 * purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
 * copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <regex.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "tmux.h"
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
regsub_copy(char **buf, size_t *len, const char *text, size_t start,
 | 
			
		||||
    size_t end)
 | 
			
		||||
{
 | 
			
		||||
	size_t	add = end - start;
 | 
			
		||||
 | 
			
		||||
	*buf = xrealloc(*buf, (*len) + add + 1);
 | 
			
		||||
	memcpy((*buf) + *len, text + start, add);
 | 
			
		||||
	(*len) += add;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
regsub_expand(char **buf, size_t *len, const char *with, const char *text,
 | 
			
		||||
    regmatch_t *m, u_int n)
 | 
			
		||||
{
 | 
			
		||||
	const char	*cp;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
 | 
			
		||||
	for (cp = with; *cp != '\0'; cp++) {
 | 
			
		||||
		if (*cp == '\\') {
 | 
			
		||||
			cp++;
 | 
			
		||||
			if (*cp >= '0' && *cp <= '9') {
 | 
			
		||||
				i = *cp - '0';
 | 
			
		||||
				if (i < n && m[i].rm_so != m[i].rm_eo) {
 | 
			
		||||
					regsub_copy(buf, len, text, m[i].rm_so,
 | 
			
		||||
					    m[i].rm_eo);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		*buf = xrealloc(*buf, (*len) + 2);
 | 
			
		||||
		(*buf)[(*len)++] = *cp;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *
 | 
			
		||||
regsub(const char *pattern, const char *with, const char *text, int flags)
 | 
			
		||||
{
 | 
			
		||||
	regex_t		 r;
 | 
			
		||||
	regmatch_t	 m[10];
 | 
			
		||||
	size_t		 start, end, len = 0;
 | 
			
		||||
	char		*buf = NULL;
 | 
			
		||||
 | 
			
		||||
	if (*text == '\0')
 | 
			
		||||
		return (xstrdup(""));
 | 
			
		||||
	if (regcomp(&r, pattern, flags) != 0)
 | 
			
		||||
		return (NULL);
 | 
			
		||||
 | 
			
		||||
	start = 0;
 | 
			
		||||
	end = strlen(text);
 | 
			
		||||
 | 
			
		||||
	while (start != end) {
 | 
			
		||||
		m[0].rm_so = start;
 | 
			
		||||
		m[0].rm_eo = end;
 | 
			
		||||
 | 
			
		||||
		if (regexec(&r, text, nitems(m), m, REG_STARTEND) != 0) {
 | 
			
		||||
			regsub_copy(&buf, &len, text, start, end);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		if (m[0].rm_so == m[0].rm_eo) {
 | 
			
		||||
			regsub_copy(&buf, &len, text, start, end);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		regsub_copy(&buf, &len, text, start, m[0].rm_so);
 | 
			
		||||
		regsub_expand(&buf, &len, with, text, m, nitems(m));
 | 
			
		||||
		start = m[0].rm_eo;
 | 
			
		||||
	}
 | 
			
		||||
	buf[len] = '\0';
 | 
			
		||||
 | 
			
		||||
	regfree(&r);
 | 
			
		||||
	return (buf);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								tmux.1
									
									
									
									
									
								
							@@ -4012,25 +4012,45 @@ if running on
 | 
			
		||||
.Ql myhost ,
 | 
			
		||||
otherwise by
 | 
			
		||||
.Ql 0 .
 | 
			
		||||
An
 | 
			
		||||
.Ql m
 | 
			
		||||
specifies an
 | 
			
		||||
.Xr fnmatch 3
 | 
			
		||||
comparison where the first argument is the pattern and the second the string to
 | 
			
		||||
compare, for example
 | 
			
		||||
.Ql #{m:*foo*,#{host}} .
 | 
			
		||||
.Ql ||
 | 
			
		||||
and
 | 
			
		||||
.Ql &&
 | 
			
		||||
evaluate to true if either or both of two comma-separated alternatives are
 | 
			
		||||
true, for example
 | 
			
		||||
.Ql #{||:#{pane_in_mode},#{alternate_on}} .
 | 
			
		||||
.Pp
 | 
			
		||||
An
 | 
			
		||||
.Ql m
 | 
			
		||||
specifies an
 | 
			
		||||
.Xr fnmatch 3
 | 
			
		||||
or regular expression comparison.
 | 
			
		||||
The first argument is the pattern and the second the string to compare.
 | 
			
		||||
An optional third argument specifies flags:
 | 
			
		||||
.Ql r
 | 
			
		||||
means the pattern is a regular expression instead of the default
 | 
			
		||||
.Xr fnmatch 3
 | 
			
		||||
pattern, and
 | 
			
		||||
.Ql i
 | 
			
		||||
means to ignore case.
 | 
			
		||||
For example:
 | 
			
		||||
.Ql #{m:*foo*,#{host}}
 | 
			
		||||
or
 | 
			
		||||
.Ql #{m/ri:^A,MYVAR} .
 | 
			
		||||
A
 | 
			
		||||
.Ql C
 | 
			
		||||
performs a search for an
 | 
			
		||||
.Xr fnmatch 3
 | 
			
		||||
pattern in the pane content and evaluates to zero if not found, or a line
 | 
			
		||||
number if found.
 | 
			
		||||
pattern or regular expression in the pane content and evaluates to zero if not
 | 
			
		||||
found, or a line number if found.
 | 
			
		||||
Like
 | 
			
		||||
.Ql m ,
 | 
			
		||||
a
 | 
			
		||||
.Ql r
 | 
			
		||||
flag means search for a regular expression and
 | 
			
		||||
.Ql i
 | 
			
		||||
ignores case.
 | 
			
		||||
For example:
 | 
			
		||||
.Ql #{C/r:^Start}
 | 
			
		||||
.Pp
 | 
			
		||||
A limit may be placed on the length of the resultant string by prefixing it
 | 
			
		||||
by an
 | 
			
		||||
@@ -4103,6 +4123,14 @@ will substitute
 | 
			
		||||
with
 | 
			
		||||
.Ql bar
 | 
			
		||||
throughout.
 | 
			
		||||
The first argument may be an extended regular expression and a final argument may be
 | 
			
		||||
.Ql i
 | 
			
		||||
to ignore case, for example
 | 
			
		||||
.Ql s/a(.)/\1x/i:
 | 
			
		||||
would change
 | 
			
		||||
.Ql abABab
 | 
			
		||||
into
 | 
			
		||||
.Ql bxBxbx .
 | 
			
		||||
.Pp
 | 
			
		||||
In addition, the first line of a shell command's output may be inserted using
 | 
			
		||||
.Ql #() .
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								tmux.h
									
									
									
									
									
								
							@@ -2396,7 +2396,8 @@ void		 window_pane_key(struct window_pane *, struct client *,
 | 
			
		||||
		     struct session *, struct winlink *, key_code,
 | 
			
		||||
		     struct mouse_event *);
 | 
			
		||||
int		 window_pane_visible(struct window_pane *);
 | 
			
		||||
u_int		 window_pane_search(struct window_pane *, const char *);
 | 
			
		||||
u_int		 window_pane_search(struct window_pane *, const char *, int,
 | 
			
		||||
		     int);
 | 
			
		||||
const char	*window_printable_flags(struct winlink *);
 | 
			
		||||
struct window_pane *window_pane_find_up(struct window_pane *);
 | 
			
		||||
struct window_pane *window_pane_find_down(struct window_pane *);
 | 
			
		||||
@@ -2631,4 +2632,7 @@ int		 style_is_default(struct style *);
 | 
			
		||||
struct winlink	*spawn_window(struct spawn_context *, char **);
 | 
			
		||||
struct window_pane *spawn_pane(struct spawn_context *, char **);
 | 
			
		||||
 | 
			
		||||
/* regsub.c */
 | 
			
		||||
char		*regsub(const char *, const char *, const char *, int);
 | 
			
		||||
 | 
			
		||||
#endif /* TMUX_H */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								window.c
									
									
									
									
									
								
							@@ -22,6 +22,7 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <fnmatch.h>
 | 
			
		||||
#include <regex.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
@@ -1206,24 +1207,41 @@ window_pane_visible(struct window_pane *wp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u_int
 | 
			
		||||
window_pane_search(struct window_pane *wp, const char *searchstr)
 | 
			
		||||
window_pane_search(struct window_pane *wp, const char *term, int regex,
 | 
			
		||||
    int ignore)
 | 
			
		||||
{
 | 
			
		||||
	struct screen	*s = &wp->base;
 | 
			
		||||
	char		*newsearchstr, *line;
 | 
			
		||||
	regex_t		 r;
 | 
			
		||||
	char		*new = NULL, *line;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
	int		 flags = 0, found;
 | 
			
		||||
 | 
			
		||||
	xasprintf(&newsearchstr, "*%s*", searchstr);
 | 
			
		||||
	if (!regex) {
 | 
			
		||||
		if (ignore)
 | 
			
		||||
			flags |= FNM_CASEFOLD;
 | 
			
		||||
		xasprintf(&new, "*%s*", term);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (ignore)
 | 
			
		||||
			flags |= REG_ICASE;
 | 
			
		||||
		if (regcomp(&r, term, flags|REG_EXTENDED) != 0)
 | 
			
		||||
			return (0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < screen_size_y(s); i++) {
 | 
			
		||||
		line = grid_view_string_cells(s->grid, 0, i, screen_size_x(s));
 | 
			
		||||
		if (fnmatch(newsearchstr, line, 0) == 0) {
 | 
			
		||||
		if (!regex)
 | 
			
		||||
			found = (fnmatch(new, line, 0) == 0);
 | 
			
		||||
		else
 | 
			
		||||
			found = (regexec(&r, line, 0, NULL, 0) == 0);
 | 
			
		||||
		free(line);
 | 
			
		||||
		if (found)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
		free(line);
 | 
			
		||||
	}
 | 
			
		||||
	if (!regex)
 | 
			
		||||
		free(new);
 | 
			
		||||
	else
 | 
			
		||||
		regfree(&r);
 | 
			
		||||
 | 
			
		||||
	free(newsearchstr);
 | 
			
		||||
	if (i == screen_size_y(s))
 | 
			
		||||
		return (0);
 | 
			
		||||
	return (i + 1);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user