[gnome-builder] emacs: Add move_(forward | backward)_word commands



commit 37691da7aa17808a1d3bacbe563b6e81f8e7e620
Author: Roberto Majadas <roberto majadas openshine com>
Date:   Sun Feb 8 15:51:38 2015 +0100

    emacs: Add move_(forward | backward)_word commands

 src/emacs/gb-source-emacs.c |  211 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 211 insertions(+), 0 deletions(-)
---
diff --git a/src/emacs/gb-source-emacs.c b/src/emacs/gb-source-emacs.c
index 53f38e4..a8e019a 100644
--- a/src/emacs/gb-source-emacs.c
+++ b/src/emacs/gb-source-emacs.c
@@ -47,6 +47,14 @@ enum
   LAST_PROP
 };
 
+enum
+{
+  CLASS_0,
+  CLASS_SPACE,
+  CLASS_SPECIAL,
+  CLASS_WORD,
+};
+
 typedef enum
 {
   GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
@@ -280,6 +288,201 @@ gb_source_emacs_cmd_delete_forward_char (GbSourceEmacs           *emacs,
   gb_source_emacs_delete_selection (emacs);
 }
 
+static int
+gb_source_emacs_classify (gunichar ch)
+{
+  switch (ch)
+    {
+    case ' ':
+    case '\t':
+    case '\n':
+      return CLASS_SPACE;
+
+    case '"': case '\'':
+    case '(': case ')':
+    case '{': case '}':
+    case '[': case ']':
+    case '<': case '>':
+    case '-': case '+': case '*': case '/':
+    case '!': case '@': case '#': case '$': case '%':
+    case '^': case '&': case ':': case ';': case '?':
+    case '|': case '=': case '\\': case '.': case ',':
+    case '_':
+      return CLASS_SPECIAL;
+
+    default:
+      return CLASS_WORD;
+    }
+}
+
+static gboolean
+text_iter_forward_emacs_word (GtkTextIter *iter)
+{
+  gint begin_class;
+  gint cur_class;
+  gunichar ch;
+
+  g_assert (iter);
+
+  ch = gtk_text_iter_get_char (iter);
+  begin_class = gb_source_emacs_classify (ch);
+
+  /* Move to the first non-whitespace character if necessary. */
+  if (begin_class == CLASS_SPACE)
+    {
+      for (;;)
+        {
+          if (!gtk_text_iter_forward_char (iter))
+            return FALSE;
+
+          ch = gtk_text_iter_get_char (iter);
+          cur_class = gb_source_emacs_classify (ch);
+          if (cur_class != CLASS_SPACE)
+            return TRUE;
+        }
+    }
+
+  /* move to first character not at same class level. */
+  while (gtk_text_iter_forward_char (iter))
+    {
+      ch = gtk_text_iter_get_char (iter);
+      cur_class = gb_source_emacs_classify (ch);
+
+      if (cur_class == CLASS_SPACE)
+        {
+          begin_class = CLASS_0;
+          continue;
+        }
+
+      if (cur_class != begin_class)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gboolean
+text_iter_backward_emacs_word (GtkTextIter *iter)
+{
+  gunichar ch;
+  gint begin_class;
+  gint cur_class;
+
+  g_assert (iter);
+
+  if (!gtk_text_iter_backward_char (iter))
+    return FALSE;
+
+  /*
+   * If we are on space, walk until we get to non-whitespace. Then work our way
+   * back to the beginning of the word.
+   */
+  ch = gtk_text_iter_get_char (iter);
+  if (gb_source_emacs_classify (ch) == CLASS_SPACE)
+    {
+      for (;;)
+        {
+          if (!gtk_text_iter_backward_char (iter))
+            return FALSE;
+
+          ch = gtk_text_iter_get_char (iter);
+          if (gb_source_emacs_classify (ch) != CLASS_SPACE)
+            break;
+        }
+
+      ch = gtk_text_iter_get_char (iter);
+      begin_class = gb_source_emacs_classify (ch);
+
+      for (;;)
+        {
+          if (!gtk_text_iter_backward_char (iter))
+            return FALSE;
+
+          ch = gtk_text_iter_get_char (iter);
+          cur_class = gb_source_emacs_classify (ch);
+
+          if (cur_class != begin_class)
+            {
+              gtk_text_iter_forward_char (iter);
+              return TRUE;
+            }
+        }
+
+      return FALSE;
+    }
+
+  ch = gtk_text_iter_get_char (iter);
+  begin_class = gb_source_emacs_classify (ch);
+
+  for (;;)
+    {
+      if (!gtk_text_iter_backward_char (iter))
+        return FALSE;
+
+      ch = gtk_text_iter_get_char (iter);
+      cur_class = gb_source_emacs_classify (ch);
+
+      if (cur_class != begin_class)
+        {
+          gtk_text_iter_forward_char (iter);
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+static void
+gb_source_emacs_cmd_move_forward_word (GbSourceEmacs           *emacs,
+                                       GRegex                  *matcher,
+                                       GbSourceEmacsCommandFlags flags)
+{
+  GtkTextBuffer *buffer;
+  GtkTextIter iter;
+  GtkTextIter selection;
+  gboolean has_selection;
+
+  g_assert (GB_IS_SOURCE_EMACS (emacs));
+
+  buffer = gtk_text_view_get_buffer (emacs->priv->text_view);
+  if (!GTK_SOURCE_IS_BUFFER (buffer))
+    return;
+
+  buffer = gtk_text_view_get_buffer (emacs->priv->text_view);
+  has_selection = gb_source_emacs_get_selection_bounds (emacs, &iter, &selection);
+
+  if (!text_iter_forward_emacs_word (&iter))
+    gtk_text_buffer_get_end_iter (buffer, &iter);
+
+  gtk_text_buffer_select_range (buffer, &iter, &iter);
+
+}
+
+static void
+gb_source_emacs_cmd_move_backward_word  (GbSourceEmacs           *emacs,
+                                         GRegex                  *matcher,
+                                         GbSourceEmacsCommandFlags flags)
+{
+  GtkTextBuffer *buffer;
+  GtkTextIter iter;
+  GtkTextIter selection;
+  gboolean has_selection;
+
+  g_assert (GB_IS_SOURCE_EMACS (emacs));
+
+  buffer = gtk_text_view_get_buffer (emacs->priv->text_view);
+  if (!GTK_SOURCE_IS_BUFFER (buffer))
+    return;
+
+  buffer = gtk_text_view_get_buffer (emacs->priv->text_view);
+  has_selection = gb_source_emacs_get_selection_bounds (emacs, &iter, &selection);
+
+  if (!text_iter_backward_emacs_word (&iter))
+    gtk_text_buffer_get_start_iter (buffer, &iter);
+
+  gtk_text_buffer_select_range (buffer, &iter, &iter);
+}
+
 static gboolean
 gb_source_emacs_eval_cmd (GbSourceEmacs *emacs)
 {
@@ -666,6 +869,14 @@ gb_source_emacs_class_init (GbSourceEmacsClass *klass)
                                           g_regex_new("^C-d$", 0, 0, NULL),
                                           GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
                                           gb_source_emacs_cmd_delete_forward_char);
+  gb_source_emacs_class_register_command (klass,
+                                          g_regex_new("^M-f$", 0, 0, NULL),
+                                          GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
+                                          gb_source_emacs_cmd_move_forward_word);
+  gb_source_emacs_class_register_command (klass,
+                                          g_regex_new("^M-b$", 0, 0, NULL),
+                                          GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
+                                          gb_source_emacs_cmd_move_backward_word);
 
 }
 


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