[gnome-builder] vim: add support for % to jump between matching brackets.



commit 288af0bef3ba5cb7fd85f7ffd61a141403a7cc71
Author: Christian Hergert <christian hergert me>
Date:   Mon Oct 6 01:06:38 2014 -0700

    vim: add support for % to jump between matching brackets.

 src/editor/gb-editor-vim.c |  132 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 131 insertions(+), 1 deletions(-)
---
diff --git a/src/editor/gb-editor-vim.c b/src/editor/gb-editor-vim.c
index 630a347..ff7f85c 100644
--- a/src/editor/gb-editor-vim.c
+++ b/src/editor/gb-editor-vim.c
@@ -128,6 +128,13 @@ typedef struct
   gchar modifier;
 } GbEditorVimPhrase;
 
+typedef struct
+{
+  gunichar jump_to;
+  gunichar jump_from;
+  guint    depth;
+} MatchingBracketState;
+
 enum
 {
   PROP_0,
@@ -884,6 +891,98 @@ gb_editor_vim_move_forward_word_end (GbEditorVim *vim)
 }
 
 static gboolean
+bracket_predicate (gunichar ch,
+                   gpointer user_data)
+{
+  MatchingBracketState *state = user_data;
+
+  if (ch == state->jump_from)
+    state->depth++;
+  else if (ch == state->jump_to)
+    state->depth--;
+
+  return (state->depth == 0);
+}
+
+static void
+gb_editor_vim_move_matching_bracket (GbEditorVim *vim)
+{
+  MatchingBracketState state;
+  GtkTextBuffer *buffer;
+  GtkTextMark *insert;
+  GtkTextIter iter;
+  GtkTextIter selection;
+  gboolean has_selection;
+  gboolean is_forward;
+  gboolean ret;
+
+  g_return_if_fail (GB_IS_EDITOR_VIM (vim));
+
+  buffer = gtk_text_view_get_buffer (vim->priv->text_view);
+  has_selection = gb_editor_vim_get_selection_bounds (vim, &iter, &selection);
+
+  state.depth = 1;
+  state.jump_from = gtk_text_iter_get_char (&iter);
+
+  switch (state.jump_from)
+    {
+    case '{':
+      state.jump_to = '}';
+      is_forward = TRUE;
+      break;
+
+    case '[':
+      state.jump_to = ']';
+      is_forward = TRUE;
+      break;
+
+    case '(':
+      state.jump_to = ')';
+      is_forward = TRUE;
+      break;
+
+    case '}':
+      state.jump_to = '{';
+      is_forward = FALSE;
+      break;
+
+    case ']':
+      state.jump_to = '[';
+      is_forward = FALSE;
+      break;
+
+    case ')':
+      state.jump_to = '(';
+      is_forward = FALSE;
+      break;
+
+    default:
+      return;
+    }
+
+  if (is_forward)
+    ret = gtk_text_iter_forward_find_char (&iter, bracket_predicate, &state,
+                                           NULL);
+  else
+    ret = gtk_text_iter_backward_find_char (&iter, bracket_predicate, &state,
+                                            NULL);
+
+  if (ret)
+    {
+      if (has_selection)
+        {
+          gtk_text_buffer_select_range (buffer, &iter, &selection);
+          gb_editor_vim_ensure_anchor_selected (vim);
+        }
+      else
+        gtk_text_buffer_select_range (buffer, &iter, &iter);
+
+      insert = gtk_text_buffer_get_insert (buffer);
+      gtk_text_view_scroll_mark_onscreen (vim->priv->text_view, insert);
+    }
+}
+
+static gboolean
 is_single_line_selection (const GtkTextIter *begin,
                           const GtkTextIter *end)
 {
@@ -3318,7 +3417,6 @@ gb_editor_vim_cmd_change_to_end (GbEditorVim *vim,
   gb_editor_vim_move_forward (vim);
 }
 
-
 static void
 gb_editor_vim_cmd_delete (GbEditorVim *vim,
                           guint        count,
@@ -3719,6 +3817,34 @@ gb_editor_vim_cmd_center (GbEditorVim *vim,
 }
 
 static void
+gb_editor_vim_cmd_matching_bracket (GbEditorVim *vim,
+                                    guint        count,
+                                    gchar        modifier)
+{
+  GtkTextIter iter;
+  GtkTextIter selection;
+
+  g_return_if_fail (GB_IS_EDITOR_VIM (vim));
+
+  gb_editor_vim_get_selection_bounds (vim, &iter, &selection);
+
+  switch (gtk_text_iter_get_char (&iter))
+    {
+    case '{':
+    case '}':
+    case '[':
+    case ']':
+    case '(':
+    case ')':
+      gb_editor_vim_move_matching_bracket (vim);
+      break;
+
+    default:
+      break;
+    }
+}
+
+static void
 gb_editor_vim_class_register_command (GbEditorVimClass       *klass,
                                       gchar                   key,
                                       GbEditorVimCommandFlags flags,
@@ -3891,6 +4017,10 @@ gb_editor_vim_class_init (GbEditorVimClass *klass)
                                         GB_EDITOR_VIM_COMMAND_FLAG_NONE,
                                         GB_EDITOR_VIM_COMMAND_CHANGE,
                                         gb_editor_vim_cmd_unindent);
+  gb_editor_vim_class_register_command (klass, '%',
+                                        GB_EDITOR_VIM_COMMAND_FLAG_NONE,
+                                        GB_EDITOR_VIM_COMMAND_JUMP,
+                                        gb_editor_vim_cmd_matching_bracket);
   gb_editor_vim_class_register_command (klass, 'A',
                                         GB_EDITOR_VIM_COMMAND_FLAG_NONE,
                                         GB_EDITOR_VIM_COMMAND_CHANGE,


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