示例#1
0
static void
ide_subprocess_supervisor_wait_cb (GObject      *object,
                                   GAsyncResult *result,
                                   gpointer      user_data)
{
  IdeSubprocess *subprocess = (IdeSubprocess *)object;
  g_autoptr(IdeSubprocessSupervisor) self = user_data;
  IdeSubprocessSupervisorPrivate *priv = ide_subprocess_supervisor_get_instance_private (self);
  g_autoptr(GError) error = NULL;

  g_return_if_fail (IDE_IS_SUBPROCESS_SUPERVISOR (self));
  g_return_if_fail (IDE_IS_SUBPROCESS (subprocess));

  if (!ide_subprocess_wait_finish (subprocess, result, &error))
    g_warning ("%s", error->message);

#ifdef IDE_ENABLE_TRACE
  {
    if (ide_subprocess_get_if_exited (subprocess))
      IDE_TRACE_MSG ("process exited with code: %u",
                     ide_subprocess_get_exit_status (subprocess));
    else
      IDE_TRACE_MSG ("process terminated due to signal: %u",
                     ide_subprocess_get_term_sig (subprocess));
  }
#endif

  /*
   * If we end up here in response to ide_subprocess_supervisor_reset() force
   * exiting the process, we won't successfully match
   * (priv->subprocess==subprocess) and therefore will not restart the process
   * immediately (allowing the caller of ide_subprocess_supervisor_reset() to
   * complete the operation.
   */

  if (priv->subprocess == subprocess)
    {
      g_clear_object (&priv->subprocess);

      if (priv->supervising)
        {
          gint64 sleep_usec;

          if (ide_subprocess_supervisor_needs_rate_limit (self, &sleep_usec))
            ide_subprocess_supervisor_start_in_usec (self, sleep_usec);
          else
            ide_subprocess_supervisor_start (self);
        }
    }
}
void
_ide_back_forward_list_load_async (IdeBackForwardList  *self,
                                   GFile               *file,
                                   GCancellable        *cancellable,
                                   GAsyncReadyCallback  callback,
                                   gpointer             user_data)
{
  g_autoptr(GTask) task = NULL;

  g_assert (IDE_IS_BACK_FORWARD_LIST (self));
  g_assert (G_IS_FILE (file));
  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));

#ifdef IDE_ENABLE_TRACE
  {
    g_autofree gchar *path = NULL;

    path = g_file_get_path (file);
    IDE_TRACE_MSG ("Loading %s", path);
  }
