summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Persch <chpe@gnome.org>2015-10-07 22:15:06 +0200
committerChristian Persch <chpe@gnome.org>2015-10-07 22:15:06 +0200
commit71944514e7d8837c624933f65bf716d9106dea88 (patch)
tree931a5a342710f6f58435147b53270d59680e521e
parentb9f2f05eba85bab72db475e0dc2738de7b553eeb (diff)
downloadvte-71944514e7d8837c624933f65bf716d9106dea88.tar.gz
regex: Add API to check if some regexes match at an event position
https://bugzilla.gnome.org/show_bug.cgi?id=741728
-rw-r--r--doc/reference/vte-sections.txt2
-rw-r--r--src/vte.cc190
-rw-r--r--src/vte/vtedeprecated.h8
-rw-r--r--src/vte/vteterminal.h6
-rw-r--r--src/vteapp.c39
5 files changed, 227 insertions, 18 deletions
diff --git a/doc/reference/vte-sections.txt b/doc/reference/vte-sections.txt
index ecdaae34..6252fcd8 100644
--- a/doc/reference/vte-sections.txt
+++ b/doc/reference/vte-sections.txt
@@ -73,6 +73,7 @@ vte_terminal_search_get_regex
vte_terminal_search_get_wrap_around
vte_terminal_search_set_regex
vte_terminal_search_set_wrap_around
+vte_terminal_event_check_regex_simple
<SUBSECTION>
vte_get_user_shell
@@ -121,6 +122,7 @@ vte_terminal_match_set_cursor
vte_terminal_match_add_gregex
vte_terminal_search_get_gregex
vte_terminal_search_set_gregex
+vte_terminal_event_check_gregex_simple
<SUBSECTION Private>
VteCharAttributes
diff --git a/src/vte.cc b/src/vte.cc
index f3b186fe..4ae96bbf 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -1624,7 +1624,8 @@ static gboolean
match_check_pcre(VteTerminalPrivate *pvt,
pcre2_match_data_8 *match_data,
pcre2_match_context_8 *match_context,
- struct vte_regex_and_flags *regex,
+ VteRegex *regex,
+ guint32 match_flags,
gsize sattr,
gsize eattr,
gsize offset,
@@ -1642,9 +1643,7 @@ match_check_pcre(VteTerminalPrivate *pvt,
const char *line;
int r = 0;
- g_assert_cmpint(regex->mode, ==, VTE_REGEX_PCRE2);
-
- if (_vte_regex_get_jited(regex->pcre.regex))
+ if (_vte_regex_get_jited(regex))
match_fn = pcre2_jit_match_8;
else
match_fn = pcre2_match_8;
@@ -1661,10 +1660,10 @@ match_check_pcre(VteTerminalPrivate *pvt,
*/
position = sattr;
while (position < eattr &&
- ((r = match_fn(vte_regex_get_pcre(regex->pcre.regex),
+ ((r = match_fn(vte_regex_get_pcre(regex),
(PCRE2_SPTR8)line, line_length, /* subject, length */
position, /* start offset */
- regex->pcre.match_flags |
+ match_flags |
PCRE2_NO_UTF_CHECK | PCRE2_NOTEMPTY | PCRE2_PARTIAL_SOFT /* FIXME: HARD? */,
match_data,
match_context)) >= 0 || r == PCRE2_ERROR_PARTIAL)) {
@@ -1779,9 +1778,12 @@ vte_terminal_match_check_internal_pcre(VteTerminal *terminal,
continue;
}
+ g_assert_cmpint(regex->regex.mode, ==, VTE_REGEX_PCRE2);
+
if (match_check_pcre(terminal->pvt,
match_data, match_context,
- &regex->regex,
+ regex->regex.pcre.regex,
+ regex->regex.pcre.match_flags,
sattr, eattr, offset,
&dingu_match,
start, end,
@@ -1831,7 +1833,8 @@ vte_terminal_match_check_internal_pcre(VteTerminal *terminal,
static gboolean
match_check_gregex(VteTerminalPrivate *pvt,
- struct vte_regex_and_flags *regex,
+ GRegex *regex,
+ GRegexMatchFlags match_flags,
gsize sattr,
gsize eattr,
gsize offset,
@@ -1846,18 +1849,16 @@ match_check_gregex(VteTerminalPrivate *pvt,
gsize line_length;
gint sblank = G_MININT, eblank = G_MAXINT;
- g_assert_cmpint(regex->mode, ==, VTE_REGEX_GREGEX);
-
line = pvt->match_contents;
line_length = eattr;
/* We'll only match the first item in the buffer which
* matches, so we'll have to skip each match until we
* stop getting matches. */
- if (!g_regex_match_full(regex->gregex.regex,
+ if (!g_regex_match_full(regex,
line, line_length, /* subject, length */
sattr, /* start position */
- regex->gregex.match_flags,
+ match_flags,
&match_info,
NULL)) {
g_match_info_free(match_info);
@@ -1958,8 +1959,11 @@ vte_terminal_match_check_internal_gregex(VteTerminal *terminal,
continue;
}
+ g_assert_cmpint(regex->regex.mode, ==, VTE_REGEX_GREGEX);
+
if (match_check_gregex(terminal->pvt,
- &regex->regex,
+ regex->regex.gregex.regex,
+ regex->regex.gregex.match_flags,
sattr, eattr, offset,
&dingu_match,
start, end,
@@ -2163,6 +2167,166 @@ vte_terminal_match_check_event(VteTerminal *terminal,
return vte_terminal_match_check(terminal, col, row, tag);
}
+/**
+ * vte_terminal_event_check_regex_simple:
+ * @terminal: a #VteTerminal
+ * @event: a #GdkEvent
+ * @regexes: (array length=n_regexes): an array of #VteRegex
+ * @n_regexes: number of items in @regexes
+ * @flags: PCRE2 match flags, or 0
+ * @matches: (out caller-allocates) (array length=n_regexes): a location to store the matches
+ *
+ * Checks each regex in @regexes if the text in and around the position of
+ * the event matches the regular expressions. If a match exists, the matched
+ * text is stored in @matches at the position of the regex in @regexes; otherwise
+ * %NULL is stored there.
+ *
+ * Returns: %TRUE iff any of the regexes produced a match
+ *
+ * Since: 0.44
+ */
+gboolean
+vte_terminal_event_check_regex_simple(VteTerminal *terminal,
+ GdkEvent *event,
+ VteRegex **regexes,
+ gsize n_regexes,
+ guint32 match_flags,
+ char **matches)
+{
+ VteTerminalPrivate *pvt = terminal->pvt;
+ gsize offset, sattr, eattr;
+ pcre2_match_data_8 *match_data;
+ pcre2_match_context_8 *match_context;
+ gboolean any_matches = FALSE;
+ double x, y;
+ long col, row;
+ guint i;
+
+ g_return_val_if_fail(VTE_IS_TERMINAL(terminal), FALSE);
+ g_return_val_if_fail(event != NULL, FALSE);
+ g_return_val_if_fail(regexes != NULL || n_regexes == 0, FALSE);
+ g_return_val_if_fail(matches != NULL, FALSE);
+
+ if (((GdkEventAny*)event)->window != gtk_widget_get_window(&terminal->widget))
+ return FALSE;
+ if (!gdk_event_get_coords(event, &x, &y))
+ return FALSE;
+ if (!_vte_terminal_xy_to_grid(terminal, x, y, &col, &row))
+ return FALSE;
+
+ if (pvt->match_contents == NULL) {
+ vte_terminal_match_contents_refresh(terminal);
+ }
+
+ if (!match_rowcol_to_offset(terminal, col, row,
+ &offset, &sattr, &eattr))
+ return FALSE;
+
+ match_context = create_match_context();
+ match_data = pcre2_match_data_create_8(256 /* should be plenty */, NULL /* general context */);
+
+ for (i = 0; i < n_regexes; i++) {
+ gsize start, end, sblank, eblank;
+ char *match;
+
+ g_return_val_if_fail(regexes[i] != NULL, FALSE);
+
+ if (match_check_pcre(terminal->pvt,
+ match_data, match_context,
+ regexes[i], match_flags,
+ sattr, eattr, offset,
+ &match,
+ &start, &end,
+ &sblank, &eblank)) {
+ _vte_debug_print(VTE_DEBUG_REGEX, "Matched regex with text: %s\n", match);
+ matches[i] = match;
+ any_matches = TRUE;
+ } else
+ matches[i] = NULL;
+ }
+
+ pcre2_match_data_free_8(match_data);
+ pcre2_match_context_free_8(match_context);
+
+ return any_matches;
+}
+
+/**
+ * vte_terminal_event_check_gregex_simple:
+ * @terminal: a #VteTerminal
+ * @event: a #GdkEvent
+ * @regexes: (array length=n_regexes): an array of #GRegex
+ * @n_regexes: number of items in @regexes
+ * @gflags: the #GRegexMatchFlags to use when matching the regexes
+ * @matches: (out caller-allocates) (array length=n_regexes): a location to store the matches
+ *
+ * Checks each regex in @regexes if the text in and around the position of
+ * the event matches the regular expressions. If a match exists, the matched
+ * text is stored in @matches at the position of the regex in @regexes; otherwise
+ * %NULL is stored there.
+ *
+ * Returns: %TRUE iff any of the regexes produced a match
+ *
+ * Since: 0.44
+ * Deprecated: 0.44: Use vte_terminal_event_check_regex_simple() instead.
+ */
+gboolean
+vte_terminal_event_check_gregex_simple(VteTerminal *terminal,
+ GdkEvent *event,
+ GRegex **regexes,
+ gsize n_regexes,
+ GRegexMatchFlags match_flags,
+ char **matches)
+{
+ VteTerminalPrivate *pvt = terminal->pvt;
+ gsize offset, sattr, eattr;
+ gboolean any_matches = FALSE;
+ double x, y;
+ long col, row;
+ guint i;
+
+ g_return_val_if_fail(VTE_IS_TERMINAL(terminal), FALSE);
+ g_return_val_if_fail(event != NULL, FALSE);
+ g_return_val_if_fail(regexes != NULL || n_regexes == 0, FALSE);
+ g_return_val_if_fail(matches != NULL, FALSE);
+
+ if (((GdkEventAny*)event)->window != gtk_widget_get_window(&terminal->widget))
+ return FALSE;
+ if (!gdk_event_get_coords(event, &x, &y))
+ return FALSE;
+ if (!_vte_terminal_xy_to_grid(terminal, x, y, &col, &row))
+ return FALSE;
+
+ if (pvt->match_contents == NULL) {
+ vte_terminal_match_contents_refresh(terminal);
+ }
+
+ if (!match_rowcol_to_offset(terminal, col, row,
+ &offset, &sattr, &eattr))
+ return FALSE;
+
+ for (i = 0; i < n_regexes; i++) {
+ gsize start, end, sblank, eblank;
+ char *match;
+
+ g_return_val_if_fail(regexes[i] != NULL, FALSE);
+
+ if (match_check_gregex(terminal->pvt,
+ regexes[i], match_flags,
+ sattr, eattr, offset,
+ &match,
+ &start, &end,
+ &sblank, &eblank)) {
+ _vte_debug_print(VTE_DEBUG_REGEX, "Matched gregex with text: %s\n", match);
+ matches[i] = match;
+ any_matches = TRUE;
+ } else
+ matches[i] = NULL;
+ }
+
+ return any_matches;
+}
+
/* Emit an adjustment changed signal on our adjustment object. */
static void
vte_terminal_emit_adjustment_changed(VteTerminal *terminal)
diff --git a/src/vte/vtedeprecated.h b/src/vte/vtedeprecated.h
index fcd928f4..32f26841 100644
--- a/src/vte/vtedeprecated.h
+++ b/src/vte/vtedeprecated.h
@@ -47,6 +47,14 @@ char *vte_terminal_match_check(VteTerminal *terminal,
int *tag) _VTE_GNUC_NONNULL(1) G_GNUC_MALLOC;
_VTE_DEPRECATED
+gboolean vte_terminal_event_check_gregex_simple(VteTerminal *terminal,
+ GdkEvent *event,
+ GRegex **regexes,
+ gsize n_regexes,
+ GRegexMatchFlags match_flags,
+ char **matches) _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2);
+
+_VTE_DEPRECATED
void vte_terminal_search_set_gregex (VteTerminal *terminal,
GRegex *gregex,
GRegexMatchFlags gflags) _VTE_GNUC_NONNULL(1);
diff --git a/src/vte/vteterminal.h b/src/vte/vteterminal.h
index 8f8a1e52..857819f3 100644
--- a/src/vte/vteterminal.h
+++ b/src/vte/vteterminal.h
@@ -310,6 +310,12 @@ void vte_terminal_match_remove_all(VteTerminal *terminal) _VTE_GNUC_NONNULL(1);
char *vte_terminal_match_check_event(VteTerminal *terminal,
GdkEvent *event,
int *tag) _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2) G_GNUC_MALLOC;
+gboolean vte_terminal_event_check_regex_simple(VteTerminal *terminal,
+ GdkEvent *event,
+ VteRegex **regexes,
+ gsize n_regexes,
+ guint32 match_flags,
+ char **matches) _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2);
void vte_terminal_search_set_regex (VteTerminal *terminal,
VteRegex *regex,
diff --git a/src/vteapp.c b/src/vteapp.c
index 9931b5f1..bfddf8cc 100644
--- a/src/vteapp.c
+++ b/src/vteapp.c
@@ -48,6 +48,8 @@ static const char *builtin_dingus[] = {
NULL
};
+static gboolean use_gregex = FALSE;
+
static void
window_title_changed(GtkWidget *widget, gpointer win)
{
@@ -145,6 +147,8 @@ button_pressed(GtkWidget *widget, GdkEventButton *event, gpointer data)
char *match;
int tag;
GtkBorder padding;
+ gboolean has_extra_match;
+ char *extra_match;
switch (event->button) {
case 3:
@@ -163,6 +167,32 @@ button_pressed(GtkWidget *widget, GdkEventButton *event, gpointer data)
vte_terminal_match_remove(terminal, tag);
}
}
+#ifdef WITH_PCRE2
+ if (!use_gregex) {
+ VteRegex *regex = vte_regex_new("\\d+", -1, PCRE2_UTF, NULL);
+ has_extra_match = vte_terminal_event_check_regex_simple(terminal,
+ (GdkEvent*)event,
+ &regex, 1,
+ 0,
+ &extra_match);
+ vte_regex_unref(regex);
+ } else
+#endif
+ {
+ GRegex *regex = g_regex_new("\\d+", 0, 0, NULL);
+ has_extra_match = vte_terminal_event_check_gregex_simple(terminal,
+ (GdkEvent*)event,
+ &regex, 1,
+ 0,
+ &extra_match);
+ g_regex_unref(regex);
+ }
+
+ if (has_extra_match)
+ g_print("Extra regex match: %s\n", extra_match);
+ else
+ g_print("Extra regex didn't match\n");
+ g_free(extra_match);
break;
case 1:
case 2:
@@ -525,8 +555,7 @@ parse_color (const gchar *value,
static void
add_dingus (VteTerminal *terminal,
- char **dingus,
- gboolean use_gregex)
+ char **dingus)
{
const GdkCursorType cursors[] = { GDK_GUMBY, GDK_HAND1 };
int id, i;
@@ -591,7 +620,7 @@ main(int argc, char **argv)
console = FALSE, keep = FALSE,
icon_title = FALSE, shell = TRUE,
reverse = FALSE, use_geometry_hints = TRUE,
- use_scrolled_window = FALSE, use_gregex = FALSE,
+ use_scrolled_window = FALSE,
show_object_notifications = FALSE, rewrap = TRUE;
char *geometry = NULL;
gint lines = -1;
@@ -1006,10 +1035,10 @@ main(int argc, char **argv)
/* Match "abcdefg". */
if (!no_builtin_dingus) {
- add_dingus (terminal, (char **) builtin_dingus, use_gregex);
+ add_dingus (terminal, (char **) builtin_dingus);
}
if (dingus) {
- add_dingus (terminal, dingus, use_gregex);
+ add_dingus (terminal, dingus);
g_strfreev (dingus);
}