[gnome-builder/wip/libide-merge] vim: add vim style search and replace
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/libide-merge] vim: add vim style search and replace
- Date: Mon, 23 Mar 2015 10:57:37 +0000 (UTC)
commit e1d77d4c854ecafaaadd8a147e848bff06c00d7a
Author: Christian Hergert <christian hergert me>
Date: Mon Mar 23 03:57:25 2015 -0700
vim: add vim style search and replace
This is from GbSourceVim, and has all the same deficiencies. But important
to have something for search and replace until we get the real dialogs
in place.
src/vim/gb-vim.c | 228 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 226 insertions(+), 2 deletions(-)
---
diff --git a/src/vim/gb-vim.c b/src/vim/gb-vim.c
index 6d7fdce..0902d50 100644
--- a/src/vim/gb-vim.c
+++ b/src/vim/gb-vim.c
@@ -180,7 +180,6 @@ gb_vim_set_nonumber (GtkSourceView *source_view,
const gchar *value,
GError **error)
{
- g_print ("disablign line numbers\n");
g_object_set (source_view, "show-line-numbers", FALSE, NULL);
return TRUE;
}
@@ -629,6 +628,218 @@ gb_vim_command_help (GtkSourceView *source_view,
return TRUE;
}
+static gboolean
+gb_vim_match_is_selected (GtkTextBuffer *buffer,
+ GtkTextIter *match_begin,
+ GtkTextIter *match_end)
+{
+ GtkTextIter sel_begin;
+ GtkTextIter sel_end;
+
+ g_assert (GTK_IS_TEXT_BUFFER (buffer));
+ g_assert (match_begin);
+ g_assert (match_end);
+
+ gtk_text_buffer_get_selection_bounds (buffer, &sel_begin, &sel_end);
+ gtk_text_iter_order (&sel_begin, &sel_end);
+
+ return ((gtk_text_iter_compare (&sel_begin, match_begin) <= 0) &&
+ (gtk_text_iter_compare (&sel_begin, match_end) < 0) &&
+ (gtk_text_iter_compare (&sel_end, match_begin) > 0) &&
+ (gtk_text_iter_compare (&sel_end, match_end) >= 0));
+}
+
+static void
+gb_vim_do_search_and_replace (GtkTextBuffer *buffer,
+ GtkTextIter *begin,
+ GtkTextIter *end,
+ const gchar *search_text,
+ const gchar *replace_text,
+ gboolean is_global)
+{
+ GtkSourceSearchContext *search_context;
+ GtkSourceSearchSettings *search_settings;
+ GtkTextMark *mark;
+ GtkTextIter tmp1;
+ GtkTextIter tmp2;
+ GtkTextIter match_begin;
+ GtkTextIter match_end;
+ GError *error = NULL;
+
+ g_assert (GB_IS_SOURCE_VIM (vim));
+ g_assert (search_text);
+ g_assert (replace_text);
+ g_assert ((!begin && !end) || (begin && end));
+
+ search_settings = gtk_source_search_settings_new ();
+ search_context = gtk_source_search_context_new (GTK_SOURCE_BUFFER (buffer), search_settings);
+
+ if (!begin)
+ {
+ gtk_text_buffer_get_start_iter (buffer, &tmp1);
+ begin = &tmp1;
+ }
+
+ if (!end)
+ {
+ gtk_text_buffer_get_end_iter (buffer, &tmp2);
+ end = &tmp2;
+ }
+
+ mark = gtk_text_buffer_create_mark (buffer, NULL, end, FALSE);
+
+ gtk_source_search_settings_set_search_text (search_settings, search_text);
+ gtk_source_search_settings_set_case_sensitive (search_settings, TRUE);
+
+ while (gtk_source_search_context_forward (search_context, begin, &match_begin, &match_end))
+ {
+ if (is_global || gb_vim_match_is_selected (buffer, &match_begin, &match_end))
+ {
+ GtkTextMark *mark2;
+
+ mark2 = gtk_text_buffer_create_mark (buffer, NULL, &match_end, FALSE);
+
+ if (!gtk_source_search_context_replace (search_context, &match_begin, &match_end,
+ replace_text, -1, &error))
+ {
+ g_warning ("%s", error->message);
+ g_clear_error (&error);
+ gtk_text_buffer_delete_mark (buffer, mark2);
+ break;
+ }
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &match_end, mark2);
+ gtk_text_buffer_delete_mark (buffer, mark2);
+ }
+
+ *begin = match_end;
+
+ gtk_text_buffer_get_iter_at_mark (buffer, end, mark);
+ }
+
+ gtk_text_buffer_delete_mark (buffer, mark);
+
+ g_clear_object (&search_settings);
+ g_clear_object (&search_context);
+}
+
+static gboolean
+gb_vim_command_search (GtkSourceView *source_view,
+ const gchar *command,
+ const gchar *options,
+ GError **error)
+{
+ GtkTextBuffer *buffer;
+ const gchar *search_begin = NULL;
+ const gchar *search_end = NULL;
+ const gchar *replace_begin = NULL;
+ const gchar *replace_end = NULL;
+ gchar *search_text = NULL;
+ gchar *replace_text = NULL;
+ gunichar separator;
+
+ g_assert (g_str_has_prefix (command, "%s") || g_str_has_prefix (command, "s"));
+
+ if (*command == '%')
+ command++;
+ command++;
+
+ separator = g_utf8_get_char (command);
+ if (!separator)
+ goto invalid_request;
+
+ search_begin = command = g_utf8_next_char (command);
+
+ for (; *command; command = g_utf8_next_char (command))
+ {
+ if (*command == '\\')
+ {
+ command = g_utf8_next_char (command);
+ if (!*command)
+ goto invalid_request;
+ continue;
+ }
+
+ if (g_utf8_get_char (command) == separator)
+ {
+ search_end = command;
+ break;
+ }
+ }
+
+ if (!search_end)
+ goto invalid_request;
+
+ replace_begin = command = g_utf8_next_char (command);
+
+ for (; *command; command = g_utf8_next_char (command))
+ {
+ if (*command == '\\')
+ {
+ command = g_utf8_next_char (command);
+ if (!*command)
+ goto invalid_request;
+ continue;
+ }
+
+ if (g_utf8_get_char (command) == separator)
+ {
+ replace_end = command;
+ break;
+ }
+ }
+
+ if (!replace_end)
+ goto invalid_request;
+
+ command = g_utf8_next_char (command);
+
+ if (*command)
+ {
+ for (; *command; command++)
+ {
+ switch (*command)
+ {
+ case 'g':
+ break;
+
+ /* what other options are supported? */
+ default:
+ break;
+ }
+ }
+ }
+
+ search_text = g_strndup (search_begin, search_end - search_begin);
+ replace_text = g_strndup (replace_begin, replace_end - replace_begin);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view));
+
+ if (gtk_text_buffer_get_has_selection (buffer))
+ {
+ GtkTextIter begin;
+ GtkTextIter end;
+
+ gtk_text_buffer_get_selection_bounds (buffer, &begin, &end);
+ gtk_text_iter_order (&begin, &end);
+ gb_vim_do_search_and_replace (buffer, &begin, &end, search_text, replace_text, FALSE);
+ }
+ else
+ gb_vim_do_search_and_replace (buffer, NULL, NULL, search_text, replace_text, TRUE);
+
+ g_free (search_text);
+ g_free (replace_text);
+
+ return TRUE;
+
+invalid_request:
+ g_set_error (error,
+ GB_VIM_ERROR,
+ GB_VIM_ERROR_UNKNOWN_OPTION,
+ _("Invalid searcn and replace request"));
+ return FALSE;
+}
+
static const GbVimCommand vim_commands[] = {
{ "cnext", gb_vim_command_cnext },
{ "colorscheme", gb_vim_command_colorscheme },
@@ -650,6 +861,16 @@ static const GbVimCommand vim_commands[] = {
{ NULL }
};
+static gboolean
+looks_like_search_and_replace (const gchar *line)
+{
+ g_assert (line);
+
+ if (g_str_has_prefix (line, "%s"))
+ return TRUE;
+ return *line == 's';
+}
+
static const GbVimCommand *
lookup_command (const gchar *name)
{
@@ -665,7 +886,7 @@ lookup_command (const gchar *name)
return &vim_commands [i];
}
- if (int32_parse (&line, name, 0, G_MAXINT32, "line", NULL))
+ if (g_ascii_isdigit (*name) && int32_parse (&line, name, 0, G_MAXINT32, "line", NULL))
return &line_command;
return NULL;
@@ -716,6 +937,9 @@ gb_vim_execute (GtkSourceView *source_view,
if (command == NULL)
{
+ if (looks_like_search_and_replace (line))
+ return gb_vim_command_search (source_view, line, "", error);
+
g_set_error (error,
GB_VIM_ERROR,
GB_VIM_ERROR_NOT_FOUND,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]