[gnome-builder] file: add ide_file_find_other_async()



commit 15f241bc81ebf21f6365cf8a2162b56dde97e994
Author: Christian Hergert <christian hergert me>
Date:   Wed Apr 1 00:37:56 2015 -0700

    file: add ide_file_find_other_async()
    
    This async/finish pair will perform a "find-other-file" familiar to those
    with emacs. We need this in a few different places, so makes sense to push
    this into IdeFile.

 libide/ide-file.c |  139 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 libide/ide-file.h |    7 +++
 2 files changed, 146 insertions(+), 0 deletions(-)
---
diff --git a/libide/ide-file.c b/libide/ide-file.c
index 7ed3be2..a58841b 100644
--- a/libide/ide-file.c
+++ b/libide/ide-file.c
@@ -19,10 +19,12 @@
 #include <glib/gi18n.h>
 #include <gtksourceview/gtksource.h>
 
+#include "ide-context.h"
 #include "ide-debug.h"
 #include "ide-file.h"
 #include "ide-file-settings.h"
 #include "ide-language.h"
+#include "ide-vcs.h"
 
 struct _IdeFile
 {
@@ -510,3 +512,140 @@ static void
 ide_file_init (IdeFile *file)
 {
 }
+
+static gboolean
+has_suffix (const gchar          *path,
+            const gchar * const *allowed_suffixes)
+{
+  const gchar *dot;
+  gsize i;
+
+  dot = strrchr (path, '.');
+  if (!dot)
+    return FALSE;
+
+  dot++;
+
+  for (i = 0; allowed_suffixes [i]; i++)
+    {
+      if (g_str_equal (dot, allowed_suffixes [i]))
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+ide_file_find_other_worker (GTask        *task,
+                            gpointer      source_object,
+                            gpointer      task_data,
+                            GCancellable *cancellable)
+{
+  IdeFile *self = source_object;
+  const gchar *src_suffixes[] = { "c", "cc", "cpp", "cxx", NULL };
+  const gchar *hdr_suffixes[] = { "h", "hh", "hpp", "hxx", NULL };
+  const gchar **target = NULL;
+  g_autofree gchar *prefix = NULL;
+  g_autofree gchar *uri = NULL;
+  gsize i;
+
+  g_assert (IDE_IS_FILE (self));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  uri = g_file_get_uri (self->file);
+
+  if (has_suffix (uri, src_suffixes))
+    {
+      target = hdr_suffixes;
+    }
+  else if (has_suffix (uri, hdr_suffixes))
+    {
+      target = src_suffixes;
+    }
+  else
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_INVALID_FILENAME,
+                               "File is missing a suffix.");
+      return;
+    }
+
+  prefix = g_strndup (uri, strrchr (uri, '.') - uri);
+
+  for (i = 0; target [i]; i++)
+    {
+      g_autofree gchar *new_uri = NULL;
+      g_autoptr(GFile) gfile = NULL;
+
+      new_uri = g_strdup_printf ("%s.%s", prefix, target [i]);
+      gfile = g_file_new_for_uri (new_uri);
+
+      if (g_file_query_exists (gfile, cancellable))
+        {
+          g_autofree gchar *path = NULL;
+          IdeContext *context;
+          IdeVcs *vcs;
+          IdeFile *ret;
+          GFile *workdir;
+
+          context = ide_object_get_context (IDE_OBJECT (self));
+          vcs = ide_context_get_vcs (context);
+          workdir = ide_vcs_get_working_directory (vcs);
+          path = g_file_get_relative_path (workdir, gfile);
+
+          ret = g_object_new (IDE_TYPE_FILE,
+                              "context", context,
+                              "path", path,
+                              "file", gfile,
+                              NULL);
+          g_task_return_pointer (task, ret, g_object_unref);
+          return;
+        }
+    }
+
+  g_task_return_new_error (task,
+                           G_IO_ERROR,
+                           G_IO_ERROR_NOT_FOUND,
+                           "Failed to locate other file.");
+}
+
+void
+ide_file_find_other_async (IdeFile             *self,
+                           GCancellable        *cancellable,
+                           GAsyncReadyCallback  callback,
+                           gpointer             user_data)
+{
+  g_autoptr(GTask) task = NULL;
+
+  g_return_if_fail (IDE_IS_FILE (self));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_run_in_thread (task, ide_file_find_other_worker);
+}
+
+/**
+ * ide_file_find_other_finish:
+ *
+ * Completes an asynchronous call to ide_file_find_other_async(). This function
+ * will try to find a matching file for languages where this exists. Such cases
+ * include C and C++ where a .c or .cpp file may have a .h or .hh header. Additional
+ * suffixes are implemented including (.c, .cc, .cpp, .cxx, .h, .hh, .hpp, and .hxx).
+ *
+ * Returns an #IdeFile if successful, otherwise %NULL and @error is set.
+ *
+ * Returns: (transfer full) (nullable): An #IdeFIle or %NULL.
+ */
+IdeFile *
+ide_file_find_other_finish (IdeFile       *self,
+                            GAsyncResult  *result,
+                            GError       **error)
+{
+  GTask *task = (GTask *)result;
+
+  g_return_val_if_fail (IDE_IS_FILE (self), NULL);
+  g_return_val_if_fail (G_IS_TASK (task), NULL);
+
+  return g_task_propagate_pointer (task, error);
+}
diff --git a/libide/ide-file.h b/libide/ide-file.h
index 2757746..290c597 100644
--- a/libide/ide-file.h
+++ b/libide/ide-file.h
@@ -43,6 +43,13 @@ void             ide_file_load_settings_async  (IdeFile              *self,
 IdeFileSettings *ide_file_load_settings_finish (IdeFile              *self,
                                                 GAsyncResult         *result,
                                                 GError              **error);
+void             ide_file_find_other_async     (IdeFile              *self,
+                                                GCancellable         *cancellable,
+                                                GAsyncReadyCallback   callback,
+                                                gpointer              user_data);
+IdeFile         *ide_file_find_other_finish    (IdeFile              *self,
+                                                GAsyncResult         *result,
+                                                GError              **error);
 
 
 G_END_DECLS


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