[gnome-builder/wip/libide-merge] restore vim style command bar
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/libide-merge] restore vim style command bar
- Date: Fri, 20 Mar 2015 08:40:26 +0000 (UTC)
commit 8cb558c5de4ee6a60cc19616b40f7f5959d88ff3
Author: Christian Hergert <christian hergert me>
Date: Fri Mar 20 01:40:14 2015 -0700
restore vim style command bar
src/commands/gb-command-vim-provider.c | 123 ++-----
src/commands/gb-command-vim-provider.h | 29 +--
src/commands/gb-command-vim.c | 42 +--
src/gnome-builder.mk | 11 +-
src/vim/gb-vim.c | 632 ++++++++++++++++++++++++++++++++
src/vim/gb-vim.h | 47 +++
src/workbench/gb-workbench.c | 7 +-
7 files changed, 734 insertions(+), 157 deletions(-)
---
diff --git a/src/commands/gb-command-vim-provider.c b/src/commands/gb-command-vim-provider.c
index 67d0a4f..b34c452 100644
--- a/src/commands/gb-command-vim-provider.c
+++ b/src/commands/gb-command-vim-provider.c
@@ -16,56 +16,37 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#define G_LOG_DOMAIN "vim-command-provider"
+#define G_LOG_DOMAIN "gb-vim-command-provider"
-#if 0
+#include <ide.h>
-#include "gb-editor-view.h"
-#include "gb-editor-frame-private.h"
#include "gb-command-vim.h"
#include "gb-command-vim-provider.h"
-#include "gb-source-view.h"
-#include "gb-source-vim.h"
+#include "gb-editor-frame.h"
+#include "gb-editor-frame-private.h"
+#include "gb-editor-view.h"
+#include "gb-editor-view-private.h"
+#include "gb-vim.h"
#include "gb-workbench.h"
-#include "trie.h"
-struct _GbCommandVimProviderPrivate
+struct _GbCommandVimProvider
{
- Trie *trie;
+ GbCommandProvider parent_instance;
};
-G_DEFINE_TYPE_WITH_PRIVATE (GbCommandVimProvider, gb_command_vim_provider,
- GB_TYPE_COMMAND_PROVIDER)
-
-GbCommandProvider *
-gb_command_vim_provider_new (GbWorkbench *workbench)
-{
- return g_object_new (GB_TYPE_COMMAND_VIM_PROVIDER,
- "workbench", workbench,
- NULL);
-}
+G_DEFINE_TYPE (GbCommandVimProvider, gb_command_vim_provider, GB_TYPE_COMMAND_PROVIDER)
static GbCommand *
gb_command_vim_provider_lookup (GbCommandProvider *provider,
const gchar *command_text)
{
+ IdeSourceView *source_view;
GbWorkbench *workbench;
- GSettings *settings;
- GbDocumentView *active_view;
- GbEditorFrame *frame;
+ GbView *active_view;
g_return_val_if_fail (GB_IS_COMMAND_VIM_PROVIDER (provider), NULL);
g_return_val_if_fail (command_text, NULL);
- /* Fetch our editor gsettings */
- settings = g_object_get_data (G_OBJECT (provider), "editor-settings");
- if (!G_IS_SETTINGS (settings))
- return NULL;
-
- /* Make sure vim-mode is enabled */
- if (!g_settings_get_boolean (settings, "vim-mode"))
- return NULL;
-
/* Make sure we have a workbench */
workbench = gb_command_provider_get_workbench (provider);
if (!GB_IS_WORKBENCH (workbench))
@@ -77,29 +58,14 @@ gb_command_vim_provider_lookup (GbCommandProvider *provider,
return NULL;
/* TODO: Perhaps get the last focused frame? */
- frame = gb_editor_view_get_frame1 (GB_EDITOR_VIEW (active_view));
- if (!GB_IS_EDITOR_FRAME (frame))
+ source_view = GB_EDITOR_VIEW (active_view)->frame1->source_view;
+ if (!IDE_IS_SOURCE_VIEW (source_view))
return NULL;
- /* See if GbEditorVim recognizes this command */
- if (gb_source_vim_is_command (command_text))
- return g_object_new (GB_TYPE_COMMAND_VIM,
- "command-text", command_text,
- "source-view", frame->priv->source_view,
- NULL);
-
- return NULL;
-}
-
-static gboolean
-traverse_func (Trie *trie,
- const gchar *key,
- gpointer value,
- gpointer user_data)
-{
- GPtrArray *ar = user_data;
- g_ptr_array_add (ar, g_strdup (key));
- return FALSE;
+ return g_object_new (GB_TYPE_COMMAND_VIM,
+ "command-text", command_text,
+ "source-view", source_view,
+ NULL);
}
static void
@@ -107,39 +73,23 @@ gb_command_vim_provider_complete (GbCommandProvider *provider,
GPtrArray *completions,
const gchar *initial_command_text)
{
- GbCommandVimProvider *self = (GbCommandVimProvider *)provider;
+ gchar **results;
+ gsize i;
g_return_if_fail (GB_IS_COMMAND_VIM_PROVIDER (provider));
g_return_if_fail (completions);
g_return_if_fail (initial_command_text);
- trie_traverse (self->priv->trie,
- initial_command_text,
- G_PRE_ORDER,
- G_TRAVERSE_LEAVES,
- -1,
- traverse_func,
- completions);
-}
-
-static void
-gb_command_vim_provider_finalize (GObject *object)
-{
- GbCommandVimProvider *provider = (GbCommandVimProvider *)object;
-
- trie_destroy (provider->priv->trie);
- provider->priv->trie = NULL;
-
- G_OBJECT_CLASS (gb_command_vim_provider_parent_class)->finalize (object);
+ results = gb_vim_complete (initial_command_text);
+ for (i = 0; results [i]; i++)
+ g_ptr_array_add (completions, results [i]);
+ g_free (results);
}
static void
gb_command_vim_provider_class_init (GbCommandVimProviderClass *klass)
{
GbCommandProviderClass *provider_class = GB_COMMAND_PROVIDER_CLASS (klass);
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = gb_command_vim_provider_finalize;
provider_class->lookup = gb_command_vim_provider_lookup;
provider_class->complete = gb_command_vim_provider_complete;
@@ -148,29 +98,4 @@ gb_command_vim_provider_class_init (GbCommandVimProviderClass *klass)
static void
gb_command_vim_provider_init (GbCommandVimProvider *self)
{
- static const gchar *commands[] = {
- "colorscheme ",
- "edit",
- "nohl",
- "set ",
- "sort",
- "split",
- "syntax ",
- "vsplit",
- NULL
- };
- GSettings *settings;
- guint i;
-
- self->priv = gb_command_vim_provider_get_instance_private (self);
-
- self->priv->trie = trie_new (NULL);
- for (i = 0; commands [i]; i++)
- trie_insert (self->priv->trie, commands [i], (gchar *)commands [i]);
-
- settings = g_settings_new ("org.gnome.builder.editor");
- g_object_set_data_full (G_OBJECT (self), "editor-settings", settings,
- g_object_unref);
}
-
-#endif
diff --git a/src/commands/gb-command-vim-provider.h b/src/commands/gb-command-vim-provider.h
index 994f987..5e4dffe 100644
--- a/src/commands/gb-command-vim-provider.h
+++ b/src/commands/gb-command-vim-provider.h
@@ -23,33 +23,10 @@
G_BEGIN_DECLS
-#define GB_TYPE_COMMAND_VIM_PROVIDER (gb_command_vim_provider_get_type())
-#define GB_COMMAND_VIM_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GB_TYPE_COMMAND_VIM_PROVIDER, GbCommandVimProvider))
-#define GB_COMMAND_VIM_PROVIDER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GB_TYPE_COMMAND_VIM_PROVIDER, GbCommandVimProvider const))
-#define GB_COMMAND_VIM_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),
GB_TYPE_COMMAND_VIM_PROVIDER, GbCommandVimProviderClass))
-#define GB_IS_COMMAND_VIM_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
GB_TYPE_COMMAND_VIM_PROVIDER))
-#define GB_IS_COMMAND_VIM_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
GB_TYPE_COMMAND_VIM_PROVIDER))
-#define GB_COMMAND_VIM_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
GB_TYPE_COMMAND_VIM_PROVIDER, GbCommandVimProviderClass))
+#define GB_TYPE_COMMAND_VIM_PROVIDER (gb_command_vim_provider_get_type())
-typedef struct _GbCommandVimProvider GbCommandVimProvider;
-typedef struct _GbCommandVimProviderClass GbCommandVimProviderClass;
-typedef struct _GbCommandVimProviderPrivate GbCommandVimProviderPrivate;
-
-struct _GbCommandVimProvider
-{
- GbCommandProvider parent;
-
- /*< private >*/
- GbCommandVimProviderPrivate *priv;
-};
-
-struct _GbCommandVimProviderClass
-{
- GbCommandProviderClass parent;
-};
-
-GType gb_command_vim_provider_get_type (void);
-GbCommandProvider *gb_command_vim_provider_new (GbWorkbench *workbench);
+G_DECLARE_FINAL_TYPE (GbCommandVimProvider, gb_command_vim_provider,
+ GB, COMMAND_VIM_PROVIDER, GbCommandProvider)
G_END_DECLS
diff --git a/src/commands/gb-command-vim.c b/src/commands/gb-command-vim.c
index 11c8d36..dbff795 100644
--- a/src/commands/gb-command-vim.c
+++ b/src/commands/gb-command-vim.c
@@ -20,6 +20,7 @@
#include <ide.h>
#include "gb-command-vim.h"
+#include "gb-vim.h"
struct _GbCommandVimPrivate
{
@@ -51,26 +52,10 @@ gb_command_vim_set_source_view (GbCommandVim *vim,
IdeSourceView *source_view)
{
g_return_if_fail (GB_IS_COMMAND_VIM (vim));
- g_return_if_fail (!source_view || IDE_IS_SOURCE_VIEW (source_view));
+ g_return_if_fail (IDE_IS_SOURCE_VIEW (source_view));
- if (source_view != vim->priv->source_view)
- {
- if (vim->priv->source_view)
- {
- g_object_remove_weak_pointer (G_OBJECT (vim->priv->source_view),
- (gpointer *)&vim->priv->source_view);
- vim->priv->source_view = NULL;
- }
-
- if (source_view)
- {
- vim->priv->source_view = source_view;
- g_object_add_weak_pointer (G_OBJECT (vim->priv->source_view),
- (gpointer *)&vim->priv->source_view);
- }
-
- g_object_notify_by_pspec (G_OBJECT (vim), gParamSpecs [PROP_SOURCE_VIEW]);
- }
+ if (ide_set_weak_pointer (&vim->priv->source_view, source_view))
+ g_object_notify_by_pspec (G_OBJECT (vim), gParamSpecs [PROP_SOURCE_VIEW]);
}
const gchar *
@@ -92,8 +77,7 @@ gb_command_vim_set_command_text (GbCommandVim *vim,
{
g_free (vim->priv->command_text);
vim->priv->command_text = g_strdup (command_text);
- g_object_notify_by_pspec (G_OBJECT (vim),
- gParamSpecs [PROP_COMMAND_TEXT]);
+ g_object_notify_by_pspec (G_OBJECT (vim), gParamSpecs [PROP_COMMAND_TEXT]);
}
}
@@ -106,12 +90,16 @@ gb_command_vim_execute (GbCommand *command)
if (self->priv->source_view)
{
-#if 0
- GbSourceVim *vim;
+ GtkSourceView *source_view = (GtkSourceView *)self->priv->source_view;
+ GError *error = NULL;
+
+ IDE_TRACE_MSG ("Executing Vim command: %s", self->priv->command_text);
- vim = gb_source_view_get_vim (self->priv->source_view);
- gb_source_vim_execute_command (vim, self->priv->command_text);
-#endif
+ if (!gb_vim_execute (source_view, self->priv->command_text, &error))
+ {
+ g_warning ("%s", error->message);
+ g_clear_error (&error);
+ }
}
return NULL;
@@ -122,7 +110,7 @@ gb_command_vim_finalize (GObject *object)
{
GbCommandVimPrivate *priv = GB_COMMAND_VIM (object)->priv;
- gb_command_vim_set_source_view (GB_COMMAND_VIM (object), NULL);
+ ide_clear_weak_pointer (&priv->source_view);
g_clear_pointer (&priv->command_text, g_free);
G_OBJECT_CLASS (gb_command_vim_parent_class)->finalize (object);
diff --git a/src/gnome-builder.mk b/src/gnome-builder.mk
index 73167b2..2803774 100644
--- a/src/gnome-builder.mk
+++ b/src/gnome-builder.mk
@@ -24,6 +24,10 @@ libgnome_builder_la_SOURCES = \
src/commands/gb-command-provider.h \
src/commands/gb-command-result.c \
src/commands/gb-command-result.h \
+ src/commands/gb-command-vim-provider.c \
+ src/commands/gb-command-vim-provider.h \
+ src/commands/gb-command-vim.c \
+ src/commands/gb-command-vim.h \
src/commands/gb-command.c \
src/commands/gb-command.h \
src/documents/gb-document.c \
@@ -122,6 +126,8 @@ libgnome_builder_la_SOURCES = \
src/views/gb-view-stack.h \
src/views/gb-view.c \
src/views/gb-view.h \
+ src/vim/gb-vim.c \
+ src/vim/gb-vim.h \
src/workbench/gb-workbench-actions.c \
src/workbench/gb-workbench-actions.h \
src/workbench/gb-workbench-private.h \
@@ -133,10 +139,6 @@ libgnome_builder_la_SOURCES = \
$(NULL)
disabled_files = \
- src/commands/gb-command-vim-provider.c \
- src/commands/gb-command-vim-provider.h \
- src/commands/gb-command-vim.c \
- src/commands/gb-command-vim.h \
src/devhelp/gb-devhelp-document.c \
src/devhelp/gb-devhelp-document.h \
src/devhelp/gb-devhelp-view.c \
@@ -181,6 +183,7 @@ libgnome_builder_la_CFLAGS = \
-I$(top_srcdir)/src/tree \
-I$(top_srcdir)/src/util \
-I$(top_srcdir)/src/views \
+ -I$(top_srcdir)/src/vim \
-I$(top_srcdir)/src/workbench
if ENABLE_TRACING
diff --git a/src/vim/gb-vim.c b/src/vim/gb-vim.c
new file mode 100644
index 0000000..2c51c64
--- /dev/null
+++ b/src/vim/gb-vim.c
@@ -0,0 +1,632 @@
+/* gb-vim.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <glib/gi18n.h>
+#include <ide.h>
+
+#include "gb-vim.h"
+
+G_DEFINE_QUARK (gb-vim-error-quark, gb_vim_error)
+
+typedef gboolean (*GbVimSetFunc) (GtkSourceView *source_view,
+ const gchar *key,
+ const gchar *value,
+ GError **error);
+typedef gboolean (*GbVimCommandFunc) (GtkSourceView *source_view,
+ const gchar *command,
+ const gchar *options,
+ GError **error);
+
+typedef struct
+{
+ gchar *name;
+ GbVimSetFunc func;
+} GbVimSet;
+
+typedef struct
+{
+ gchar *name;
+ gchar *alias;
+} GbVimSetAlias;
+
+typedef struct
+{
+ gchar *name;
+ GbVimCommandFunc func;
+} GbVimCommand;
+
+static gboolean
+int32_parse (gint *value,
+ const gchar *str,
+ gint lower,
+ gint upper,
+ const gchar *param_name,
+ GError **error)
+{
+ gint64 v64;
+
+ g_assert (value);
+ g_assert (str);
+ g_assert_cmpint (lower, <=, upper);
+ g_assert (param_name);
+
+ v64 = g_ascii_strtoll (str, NULL, 10);
+
+ if (((v64 == G_MININT64) || (v64 == G_MAXINT64)) && (errno == ERANGE))
+ {
+ g_set_error (error,
+ GB_VIM_ERROR,
+ GB_VIM_ERROR_NOT_NUMBER,
+ _("Number required"));
+ return FALSE;
+ }
+
+ if ((v64 < lower) || (v64 > upper))
+ {
+ g_set_error (error,
+ GB_VIM_ERROR,
+ GB_VIM_ERROR_NUMBER_OUT_OF_RANGE,
+ _("%"G_GINT64_FORMAT" is invalid for %s"),
+ v64, param_name);
+ return FALSE;
+ }
+
+ *value = v64;
+
+ return TRUE;
+}
+
+static gboolean
+gb_vim_set_autoindent (GtkSourceView *source_view,
+ const gchar *key,
+ const gchar *value,
+ GError **error)
+{
+ g_object_set (source_view, "auto-indent", TRUE, NULL);
+ return TRUE;
+}
+
+
+static gboolean
+gb_vim_set_expandtab (GtkSourceView *source_view,
+ const gchar *key,
+ const gchar *value,
+ GError **error)
+{
+ g_object_set (source_view, "insert-spaces-instead-of-tabs", TRUE, NULL);
+ return TRUE;
+}
+
+static gboolean
+gb_vim_set_filetype (GtkSourceView *source_view,
+ const gchar *key,
+ const gchar *value,
+ GError **error)
+{
+ GtkSourceLanguageManager *manager;
+ GtkSourceLanguage *language;
+ GtkTextBuffer *buffer;
+
+ if (0 == g_strcmp0 (value, "cs"))
+ value = "c-sharp";
+ else if (0 == g_strcmp0 (value, "xhmtl"))
+ value = "html";
+ else if (0 == g_strcmp0 (value, "javascript"))
+ value = "js";
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view));
+ manager = gtk_source_language_manager_get_default ();
+ language = gtk_source_language_manager_get_language (manager, value);
+
+ if (language == NULL)
+ {
+ g_set_error (error,
+ GB_VIM_ERROR,
+ GB_VIM_ERROR_UNKNOWN_OPTION,
+ _("Cannot find language '%s'"),
+ value);
+ return FALSE;
+ }
+
+ g_object_set (buffer, "language", language, NULL);
+
+ return TRUE;
+}
+
+static gboolean
+gb_vim_set_noautoindent (GtkSourceView *source_view,
+ const gchar *key,
+ const gchar *value,
+ GError **error)
+{
+ g_object_set (source_view, "auto-indent", FALSE, NULL);
+ return TRUE;
+}
+
+static gboolean
+gb_vim_set_noexpandtab (GtkSourceView *source_view,
+ const gchar *key,
+ const gchar *value,
+ GError **error)
+{
+ g_object_set (source_view, "insert-spaces-instead-of-tabs", FALSE, NULL);
+ return TRUE;
+}
+
+static gboolean
+gb_vim_set_nonumber (GtkSourceView *source_view,
+ const gchar *key,
+ const gchar *value,
+ GError **error)
+{
+ g_print ("disablign line numbers\n");
+ g_object_set (source_view, "show-line-numbers", FALSE, NULL);
+ return TRUE;
+}
+
+static gboolean
+gb_vim_set_number (GtkSourceView *source_view,
+ const gchar *key,
+ const gchar *value,
+ GError **error)
+{
+ g_object_set (source_view, "show-line-numbers", TRUE, NULL);
+ return TRUE;
+}
+
+static gboolean
+gb_vim_set_scrolloff (GtkSourceView *source_view,
+ const gchar *key,
+ const gchar *value,
+ GError **error)
+{
+ gint scroll_offset = 0;
+
+ if (!int32_parse (&scroll_offset, value, 0, G_MAXINT32, "scroll size", error))
+ return FALSE;
+ if (IDE_IS_SOURCE_VIEW (source_view))
+ g_object_set (source_view, "scroll-offset", scroll_offset, NULL);
+ return TRUE;
+}
+
+static gboolean
+gb_vim_set_shiftwidth (GtkSourceView *source_view,
+ const gchar *key,
+ const gchar *value,
+ GError **error)
+{
+ gint shiftwidth = 0;
+
+ if (!int32_parse (&shiftwidth, value, 0, G_MAXINT32, "shift width", error))
+ return FALSE;
+
+ if (shiftwidth == 0)
+ shiftwidth = -1;
+
+ g_object_set (source_view, "indent-width", shiftwidth, NULL);
+ return TRUE;
+}
+
+static gboolean
+gb_vim_set_tabstop (GtkSourceView *source_view,
+ const gchar *key,
+ const gchar *value,
+ GError **error)
+{
+ gint tabstop = 0;
+
+ if (!int32_parse (&tabstop , value, 1, 32, "tab stop", error))
+ return FALSE;
+
+ g_object_set (source_view, "tab-width", tabstop, NULL);
+ return TRUE;
+}
+
+static const GbVimSet vim_sets [] = {
+ { "autoindent", gb_vim_set_autoindent },
+ { "expandtab", gb_vim_set_expandtab },
+ { "filetype", gb_vim_set_filetype },
+ { "noautoindent", gb_vim_set_noautoindent },
+ { "noexpandtab", gb_vim_set_noexpandtab },
+ { "nonumber", gb_vim_set_nonumber },
+ { "number", gb_vim_set_number },
+ { "scrolloff", gb_vim_set_scrolloff },
+ { "shiftwidth", gb_vim_set_shiftwidth },
+ { "tabstop", gb_vim_set_tabstop },
+ { NULL }
+};
+
+static const GbVimSetAlias vim_set_aliases[] = {
+ { "ai", "autoindent" },
+ { "et", "expandtab" },
+ { "ft", "filetype" },
+ { "noet", "noexpandtab" },
+ { "nu", "number" },
+ { "nonu", "nonumber" },
+ { "so", "scrolloff" },
+ { "sw", "shiftwidth" },
+ { "ts", "tabstop" },
+ { NULL }
+};
+
+static const GbVimSet *
+lookup_set (const gchar *key)
+{
+ gsize i;
+
+ g_assert (key);
+
+ for (i = 0; vim_set_aliases [i].name; i++)
+ {
+ if (g_str_equal (vim_set_aliases [i].name, key))
+ {
+ key = vim_set_aliases [i].alias;
+ break;
+ }
+ }
+
+ for (i = 0; vim_sets [i].name; i++)
+ {
+ if (g_str_equal (vim_sets [i].name, key))
+ return &vim_sets [i];
+ }
+
+ return NULL;
+}
+
+static gboolean
+gb_vim_command_set (GtkSourceView *source_view,
+ const gchar *command,
+ const gchar *options,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gchar **parts;
+ gsize i;
+
+ g_assert (GTK_SOURCE_IS_VIEW (source_view));
+ g_assert (command);
+ g_assert (options);
+
+ parts = g_strsplit (options, " ", 0);
+
+ if (parts [0] == NULL)
+ {
+ ret = TRUE;
+ goto cleanup;
+ }
+
+ for (i = 0; parts [i]; i++)
+ {
+ const GbVimSet *set;
+ const gchar *value = "";
+ gchar *key = parts [i];
+ gchar *tmp;
+
+ for (tmp = key; *tmp; tmp = g_utf8_next_char (tmp))
+ {
+ if (g_utf8_get_char (tmp) == '=')
+ {
+ *tmp = '\0';
+ value = ++tmp;
+ break;
+ }
+ }
+
+ set = lookup_set (key);
+
+ if (set == NULL)
+ {
+ g_set_error (error,
+ GB_VIM_ERROR,
+ GB_VIM_ERROR_UNKNOWN_OPTION,
+ _("Unknown option: %s"),
+ key);
+ goto cleanup;
+ }
+
+ if (!set->func (source_view, key, value, error))
+ goto cleanup;
+ }
+
+ ret = TRUE;
+
+cleanup:
+ g_strfreev (parts);
+
+ return ret;
+}
+
+static gboolean
+gb_vim_command_colorscheme (GtkSourceView *source_view,
+ const gchar *command,
+ const gchar *options,
+ GError **error)
+{
+ GtkSourceStyleSchemeManager *manager;
+ GtkSourceStyleScheme *style_scheme;
+ GtkTextBuffer *buffer;
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view));
+ manager = gtk_source_style_scheme_manager_get_default ();
+ style_scheme = gtk_source_style_scheme_manager_get_scheme (manager, options);
+
+ if (style_scheme == NULL)
+ {
+ g_set_error (error,
+ GB_VIM_ERROR,
+ GB_VIM_ERROR_UNKNOWN_OPTION,
+ _("Cannot find colorscheme '%s'"),
+ options);
+ return FALSE;
+ }
+
+ g_object_set (buffer, "style-scheme", style_scheme, NULL);
+
+ return TRUE;
+}
+
+static gboolean
+gb_vim_command_edit (GtkSourceView *source_view,
+ const gchar *command,
+ const gchar *options,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+gb_vim_command_quit (GtkSourceView *source_view,
+ const gchar *command,
+ const gchar *options,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+gb_vim_command_split (GtkSourceView *source_view,
+ const gchar *command,
+ const gchar *options,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+gb_vim_command_vsplit (GtkSourceView *source_view,
+ const gchar *command,
+ const gchar *options,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+gb_vim_command_write (GtkSourceView *source_view,
+ const gchar *command,
+ const gchar *options,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+gb_vim_command_wq (GtkSourceView *source_view,
+ const gchar *command,
+ const gchar *options,
+ GError **error)
+{
+ return (gb_vim_command_write (source_view, command, options, error) &&
+ gb_vim_command_quit (source_view, command, options, error));
+}
+
+static gboolean
+gb_vim_command_syntax (GtkSourceView *source_view,
+ const gchar *command,
+ const gchar *options,
+ GError **error)
+{
+ if (g_str_equal (options, "enable") || g_str_equal (options, "on"))
+ g_object_set (source_view, "highlight-syntax", TRUE, NULL);
+ else if (g_str_equal (options, "off"))
+ g_object_set (source_view, "highlight-syntax", FALSE, NULL);
+ else
+ {
+ g_set_error (error,
+ GB_VIM_ERROR,
+ GB_VIM_ERROR_UNKNOWN_OPTION,
+ _("Invalid :syntax subcommand : %s"),
+ options);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static const GbVimCommand vim_commands[] = {
+ { "colorscheme", gb_vim_command_colorscheme },
+ { "edit", gb_vim_command_edit },
+ { "quit", gb_vim_command_quit },
+ { "set", gb_vim_command_set },
+ //{ "sort", gb_vim_command_sort },
+ { "split", gb_vim_command_split },
+ { "syntax", gb_vim_command_syntax },
+ { "vsplit", gb_vim_command_vsplit },
+ { "w", gb_vim_command_write },
+ { "wq", gb_vim_command_wq },
+ { "write", gb_vim_command_write },
+ { NULL }
+};
+
+static const GbVimCommand *
+lookup_command (const gchar *name)
+{
+ gsize i;
+
+ g_assert (name);
+
+ for (i = 0; vim_commands [i].name; i++)
+ {
+ if (g_str_has_prefix (vim_commands [i].name, name))
+ return &vim_commands [i];
+ }
+
+ return NULL;
+}
+
+gboolean
+gb_vim_execute (GtkSourceView *source_view,
+ const gchar *line,
+ GError **error)
+{
+ GtkTextBuffer *buffer;
+ g_autofree gchar *name_slice = NULL;
+ const GbVimCommand *command;
+ const gchar *command_name = line;
+ const gchar *options;
+
+ g_return_val_if_fail (GTK_SOURCE_IS_VIEW (source_view), FALSE);
+ g_return_val_if_fail (line, FALSE);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view));
+
+ if (!GTK_SOURCE_IS_BUFFER (buffer))
+ {
+ g_set_error (error,
+ GB_VIM_ERROR,
+ GB_VIM_ERROR_NOT_SOURCE_VIEW,
+ _("vim mode requires GtkSourceView"));
+ return FALSE;
+ }
+
+ for (options = line; *options; options = g_utf8_next_char (options))
+ {
+ gunichar ch;
+
+ ch = g_utf8_get_char (options);
+
+ if (g_unichar_isspace (ch))
+ break;
+ }
+
+ if (g_unichar_isspace (g_utf8_get_char (options)))
+ {
+ command_name = name_slice = g_strndup (line, options - line);
+ options = g_utf8_next_char (options);
+ }
+
+ command = lookup_command (command_name);
+
+ if (command == NULL)
+ {
+ g_set_error (error,
+ GB_VIM_ERROR,
+ GB_VIM_ERROR_NOT_FOUND,
+ _("Not an editor command: %s"),
+ command_name);
+ return FALSE;
+ }
+
+ return command->func (source_view, command_name, options, error);
+}
+
+static gchar *
+joinv_and_add (gchar **parts,
+ gsize len,
+ const gchar *delim,
+ const gchar *str)
+{
+ GString *gstr;
+ gsize i;
+
+ gstr = g_string_new (parts [0]);
+ for (i = 1; i < len; i++)
+ g_string_append_printf (gstr, "%s%s", delim, parts [i]);
+ g_string_append_printf (gstr, "%s%s", delim, str);
+ return g_string_free (gstr, FALSE);
+}
+
+static void
+gb_vim_complete_set (const gchar *line,
+ GPtrArray *ar)
+{
+ const gchar *key;
+ gchar **parts;
+ guint len;
+ gsize i;
+
+ parts = g_strsplit (line, " ", 0);
+ len = g_strv_length (parts);
+
+ if (len < 2)
+ {
+ g_strfreev (parts);
+ return;
+ }
+
+ key = parts [len - 1];
+
+ for (i = 0; vim_sets [i].name; i++)
+ {
+ if (g_str_has_prefix (vim_sets [i].name, key))
+ g_ptr_array_add (ar, joinv_and_add (parts, len - 1, " ", vim_sets [i].name));
+ }
+
+ for (i = 0; vim_set_aliases [i].name; i++)
+ {
+ if (g_str_has_prefix (vim_set_aliases [i].name, key))
+ g_ptr_array_add (ar, joinv_and_add (parts, len - 1, " ", vim_set_aliases [i].name));
+ }
+
+ g_strfreev (parts);
+}
+
+static void
+gb_vim_complete_command (const gchar *line,
+ GPtrArray *ar)
+{
+ gsize i;
+
+ for (i = 0; vim_commands [i].name; i++)
+ {
+ if (g_str_has_prefix (vim_commands [i].name, line))
+ g_ptr_array_add (ar, g_strdup (vim_commands [i].name));
+ }
+}
+
+gchar **
+gb_vim_complete (const gchar *line)
+{
+ GPtrArray *ar;
+
+ ar = g_ptr_array_new ();
+
+ if (line != NULL)
+ {
+ if (g_str_has_prefix (line, "set "))
+ gb_vim_complete_set (line, ar);
+ else
+ gb_vim_complete_command (line, ar);
+ }
+
+ g_ptr_array_add (ar, NULL);
+
+ return (gchar **)g_ptr_array_free (ar, FALSE);
+}
diff --git a/src/vim/gb-vim.h b/src/vim/gb-vim.h
new file mode 100644
index 0000000..54d4678
--- /dev/null
+++ b/src/vim/gb-vim.h
@@ -0,0 +1,47 @@
+/* gb-vim.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GB_VIM_H
+#define GB_VIM_H
+
+#include <gtksourceview/gtksource.h>
+
+G_BEGIN_DECLS
+
+#define GB_VIM_ERROR (gb_vim_error_quark())
+
+typedef enum
+{
+ GB_VIM_ERROR_NOT_IMPLEMENTED,
+ GB_VIM_ERROR_NOT_FOUND,
+ GB_VIM_ERROR_NOT_NUMBER,
+ GB_VIM_ERROR_NUMBER_OUT_OF_RANGE,
+ GB_VIM_ERROR_CANNOT_FIND_COLORSCHEME,
+ GB_VIM_ERROR_UNKNOWN_OPTION,
+ GB_VIM_ERROR_NOT_SOURCE_VIEW,
+} IdeVimError;
+
+GQuark gb_vim_error_quark (void);
+gboolean gb_vim_execute (GtkSourceView *source_view,
+ const gchar *line,
+ GError **error);
+gchar **gb_vim_complete (const gchar *line);
+
+G_END_DECLS
+
+#endif /* GB_VIM_H */
diff --git a/src/workbench/gb-workbench.c b/src/workbench/gb-workbench.c
index 12fdfec..3a07b22 100644
--- a/src/workbench/gb-workbench.c
+++ b/src/workbench/gb-workbench.c
@@ -22,6 +22,7 @@
#include <ide.h>
#include "gb-command-gaction-provider.h"
+#include "gb-command-vim-provider.h"
#include "gb-dnd.h"
#include "gb-widget.h"
#include "gb-workbench-actions.h"
@@ -389,6 +390,7 @@ static void
gb_workbench_init (GbWorkbench *self)
{
g_autoptr(GbCommandProvider) gaction_provider = NULL;
+ g_autoptr(GbCommandProvider) vim_provider = NULL;
IDE_ENTRY;
@@ -399,8 +401,11 @@ gb_workbench_init (GbWorkbench *self)
gaction_provider = g_object_new (GB_TYPE_COMMAND_GACTION_PROVIDER,
"workbench", self,
NULL);
+ vim_provider = g_object_new (GB_TYPE_COMMAND_VIM_PROVIDER,
+ "workbench", self,
+ NULL);
gb_command_manager_add_provider (self->command_manager, gaction_provider);
-
+ gb_command_manager_add_provider (self->command_manager, vim_provider);
/* Drag and drop support*/
gtk_drag_dest_set (GTK_WIDGET (self),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]