#endif

  task = g_task_new (self, cancellable, callback, user_data);

  g_file_load_contents_async (file,
                              cancellable,
                              ide_back_forward_list_load_cb,
                              g_object_ref (task));
}
示例#3
0
gboolean
ide_unsaved_file_persist (IdeUnsavedFile  *self,
                          GCancellable    *cancellable,
                          GError         **error)
{
  gboolean ret;

  IDE_ENTRY;

  g_return_val_if_fail (self, FALSE);
  g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);

  IDE_TRACE_MSG ("Saving draft to \"%s\"", self->temp_path);

  /*
   * TODO: Support cancellable.
   */

  ret = g_file_set_contents (self->temp_path,
                             g_bytes_get_data (self->content, NULL),
                             g_bytes_get_size (self->content),
                             error);

  IDE_RETURN (ret);
}
示例#4
0
static void
gb_keybindings_reload (GbKeybindings *self)
{
  const gchar *mode;
  g_autofree gchar *path = NULL;
  g_autoptr(GBytes) bytes = NULL;
  g_autoptr(GError) error = NULL;

  IDE_ENTRY;

  g_assert (GB_IS_KEYBINDINGS (self));

  mode = self->mode ? self->mode : "default";
  IDE_TRACE_MSG ("Loading %s keybindings", mode);
  path = g_strdup_printf ("/org/gnome/builder/keybindings/%s.css", mode);
  bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, &error);

  if (error == NULL)
    gtk_css_provider_load_from_data (self->css_provider,
                                     g_bytes_get_data (bytes, NULL),
                                     g_bytes_get_size (bytes),
                                     &error);

  if (error)
    g_warning ("%s", error->message);

  IDE_EXIT;
}
示例#5
0
static void
ide_keybindings_load_plugin (IdeKeybindings *self,
                             PeasPluginInfo *plugin_info,
                             PeasEngine     *engine)
{
  g_autofree gchar *path = NULL;
  const gchar *module_name;
  g_autoptr(GBytes) bytes = NULL;
  g_autoptr(GtkCssProvider) provider = NULL;

  g_assert (IDE_IS_KEYBINDINGS (self));
  g_assert (plugin_info != NULL);
  g_assert (PEAS_IS_ENGINE (engine));

  if (!self->mode || !self->plugin_providers)
    return;

  module_name = peas_plugin_info_get_module_name (plugin_info);
  path = g_strdup_printf ("/org/gnome/builder/plugins/%s/keybindings/%s.css",
                          module_name, self->mode);
  bytes = g_resources_lookup_data (path, 0, NULL);
  if (bytes == NULL)
    return;

  IDE_TRACE_MSG ("Loading %s keybindings for \"%s\" plugin", self->mode, module_name);

  provider = gtk_css_provider_new ();
  gtk_css_provider_load_from_resource (provider, path);
  gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
                                             GTK_STYLE_PROVIDER (provider),
                                             GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
  g_hash_table_insert (self->plugin_providers,
                       g_strdup (module_name),
                       g_steal_pointer (&provider));
}
示例#6
0
static gboolean
ide_git_vcs_load_monitor (IdeGitVcs  *self,
                          GError    **error)
{
  gboolean ret = TRUE;

  g_assert (IDE_IS_GIT_VCS (self));

  if (self->monitor == NULL)
    {
      g_autoptr(GFile) location = NULL;
      g_autoptr(GFileMonitor) monitor = NULL;
      g_autoptr(GFile) heads_dir = NULL;
      GFileMonitorFlags flags = G_FILE_MONITOR_WATCH_MOUNTS;

      location = ggit_repository_get_location (self->repository);
      heads_dir = g_file_get_child (location, "refs/heads");
      monitor = g_file_monitor (heads_dir, flags, NULL, error);

      ret = !!monitor;

      if (monitor)
        {
          IDE_TRACE_MSG ("Git index monitor registered.");
          g_signal_connect_object (monitor,
                                   "changed",
                                   G_CALLBACK (ide_git_vcs__monitor_changed_cb),
                                   self,
                                   G_CONNECT_SWAPPED);
          self->monitor = g_object_ref (monitor);
        }
    }

  return ret;
}
示例#7
0
static void
ide_worker_manager_constructed (GObject *object)
{
  IdeWorkerManager *self = (IdeWorkerManager *)object;
  g_autofree gchar *guid = NULL;
  g_autofree gchar *address = NULL;
  GError *error = NULL;

  g_assert (IDE_IS_WORKER_MANAGER (self));

  G_OBJECT_CLASS (ide_worker_manager_parent_class)->constructed (object);

  if (g_unix_socket_address_abstract_names_supported ())
    {
      address = g_strdup_printf ("unix:abstract=/tmp/gnome-builder-%u", (int)getpid ());
    }
  else
    {
      g_autofree gchar *tmpdir = NULL;

      tmpdir = g_dir_make_tmp ("gnome-builder-worker-XXXXXX", NULL);

      if (tmpdir == NULL)
        {
          g_error ("Failed to determine temporary directory for DBus.");
          exit (EXIT_FAILURE);
        }

      address = g_strdup_printf ("unix:tmpdir=%s", tmpdir);
    }

  guid = g_dbus_generate_guid ();

  self->dbus_server = g_dbus_server_new_sync (address,
                                              G_DBUS_SERVER_FLAGS_NONE,
                                              guid,
                                              NULL,
                                              NULL,
                                              &error);

  if (error != NULL)
    {
      g_error ("%s", error->message);
      exit (EXIT_FAILURE);
    }

  g_signal_connect_object (self->dbus_server,
                           "new-connection",
                           G_CALLBACK (ide_worker_manager_new_connection_cb),
                           self,
                           G_CONNECT_SWAPPED);

  IDE_TRACE_MSG ("GDBusServer listening at %s", address);

  g_dbus_server_start (self->dbus_server);

  g_assert (g_dbus_server_is_active (self->dbus_server));
}
static void
provider_entry_destroy (gpointer data)
{
  ProviderEntry *entry = data;

  IDE_ENTRY;

  IDE_TRACE_MSG ("releasing %p", data);

  ide_clear_weak_pointer (&entry->group);
  g_clear_object (&entry->provider);
  g_free (entry);

  IDE_EXIT;
}
示例#9
0
static void
ide_workbench_addin_added (PeasExtensionSet *set,
                           PeasPluginInfo   *plugin_info,
                           PeasExtension    *extension,
                           gpointer          user_data)
{
  IdeWorkbench *self = user_data;

  g_assert (PEAS_IS_EXTENSION_SET (set));
  g_assert (plugin_info != NULL);
  g_assert (IDE_IS_WORKBENCH_ADDIN (extension));
  g_assert (IDE_IS_WORKBENCH (self));

  IDE_TRACE_MSG ("Loading workbench addin for %s",
                 peas_plugin_info_get_module_name (plugin_info));

  ide_workbench_addin_load (IDE_WORKBENCH_ADDIN (extension), self);
}
示例#10
0
static void
ide_clang_service__get_build_flags_cb (GObject      *object,
                                       GAsyncResult *result,
                                       gpointer      user_data)
{
  IdeBuildSystem *build_system = (IdeBuildSystem *)object;
  g_autoptr(GTask) task = user_data;
  ParseRequest *request;
  gchar **argv;
  GError *error = NULL;

  g_assert (IDE_IS_BUILD_SYSTEM (build_system));
  g_assert (G_IS_TASK (task));

  request = g_task_get_task_data (task);

  argv = ide_build_system_get_build_flags_finish (build_system, result, &error);

  if (!argv)
    {
      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
        g_message ("%s", error->message);
      g_clear_error (&error);
      argv = g_new0 (gchar*, 1);
    }

  request->command_line_args = argv;

#ifdef IDE_ENABLE_TRACE
  {
    gchar *cflags;

    cflags = g_strjoinv (" ", argv);
    IDE_TRACE_MSG ("CFLAGS = %s", cflags);
    g_free (cflags);
  }
#endif

  ide_thread_pool_push_task (IDE_THREAD_POOL_COMPILER,
                             task,
                             ide_clang_service_parse_worker);
}
示例#11
0
static gboolean
ide_git_vcs_load_monitor_locked (IdeGitVcs  *self,
                                 GError    **error)
{
  gboolean ret = TRUE;

  g_assert (IDE_IS_GIT_VCS (self));

  if (self->monitor == NULL)
    {
      g_autoptr(GFile) location = NULL;
      g_autoptr(GFileMonitor) monitor = NULL;
      GError *local_error = NULL;

      location = ggit_repository_get_location (self->repository);

      monitor = g_file_monitor_directory (location,
                                          G_FILE_MONITOR_NONE,
                                          NULL,
                                          &local_error);

      if (monitor == NULL)
        {
          g_warning ("Failed to establish git monitor: %s", local_error->message);
          g_propagate_error (error, local_error);
          ret = FALSE;
        }
      else
        {
          IDE_TRACE_MSG ("Git index monitor registered.");
          g_signal_connect_object (monitor,
                                   "changed",
                                   G_CALLBACK (ide_git_vcs__monitor_changed_cb),
                                   self,
                                   G_CONNECT_SWAPPED);
          self->monitor = g_steal_pointer (&monitor);
        }
    }

  return ret;
}
示例#12
0
void
ide_run_manager_set_handler (IdeRunManager *self,
                             const gchar   *id)
{
  g_return_if_fail (IDE_IS_RUN_MANAGER (self));

  self->handler = NULL;

  for (GList *iter = self->handlers; iter; iter = iter->next)
    {
      const IdeRunHandlerInfo *info = iter->data;

      if (g_strcmp0 (info->id, id) == 0)
        {
          self->handler = info;
          IDE_TRACE_MSG ("run handler set to %s", info->title);
          g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_HANDLER]);
          break;
        }
    }
}
示例#13
0
static void
gb_vim_complete_colorscheme (const gchar *line,
                             GPtrArray   *ar)
{
  GtkSourceStyleSchemeManager *manager;
  const gchar * const *scheme_ids;
  const gchar *tmp;
  g_autofree gchar *prefix = NULL;
  gsize i;

  manager = gtk_source_style_scheme_manager_get_default ();
  scheme_ids = gtk_source_style_scheme_manager_get_scheme_ids (manager);

  for (tmp = strchr (line, ' ');
       tmp && *tmp && g_unichar_isspace (g_utf8_get_char (tmp));
       tmp = g_utf8_next_char (tmp))
    {
      /* do nothing */
    }

  if (!tmp)
    return;

  prefix = g_strndup (line, tmp - line);

  for (i = 0; scheme_ids [i]; i++)
    {
      const gchar *scheme_id = scheme_ids [i];

      if (g_str_has_prefix (scheme_id, tmp))
        {
          gchar *item;

          item = g_strdup_printf ("%s%s", prefix, scheme_id);
          IDE_TRACE_MSG ("colorscheme: %s", item);
          g_ptr_array_add (ar, item);
        }
    }
}
static void
ide_language_defaults_init_worker (GTask        *task,
                                   gpointer      source_object,
                                   gpointer      task_data,
                                   GCancellable *cancellable)
{
  g_autofree gchar *version_path = NULL;
  g_autofree gchar *version_contents = NULL;
  g_autofree gchar *version_dir = NULL;
  g_autoptr(GBytes) defaults = NULL;
  g_autoptr(GKeyFile) key_file = NULL;
  gint global_version;
  gboolean ret;
  GError *error = NULL;
  gint current_version;

  IDE_ENTRY;

  g_assert (G_IS_TASK (task));
  g_assert (source_object == NULL);
  g_assert (task_data == NULL);
  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));

  version_path = g_build_filename (g_get_user_config_dir (),
                                   ide_get_program_name (),
                                   "syntax",
                                   ".defaults",
                                   NULL);
  current_version = ide_language_defaults_get_current_version (version_path, &error);

  if (current_version < 0)
    {
      g_task_return_error (task, error);
      goto failure;
    }

  defaults = ide_language_defaults_get_defaults (&error);

  if (!defaults)
    {
      g_task_return_error (task, error);
      goto failure;
    }

  key_file = g_key_file_new ();
  ret = g_key_file_load_from_data (key_file,
                                   g_bytes_get_data (defaults, NULL),
                                   g_bytes_get_size (defaults),
                                   G_KEY_FILE_NONE,
                                   &error);

  if (!ret)
    {
      g_task_return_error (task, error);
      goto failure;
    }

  if (!g_key_file_has_group (key_file, "global") ||
      !g_key_file_has_key (key_file, "global", "version", NULL))
    {
      g_task_return_new_error (task,
                               G_IO_ERROR,
                               G_IO_ERROR_INVALID_DATA,
                               _("language defaults missing version in [global] group."));
      goto failure;
    }

  global_version = g_key_file_get_integer (key_file, "global", "version", &error);

  if ((global_version == 0) && error)
    {
      g_task_return_error (task, error);
      goto failure;
    }

  if (global_version > current_version)
    {
      if (!ide_language_defaults_migrate (key_file, current_version, global_version, &error))
        {
          g_task_return_error (task, error);
          goto failure;
        }

      version_contents = g_strdup_printf ("%d", global_version);

      version_dir = g_path_get_dirname (version_path);

      if (!g_file_test (version_dir, G_FILE_TEST_IS_DIR))
        {
          if (g_mkdir_with_parents (version_dir, 0750) == -1)
            {
              g_task_return_new_error (task,
                                       G_IO_ERROR,
                                       g_io_error_from_errno (errno),
                                       "%s", g_strerror (errno));
              goto failure;
            }
        }

      IDE_TRACE_MSG ("Writing new language defaults version to \"%s\"", version_path);

      if (!g_file_set_contents (version_path, version_contents, -1, &error))
        {
          g_task_return_error (task, error);
          goto failure;
        }
    }

  g_task_return_boolean (task, TRUE);

  {
    GList *list;
    GList *iter;

    G_LOCK (lock);

    initializing = FALSE;
    initialized = TRUE;

    list = tasks;
    tasks = NULL;

    G_UNLOCK (lock);

    for (iter = list; iter; iter = iter->next)
      {
        g_task_return_boolean (iter->data, TRUE);
        g_object_unref (iter->data);
      }

    g_list_free (list);
  }

  IDE_EXIT;

