[gnome-builder] emacs: Add select-region/cut/copy/paste commands
- From: Roberto Majadas <telemaco src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] emacs: Add select-region/cut/copy/paste commands
- Date: Sat, 14 Feb 2015 20:11:15 +0000 (UTC)
commit f6dd89031ad6dfa4ecb2da54d2ab333f9292f340
Author: Roberto Majadas <roberto majadas openshine com>
Date: Sat Feb 14 20:56:08 2015 +0100
emacs: Add select-region/cut/copy/paste commands
src/emacs/gb-source-emacs.c | 389 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 382 insertions(+), 7 deletions(-)
---
diff --git a/src/emacs/gb-source-emacs.c b/src/emacs/gb-source-emacs.c
index 1387037..9e5129e 100644
--- a/src/emacs/gb-source-emacs.c
+++ b/src/emacs/gb-source-emacs.c
@@ -36,8 +36,12 @@ struct _GbSourceEmacsPrivate
{
GtkTextView *text_view;
GString *cmd;
+ GtkTextMark *selection_begin;
+ GtkTextMark *selection_end;
+ gint selection_line_offset;
guint enabled : 1;
guint connected : 1;
+ guint select_region :1;
gulong key_press_event_handler;
gulong event_after_handler;
gulong key_release_event_handler;
@@ -116,6 +120,38 @@ gb_source_emacs_get_selection_bounds (GbSourceEmacs *emacs,
}
static void
+gb_source_emacs_clear_selection_data (GbSourceEmacs *emacs)
+{
+ GbSourceEmacsPrivate *priv = GB_SOURCE_EMACS (emacs)->priv;
+ GtkTextBuffer *buffer;
+ GtkTextIter end_iter;
+
+ buffer = gtk_text_view_get_buffer (priv->text_view);
+
+ if (priv->select_region == TRUE && priv->selection_begin != NULL && priv->selection_end != NULL)
+ {
+ gtk_text_buffer_get_iter_at_mark (buffer, &end_iter,
+ priv->selection_end);
+
+ gtk_text_buffer_select_range (buffer, &end_iter, &end_iter);
+ }
+
+ priv->select_region = FALSE;
+ priv->selection_line_offset = 0;
+ if (priv->selection_begin != NULL)
+ {
+ gtk_text_buffer_delete_mark(buffer, priv->selection_begin);
+ priv->selection_begin = NULL;
+ }
+
+ if (priv->selection_end != NULL)
+ {
+ gtk_text_buffer_delete_mark(buffer, priv->selection_end);
+ priv->selection_end = NULL;
+ }
+}
+
+static void
gb_source_emacs_delete_selection (GbSourceEmacs *emacs)
{
GtkTextBuffer *buffer;
@@ -179,6 +215,260 @@ gb_source_emacs_cmd_exit_from_command_line (GbSourceEmacs *emacs,
if (priv->cmd != NULL)
g_string_free(priv->cmd, TRUE);
priv->cmd = g_string_new(NULL);
+
+ gb_source_emacs_clear_selection_data(emacs);
+}
+
+static void
+gb_source_emacs_cmd_select_region (GbSourceEmacs *emacs,
+ GRegex *matcher,
+ GbSourceEmacsCommandFlags flags)
+{
+ GbSourceEmacsPrivate *priv = GB_SOURCE_EMACS (emacs)->priv;
+ GtkTextBuffer *buffer;
+ GtkTextIter iter;
+ GtkTextIter selection;
+ gboolean has_selection;
+
+ g_assert (GB_IS_SOURCE_EMACS (emacs));
+
+ priv->select_region = TRUE;
+
+ buffer = gtk_text_view_get_buffer (priv->text_view);
+
+ has_selection = gb_source_emacs_get_selection_bounds (emacs, &iter, &selection);
+ if (has_selection) {
+ gtk_text_buffer_select_range (buffer, &iter, &iter);
+ }
+
+ if (priv->selection_begin != NULL)
+ {
+ gtk_text_buffer_delete_mark(buffer, priv->selection_begin);
+ priv->selection_begin = NULL;
+ }
+
+ if (priv->selection_end != NULL)
+ {
+ gtk_text_buffer_delete_mark(buffer, priv->selection_end);
+ priv->selection_end = NULL;
+ }
+
+ priv->selection_begin = gtk_text_buffer_create_mark (buffer,
+ "selection-begin",
+ &iter,
+ TRUE);
+ priv->selection_end = gtk_text_buffer_create_mark (buffer,
+ "selection-end",
+ &iter,
+ TRUE);
+ priv->selection_line_offset = gtk_text_iter_get_visible_line_offset (&iter);
+}
+
+static void
+gb_source_emacs_cmd_cut (GbSourceEmacs *emacs,
+ GRegex *matcher,
+ GbSourceEmacsCommandFlags flags)
+{
+ GbSourceEmacsPrivate *priv = GB_SOURCE_EMACS (emacs)->priv;
+ GtkTextBuffer *buffer;
+ GtkTextIter begin;
+ GtkTextIter end;
+ gboolean has_selection;
+ GtkClipboard *clipboard;
+ gchar *text;
+
+ buffer = gtk_text_view_get_buffer (priv->text_view);
+ has_selection = gb_source_emacs_get_selection_bounds (emacs, &begin, &end);
+ if (has_selection) {
+ text = gtk_text_iter_get_slice (&begin, &end);
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (priv->text_view),
+ GDK_SELECTION_CLIPBOARD);
+ gtk_clipboard_set_text (clipboard, text, -1);
+ g_free (text);
+
+ gtk_text_buffer_begin_user_action (buffer);
+ gtk_text_buffer_delete (buffer, &begin, &end);
+ gb_source_emacs_clear_selection_data(emacs);
+ gtk_text_buffer_end_user_action (buffer);
+ }
+}
+
+static void
+gb_source_emacs_cmd_copy (GbSourceEmacs *emacs,
+ GRegex *matcher,
+ GbSourceEmacsCommandFlags flags)
+{
+ GbSourceEmacsPrivate *priv = GB_SOURCE_EMACS (emacs)->priv;
+ GtkTextBuffer *buffer;
+ GtkTextIter begin;
+ GtkTextIter end;
+ gboolean has_selection;
+ GtkClipboard *clipboard;
+ gchar *text;
+
+ buffer = gtk_text_view_get_buffer (priv->text_view);
+ has_selection = gb_source_emacs_get_selection_bounds (emacs, &begin, &end);
+ if (has_selection)
+ {
+ text = gtk_text_iter_get_slice (&begin, &end);
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (priv->text_view),
+ GDK_SELECTION_CLIPBOARD);
+ gtk_clipboard_set_text (clipboard, text, -1);
+ g_free (text);
+
+ if (priv->select_region == TRUE && priv->selection_end != NULL)
+ gtk_text_buffer_get_iter_at_mark (buffer, &end,
+ priv->selection_end);
+
+ gtk_text_buffer_select_range (buffer, &end, &end);
+ gb_source_emacs_clear_selection_data(emacs);
+ }
+}
+
+static void
+gb_source_emacs_cmd_yank (GbSourceEmacs *emacs,
+ GRegex *matcher,
+ GbSourceEmacsCommandFlags flags)
+{
+ GbSourceEmacsPrivate *priv = GB_SOURCE_EMACS (emacs)->priv;
+ g_signal_emit_by_name (priv->text_view, "paste-clipboard");
+}
+
+static void
+gb_source_emacs_cmd_select_region_go_up (GbSourceEmacs *emacs,
+ GRegex *matcher,
+ GbSourceEmacsCommandFlags flags)
+{
+ GbSourceEmacsPrivate *priv = GB_SOURCE_EMACS (emacs)->priv;
+ GtkTextBuffer *buffer;
+ GtkTextIter begin_iter;
+ GtkTextIter end_iter;
+ gint current_line;
+
+ if (priv->select_region == FALSE || priv->selection_begin == NULL || priv->selection_end == NULL)
+ return;
+
+ buffer = gtk_text_view_get_buffer (priv->text_view);
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &begin_iter,
+ priv->selection_begin);
+ gtk_text_buffer_get_iter_at_mark (buffer, &end_iter,
+ priv->selection_end);
+
+ current_line = gtk_text_iter_get_line (&end_iter);
+
+ if (current_line == 0)
+ return;
+
+ gtk_text_iter_backward_line (&end_iter);
+ gtk_text_iter_forward_to_line_end (&end_iter);
+
+ if (current_line == gtk_text_iter_get_line (&end_iter))
+ // Empty line fix position
+ gtk_text_iter_backward_line (&end_iter);
+ else
+ while (priv->selection_line_offset < gtk_text_iter_get_visible_line_offset (&end_iter))
+ gtk_text_iter_backward_char (&end_iter);
+
+ gtk_text_buffer_move_mark (buffer, priv->selection_end, &end_iter);
+ gtk_text_buffer_select_range (buffer, &begin_iter, &end_iter);
+}
+
+static void
+gb_source_emacs_cmd_select_region_go_down (GbSourceEmacs *emacs,
+ GRegex *matcher,
+ GbSourceEmacsCommandFlags flags)
+{
+ GbSourceEmacsPrivate *priv = GB_SOURCE_EMACS (emacs)->priv;
+ GtkTextBuffer *buffer;
+ GtkTextIter begin_iter;
+ GtkTextIter end_iter;
+ gint current_line;
+ gint lines_number;
+
+ if (priv->select_region == FALSE || priv->selection_begin == NULL || priv->selection_end == NULL)
+ return;
+
+ buffer = gtk_text_view_get_buffer (priv->text_view);
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &begin_iter,
+ priv->selection_begin);
+ gtk_text_buffer_get_iter_at_mark (buffer, &end_iter,
+ priv->selection_end);
+
+
+ lines_number = gtk_text_buffer_get_line_count (buffer);
+ current_line = gtk_text_iter_get_line (&end_iter);
+
+ if (lines_number == current_line + 1)
+ return;
+
+ gtk_text_iter_forward_line (&end_iter);
+ gtk_text_iter_forward_to_line_end (&end_iter);
+
+ if (current_line + 2 == gtk_text_iter_get_line (&end_iter))
+ // Empty line fix position
+ gtk_text_iter_backward_line (&end_iter);
+ else
+ while (priv->selection_line_offset < gtk_text_iter_get_visible_line_offset (&end_iter))
+ gtk_text_iter_backward_char (&end_iter);
+
+ gtk_text_buffer_move_mark (buffer, priv->selection_end, &end_iter);
+ gtk_text_buffer_select_range (buffer, &begin_iter, &end_iter);
+}
+
+static void
+gb_source_emacs_cmd_select_region_go_left (GbSourceEmacs *emacs,
+ GRegex *matcher,
+ GbSourceEmacsCommandFlags flags)
+{
+ GbSourceEmacsPrivate *priv = GB_SOURCE_EMACS (emacs)->priv;
+ GtkTextBuffer *buffer;
+ GtkTextIter begin_iter;
+ GtkTextIter end_iter;
+
+ if (priv->select_region == FALSE || priv->selection_begin == NULL || priv->selection_end == NULL)
+ return;
+
+ buffer = gtk_text_view_get_buffer (priv->text_view);
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &begin_iter,
+ priv->selection_begin);
+ gtk_text_buffer_get_iter_at_mark (buffer, &end_iter,
+ priv->selection_end);
+
+ gtk_text_iter_backward_char(&end_iter);
+ gtk_text_buffer_move_mark (buffer, priv->selection_end, &end_iter);
+ gtk_text_buffer_select_range (buffer, &begin_iter, &end_iter);
+
+ priv->selection_line_offset = gtk_text_iter_get_visible_line_offset (&end_iter);
+}
+
+static void
+gb_source_emacs_cmd_select_region_go_right (GbSourceEmacs *emacs,
+ GRegex *matcher,
+ GbSourceEmacsCommandFlags flags)
+{
+ GbSourceEmacsPrivate *priv = GB_SOURCE_EMACS (emacs)->priv;
+ GtkTextBuffer *buffer;
+ GtkTextIter begin_iter;
+ GtkTextIter end_iter;
+
+ if (priv->select_region == FALSE || priv->selection_begin == NULL || priv->selection_end == NULL)
+ return;
+
+ buffer = gtk_text_view_get_buffer (priv->text_view);
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &begin_iter,
+ priv->selection_begin);
+ gtk_text_buffer_get_iter_at_mark (buffer, &end_iter,
+ priv->selection_end);
+
+ gtk_text_iter_forward_char(&end_iter);
+ gtk_text_buffer_move_mark (buffer, priv->selection_end, &end_iter);
+ gtk_text_buffer_select_range (buffer, &begin_iter, &end_iter);
+
+ priv->selection_line_offset = gtk_text_iter_get_visible_line_offset (&end_iter);
}
static void
@@ -560,7 +850,6 @@ gb_source_emacs_eval_cmd (GbSourceEmacs *emacs)
if (g_match_info_matches(match_info))
{
cmd->func (emacs, cmd->matcher, cmd->flags);
- g_message("evaluate command: %s", priv->cmd->str);
g_match_info_free (match_info);
if (priv->cmd != NULL)
g_string_free(priv->cmd, TRUE);
@@ -573,6 +862,34 @@ gb_source_emacs_eval_cmd (GbSourceEmacs *emacs)
}
static void
+gb_source_emacs_check_select_region (GbSourceEmacs *emacs) {
+ GbSourceEmacsPrivate *priv = GB_SOURCE_EMACS (emacs)->priv;
+ GtkTextBuffer *buffer;
+ GtkTextIter selected_begin_iter;
+ GtkTextIter selected_end_iter;
+ GtkTextIter real_begin_iter;
+ GtkTextIter real_end_iter;
+
+ if (priv->select_region == FALSE || priv->selection_begin == NULL || priv->selection_end == NULL)
+ return;
+
+ buffer = gtk_text_view_get_buffer (priv->text_view);
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &selected_begin_iter,
+ priv->selection_begin);
+ gtk_text_buffer_get_iter_at_mark (buffer, &selected_end_iter,
+ priv->selection_end);
+
+ gb_source_emacs_get_selection_bounds (emacs, &real_begin_iter, &real_end_iter);
+
+ if (gtk_text_iter_compare(&selected_begin_iter, &real_begin_iter) != 0 &&
+ gtk_text_iter_compare(&selected_end_iter, &real_end_iter) != 0)
+ {
+ gb_source_emacs_clear_selection_data(emacs);
+ }
+}
+
+static void
gb_source_emacs_event_after_cb (GtkTextView *text_view,
GdkEventKey *event,
GbSourceEmacs *emacs)
@@ -592,9 +909,18 @@ gb_source_emacs_key_press_event_cb (GtkTextView *text_view,
g_return_val_if_fail (event, FALSE);
g_return_val_if_fail (GB_IS_SOURCE_EMACS (emacs), FALSE);
+ gb_source_emacs_check_select_region(emacs);
+
+ if (priv->select_region == TRUE && event->keyval >= GDK_KEY_Left && event->keyval <= GDK_KEY_Down)
+ {
+ g_string_append_printf(priv->cmd, "%s", gdk_keyval_name(event->keyval));
+ eval_cmd = TRUE;
+ }
+
if ((event->keyval >= GDK_KEY_A && event->keyval <= GDK_KEY_Z) ||
(event->keyval >= GDK_KEY_a && event->keyval <= GDK_KEY_z) ||
- (event->keyval == GDK_KEY_underscore) || (event->keyval == GDK_KEY_Escape )
+ (event->keyval == GDK_KEY_underscore) || (event->keyval == GDK_KEY_Escape ) ||
+ (event->keyval == GDK_KEY_space)
)
{
if (event->keyval == GDK_KEY_Escape)
@@ -650,10 +976,7 @@ gb_source_emacs_key_press_event_cb (GtkTextView *text_view,
}
if (eval_cmd)
- {
- g_message ("cmd line: %s", priv->cmd->str);
- return gb_source_emacs_eval_cmd(emacs);
- }
+ return gb_source_emacs_eval_cmd(emacs);
return FALSE;
}
@@ -847,9 +1170,25 @@ gb_source_emacs_set_property (GObject *object,
static void
gb_source_emacs_finalize (GObject *object)
{
- GbSourceEmacsPrivate *priv = GB_SOURCE_EMACS (object)->priv;
+ GbSourceEmacsPrivate *priv = GB_SOURCE_EMACS (object)->priv;
+ GtkTextBuffer *buffer;
+
if (priv->text_view)
{
+ buffer = gtk_text_view_get_buffer (priv->text_view);
+
+ if (priv->selection_begin != NULL)
+ {
+ gtk_text_buffer_delete_mark(buffer, priv->selection_begin);
+ priv->selection_begin = NULL;
+ }
+
+ if (priv->selection_end != NULL)
+ {
+ gtk_text_buffer_delete_mark(buffer, priv->selection_end);
+ priv->selection_end = NULL;
+ }
+
gb_source_emacs_disconnect (GB_SOURCE_EMACS (object));
g_object_remove_weak_pointer (G_OBJECT (priv->text_view),
(gpointer *)&priv->text_view);
@@ -921,6 +1260,38 @@ gb_source_emacs_class_init (GbSourceEmacsClass *klass)
GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
gb_source_emacs_cmd_exit_from_command_line);
gb_source_emacs_class_register_command (klass,
+ g_regex_new("^C-space$", 0, 0, NULL),
+ GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
+ gb_source_emacs_cmd_select_region);
+ gb_source_emacs_class_register_command (klass,
+ g_regex_new("^C-w$", 0, 0, NULL),
+ GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
+ gb_source_emacs_cmd_cut);
+ gb_source_emacs_class_register_command (klass,
+ g_regex_new("^M-w$", 0, 0, NULL),
+ GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
+ gb_source_emacs_cmd_copy);
+ gb_source_emacs_class_register_command (klass,
+ g_regex_new("^C-y$", 0, 0, NULL),
+ GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
+ gb_source_emacs_cmd_yank);
+ gb_source_emacs_class_register_command (klass,
+ g_regex_new("^Up$", 0, 0, NULL),
+ GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
+ gb_source_emacs_cmd_select_region_go_up);
+ gb_source_emacs_class_register_command (klass,
+ g_regex_new("^Down$", 0, 0, NULL),
+ GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
+ gb_source_emacs_cmd_select_region_go_down);
+ gb_source_emacs_class_register_command (klass,
+ g_regex_new("^Left$", 0, 0, NULL),
+ GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
+ gb_source_emacs_cmd_select_region_go_left);
+ gb_source_emacs_class_register_command (klass,
+ g_regex_new("^Right$", 0, 0, NULL),
+ GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
+ gb_source_emacs_cmd_select_region_go_right);
+ gb_source_emacs_class_register_command (klass,
g_regex_new("^C-x C-c$", 0, 0, NULL),
GB_SOURCE_EMACS_COMMAND_FLAG_NONE,
gb_source_emacs_cmd_exit);
@@ -984,6 +1355,10 @@ gb_source_emacs_init (GbSourceEmacs *emacs)
{
emacs->priv = gb_source_emacs_get_instance_private (emacs);
emacs->priv->enabled = FALSE;
+ emacs->priv->select_region = FALSE;
+ emacs->priv->selection_begin = NULL;
+ emacs->priv->selection_end = NULL;
+ emacs->priv->selection_line_offset = 0;
emacs->priv->cmd = g_string_new(NULL);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]