[vte] regex: Add API to check if some regexes match at an event position



commit 71944514e7d8837c624933f65bf716d9106dea88
Author: Christian Persch <chpe gnome org>
Date:   Wed Oct 7 22:15:06 2015 +0200

    regex: Add API to check if some regexes match at an event position
    
    https://bugzilla.gnome.org/show_bug.cgi?id=741728

 doc/reference/vte-sections.txt |    2 +
 src/vte.cc                     |  190 +++++++++++++++++++++++++++++++++++++---
 src/vte/vtedeprecated.h        |    8 ++
 src/vte/vteterminal.h          |    6 ++
 src/vteapp.c                   |   39 +++++++-
 5 files changed, 227 insertions(+), 18 deletions(-)
---
diff --git a/doc/reference/vte-sections.txt b/doc/reference/vte-sections.txt
index ecdaae3..6252fcd 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 f3b186f..4ae96bb 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 fcd928f..32f2684 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 8f8a1e5..857819f 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 9931b5f..bfddf8c 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);
         }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]