failure:
  {
    GList *list;
    GList *iter;

    G_LOCK (lock);

    initializing = FALSE;
    initialized = TRUE;

    list = tasks;
    tasks = NULL;

    G_UNLOCK (lock);

    for (iter = list; iter; iter = iter->next)
      {
        g_task_return_new_error (iter->data,
                                 G_IO_ERROR,
                                 G_IO_ERROR_FAILED,
                                 _("Failed to initialize defaults."));
        g_object_unref (iter->data);
      }

    g_list_free (list);
  }

  IDE_EXIT;
}
示例#15
0
static void
ide_lsp_formatter_apply_changes (IdeLspFormatter *self,
                                 IdeBuffer       *buffer,
                                 GVariant        *text_edits)
{
  g_autoptr(GPtrArray) edits = NULL;
  g_autoptr(IdeContext) context = NULL;
  IdeBufferManager *buffer_manager;
  GVariant *text_edit;
  GFile *file;
  GVariantIter iter;

  IDE_ENTRY;

  g_assert (IDE_IS_LSP_FORMATTER (self));
  g_assert (text_edits != NULL);

  if (!g_variant_is_container (text_edits))
    {
      g_warning ("variant is not a container, ignoring");
      IDE_EXIT;
    }

  file = ide_buffer_get_file (buffer);
  edits = g_ptr_array_new_with_free_func (g_object_unref);

  g_variant_iter_init (&iter, text_edits);

  while (g_variant_iter_loop (&iter, "v", &text_edit))
    {
      g_autoptr(IdeLocation) begin_location = NULL;
      g_autoptr(IdeLocation) end_location = NULL;
      g_autoptr(IdeRange) range = NULL;
      const gchar *new_text = NULL;
      gboolean success;
      struct {
        gint64 line;
        gint64 column;
      } begin, end;

      success = JSONRPC_MESSAGE_PARSE (text_edit,
        "range", "{",
          "start", "{",
            "line", JSONRPC_MESSAGE_GET_INT64 (&begin.line),
            "character", JSONRPC_MESSAGE_GET_INT64 (&begin.column),
          "}",
          "end", "{",
            "line", JSONRPC_MESSAGE_GET_INT64 (&end.line),
            "character", JSONRPC_MESSAGE_GET_INT64 (&end.column),
          "}",
        "}",
        "newText", JSONRPC_MESSAGE_GET_STRING (&new_text)
      );

      if (!success)
        {
          IDE_TRACE_MSG ("Failed to extract change from variant");
          continue;
        }

      begin_location = ide_location_new (file, begin.line, begin.column);
      end_location = ide_location_new (file, end.line, end.column);
      range = ide_range_new (begin_location, end_location);

      g_ptr_array_add (edits, ide_text_edit_new (range, new_text));
    }

  context = ide_buffer_ref_context (buffer);
  buffer_manager = ide_buffer_manager_from_context (context);

  ide_buffer_manager_apply_edits_async (buffer_manager,
                                        IDE_PTR_ARRAY_STEAL_FULL (&edits),
                                        NULL, NULL, NULL);

  IDE_EXIT;
}
示例#16
0
static void
gb_vim_complete_edit_files (GtkWidget *active_widget,
                            const gchar   *command,
                            GPtrArray     *ar,
                            const gchar   *prefix)
{
  IdeWorkbench *workbench;
  IdeContext *context;
  IdeVcs *vcs;
  GFile *workdir;
  g_autoptr(GFile) child = NULL;
  g_autoptr(GFile) parent = NULL;

  IDE_ENTRY;

  g_assert (command);
  g_assert (ar);
  g_assert (prefix);

  if (!(workbench = ide_widget_get_workbench (GTK_WIDGET (active_widget))) ||
      !(context = ide_workbench_get_context (workbench)) ||
      !(vcs = ide_context_get_vcs (context)) ||
      !(workdir = ide_vcs_get_working_directory (vcs)))
    IDE_EXIT;

  child = g_file_get_child (workdir, prefix);

  if (g_file_query_exists (child, NULL))
    {
      if (g_file_query_file_type (child, 0, NULL) == G_FILE_TYPE_DIRECTORY)
        {
          g_autoptr(GFileEnumerator) fe = NULL;
          GFileInfo *descendent;

          if (!g_str_has_suffix (prefix, "/"))
            {
              g_ptr_array_add (ar, g_strdup_printf ("%s %s/", command, prefix));
              IDE_EXIT;
            }

          fe = g_file_enumerate_children (child,
                                          G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
                                          G_FILE_QUERY_INFO_NONE,
                                          NULL, NULL);

          if (fe == NULL)
            IDE_EXIT;

          while ((descendent = g_file_enumerator_next_file (fe, NULL, NULL)))
            {
              const gchar *name;

              name = g_file_info_get_display_name (descendent);
              g_ptr_array_add (ar, g_strdup_printf ("%s %s%s", command, prefix, name));
              g_object_unref (descendent);
            }

          IDE_EXIT;
        }
    }

  parent = g_file_get_parent (child);

  if (parent != NULL)
    {
      g_autoptr(GFileEnumerator) fe = NULL;
      GFileInfo *descendent;
      const gchar *slash;
      const gchar *partial_name;
      g_autofree gchar *prefix_dir = NULL;

#ifdef IDE_ENABLE_TRACE
      {
        g_autofree gchar *parent_path = g_file_get_path (parent);
        IDE_TRACE_MSG ("parent_path: %s", parent_path);
      }
#endif

      if ((slash = strrchr (prefix, G_DIR_SEPARATOR)))
        {
          partial_name = slash + 1;
          prefix_dir = g_strndup (prefix, slash - prefix + 1);
        }
      else
        {
          partial_name = prefix;
        }

      fe = g_file_enumerate_children (parent,
                                      G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
                                      G_FILE_QUERY_INFO_NONE,
                                      NULL, NULL);

      if (fe == NULL)
        IDE_EXIT;

      while ((descendent = g_file_enumerator_next_file (fe, NULL, NULL)))
        {
          const gchar *name;
          name = g_file_info_get_display_name (descendent);

          IDE_TRACE_MSG ("name=%s prefix=%s", name, prefix);

          if (name && g_str_has_prefix (name, partial_name))
            {
              gchar *completed_command;
              const gchar *descendent_name;
              g_autofree gchar *full_path = NULL;
              g_autofree gchar *parent_path = NULL;

              parent_path = g_file_get_path (parent);
              descendent_name = g_file_info_get_name (descendent);
              full_path = g_build_filename (parent_path, descendent_name, NULL);

              if (prefix[0] == G_DIR_SEPARATOR)
                completed_command = g_strdup_printf ("%s %s", command, full_path);
              else if (strchr (prefix, G_DIR_SEPARATOR) == NULL)
                completed_command = g_strdup_printf ("%s %s", command, descendent_name);
              else
                completed_command = g_strdup_printf ("%s %s%s", command, prefix_dir, descendent_name);

              IDE_TRACE_MSG ("edit completion: %s", completed_command);

              g_ptr_array_add (ar, completed_command);
            }
          g_object_unref (descendent);
        }

      IDE_EXIT;
    }

  IDE_EXIT;
}
示例#17
0
static void
ide_frame_pan_end (IdeFrame         *self,
                   GdkEventSequence *sequence,
                   GtkGesturePan    *gesture)
{
  IdeFramePrivate *priv = ide_frame_get_instance_private (self);
  IdeFramePrivate *dest_priv;
  IdeFrame *dest;
  GtkAllocation alloc;
  GtkWidget *grid;
  GtkWidget *column;
  gdouble x, y;
  gint direction;
  gint index = 0;

  IDE_ENTRY;

  g_assert (IDE_IS_FRAME (self));
  g_assert (GTK_IS_GESTURE_PAN (gesture));

  if (priv->pan_theatric == NULL || priv->pan_page == NULL)
    IDE_GOTO (cleanup);

  gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);

  gtk_gesture_drag_get_offset (GTK_GESTURE_DRAG (gesture), &x, &y);

  if (x > DISTANCE_THRESHOLD (&alloc))
    direction = 1;
  else if (x < -DISTANCE_THRESHOLD (&alloc))
    direction = -1;
  else
    direction = 0;

  grid = gtk_widget_get_ancestor (GTK_WIDGET (self), IDE_TYPE_GRID);
  g_assert (grid != NULL);
  g_assert (IDE_IS_GRID (grid));

  column = gtk_widget_get_ancestor (GTK_WIDGET (self), IDE_TYPE_GRID_COLUMN);
  g_assert (column != NULL);
  g_assert (IDE_IS_GRID_COLUMN (column));

  gtk_container_child_get (GTK_CONTAINER (grid), GTK_WIDGET (column),
                           "index", &index,
                           NULL);

  dest = _ide_grid_get_nth_stack (IDE_GRID (grid), index + direction);
  dest_priv = ide_frame_get_instance_private (dest);
  g_assert (dest != NULL);
  g_assert (IDE_IS_FRAME (dest));

  gtk_widget_get_allocation (GTK_WIDGET (dest), &alloc);

  if (!is_uninitialized (&alloc))
    {
      AnimationState *state;

      state = g_slice_new0 (AnimationState);
      state->source = g_object_ref (self);
      state->dest = g_object_ref (dest);
      state->page = g_object_ref (priv->pan_page);
      state->theatric = g_object_ref (priv->pan_theatric);

      gtk_widget_translate_coordinates (GTK_WIDGET (dest_priv->top_stack), grid, 0, 0,
                                        &alloc.x, &alloc.y);

      /*
       * Use EASE_OUT_CUBIC, because user initiated the beginning of the
       * acceleration curve just by swiping. No need to duplicate.
       */
      dzl_object_animate_full (state->theatric,
                               DZL_ANIMATION_EASE_OUT_CUBIC,
                               TRANSITION_DURATION,
                               gtk_widget_get_frame_clock (GTK_WIDGET (self)),
                               animation_state_complete,
                               state,
                               "x", alloc.x,
                               "width", alloc.width,
                               NULL);

      if (dest != self)
        {
          g_ptr_array_add (priv->in_transition, g_object_ref (priv->pan_page));
          gtk_container_remove (GTK_CONTAINER (priv->stack), GTK_WIDGET (priv->pan_page));
        }

      IDE_TRACE_MSG ("Animating transition to %s column",
                     dest != self ? "another" : "same");
    }
  else
    {
      g_autoptr(IdePage) page = g_object_ref (priv->pan_page);

      IDE_TRACE_MSG ("Moving page to a previously non-existant column");

      gtk_container_remove (GTK_CONTAINER (priv->stack), GTK_WIDGET (page));
      gtk_widget_show (GTK_WIDGET (page));
      gtk_container_add (GTK_CONTAINER (dest_priv->stack), GTK_WIDGET (page));
    }

