From 206d27c66761cedebec8bedcaa91bf9f08846095 Mon Sep 17 00:00:00 2001 From: "V.Barkov" Date: Sun, 20 Nov 2016 09:36:10 +0300 Subject: Implemented regexp finding --- pluma/dialogs/pluma-search-dialog.c | 20 +++++ pluma/dialogs/pluma-search-dialog.h | 4 + pluma/dialogs/pluma-search-dialog.ui | 27 +++++- pluma/pluma-commands-search.c | 3 + pluma/pluma-document.c | 165 ++++++++++++++++++++--------------- pluma/pluma-document.h | 8 +- pluma/pluma-utils.c | 95 ++++++++++++++++++++ pluma/pluma-utils.h | 9 ++ 8 files changed, 255 insertions(+), 76 deletions(-) (limited to 'pluma') diff --git a/pluma/dialogs/pluma-search-dialog.c b/pluma/dialogs/pluma-search-dialog.c index 329e1721..6263b937 100755 --- a/pluma/dialogs/pluma-search-dialog.c +++ b/pluma/dialogs/pluma-search-dialog.c @@ -68,6 +68,7 @@ struct _PlumaSearchDialogPrivate GtkWidget *replace_entry; GtkWidget *replace_text_entry; GtkWidget *match_case_checkbutton; + GtkWidget *match_regex_checkbutton; GtkWidget *entire_word_checkbutton; GtkWidget *backwards_checkbutton; GtkWidget *wrap_around_checkbutton; @@ -352,6 +353,7 @@ pluma_search_dialog_init (PlumaSearchDialog *dlg) "search_label", &dlg->priv->search_label, "replace_with_label", &dlg->priv->replace_label, "match_case_checkbutton", &dlg->priv->match_case_checkbutton, + "match_regex_checkbutton",&dlg->priv->match_regex_checkbutton, "entire_word_checkbutton", &dlg->priv->entire_word_checkbutton, "search_backwards_checkbutton", &dlg->priv->backwards_checkbutton, "wrap_around_checkbutton", &dlg->priv->wrap_around_checkbutton, @@ -582,6 +584,24 @@ pluma_search_dialog_get_match_case (PlumaSearchDialog *dialog) return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->match_case_checkbutton)); } +void +pluma_search_dialog_set_match_regex (PlumaSearchDialog *dialog, + gboolean match_case) +{ + g_return_if_fail (PLUMA_IS_SEARCH_DIALOG (dialog)); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->match_regex_checkbutton), + match_case); +} + +gboolean +pluma_search_dialog_get_match_regex (PlumaSearchDialog *dialog) +{ + g_return_val_if_fail (PLUMA_IS_SEARCH_DIALOG (dialog), FALSE); + + return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->match_regex_checkbutton)); +} + void pluma_search_dialog_set_entire_word (PlumaSearchDialog *dialog, gboolean entire_word) diff --git a/pluma/dialogs/pluma-search-dialog.h b/pluma/dialogs/pluma-search-dialog.h index fb92efba..e6ebe8dc 100755 --- a/pluma/dialogs/pluma-search-dialog.h +++ b/pluma/dialogs/pluma-search-dialog.h @@ -111,6 +111,10 @@ void pluma_search_dialog_set_match_case (PlumaSearchDialog *dialog, gboolean match_case); gboolean pluma_search_dialog_get_match_case (PlumaSearchDialog *dialog); +void pluma_search_dialog_set_match_regex (PlumaSearchDialog *dialog, + gboolean match_case); +gboolean pluma_search_dialog_get_match_regex (PlumaSearchDialog *dialog); + void pluma_search_dialog_set_entire_word (PlumaSearchDialog *dialog, gboolean entire_word); gboolean pluma_search_dialog_get_entire_word (PlumaSearchDialog *dialog); diff --git a/pluma/dialogs/pluma-search-dialog.ui b/pluma/dialogs/pluma-search-dialog.ui index a1a37b5d..b7b70aca 100644 --- a/pluma/dialogs/pluma-search-dialog.ui +++ b/pluma/dialogs/pluma-search-dialog.ui @@ -180,6 +180,22 @@ Author: Wolfgang Ulbrich 0 + + + Match _regular expression + True + True + False + start + True + True + + + False + False + 1 + + Match _entire word only @@ -193,7 +209,7 @@ Author: Wolfgang Ulbrich False False - 1 + 2 @@ -209,7 +225,7 @@ Author: Wolfgang Ulbrich False False - 2 + 3 @@ -226,7 +242,7 @@ Author: Wolfgang Ulbrich False False - 3 + 4 @@ -243,7 +259,7 @@ Author: Wolfgang Ulbrich False False - 4 + 5 @@ -268,5 +284,8 @@ Author: Wolfgang Ulbrich replace_button find_next_button + + + diff --git a/pluma/pluma-commands-search.c b/pluma/pluma-commands-search.c index 1a75dbca..03b8048a 100644 --- a/pluma/pluma-commands-search.c +++ b/pluma/pluma-commands-search.c @@ -227,6 +227,7 @@ do_find (PlumaSearchDialog *dialog, gchar *search_text; const gchar *entry_text; gboolean match_case; + gboolean match_regex; gboolean entire_word; gboolean wrap_around; gboolean search_backwards; @@ -244,6 +245,7 @@ do_find (PlumaSearchDialog *dialog, doc = PLUMA_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view))); match_case = pluma_search_dialog_get_match_case (dialog); + match_regex = pluma_search_dialog_get_match_regex(dialog); entire_word = pluma_search_dialog_get_entire_word (dialog); search_backwards = pluma_search_dialog_get_backwards (dialog); wrap_around = pluma_search_dialog_get_wrap_around (dialog); @@ -257,6 +259,7 @@ do_find (PlumaSearchDialog *dialog, PLUMA_SEARCH_SET_CASE_SENSITIVE (flags, match_case); PLUMA_SEARCH_SET_ENTIRE_WORD (flags, entire_word); + PLUMA_SEARCH_SET_MATCH_REGEX (flags, match_regex); search_text = pluma_document_get_search_text (doc, &old_flags); diff --git a/pluma/pluma-document.c b/pluma/pluma-document.c index 85890566..43abf989 100644 --- a/pluma/pluma-document.c +++ b/pluma/pluma-document.c @@ -1919,12 +1919,23 @@ pluma_document_search_forward (PlumaDocument *doc, while (!found) { - found = gtk_text_iter_forward_search (&iter, - doc->priv->search_text, - search_flags, - &m_start, - &m_end, - end); + if(!PLUMA_SEARCH_IS_MATCH_REGEX(doc->priv->search_flags)) + { + found = gtk_text_iter_forward_search (&iter, + doc->priv->search_text, + search_flags, + &m_start, + &m_end, + end); + }else{ + found = pluma_gtk_text_iter_regex_search (&iter, + doc->priv->search_text, + search_flags, + &m_start, + &m_end, + end, + TRUE); + } if (found && PLUMA_SEARCH_IS_ENTIRE_WORD (doc->priv->search_flags)) { @@ -1957,71 +1968,83 @@ pluma_document_search_forward (PlumaDocument *doc, **/ gboolean pluma_document_search_backward (PlumaDocument *doc, - const GtkTextIter *start, - const GtkTextIter *end, - GtkTextIter *match_start, - GtkTextIter *match_end) -{ - GtkTextIter iter; - GtkTextSearchFlags search_flags; - gboolean found = FALSE; - GtkTextIter m_start; - GtkTextIter m_end; - - g_return_val_if_fail (PLUMA_IS_DOCUMENT (doc), FALSE); - g_return_val_if_fail ((start == NULL) || - (gtk_text_iter_get_buffer (start) == GTK_TEXT_BUFFER (doc)), FALSE); - g_return_val_if_fail ((end == NULL) || - (gtk_text_iter_get_buffer (end) == GTK_TEXT_BUFFER (doc)), FALSE); - - if (doc->priv->search_text == NULL) - { - pluma_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == NULL\n"); - return FALSE; - } - else - pluma_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == \"%s\"\n", doc->priv->search_text); - - if (end == NULL) - gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &iter); - else - iter = *end; - - search_flags = GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY; - - if (!PLUMA_SEARCH_IS_CASE_SENSITIVE (doc->priv->search_flags)) - { - search_flags = search_flags | GTK_TEXT_SEARCH_CASE_INSENSITIVE; - } - - while (!found) - { - found = gtk_text_iter_backward_search (&iter, - doc->priv->search_text, - search_flags, - &m_start, - &m_end, - start); - - if (found && PLUMA_SEARCH_IS_ENTIRE_WORD (doc->priv->search_flags)) - { - found = gtk_text_iter_starts_word (&m_start) && - gtk_text_iter_ends_word (&m_end); - - if (!found) - iter = m_start; - } - else - break; - } - - if (found && (match_start != NULL)) - *match_start = m_start; - - if (found && (match_end != NULL)) - *match_end = m_end; - - return found; + const GtkTextIter *start, + const GtkTextIter *end, + GtkTextIter *match_start, + GtkTextIter *match_end) +{ + GtkTextIter iter; + GtkTextSearchFlags search_flags; + gboolean found = FALSE; + GtkTextIter m_start; + GtkTextIter m_end; + + g_return_val_if_fail (PLUMA_IS_DOCUMENT (doc), FALSE); + g_return_val_if_fail ((start == NULL) || + (gtk_text_iter_get_buffer (start) == GTK_TEXT_BUFFER (doc)), FALSE); + g_return_val_if_fail ((end == NULL) || + (gtk_text_iter_get_buffer (end) == GTK_TEXT_BUFFER (doc)), FALSE); + + if (doc->priv->search_text == NULL) + { + pluma_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == NULL\n"); + return FALSE; + } + else + pluma_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == \"%s\"\n", doc->priv->search_text); + + if (end == NULL) + gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &iter); + else + iter = *end; + + search_flags = GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY; + + if (!PLUMA_SEARCH_IS_CASE_SENSITIVE (doc->priv->search_flags)) + { + search_flags = search_flags | GTK_TEXT_SEARCH_CASE_INSENSITIVE; + } + + while (!found) + { + if(!PLUMA_SEARCH_IS_MATCH_REGEX(doc->priv->search_flags)) + { + found = gtk_text_iter_backward_search (&iter, + doc->priv->search_text, + search_flags, + &m_start, + &m_end, + start); + } + else{ + found = pluma_gtk_text_iter_regex_search (&iter, + doc->priv->search_text, + search_flags, + &m_start, + &m_end, + end, + FALSE); + } + + if (found && PLUMA_SEARCH_IS_ENTIRE_WORD (doc->priv->search_flags)) + { + found = gtk_text_iter_starts_word (&m_start) && + gtk_text_iter_ends_word (&m_end); + + if (!found) + iter = m_start; + } + else + break; + } + + if (found && (match_start != NULL)) + *match_start = m_start; + + if (found && (match_end != NULL)) + *match_end = m_end; + + return found; } /* FIXME this is an issue for introspection regardning @find */ diff --git a/pluma/pluma-document.h b/pluma/pluma-document.h index 6d90323e..ee8d6f88 100644 --- a/pluma/pluma-document.h +++ b/pluma/pluma-document.h @@ -69,7 +69,8 @@ typedef enum PLUMA_SEARCH_DONT_SET_FLAGS = 1 << 0, PLUMA_SEARCH_ENTIRE_WORD = 1 << 1, PLUMA_SEARCH_CASE_SENSITIVE = 1 << 2, - PLUMA_SEARCH_PARSE_ESCAPES = 1 << 3 + PLUMA_SEARCH_PARSE_ESCAPES = 1 << 3, + PLUMA_SEARCH_MATCH_REGEX = 1 << 4, } PlumaSearchFlags; @@ -317,6 +318,11 @@ void _pluma_document_search_region (PlumaDocument *doc, #define PLUMA_SEARCH_SET_PARSE_ESCAPES(sflags,state) ((state == TRUE) ? \ (sflags |= PLUMA_SEARCH_PARSE_ESCAPES) : (sflags &= ~PLUMA_SEARCH_PARSE_ESCAPES)) +#define PLUMA_SEARCH_IS_MATCH_REGEX(sflags) ((sflags & PLUMA_SEARCH_MATCH_REGEX) != 0) +#define PLUMA_SEARCH_SET_MATCH_REGEX(sflags,state) ((state == TRUE) ? \ +(sflags |= PLUMA_SEARCH_MATCH_REGEX) : (sflags &= ~PLUMA_SEARCH_MATCH_REGEX)) + + typedef GMountOperation *(*PlumaMountOperationFactory)(PlumaDocument *doc, gpointer userdata); diff --git a/pluma/pluma-utils.c b/pluma/pluma-utils.c index 887e9ff5..a5f67a2c 100644 --- a/pluma/pluma-utils.c +++ b/pluma/pluma-utils.c @@ -1571,3 +1571,98 @@ pluma_utils_decode_uri (const gchar *uri, return TRUE; } + +gboolean +pluma_gtk_text_iter_regex_search (const GtkTextIter *iter, + const gchar *str, + GtkTextSearchFlags flags, + GtkTextIter *match_start, + GtkTextIter *match_end, + const GtkTextIter *limit, + gboolean forward_search) +{ + GRegex *regex; + GRegexCompileFlags compile_flags; + GMatchInfo *match_info; + gchar *text; + GtkTextIter *begin_iter; + GtkTextIter *end_iter; + gchar **all_matches; + gchar *match_string; + gboolean found; + + compile_flags = 0; + if ((flags & GTK_TEXT_SEARCH_CASE_INSENSITIVE) != 0) + compile_flags |= G_REGEX_CASELESS; + + regex = g_regex_new (str,compile_flags,0,NULL); + if (regex == NULL) + return FALSE; + + begin_iter=gtk_text_iter_copy(iter); + if (limit == NULL) + { + end_iter=gtk_text_iter_copy(begin_iter); + if(forward_search) + { + gtk_text_buffer_get_end_iter(gtk_text_iter_get_buffer(begin_iter), + end_iter); + } + else + { + gtk_text_buffer_get_start_iter(gtk_text_iter_get_buffer(begin_iter), + end_iter); + } + } + else + { + end_iter=gtk_text_iter_copy(limit); + } + + if ((flags & GTK_TEXT_SEARCH_TEXT_ONLY) != 0) + { + if ((flags & GTK_TEXT_SEARCH_VISIBLE_ONLY) != 0) + text=gtk_text_iter_get_visible_text(begin_iter,end_iter); + else + text=gtk_text_iter_get_text(begin_iter,end_iter); + } + else + { + if ((flags & GTK_TEXT_SEARCH_VISIBLE_ONLY) != 0) + text=gtk_text_iter_get_visible_slice(begin_iter,end_iter); + else + text=gtk_text_iter_get_slice(begin_iter,end_iter); + } + + found = g_regex_match_all(regex,text,0,&match_info); + if (found) + { + all_matches=g_match_info_fetch_all(match_info); + if(forward_search) + { + match_string=all_matches[0]; + gtk_text_iter_forward_search(begin_iter + ,match_string + ,flags + ,match_start + ,match_end + ,limit); + } + else + { + match_string=all_matches[g_strv_length(all_matches)-1]; + gtk_text_iter_backward_search(begin_iter + ,match_string + ,flags + ,match_start + ,match_end + ,limit); + } + } + + gtk_text_iter_free(begin_iter); + gtk_text_iter_free(end_iter); + g_match_info_free (match_info); + g_regex_unref (regex); + return found; +} diff --git a/pluma/pluma-utils.h b/pluma/pluma-utils.h index 066bb438..fb62ec48 100644 --- a/pluma/pluma-utils.h +++ b/pluma/pluma-utils.h @@ -151,6 +151,15 @@ gboolean pluma_utils_decode_uri (const gchar *uri, /* Turns data from a drop into a list of well formatted uris */ gchar **pluma_utils_drop_get_uris (GtkSelectionData *selection_data); +/* Provides regexp forward search */ +gboolean +pluma_gtk_text_iter_regex_search (const GtkTextIter *iter, + const gchar *str, + GtkTextSearchFlags flags, + GtkTextIter *match_start, + GtkTextIter *match_end, + const GtkTextIter *limit, gboolean forward_search); + G_END_DECLS #endif /* __PLUMA_UTILS_H__ */ -- cgit v1.2.1