Beispiel #1
0
static gboolean
gb_beautifier_config_check_duplicates (GbBeautifierWorkbenchAddin *self,
                                       GArray                     *entries,
                                       const gchar                *lang_id,
                                       const gchar                *display_name)
{
  g_assert (GB_IS_BEAUTIFIER_WORKBENCH_ADDIN (self));
  g_assert (entries != NULL);
  g_assert (!ide_str_empty0 (lang_id));
  g_assert (!ide_str_empty0 (display_name));

  for (gint i = 0; i < entries->len; ++i)
    {
      GbBeautifierConfigEntry *entry = &g_array_index (entries, GbBeautifierConfigEntry, i);

      /* Check for a NULL element at the array end */
      if (entry->config_file == NULL)
        break;

      if (0 == g_strcmp0 (entry->lang_id, lang_id) &&
          0 == g_strcmp0 (entry->name, display_name))
        return TRUE;
    }

  return FALSE;
}
Beispiel #2
0
void
gb_beautifier_process_launch_async (GbBeautifierWorkbenchAddin  *self,
                                    IdeSourceView               *source_view,
                                    GtkTextIter                 *begin,
                                    GtkTextIter                 *end,
                                    GbBeautifierConfigEntry     *entry,
                                    GAsyncReadyCallback          callback,
                                    GCancellable                *cancellable,
                                    gpointer                     user_data)
{
  GtkTextBuffer *buffer;
  ProcessState *state;
  g_autoptr(GTask) task = NULL;
  const gchar *lang_id;

  g_assert (GB_IS_BEAUTIFIER_WORKBENCH_ADDIN (self));
  g_assert (IDE_IS_SOURCE_VIEW (source_view));
  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
  g_assert (entry != NULL);
  g_assert (callback != NULL);

  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view));
  lang_id = gb_beautifier_helper_get_lang_id (self, source_view);

  if (begin == NULL)
    gtk_text_buffer_get_start_iter (buffer, begin);

  if (end == NULL)
    gtk_text_buffer_get_end_iter (buffer, begin);

  g_assert (gtk_text_iter_get_buffer (begin) == buffer);
  g_assert (gtk_text_iter_get_buffer (end) == buffer);

  state = g_slice_new0 (ProcessState);
  state->self = self;
  state->source_view = source_view;

  gtk_text_iter_order (begin, end);
  state->text = gtk_text_buffer_get_text (buffer, begin, end, FALSE);
  state->begin_mark = gtk_text_buffer_create_mark (buffer, NULL, begin, TRUE);
  state->end_mark = gtk_text_buffer_create_mark (buffer, NULL, end, FALSE);
  state->command = entry->command;
  state->lang_id = g_strdup (lang_id);

  if (G_IS_FILE (entry->config_file))
    state->config_file = g_file_dup (entry->config_file);

  if (entry->command_args != NULL)
    state->command_args = command_args_copy (entry->command_args);
  task = g_task_new (self, cancellable, callback, user_data);
  g_task_set_source_tag (task, gb_beautifier_process_launch_async);
  g_task_set_task_data (task, state, process_state_free);

  gb_beautifier_helper_create_tmp_file_async (self,
                                              state->text,
                                              create_tmp_file_cb,
                                              cancellable,
                                              g_steal_pointer (&task));
}
Beispiel #3
0
gboolean
gb_beautifier_process_launch_finish (GbBeautifierWorkbenchAddin  *self,
                                     GAsyncResult                *result,
                                     GError                     **error)
{
  g_assert (GB_IS_BEAUTIFIER_WORKBENCH_ADDIN (self));
  g_assert (g_task_is_valid (result, self));

  return g_task_propagate_boolean (G_TASK (result), error);
}
Beispiel #4
0
static GArray *
gb_beautifier_config_get_map (GbBeautifierWorkbenchAddin *self,
                              const gchar                *path)
{
  GArray *map;
  g_autofree gchar *file_name = NULL;
  g_autoptr(GKeyFile) key_file = NULL;
  g_auto(GStrv) lang_ids = NULL;
  gsize nb_lang_ids;
  GError *error = NULL;

  g_assert (GB_IS_BEAUTIFIER_WORKBENCH_ADDIN (self));
  g_assert (!ide_str_empty0 (path));

  map = g_array_new (TRUE, TRUE, sizeof (GbBeautifierMapEntry));
  g_array_set_clear_func (map, map_entry_clear_func);
  file_name = g_build_filename (path,
                                "global.ini",
                                NULL);

  key_file = g_key_file_new ();
  if (!g_file_test (file_name, G_FILE_TEST_EXISTS))
    {
      g_debug ("%s doesn't exist", file_name);
      return map;
    }

  if (g_key_file_load_from_file (key_file, file_name, G_KEY_FILE_NONE, &error) &&
      NULL != (lang_ids = g_key_file_get_groups (key_file, &nb_lang_ids)))
    {
      for (gint i = 0; i < nb_lang_ids; ++i)
        {
          g_autofree gchar *mapped_lang_id = NULL;
          g_autofree gchar *default_profile = NULL;
          GbBeautifierMapEntry entry;
          gchar *lang_id = lang_ids [i];

          if (!is_a_lang_id (self, lang_id) ||
              NULL == (mapped_lang_id = g_key_file_get_string (key_file, lang_id, "map", NULL)))
            continue;

          if (gb_beautifier_map_check_duplicates (self, map, lang_id))
            continue;

          default_profile = g_key_file_get_string (key_file, lang_id, "default", NULL);

          entry.lang_id = g_strdup (lang_id);
          entry.mapped_lang_id = g_steal_pointer (&mapped_lang_id);
          entry.default_profile = g_steal_pointer (&default_profile);
          g_array_append_val (map, entry);
        }
    }

  return map;
}
Beispiel #5
0
GArray *
gb_beautifier_config_get_entries (GbBeautifierWorkbenchAddin *self)
{
  IdeContext *context;
  IdeVcs *vcs;
  GArray *entries;
  GArray *map = NULL;
  g_autofree gchar *project_config_path = NULL;
  g_autofree gchar *user_config_path = NULL;

  g_assert (GB_IS_BEAUTIFIER_WORKBENCH_ADDIN (self));

  entries = g_array_new (TRUE, TRUE, sizeof (GbBeautifierConfigEntry));
  g_array_set_clear_func (entries, config_entry_clear_func);

  /* User wide config: ~/.config/gnome-builder/beautifier_plugin */
  user_config_path = g_build_filename (g_get_user_config_dir (),
                                       ide_get_program_name (),
                                       "beautifier_plugin",
                                       NULL);
  map = gb_beautifier_config_get_map (self, user_config_path);
  add_entries_from_base_path (self, user_config_path, entries, map);
  if (map != NULL)
    g_array_free (map, TRUE);

  /* Project wide config */
  if (NULL != (context = ide_workbench_get_context (self->workbench)) &&
      NULL != (vcs = ide_context_get_vcs (context)))
    {
      GFile *workdir;
      g_autofree gchar *workdir_path = NULL;

      workdir = ide_vcs_get_working_directory (vcs);
      workdir_path = g_file_get_path (workdir);
      project_config_path = g_build_filename (workdir_path,
                                              ".beautifier",
                                              NULL);
      map = gb_beautifier_config_get_map (self, project_config_path);
      add_entries_from_base_path (self, project_config_path, entries, map);
      if (map != NULL)
        g_array_free (map, TRUE);
    }

  /* System wide config */
  map = gb_beautifier_config_get_map (self, GB_BEAUTIFIER_PLUGIN_DATADIR);
  add_entries_from_base_path (self, GB_BEAUTIFIER_PLUGIN_DATADIR, entries, map);
  if (map != NULL)
    g_array_free (map, TRUE);

  return entries;
}
Beispiel #6
0
static void
create_tmp_file_cb (GObject      *object,
                    GAsyncResult *result,
                    gpointer      user_data)
{
  GbBeautifierWorkbenchAddin  *self = (GbBeautifierWorkbenchAddin  *)object;
  g_autoptr (GTask) task = (GTask *)user_data;
  g_autoptr(GError) error = NULL;
  ProcessState *state;
  GSubprocess *process;
  GCancellable *cancellable;

  g_assert (GB_IS_BEAUTIFIER_WORKBENCH_ADDIN (self));
  g_assert (G_IS_ASYNC_RESULT (result));
  g_assert (G_IS_TASK (task));

  state = (ProcessState *)g_task_get_task_data (task);
  if (NULL == (state->src_file = gb_beautifier_helper_create_tmp_file_finish (self, result, &error)))
    goto fail;

  if (state->command == GB_BEAUTIFIER_CONFIG_COMMAND_CLANG_FORMAT)
    process = gb_beautifier_process_create_for_clang_format (self, state, error);
  else
    process = gb_beautifier_process_create_generic (self, state, error);

  if (process != NULL)
    {
      if (g_task_return_error_if_cancelled (task))
        g_object_unref (process);
      else
        {
          cancellable = g_task_get_cancellable (task);
          g_subprocess_communicate_utf8_async (process,
                                               NULL,
                                               cancellable,
                                               process_communicate_utf8_cb,
                                               g_steal_pointer (&task));
        }

      return;
    }

fail:
  g_task_return_error (task, g_steal_pointer (&error));
  return;
}
Beispiel #7
0
static gboolean
gb_beautifier_map_check_duplicates (GbBeautifierWorkbenchAddin *self,
                                    GArray                     *map,
                                    const gchar                *lang_id)
{
  g_assert (GB_IS_BEAUTIFIER_WORKBENCH_ADDIN (self));
  g_assert (map != NULL);
  g_assert (!ide_str_empty0 (lang_id));

  for (gint i = 0; i < map->len; ++i)
    {
      GbBeautifierMapEntry *entry = &g_array_index (map, GbBeautifierMapEntry, i);

      /* Check for a NULL element at the array end */
      if (entry->lang_id == NULL)
        break;

      if (0 == g_strcmp0 (entry->lang_id, lang_id))
        return TRUE;
    }

  return FALSE;
}
Beispiel #8
0
static GSubprocess *
gb_beautifier_process_create_generic (GbBeautifierWorkbenchAddin *self,
                                      ProcessState               *state,
                                      GError                     *error)
{
  GSubprocess *subprocess = NULL;
  gchar *src_path;

  g_assert (GB_IS_BEAUTIFIER_WORKBENCH_ADDIN (self));
  g_assert (state != NULL);

  src_path = g_file_get_path (state->src_file);

  g_assert (!ide_str_empty0 (src_path));
  g_assert (!ide_str_empty0 (state->lang_id));

  command_args_expand (self, state->command_args, state);
  subprocess = g_subprocess_newv ((const gchar * const *)state->command_args->pdata,
                                  G_SUBPROCESS_FLAGS_STDOUT_PIPE |
                                  G_SUBPROCESS_FLAGS_STDERR_PIPE,
                                  &error);

  return subprocess;
}
Beispiel #9
0
static GSubprocess *
gb_beautifier_process_create_for_clang_format (GbBeautifierWorkbenchAddin *self,
                                               ProcessState               *state,
                                               GError                     *error)
{
  g_autoptr(GSubprocessLauncher) launcher = NULL;
  GSubprocess *subprocess = NULL;
  GPtrArray *args;
  gchar *config_path;
  gchar *src_path;
  g_autofree gchar *tmp_workdir = NULL;
  g_autofree gchar *tmp_config_path = NULL;
  g_autofree gchar *tmp_src_path = NULL;

  g_assert (GB_IS_BEAUTIFIER_WORKBENCH_ADDIN (self));
  g_assert (state != NULL);

  config_path = g_file_get_path (state->config_file);
  src_path = g_file_get_path (state->src_file);

  g_assert (!ide_str_empty0 (config_path));
  g_assert (!ide_str_empty0 (src_path));
  g_assert (!ide_str_empty0 (state->lang_id));

  if (NULL == (tmp_workdir = g_dir_make_tmp ("gnome-builder-beautify-XXXXXX",
                                             &error)))
    return NULL;

  state->tmp_workdir_file = g_file_new_for_path (tmp_workdir);
  tmp_config_path = g_build_filename (tmp_workdir,
                                      ".clang-format",
                                      NULL);
  state->tmp_config_file = g_file_new_for_path (tmp_config_path);
  if (!g_file_copy (state->config_file,
                    state->tmp_config_file,
                    G_FILE_COPY_OVERWRITE,
                    NULL, NULL, NULL,
                    &error))
    return NULL;

  tmp_src_path = g_build_filename (tmp_workdir,
                                   "src_file",
                                   NULL);
  state->tmp_src_file = g_file_new_for_path (tmp_src_path);
  if (!g_file_copy (state->src_file,
                    state->tmp_src_file,
                    G_FILE_COPY_OVERWRITE,
                    NULL, NULL, NULL,
                    &error))
    return NULL;

  args = g_ptr_array_new ();
  g_ptr_array_add (args, "clang-format");
  g_ptr_array_add (args, "-style=file");
  g_ptr_array_add (args, tmp_src_path);
  g_ptr_array_add (args, NULL);

  launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE);
  g_subprocess_launcher_set_cwd (launcher, tmp_workdir);
  subprocess = g_subprocess_launcher_spawnv (launcher,
                                             (const gchar * const *)args->pdata,
                                             &error);

  g_ptr_array_free (args, TRUE);
  return subprocess;
}
Beispiel #10
0
static gboolean
add_entries_from_base_path (GbBeautifierWorkbenchAddin *self,
                            const gchar                *base_path,
                            GArray                     *entries,
                            GArray                     *map)
{
  g_autoptr(GFileEnumerator) enumerator = NULL;
  g_autoptr(GFile) parent_file = NULL;
  GFileInfo *child_info;
  GError *error = NULL;
  gboolean ret = FALSE;

  g_assert (GB_IS_BEAUTIFIER_WORKBENCH_ADDIN (self));
  g_assert (!ide_str_empty0 (base_path));
  g_assert (entries != NULL);
  g_assert (map != NULL);

  parent_file = g_file_new_for_path (base_path);
  if (NULL == (enumerator = g_file_enumerate_children (parent_file,
                                                       G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME","
                                                       G_FILE_ATTRIBUTE_STANDARD_TYPE,
                                                       G_FILE_QUERY_INFO_NONE,
                                                       NULL,
                                                       &error)))
    {
      g_debug ("\"%s\"", error->message);
      return FALSE;
    }

  while ((child_info = g_file_enumerator_next_file (enumerator, NULL, &error)))
    {
      g_autoptr(GFileInfo) info = child_info;
      GFileType type;
      GbBeautifierMapEntry *entry;
      const gchar *real_lang_id;

      type = g_file_info_get_file_type (info);
      if (type == G_FILE_TYPE_DIRECTORY)
        {
          real_lang_id = g_file_info_get_display_name (info);
          if (is_a_lang_id (self, real_lang_id) &&
              add_entries_from_config_ini_file (self,
                                                base_path,
                                                real_lang_id,
                                                real_lang_id,
                                                entries,
                                                NULL,
                                                FALSE))
            ret = TRUE;

          for (gint i = 0; i < map->len; ++i)
            {
              entry = &g_array_index (map, GbBeautifierMapEntry, i);
              if (0 == g_strcmp0 (entry->mapped_lang_id, real_lang_id) &&
                  add_entries_from_config_ini_file (self,
                                                    base_path,
                                                    entry->lang_id,
                                                    real_lang_id,
                                                    entries,
                                                    entry->default_profile,
                                                    TRUE))
                ret = TRUE;
            }
        }
    }

  if (error != NULL)
    g_warning ("\"%s\"", error->message);

  return ret;
}
Beispiel #11
0
static gboolean
add_entries_from_config_ini_file (GbBeautifierWorkbenchAddin *self,
                                  const gchar                *base_path,
                                  const gchar                *lang_id,
                                  const gchar                *real_lang_id,
                                  GArray                     *entries,
                                  const gchar                *map_default,
                                  gboolean                    is_from_map)
{
  g_autoptr(GKeyFile) key_file = NULL;
  g_autofree gchar *ini_path = NULL;
  g_auto(GStrv) profiles = NULL;
  g_autofree gchar *default_profile = NULL;
  GbBeautifierConfigEntry entry;
  gsize nb_profiles;
  GError *error = NULL;

  g_assert (GB_IS_BEAUTIFIER_WORKBENCH_ADDIN (self));
  g_assert (!ide_str_empty0 (base_path));
  g_assert (!ide_str_empty0 (lang_id));
  g_assert (!ide_str_empty0 (real_lang_id));
  g_assert (entries != NULL);

  key_file = g_key_file_new ();
  ini_path = g_build_filename (base_path, real_lang_id, "config.ini", NULL);

  if (!g_file_test (ini_path, G_FILE_TEST_EXISTS))
    {
      g_debug ("%s doesn't exist", ini_path);
      return FALSE;
    }

  if (!g_key_file_load_from_file (key_file, ini_path, G_KEY_FILE_NONE, &error))
    return FALSE;

  if (map_default != NULL)
    default_profile = g_strdup (map_default);

  if (NULL != (profiles = g_key_file_get_groups (key_file, &nb_profiles)))
    {
      for (gint i = 0; i < nb_profiles; ++i)
        {
          g_autofree gchar *display_name = NULL;
          g_autofree gchar *command = NULL;
          g_autofree gchar *command_pattern = NULL;
          g_autofree gchar *config_name = NULL;
          g_autofree gchar *config_path = NULL;
          g_autoptr(GFile) config_file = NULL;
          g_auto(GStrv) strv = NULL;
          gint argc;
          gchar *profile;
          gboolean has_command;
          gboolean has_command_pattern;

          profile = profiles [i];
          if (0 == g_strcmp0 (profile, "global"))
            {
              if (!is_from_map && default_profile == NULL)
                default_profile = g_key_file_get_string (key_file, profile, "default", NULL);

              continue;
            }

          if (NULL == (display_name = g_key_file_get_string (key_file, profile, "name", &error)))
            goto fail;

          if (gb_beautifier_config_check_duplicates (self, entries, lang_id, display_name))
            continue;

          has_command = g_key_file_has_key (key_file, profile, "command", NULL);
          has_command_pattern = g_key_file_has_key (key_file, profile, "command-pattern", NULL);
          if (!has_command && !has_command_pattern)
            {
              g_warning ("beautifier plugin: neither command nor command-pattern keys found");
              g_warning ("entry \"%s\" disabled", display_name);
              continue;
            }

          if (NULL != (config_name = g_key_file_get_string (key_file, profile, "config", NULL)))
            {
              config_path = g_build_filename (base_path, real_lang_id, config_name, NULL);
              config_file = g_file_new_for_path (config_path);
              if (!g_file_query_exists (config_file, NULL))
                {
                  g_warning ("beautifier plugin: \"%s\" does not exist", config_path);
                  g_warning ("entry \"%s\" disabled", display_name);
                  continue;
                }
            }

          memset (&entry, 0, sizeof(GbBeautifierConfigEntry));
          if (has_command)
            {
              command = g_key_file_get_string (key_file, profile, "command", NULL);
              if (0 == g_strcmp0 (command, "clang-format"))
                entry.command = GB_BEAUTIFIER_CONFIG_COMMAND_CLANG_FORMAT;
              else
                {
                  g_warning ("beautifier plugin: command key out of possible values");
                  g_warning ("entry \"%s\" disabled", display_name);
                  continue;
                }
            }
          else
            {
              command_pattern = g_key_file_get_string (key_file, profile, "command-pattern", NULL);
              if (g_strstr_len (command_pattern, -1, "@c@") == NULL && config_file != NULL)
                {
                  g_warning ("beautifier plugin: @c@ in \"%s\" command-pattern key but no config file set",
                             profile);
                  g_warning ("entry \"%s\" disabled", display_name);
                  continue;
                }

              if (!g_shell_parse_argv (command_pattern, &argc, &strv, &error))
                {
                  g_warning ("beautifier plugin: \"%s\"", error->message);
                  return FALSE;
                }

              entry.command = GB_BEAUTIFIER_CONFIG_COMMAND_NONE;
              entry.command_args = g_ptr_array_new_with_free_func (g_free);
              for (gint j = 0; strv [j] != NULL; ++j)
                g_ptr_array_add (entry.command_args, g_strdup (strv [j]));

              g_ptr_array_add (entry.command_args, NULL);
            }

            entry.name = g_steal_pointer (&display_name);
            entry.config_file = g_steal_pointer (&config_file);
            entry.lang_id = g_strdup (lang_id);

            if (0 == g_strcmp0 (default_profile, profile))
              {
                entry.is_default = TRUE;
                g_clear_pointer (&default_profile, g_free);
              }
            else
              entry.is_default = FALSE;

            g_array_append_val (entries, entry);
        }
    }

  return TRUE;

fail:
  g_warning ("\"%s\"", error->message);

  return FALSE;
}