cleanup:
  g_clear_object (&priv->pan_theatric);
  g_clear_object (&priv->pan_page);

  gtk_widget_queue_draw (gtk_widget_get_toplevel (GTK_WIDGET (self)));

  ide_frame_set_cursor (self, "arrow");

  IDE_EXIT;
}
示例#18
0
static void
populate_cache (EggTaskCache  *cache,
                gconstpointer  key,
                GTask         *task,
                gpointer       user_data)
{
  IdeGettextDiagnosticProvider *self = user_data;
  g_autoptr(IdeUnsavedFile) unsaved_file = NULL;
  g_autoptr(GSubprocess) subprocess = NULL;
  GtkSourceLanguage *language;
  const gchar *language_id;
  const gchar *xgettext_lang;
  const gchar *temp_path;
  TranslationUnit *unit;
  IdeFile *file = (IdeFile *)key;
  GCancellable *cancellable;
  GError *error = NULL;
  GPtrArray *args;

  g_assert (EGG_IS_TASK_CACHE (cache));
  g_assert (IDE_IS_FILE (file));
  g_assert (IDE_IS_GETTEXT_DIAGNOSTIC_PROVIDER (self));

  cancellable = g_task_get_cancellable (task);

  if (NULL == (unsaved_file = get_unsaved_file (self, file)))
    {
      g_task_return_new_error (task,
                               G_IO_ERROR,
                               G_IO_ERROR_NOT_FOUND,
                               "Failed to locate file contents");
      return;
    }

  if (NULL == (language = ide_file_get_language (file)) ||
      NULL == (language_id = gtk_source_language_get_id (language)) ||
      NULL == (xgettext_lang = id_to_xgettext_language (language_id)))
    {
      g_task_return_new_error (task,
                               G_IO_ERROR,
                               G_IO_ERROR_NOT_SUPPORTED,
                               "Failed to determine language type");
      return;
    }

  if (!ide_unsaved_file_persist (unsaved_file, cancellable, &error))
    {
      g_task_return_error (task, error);
      return;
    }

  temp_path = ide_unsaved_file_get_temp_path (unsaved_file);

  g_assert (temp_path != NULL);

  args = g_ptr_array_new ();
  g_ptr_array_add (args, "xgettext");
  g_ptr_array_add (args, "--check=ellipsis-unicode");
  g_ptr_array_add (args, "--check=quote-unicode");
  g_ptr_array_add (args, "--check=space-ellipsis");
  g_ptr_array_add (args, "-k_");
  g_ptr_array_add (args, "-kN_");
  g_ptr_array_add (args, "-L");
  g_ptr_array_add (args, (gchar *)xgettext_lang);
  g_ptr_array_add (args, "-o");
  g_ptr_array_add (args, "-");
  g_ptr_array_add (args, (gchar *)temp_path);
  g_ptr_array_add (args, NULL);

#ifdef IDE_ENABLE_TRACE
  {
    g_autofree gchar *str = NULL;
    str = g_strjoinv (" ", (gchar **)args->pdata);
    IDE_TRACE_MSG ("Launching '%s'", str);
  }
#endif

  subprocess = g_subprocess_newv ((const gchar * const *)args->pdata,
                                  G_SUBPROCESS_FLAGS_STDIN_PIPE
                                  | G_SUBPROCESS_FLAGS_STDOUT_PIPE
                                  | G_SUBPROCESS_FLAGS_STDERR_PIPE,
                                  &error);

  g_ptr_array_free (args, TRUE);

  if (subprocess == NULL)
    {
      g_task_return_error (task, error);
      return;
    }

  unit = g_slice_new0 (TranslationUnit);
  unit->file = g_object_ref (file);
  unit->unsaved_file = ide_unsaved_file_ref (unsaved_file);
  g_task_set_task_data (task, unit, (GDestroyNotify)translation_unit_free);

  g_subprocess_wait_async (subprocess,
                           cancellable,
                           subprocess_wait_cb,
                           g_object_ref (task));
}
示例#19
0
static void
ide_editor_perspective_focus_location_full (IdeEditorPerspective *self,
                                            IdeSourceLocation    *location,
                                            gboolean              open_if_not_found)
{
  struct {
    IdeFile *file;
    IdeEditorView *view;
  } lookup = { 0 };
  GtkWidget *stack;
  guint line;
  guint line_offset;

  IDE_ENTRY;

  g_assert (IDE_IS_EDITOR_PERSPECTIVE (self));
  g_assert (location != NULL);

  lookup.file = ide_source_location_get_file (location);
  lookup.view = NULL;

  if (lookup.file == NULL)
    {
      g_warning ("IdeSourceLocation does not contain a file");
      IDE_EXIT;
    }

#ifdef IDE_ENABLE_TRACE
  {
    const gchar *path = ide_file_get_path (lookup.file);
    IDE_TRACE_MSG ("Locating %s, open_if_not_found=%d",
                   path, open_if_not_found);
  }
#endif

  ide_perspective_views_foreach (IDE_PERSPECTIVE (self),
                                 ide_editor_perspective_find_source_location,
                                 &lookup);

  if (!open_if_not_found && lookup.view == NULL)
    IDE_EXIT;

  if (lookup.view == NULL)
    {
      FocusLocation *state;
      IdeBufferManager *bufmgr;
      IdeWorkbench *workbench;
      IdeContext *context;

      workbench = ide_widget_get_workbench (GTK_WIDGET (self));
      context = ide_workbench_get_context (workbench);
      bufmgr = ide_context_get_buffer_manager (context);

      state = g_slice_new0 (FocusLocation);
      state->self = g_object_ref (self);
      state->location = ide_source_location_ref (location);

      ide_buffer_manager_load_file_async (bufmgr,
                                          lookup.file,
                                          FALSE,
                                          IDE_WORKBENCH_OPEN_FLAGS_NONE,
                                          NULL,
                                          NULL,
                                          ide_editor_perspective_focus_location_cb,
                                          state);
      IDE_EXIT;
    }

  line = ide_source_location_get_line (location);
  line_offset = ide_source_location_get_line_offset (location);

  stack = gtk_widget_get_ancestor (GTK_WIDGET (lookup.view), IDE_TYPE_LAYOUT_STACK);
  ide_layout_stack_set_visible_child (IDE_LAYOUT_STACK (stack), IDE_LAYOUT_VIEW (lookup.view));
  ide_editor_view_scroll_to_line_offset (lookup.view, line, line_offset);

  IDE_EXIT;
}
示例#20
0
static void
ide_keybindings_reload (IdeKeybindings *self)
{
  GdkScreen *screen;
  PeasEngine *engine;
  const GList *list;

  IDE_ENTRY;

  g_assert (IDE_IS_KEYBINDINGS (self));

  {
    g_autofree gchar *path = NULL;
    g_autoptr(GBytes) bytes = NULL;
    g_autoptr(GError) error = NULL;

    if (self->mode == NULL)
      self->mode = g_strdup ("default");

    IDE_TRACE_MSG ("Loading %s keybindings", self->mode);
    path = g_strdup_printf ("/org/gnome/builder/keybindings/%s.css", self->mode);
    bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, &error);

    if (error == NULL)
      {
        /*
         * We use -1 for the length so that the CSS provider knows that the
         * string is \0 terminated. This is guaranteed to us by GResources so
         * that interned data can be used as C strings.
         */
        gtk_css_provider_load_from_data (self->css_provider,
                                         g_bytes_get_data (bytes, NULL),
                                         -1,
                                         &error);
      }

    if (error)
      g_warning ("%s", error->message);
  }

  engine = peas_engine_get_default ();
  screen = gdk_screen_get_default ();

  if (self->plugin_providers != NULL)
    {
      GHashTableIter iter;
      GtkStyleProvider *provider;

      g_hash_table_iter_init (&iter, self->plugin_providers);
      while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&provider))
        gtk_style_context_remove_provider_for_screen (screen, provider);

      g_clear_pointer (&self->plugin_providers, g_hash_table_unref);
    }

  self->plugin_providers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);

  list = peas_engine_get_plugin_list (engine);

  for (; list != NULL; list = list->next)
    {
      PeasPluginInfo *plugin_info = list->data;

      if (!peas_plugin_info_is_loaded (plugin_info))
        continue;

      ide_keybindings_load_plugin (self, plugin_info, engine);
    }

  IDE_EXIT;
}
示例#21
0
static void
ide_langserv_completion_provider_complete_cb (GObject      *object,
                                              GAsyncResult *result,
                                              gpointer      user_data)
{
  IdeLangservClient *client = (IdeLangservClient *)object;
  g_autoptr(CompletionState) state = user_data;
  g_autoptr(GVariant) return_value = NULL;
  g_autoptr(GError) error = NULL;
  GVariant *node;
  GList *list = NULL;
  GVariantIter iter;

  IDE_ENTRY;

  g_assert (IDE_IS_LANGSERV_CLIENT (client));
  g_assert (G_IS_ASYNC_RESULT (result));
  g_assert (state != NULL);
  g_assert (IDE_IS_LANGSERV_COMPLETION_PROVIDER (state->self));
  g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (state->context));

  if (!ide_langserv_client_call_finish (client, result, &return_value, &error))
    {
      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
        g_message ("%s", error->message);
      IDE_GOTO (failure);
    }

  /*
   * TODO: We will want to make a much more optimized version of this using
   *       the other completion result work we've done.
   */

  g_variant_iter_init (&iter, return_value);

  while (g_variant_iter_loop (&iter, "v", &node))
    {
      g_autoptr(GtkSourceCompletionItem) item = NULL;
      g_autofree gchar *full_label = NULL;
      const gchar *label;
      const gchar *detail;
      const gchar *icon_name = NULL;
      gboolean success;
      gint64 kind = 0;

      success = JSONRPC_MESSAGE_PARSE (node,
        "label", JSONRPC_MESSAGE_GET_STRING (&label),
        "detail", JSONRPC_MESSAGE_GET_STRING (&detail)
      );

      if (!success)
        {
          IDE_TRACE_MSG ("Failed to extract completion item from node");
          continue;
        }

      /* Optional kind field */
      JSONRPC_MESSAGE_PARSE (node, "kind", JSONRPC_MESSAGE_GET_INT64 (&kind));
      kind = ide_langserv_decode_completion_kind (kind);
      if (kind != IDE_SYMBOL_NONE)
        icon_name = ide_symbol_kind_get_icon_name (kind);

      if (label != NULL && detail != NULL)
        full_label = g_strdup_printf ("%s : %s", label, detail);
      else
        full_label = g_strdup (label);

      //item = gtk_source_completion_item_new (full_label, label, NULL, NULL);
      item = g_object_new (GTK_SOURCE_TYPE_COMPLETION_ITEM,
                           "icon-name", icon_name,
                           "label", full_label,
                           "text", label,
                           NULL);

      list = g_list_prepend (list, g_steal_pointer (&item));
    }

failure:
  gtk_source_completion_context_add_proposals (state->context,
                                               GTK_SOURCE_COMPLETION_PROVIDER (state->self),
                                               list,
                                               TRUE);

  g_list_free_full (list, g_object_unref);

  IDE_EXIT;
}
示例#22
0
static void
ide_langserv_completion_provider_populate (GtkSourceCompletionProvider *provider,
                                           GtkSourceCompletionContext  *context)
{
  IdeLangservCompletionProvider *self = (IdeLangservCompletionProvider *)provider;
  IdeLangservCompletionProviderPrivate *priv = ide_langserv_completion_provider_get_instance_private (self);
  g_autoptr(GVariant) params = NULL;
  g_autoptr(GCancellable) cancellable = NULL;
  g_autoptr(CompletionState) state = NULL;
  g_autofree gchar *uri = NULL;
  GtkTextIter iter;
  IdeBuffer *buffer;
  gint line;
  gint column;

  IDE_ENTRY;

  g_assert (IDE_IS_LANGSERV_COMPLETION_PROVIDER (self));
  g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));

  if (priv->client == NULL)
    {
      IDE_TRACE_MSG ("No client set, cannot provide proposals");
      gtk_source_completion_context_add_proposals (context, provider, NULL, TRUE);
      IDE_EXIT;
    }

  gtk_source_completion_context_get_iter (context, &iter);

  buffer = IDE_BUFFER (gtk_text_iter_get_buffer (&iter));
  uri = ide_buffer_get_uri (buffer);

  line = gtk_text_iter_get_line (&iter);
  column = gtk_text_iter_get_line_offset (&iter);

  params = JSONRPC_MESSAGE_NEW (
    "textDocument", "{",
      "uri", JSONRPC_MESSAGE_PUT_STRING (uri),
    "}",
    "position", "{",
      "line", JSONRPC_MESSAGE_PUT_INT32 (line),
      "character", JSONRPC_MESSAGE_PUT_INT32 (column),
    "}"
  );

  cancellable = g_cancellable_new ();

  g_signal_connect_data (context,
                         "cancelled",
                         G_CALLBACK (g_cancellable_cancel),
                         g_object_ref (cancellable),
                         (GClosureNotify)g_object_unref,
                         G_CONNECT_SWAPPED);

  state = completion_state_new (self, context);

  ide_langserv_client_call_async (priv->client,
                                  "textDocument/completion",
                                  g_steal_pointer (&params),
                                  g_steal_pointer (&cancellable),
                                  ide_langserv_completion_provider_complete_cb,
                                  g_steal_pointer (&state));

  IDE_EXIT;
}
static void
ide_ctags_completion_provider_populate (GtkSourceCompletionProvider *provider,
                                        GtkSourceCompletionContext  *context)
{
  IdeCtagsCompletionProvider *self = (IdeCtagsCompletionProvider *)provider;
  g_autofree gchar *word = NULL;
  const IdeCtagsIndexEntry *entries;
  const gchar * const *allowed;
  g_autoptr(GPtrArray) ar = NULL;
  IdeCtagsIndexEntry *last = NULL;
  GtkSourceBuffer *buffer;
  gsize n_entries;
  GtkTextIter iter;
  GList *list = NULL;
  gsize i;
  gsize j;

  IDE_ENTRY;

  g_assert (IDE_IS_CTAGS_COMPLETION_PROVIDER (self));
  g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context));

  if (self->indexes->len == 0)
    IDE_GOTO (failure);

  if (!g_settings_get_boolean (self->settings, "ctags-autocompletion"))
    IDE_GOTO (failure);

  if (!gtk_source_completion_context_get_iter (context, &iter))
    IDE_GOTO (failure);

  buffer = GTK_SOURCE_BUFFER (gtk_text_iter_get_buffer (&iter));
  allowed = get_allowed_suffixes (buffer);

  word = get_word_to_cursor (&iter);
  if (ide_str_empty0 (word) || strlen (word) < self->minimum_word_size)
    IDE_GOTO (failure);

  if (strlen (word) < 3)
    IDE_GOTO (failure);

  ar = g_ptr_array_new ();

  IDE_TRACE_MSG ("Searching for %s", word);

  for (j = 0; j < self->indexes->len; j++)
    {
      IdeCtagsIndex *index = g_ptr_array_index (self->indexes, j);

      entries = ide_ctags_index_lookup_prefix (index, word, &n_entries);
      if ((entries == NULL) || (n_entries == 0))
        continue;

      for (i = 0; i < n_entries; i++)
        {
          const IdeCtagsIndexEntry *entry = &entries [i];

          if (is_allowed (entry, allowed))
            g_ptr_array_add (ar, (gpointer)entry);
        }
    }

  g_ptr_array_sort (ar, sort_wrapper);

  for (i = ar->len; i > 0; i--)
    {
      GtkSourceCompletionProposal *item;
      IdeCtagsIndexEntry *entry = g_ptr_array_index (ar, i - 1);

      /*
       * NOTE:
       *
       * We walk backwards in this ptrarray so that we can use g_list_prepend() for O(1) access.
       * I think everyone agrees that using GList for passing completion data around was not
       * a great choice, but it is what we have to work with.
       */

      /*
       * Ignore this item if the previous one looks really similar.
       * We take the first item instead of the last since the first item (when walking backwards)
       * tends to be more likely to be the one we care about (based on lexicographical
       * ordering. For example, something in "gtk-2.0" is less useful than "gtk-3.0".
       *
       * This is done here instead of during our initial object creation so that
       * we can merge items between different indexes. It often happens that the
       * same headers are included in multiple tags files.
       */
      if ((last != NULL) && too_similar (entry, last))
        continue;

      /*
       * NOTE:
       *
       * Autocompletion is very performance sensitive code. The smallest amount of
       * extra work has a very negative impact on interactivity. We are trying to
       * avoid a couple things here based on how completion works.
       *
       * 1) Avoiding referencing or copying things.
       *    Since the provider will always outlive the completion item, we use
       *    borrowed references for as much as we can.
       * 2) We delay the work of looking up icons until they are requested.
       *    No sense in doing that work before hand.
       */
      item = ide_ctags_completion_item_new (entry, self, context);
      list = g_list_prepend (list, item);

      last = entry;
    }

failure:
  gtk_source_completion_context_add_proposals (context, provider, list, TRUE);
  g_list_free_full (list, g_object_unref);

  IDE_EXIT;
}
void
_ide_source_view_apply_movement (IdeSourceView         *self,
                                 IdeSourceViewMovement  movement,
                                 gboolean               extend_selection,
                                 gboolean               exclusive,
                                 guint                  count,
                                 gunichar               command,
                                 gunichar               modifier,
                                 gunichar               search_char,
                                 gint                  *target_offset)
{
  Movement mv = { 0 };
  GtkTextBuffer *buffer;
  GtkTextMark *insert;
  gsize i;

  g_return_if_fail (IDE_IS_SOURCE_VIEW (self));

#ifdef IDE_ENABLE_TRACE
  {
    GEnumValue *enum_value;
    GEnumClass *enum_class;

    enum_class = g_type_class_ref (IDE_TYPE_SOURCE_VIEW_MOVEMENT);
    enum_value = g_enum_get_value (enum_class, movement);
    IDE_TRACE_MSG ("movement(%s, extend_selection=%s, exclusive=%s, count=%u)",
                   enum_value->value_nick,
                   extend_selection ? "YES" : "NO",
                   exclusive ? "YES" : "NO",
                   count);
    g_type_class_unref (enum_class);
  }
#endif

  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self));
  insert = gtk_text_buffer_get_insert (buffer);

  mv.self = self;
  mv.target_offset = target_offset;
  mv.type = movement;
  mv.extend_selection = extend_selection;
  mv.exclusive = exclusive;
  mv.count = count;
  mv.ignore_select = FALSE;
  mv.ignore_target_offset = FALSE;
  mv.command = command;
  mv.modifier = modifier;

  ide_source_view_movements_get_selection (&mv);

  switch (movement)
    {
    case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_OFFSET:
      gtk_text_iter_backward_chars (&mv.insert, MAX (1, mv.count));
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NEXT_OFFSET:
      gtk_text_iter_forward_chars (&mv.insert, MAX (1, mv.count));
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NTH_CHAR:
      ide_source_view_movements_nth_char (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_CHAR:
      ide_source_view_movements_previous_char (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NEXT_CHAR:
      ide_source_view_movements_next_char (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_FIRST_CHAR:
      ide_source_view_movements_first_char (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_FIRST_NONSPACE_CHAR:
      ide_source_view_movements_first_nonspace_char (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_MIDDLE_CHAR:
      ide_source_view_movements_middle_char (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_LAST_CHAR:
      ide_source_view_movements_last_char (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_FULL_WORD_START:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_previous_full_word_start (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NEXT_FULL_WORD_START:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_next_full_word_start (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_FULL_WORD_END:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_previous_full_word_end (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NEXT_FULL_WORD_END:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_next_full_word_end (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_SUB_WORD_START:
      gtk_text_iter_backward_visible_word_starts (&mv.insert, MAX (1, mv.count));
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NEXT_SUB_WORD_START:
      if (!gtk_text_iter_forward_visible_word_ends (&mv.insert, MAX (1, mv.count)))
        gtk_text_iter_forward_to_line_end (&mv.insert);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_WORD_START:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_previous_word_start (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NEXT_WORD_START:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_next_word_start (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_WORD_END:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_previous_word_end (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NEXT_WORD_END:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_next_word_end (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_SENTENCE_START:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_sentence_start (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_SENTENCE_END:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_sentence_end (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_PARAGRAPH_START:
      for (i = MAX (1, mv.count); i > 0; i--)
        {
          mv.exclusive = exclusive && i == 1;
          ide_source_view_movements_paragraph_start (&mv);
        }
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_PARAGRAPH_END:
      for (i = MAX (1, mv.count); i > 0; i--)
        {
          mv.exclusive = exclusive && i == 1;
          ide_source_view_movements_paragraph_end (&mv);
        }
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_LINE:
      mv.ignore_target_offset = TRUE;
      mv.ignore_select = TRUE;
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_previous_line (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NEXT_LINE:
      mv.ignore_target_offset = TRUE;
      mv.ignore_select = TRUE;
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_next_line (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_FIRST_LINE:
      ide_source_view_movements_first_line (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NTH_LINE:
      ide_source_view_movements_nth_line (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_LAST_LINE:
      ide_source_view_movements_last_line (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_LINE_PERCENTAGE:
      ide_source_view_movements_line_percentage (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_LINE_CHARS:
      ide_source_view_movements_line_chars (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_LINE_END:
      ide_source_view_movements_line_end (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_HALF_PAGE_UP:
    case IDE_SOURCE_VIEW_MOVEMENT_HALF_PAGE_DOWN:
    case IDE_SOURCE_VIEW_MOVEMENT_PAGE_UP:
    case IDE_SOURCE_VIEW_MOVEMENT_PAGE_DOWN:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_move_page (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_DOWN:
    case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_UP:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_scroll (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_TOP:
      ide_source_view_movements_screen_top (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_MIDDLE:
      ide_source_view_movements_screen_middle (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_BOTTOM:
      ide_source_view_movements_screen_bottom (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_MATCH_SPECIAL:
      ide_source_view_movements_match_special (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_SCROLL_SCREEN_TOP:
    case IDE_SOURCE_VIEW_MOVEMENT_SCROLL_SCREEN_CENTER:
    case IDE_SOURCE_VIEW_MOVEMENT_SCROLL_SCREEN_BOTTOM:
      ide_source_view_movements_scroll_center (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_UNMATCHED_BRACE:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_previous_unmatched (&mv, '{', '}');
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NEXT_UNMATCHED_BRACE:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_next_unmatched (&mv, '}', '{');
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_UNMATCHED_PAREN:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_previous_unmatched (&mv, '(', ')');
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NEXT_UNMATCHED_PAREN:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_next_unmatched (&mv, ')', '(');
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NEXT_MATCH_MODIFIER:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_next_match_modifier (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_MATCH_MODIFIER:
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movements_previous_match_modifier (&mv);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_MATCH_SEARCH_CHAR:
      mv.modifier = search_char;
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movement_match_search_char (&mv, FALSE);
      break;

    case IDE_SOURCE_VIEW_MOVEMENT_NEXT_MATCH_SEARCH_CHAR:
      mv.modifier = search_char;
      for (i = MAX (1, mv.count); i > 0; i--)
        ide_source_view_movement_match_search_char (&mv, TRUE);
      break;

    default:
      g_return_if_reached ();
    }

  if (!mv.ignore_select)
    ide_source_view_movements_select_range (&mv);

  if (!mv.ignore_target_offset)
    *target_offset = gtk_text_iter_get_line_offset (&mv.insert);

  if (!mv.ignore_scroll_to_insert)
    ide_source_view_scroll_mark_onscreen (self, insert, TRUE, 0.5, 0.5);
}
示例#25
0
static void
gb_vim_complete_edit_files (GtkSourceView *source_view,
                            const gchar   *command,
                            GPtrArray     *ar,
                            const gchar   *prefix)
{
  GbWorkbench *workbench;
  IdeContext *context;
  IdeVcs *vcs;
  GFile *workdir;
  g_autoptr(GFile) child = NULL;
  g_autoptr(GFile) parent = NULL;

  IDE_ENTRY;

  g_assert (command);
  g_assert (ar);
  g_assert (prefix);

  if (!(workbench = gb_widget_get_workbench (GTK_WIDGET (source_view))) ||
      !(context = gb_workbench_get_context (workbench)) ||
      !(vcs = ide_context_get_vcs (context)) ||
      !(workdir = ide_vcs_get_working_directory (vcs)))
    IDE_EXIT;

  child = g_file_get_child (workdir, prefix);

  if (g_file_query_exists (child, NULL))
    {
      if (g_file_query_file_type (child, 0, NULL) == G_FILE_TYPE_DIRECTORY)
        {
          g_autoptr(GFileEnumerator) fe = NULL;
          GFileInfo *descendent;

          if (!g_str_has_suffix (prefix, "/"))
            {
              g_ptr_array_add (ar, g_strdup_printf ("%s %s/", command, prefix));
              IDE_EXIT;
            }

          fe = g_file_enumerate_children (child,
                                          G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
                                          G_FILE_QUERY_INFO_NONE,
                                          NULL, NULL);

          if (fe == NULL)
            IDE_EXIT;

          while ((descendent = g_file_enumerator_next_file (fe, NULL, NULL)))
            {
              const gchar *name;

              name = g_file_info_get_display_name (descendent);
              g_ptr_array_add (ar, g_strdup_printf ("%s %s%s", command, prefix, name));
              g_object_unref (descendent);
            }

          IDE_EXIT;
        }
    }

  parent = g_file_get_parent (child);

  if (parent != NULL)
    {
      g_autoptr(GFileEnumerator) fe = NULL;
      g_autofree gchar *relpath = NULL;
      GFileInfo *descendent;
      const gchar *slash;

      relpath = g_file_get_relative_path (workdir, parent);

      if (relpath && g_str_has_prefix (relpath, "./"))
        {
          gchar *tmp = relpath;
          relpath = g_strdup (relpath + 2);
          g_free (tmp);
        }

#ifdef IDE_ENABLE_TRACE
      {
        g_autofree gchar *parent_path = g_file_get_path (parent);
        IDE_TRACE_MSG ("parent_path: %s", parent_path);
      }
#endif

      if ((slash = strrchr (prefix, G_DIR_SEPARATOR)))
        prefix = slash + 1;

      fe = g_file_enumerate_children (parent,
                                      G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
                                      G_FILE_QUERY_INFO_NONE,
                                      NULL, NULL);

      if (fe == NULL)
        IDE_EXIT;

      while ((descendent = g_file_enumerator_next_file (fe, NULL, NULL)))
        {
          const gchar *name;

          name = g_file_info_get_display_name (descendent);

          IDE_TRACE_MSG ("name=%s prefix=%s", name, prefix);

          if (name && g_str_has_prefix (name, prefix))
            {
              gchar *path;

              if (relpath)
                path = g_strdup_printf ("%s %s/%s", command, relpath, name);
              else
                path = g_strdup_printf ("%s %s", command, name);

              IDE_TRACE_MSG ("edit completion: %s", path);

              g_ptr_array_add (ar, path);
            }
          g_object_unref (descendent);
        }

      IDE_EXIT;
    }

  IDE_EXIT;
}
static gboolean
ide_highlight_engine_tick (IdeHighlightEngine *self)
{
    GtkTextBuffer *buffer;
    GtkTextIter iter;
    GtkTextIter invalid_begin;
    GtkTextIter invalid_end;
    GSList *tags_iter;

    IDE_PROBE;

    g_assert (IDE_IS_HIGHLIGHT_ENGINE (self));
    g_assert (self->buffer != NULL);
    g_assert (self->highlighter != NULL);
    g_assert (self->invalid_begin != NULL);
    g_assert (self->invalid_end != NULL);

    self->quanta_expiration = g_get_monotonic_time () + HIGHLIGHT_QUANTA_USEC;

    buffer = GTK_TEXT_BUFFER (self->buffer);

    gtk_text_buffer_get_iter_at_mark (buffer, &invalid_begin, self->invalid_begin);
    gtk_text_buffer_get_iter_at_mark (buffer, &invalid_end, self->invalid_end);

    IDE_TRACE_MSG ("Highlight Range [%u:%u,%u:%u] (%s)",
                   gtk_text_iter_get_line (&invalid_begin),
                   gtk_text_iter_get_line_offset (&invalid_begin),
                   gtk_text_iter_get_line (&invalid_end),
                   gtk_text_iter_get_line_offset (&invalid_end),
                   G_OBJECT_TYPE_NAME (self->highlighter));

    if (gtk_text_iter_compare (&invalid_begin, &invalid_end) >= 0)
        IDE_GOTO (up_to_date);

    /*Clear all our tags*/
    for (tags_iter = self->private_tags; tags_iter; tags_iter = tags_iter->next)
        gtk_text_buffer_remove_tag (buffer,
                                    GTK_TEXT_TAG (tags_iter->data),
                                    &invalid_begin,
                                    &invalid_end);

    iter = invalid_begin;

    ide_highlighter_update (self->highlighter, ide_highlight_engine_apply_style,
                            &invalid_begin, &invalid_end, &iter);

    if (gtk_text_iter_compare (&iter, &invalid_end) >= 0)
        IDE_GOTO (up_to_date);

    /* Stop processing until further instruction if no movement was made */
    if (gtk_text_iter_equal (&iter, &invalid_begin))
        return FALSE;

    gtk_text_buffer_move_mark (buffer, self->invalid_begin, &iter);

    return TRUE;

up_to_date:
    gtk_text_buffer_get_start_iter (buffer, &iter);
    gtk_text_buffer_move_mark (buffer, self->invalid_begin, &iter);
    gtk_text_buffer_move_mark (buffer, self->invalid_end, &iter);

    return FALSE;
}
示例#27
0
static void
ide_langserv_symbol_resolver_definition_cb (GObject      *object,
                                            GAsyncResult *result,
                                            gpointer      user_data)
{
  IdeLangservClient *client = (IdeLangservClient *)object;
  IdeLangservSymbolResolver *self;
  g_autoptr(GTask) task = user_data;
  g_autoptr(GError) error = NULL;
  g_autoptr(GVariant) return_value = NULL;
  g_autoptr(IdeSymbol) symbol = NULL;
  g_autoptr(IdeFile) ifile = NULL;
  g_autoptr(GFile) gfile = NULL;
  g_autoptr(IdeSourceLocation) location = NULL;
  g_autoptr(GVariant) variant = NULL;
  GVariantIter iter;
  const gchar *uri;
  struct {
    gint64 line;
    gint64 column;
  } begin, end;
  gboolean success = FALSE;

  IDE_ENTRY;

  g_assert (IDE_IS_LANGSERV_CLIENT (client));
  g_assert (G_IS_ASYNC_RESULT (result));
  g_assert (G_IS_TASK (task));
  self = g_task_get_source_object (task);
  g_assert (IDE_IS_LANGSERV_SYMBOL_RESOLVER (self));

  if (!ide_langserv_client_call_finish (client, result, &return_value, &error))
    {
      g_task_return_error (task, g_steal_pointer (&error));
      IDE_EXIT;
    }

#if 0
  {
    g_autofree gchar *str = g_variant_print (return_value, TRUE);
    IDE_TRACE_MSG ("Got reply: %s", str);
  }
#endif

  g_variant_iter_init (&iter, return_value);

  if (g_variant_iter_next (&iter, "v", &variant))
    {
      success = JSONRPC_MESSAGE_PARSE (variant,
        "uri", JSONRPC_MESSAGE_GET_STRING (&uri),
        "range", "{",
          "start", "{",
            "line", JSONRPC_MESSAGE_GET_INT64 (&begin.line),
            "character", JSONRPC_MESSAGE_GET_INT64 (&begin.column),
          "}",
          "end", "{",
            "line", JSONRPC_MESSAGE_GET_INT64 (&end.line),
            "character", JSONRPC_MESSAGE_GET_INT64 (&end.column),
          "}",
        "}"
      );
    }

  if (!success)
    {
      g_task_return_new_error (task,
                               G_IO_ERROR,
                               G_IO_ERROR_INVALID_DATA,
                               "Got invalid reply for textDocument/definition");
      IDE_EXIT;
    }

  IDE_TRACE_MSG ("Definition location is %s %d:%d",
                 uri, (gint)begin.line + 1, (gint)begin.column + 1);

  gfile = g_file_new_for_uri (uri);
  ifile = ide_file_new (ide_object_get_context (IDE_OBJECT (self)), gfile);
  location = ide_source_location_new (ifile, begin.line, begin.column, 0);
  symbol = ide_symbol_new ("", IDE_SYMBOL_NONE, IDE_SYMBOL_FLAGS_NONE, location, location, location);

  g_task_return_pointer (task, g_steal_pointer (&symbol), (GDestroyNotify)ide_symbol_unref);

  IDE_EXIT;
}
示例#28
0
static void
ide_clang_service_get_translation_unit_worker (EggTaskCache  *cache,
                                               gconstpointer  key,
                                               GTask         *task,
                                               gpointer       user_data)
{
  g_autoptr(GTask) real_task = NULL;
  IdeClangService *self = user_data;
  IdeUnsavedFiles *unsaved_files;
  IdeBuildSystem *build_system;
  ParseRequest *request;
  IdeContext *context;
  const gchar *path;
  IdeFile *file = (IdeFile *)key;
  GFile *gfile;

  g_assert (IDE_IS_CLANG_SERVICE (self));
  g_assert (IDE_IS_CLANG_SERVICE (self));
  g_assert (IDE_IS_FILE (key));
  g_assert (IDE_IS_FILE (file));
  g_assert (G_IS_TASK (task));

  context = ide_object_get_context (IDE_OBJECT (self));
  unsaved_files = ide_context_get_unsaved_files (context);
  build_system = ide_context_get_build_system (context);
  gfile = ide_file_get_file (file);

  if (!gfile || !(path = g_file_get_path (gfile)))
    {
      g_task_return_new_error (task,
                               G_IO_ERROR,
                               G_IO_ERROR_NOT_SUPPORTED,
                               _("File must be saved locally to parse."));
      return;
    }

  request = g_slice_new0 (ParseRequest);
  request->file = g_object_ref (file);
  request->index = self->index;
  request->source_filename = g_strdup (path);
  request->command_line_args = NULL;
  request->unsaved_files = ide_unsaved_files_to_array (unsaved_files);
  request->sequence = ide_unsaved_files_get_sequence (unsaved_files);
  /*
   * NOTE:
   *
   * I'm torn on this one. It requires a bunch of extra memory, but without it
   * we don't get information about macros.  And since we need that to provide
   * quality highlighting, I'm going try try enabling it for now and see how
   * things go.
   */
  request->options = (clang_defaultEditingTranslationUnitOptions () |
                      CXTranslationUnit_DetailedPreprocessingRecord);

  real_task = g_task_new (self,
                          g_task_get_cancellable (task),
                          ide_clang_service_unit_completed_cb,
                          g_object_ref (task));
  g_task_set_task_data (real_task, request, parse_request_free);

  /*
   * Request the build flags necessary to build this module from the build system.
   */
  IDE_TRACE_MSG ("Requesting build of translation unit");
  ide_build_system_get_build_flags_async (build_system,
                                          file,
                                          g_task_get_cancellable (task),
                                          ide_clang_service__get_build_flags_cb,
                                          g_object_ref (real_task));
}
示例#29
0
static void
ide_langserv_symbol_resolver_document_symbol_cb (GObject      *object,
                                                 GAsyncResult *result,
                                                 gpointer      user_data)
{
  IdeLangservClient *client = (IdeLangservClient *)object;
  g_autoptr(GTask) task = user_data;
  g_autoptr(IdeLangservSymbolTree) tree = NULL;
  g_autoptr(GError) error = NULL;
  g_autoptr(GVariant) return_value = NULL;
  g_autoptr(GPtrArray) symbols = NULL;
  GVariantIter iter;
  GVariant *node;

  IDE_ENTRY;

  g_assert (IDE_IS_LANGSERV_CLIENT (client));
  g_assert (G_IS_TASK (task));

  if (!ide_langserv_client_call_finish (client, result, &return_value, &error))
    {
      g_task_return_error (task, g_steal_pointer (&error));
      IDE_EXIT;
    }

  if (!g_variant_is_of_type (return_value, G_VARIANT_TYPE ("av")))
    {
      g_task_return_new_error (task,
                               G_IO_ERROR,
                               G_IO_ERROR_INVALID_DATA,
                               "Invalid result for textDocument/documentSymbol");
      IDE_EXIT;
    }

  symbols = g_ptr_array_new_with_free_func (g_object_unref);

  g_variant_iter_init (&iter, return_value);

  while (g_variant_iter_loop (&iter, "v", &node))
    {
      g_autoptr(IdeLangservSymbolNode) symbol = NULL;
      g_autoptr(GFile) file = NULL;
      const gchar *name = NULL;
      const gchar *container_name = NULL;
      const gchar *uri = NULL;
      gboolean success;
      gint64 kind = -1;
      struct {
        gint64 line;
        gint64 column;
      } begin, end;

      /* Mandatory fields */
      success = JSONRPC_MESSAGE_PARSE (node,
        "name", JSONRPC_MESSAGE_GET_STRING (&name),
        "kind", JSONRPC_MESSAGE_GET_INT64 (&kind),
        "location", "{",
          "uri", JSONRPC_MESSAGE_GET_STRING (&uri),
          "range", "{",
            "start", "{",
              "line", JSONRPC_MESSAGE_GET_INT64 (&begin.line),
              "character", JSONRPC_MESSAGE_GET_INT64 (&begin.column),
            "}",
            "end", "{",
              "line", JSONRPC_MESSAGE_GET_INT64 (&end.line),
              "character", JSONRPC_MESSAGE_GET_INT64 (&end.column),
            "}",
          "}",
        "}"
      );

      if (!success)
        {
          IDE_TRACE_MSG ("Failed to parse reply from language server");
          continue;
        }

      /* Optional fields */
      JSONRPC_MESSAGE_PARSE (node, "containerName", JSONRPC_MESSAGE_GET_STRING (&container_name));

      file = g_file_new_for_uri (uri);

      symbol = ide_langserv_symbol_node_new (file, name, container_name, kind,
                                             begin.line, begin.column,
                                             end.line, end.column);

      g_ptr_array_add (symbols, g_steal_pointer (&symbol));
    }

  tree = ide_langserv_symbol_tree_new (g_steal_pointer (&symbols));

  g_task_return_pointer (task, g_steal_pointer (&tree), g_object_unref);

  IDE_EXIT;
}