[gnome-builder] beautifier plugin: add support for generic commands
- From: Sébastien Lafargue <slafargue src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] beautifier plugin: add support for generic commands
- Date: Thu, 12 Jan 2017 22:24:57 +0000 (UTC)
commit 26db3f4613230b8f90d4751ab546364748997d6a
Author: Sebastien Lafargue <slafargue gnome org>
Date: Sun Dec 4 00:31:43 2016 +0100
beautifier plugin: add support for generic commands
in config.ini files, you can now use
command-pattern key and commandline like pattern:
the command name is used as the first argument
@c@ is replaced by the config file path
@s@ is replaced by the selected text file
for example:
command-pattern = uncrustify -c @c@ -f @s@
.beautifier/c/config.ini | 5 +
plugins/beautifier/gb-beautifier-config.c | 85 +++++++++++++------
plugins/beautifier/gb-beautifier-config.h | 5 +-
plugins/beautifier/gb-beautifier-process.c | 126 +++++++++++++++++++++++-----
4 files changed, 171 insertions(+), 50 deletions(-)
---
diff --git a/.beautifier/c/config.ini b/.beautifier/c/config.ini
index 22f9bf3..3b79ccf 100644
--- a/.beautifier/c/config.ini
+++ b/.beautifier/c/config.ini
@@ -14,3 +14,8 @@ name = GNOME Builder project
command = clang-format
name = GNOME Builder project clang-format
+
+[fake.cfg]
+
+command-pattern = uncrustify -c @c@ -f @s@
+name = GNOME Builder project pattern
diff --git a/plugins/beautifier/gb-beautifier-config.c b/plugins/beautifier/gb-beautifier-config.c
index d2c5d48..73f0aac 100644
--- a/plugins/beautifier/gb-beautifier-config.c
+++ b/plugins/beautifier/gb-beautifier-config.c
@@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <string.h>
#include <ide.h>
#include "gb-beautifier-private.h"
@@ -31,6 +32,9 @@ config_entry_clear_func (gpointer data)
g_object_unref (entry->file);
g_free (entry->name);
g_free (entry->lang_id);
+
+ if (entry->command_args != NULL)
+ g_ptr_array_unref (entry->command_args);
}
static void
@@ -132,7 +136,14 @@ add_entries_from_config_ini_file (GbBeautifierWorkbenchAddin *self,
{
g_autofree gchar *display_name = NULL;
g_autofree gchar *command = NULL;
+ g_autofree gchar *command_pattern = NULL;
+ g_autoptr(GFile) file = NULL;
+ g_autofree gchar *config_path = 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"))
@@ -149,41 +160,65 @@ add_entries_from_config_ini_file (GbBeautifierWorkbenchAddin *self,
if (gb_beautifier_config_check_duplicates (self, entries, lang_id, display_name))
continue;
- if ( NULL != (command = g_key_file_get_string (key_file, profile, "command", &error)))
+ has_command = g_key_file_has_key (key_file, profile, "command", &error);
+ has_command_pattern = g_key_file_has_key (key_file, profile, "command-pattern", &error);
+ if (!has_command && !has_command_pattern)
{
- g_autoptr(GFile) file = NULL;
- g_autofree gchar *file_path = NULL;
+ g_warning ("beautifier plugin: neither command nor command-pattern keys found");
+ g_warning ("entry \"%s\" disabled", display_name);
+ continue;
+ }
- if (0 == g_strcmp0 (command, "uncrustify"))
- entry.command = GB_BEAUTIFIER_CONFIG_COMMAND_UNCRUSTIFY;
- else if (0 == g_strcmp0 (command, "clang-format"))
+ memset (&entry, 0, sizeof(GbBeautifierConfigEntry));
+ if (has_command)
+ {
+ command = g_key_file_get_string (key_file, profile, "command", &error);
+ if (0 == g_strcmp0 (command, "clang-format"))
entry.command = GB_BEAUTIFIER_CONFIG_COMMAND_CLANG_FORMAT;
else
- goto fail;
+ {
+ 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", &error);
+ 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);
+ }
+
+ config_path = g_build_filename (base_path, real_lang_id, profile, NULL);
+ file = g_file_new_for_path (config_path);
+ if (g_file_query_exists (file, NULL))
+ {
+ entry.name = g_steal_pointer (&display_name);
+ entry.file = g_steal_pointer (&file);
+ entry.lang_id = g_strdup (lang_id);
- file_path = g_build_filename (base_path, real_lang_id, profile, NULL);
- file = g_file_new_for_path (file_path);
- if (g_file_query_exists (file, NULL))
+ if (0 == g_strcmp0 (default_profile, profile))
{
- entry.name = g_steal_pointer (&display_name);
- entry.file = g_steal_pointer (&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);
+ entry.is_default = TRUE;
+ g_clear_pointer (&default_profile, g_free);
}
else
- g_warning ("Can't find \"%s\"", file_path);
+ entry.is_default = FALSE;
+
+ g_array_append_val (entries, entry);
}
else
- goto fail;
+ g_warning ("Can't find \"%s\"", config_path);
}
}
diff --git a/plugins/beautifier/gb-beautifier-config.h b/plugins/beautifier/gb-beautifier-config.h
index 94d8cfe..53b9642 100644
--- a/plugins/beautifier/gb-beautifier-config.h
+++ b/plugins/beautifier/gb-beautifier-config.h
@@ -27,8 +27,8 @@ G_BEGIN_DECLS
typedef enum
{
- GB_BEAUTIFIER_CONFIG_COMMAND_CLANG_FORMAT,
- GB_BEAUTIFIER_CONFIG_COMMAND_UNCRUSTIFY,
+ GB_BEAUTIFIER_CONFIG_COMMAND_NONE,
+ GB_BEAUTIFIER_CONFIG_COMMAND_CLANG_FORMAT
} GbBeautifierConfigCommand;
typedef struct
@@ -37,6 +37,7 @@ typedef struct
GFile *file;
gchar *name;
GbBeautifierConfigCommand command;
+ GPtrArray *command_args;
guint is_default : 1;
} GbBeautifierConfigEntry;
diff --git a/plugins/beautifier/gb-beautifier-process.c b/plugins/beautifier/gb-beautifier-process.c
index 2c7dace..0b9e137 100644
--- a/plugins/beautifier/gb-beautifier-process.c
+++ b/plugins/beautifier/gb-beautifier-process.c
@@ -32,6 +32,7 @@ typedef struct
GtkTextMark *begin_mark;
GtkTextMark *end_mark;
GbBeautifierConfigCommand command;
+ GPtrArray *command_args;
GFile *src_file;
GFile *config_file;
GFile *tmp_workdir_file;
@@ -68,44 +69,101 @@ process_state_free (gpointer data)
g_free (state->lang_id);
g_free (state->text);
+ if (state->command_args != NULL)
+ g_ptr_array_unref (state->command_args);
+
g_slice_free (ProcessState, state);
}
+static gchar *
+match_and_replace (const gchar *str,
+ const gchar *pattern,
+ const gchar *replacement)
+{
+ g_autofree gchar *head = NULL;
+ g_autofree gchar *tail = NULL;
+ gchar *needle;
+ gsize head_len;
+
+ g_assert (!ide_str_empty0 (str));
+ g_assert (!ide_str_empty0 (pattern));
+
+ if (NULL != (needle = g_strstr_len (str, -1, pattern)))
+ {
+ head_len = needle - str;
+ if (head_len > 0)
+ head = g_strndup (str, head_len);
+ else
+ head = g_strdup ("");
+
+ tail = needle + strlen (pattern);
+ if (*tail != '\0')
+ tail = g_strdup (tail);
+ else
+ tail = g_strdup ("");
+
+ return g_strconcat (head, replacement, tail, NULL);
+ }
+ else
+ return NULL;
+}
+
+static void
+command_args_expand (GbBeautifierWorkbenchAddin *self,
+ GPtrArray *args,
+ ProcessState *state)
+{
+ g_autofree gchar *src_path = NULL;
+ g_autofree gchar *config_path = NULL;
+ gchar **arg_adr;
+ gchar *new_arg;
+ gboolean has_config = TRUE;
+
+ src_path = g_file_get_path (state->src_file);
+ if (G_IS_FILE (state->config_file))
+ config_path = g_file_get_path (state->config_file);
+ else
+ has_config = FALSE;
+
+ for (gint i = 0; g_ptr_array_index (args, i) != NULL; ++i)
+ {
+ arg_adr = (gchar **)&g_ptr_array_index (args, i);
+ if (NULL != (new_arg = match_and_replace (*arg_adr, "@s@", src_path)))
+ {
+ g_free (*arg_adr);
+ *arg_adr = new_arg;
+ }
+ else if (has_config &&
+ NULL != (new_arg = match_and_replace (*arg_adr, "@c@", config_path)))
+ {
+ g_free (*arg_adr);
+ *arg_adr = new_arg;
+ }
+ }
+}
+
static GSubprocess *
-gb_beautifier_process_create_for_uncrustify (GbBeautifierWorkbenchAddin *self,
- ProcessState *state,
- GError *error)
+gb_beautifier_process_create_generic (GbBeautifierWorkbenchAddin *self,
+ ProcessState *state,
+ GError *error)
{
GSubprocess *subprocess = NULL;
- GPtrArray *args;
- gchar *config_path;
gchar *src_path;
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));
- args = g_ptr_array_new ();
- g_ptr_array_add (args, "uncrustify");
-
- g_ptr_array_add (args, "-c");
- g_ptr_array_add (args, config_path);
- g_ptr_array_add (args, "-f");
- g_ptr_array_add (args, src_path);
- g_ptr_array_add (args, NULL);
-
- subprocess = g_subprocess_newv ((const gchar * const *)args->pdata,
+ 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);
- g_ptr_array_free (args, TRUE);
return subprocess;
}
@@ -184,6 +242,7 @@ process_communicate_utf8_cb (GObject *object,
g_autoptr (GSubprocess) process = (GSubprocess *)object;
g_autoptr (GTask) task = (GTask *)user_data;
g_autofree gchar *stdout_str = NULL;
+ g_autofree gchar *stderr_str = NULL;
g_autoptr(GError) error = NULL;
GtkSourceCompletion *completion;
GtkTextBuffer *buffer;
@@ -195,7 +254,7 @@ process_communicate_utf8_cb (GObject *object,
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (G_IS_TASK (task));
- if (!g_subprocess_communicate_utf8_finish (process, result, &stdout_str, NULL, &error))
+ if (!g_subprocess_communicate_utf8_finish (process, result, &stdout_str, &stderr_str, &error))
{
g_task_return_error (task, g_steal_pointer (&error));
return;
@@ -229,6 +288,11 @@ process_communicate_utf8_cb (GObject *object,
g_task_return_boolean (task, TRUE);
}
+ else
+ g_warning ("beautify plugin: output empty\n");
+
+ g_warning ("beautify plugin stderr:\n%s\n", stderr_str);
+
}
static void
@@ -251,12 +315,10 @@ create_tmp_file_cb (GObject *object,
if (NULL == (state->src_file = gb_beautifier_helper_create_tmp_file_finish (self, result, &error)))
goto fail;
- if (state->command == GB_BEAUTIFIER_CONFIG_COMMAND_UNCRUSTIFY)
- process = gb_beautifier_process_create_for_uncrustify (self, state, error);
- else if (state->command == GB_BEAUTIFIER_CONFIG_COMMAND_CLANG_FORMAT)
+ if (state->command == GB_BEAUTIFIER_CONFIG_COMMAND_CLANG_FORMAT)
process = gb_beautifier_process_create_for_clang_format (self, state, error);
else
- g_assert_not_reached ();
+ process = gb_beautifier_process_create_generic (self, state, error);
if (process != NULL)
{
@@ -280,6 +342,22 @@ fail:
return;
}
+static GPtrArray *
+command_args_copy (GPtrArray *args)
+{
+ GPtrArray *args_copy;
+
+ g_assert (args != NULL);
+
+ args_copy = g_ptr_array_new_with_free_func (g_free);
+ for (gint i = 0; g_ptr_array_index (args, i) != NULL; ++i)
+ g_ptr_array_add (args_copy, g_strdup (g_ptr_array_index (args, i)));
+
+ g_ptr_array_add (args_copy, NULL);
+
+ return args_copy;
+}
+
void
gb_beautifier_process_launch_async (GbBeautifierWorkbenchAddin *self,
IdeSourceView *source_view,
@@ -325,6 +403,8 @@ gb_beautifier_process_launch_async (GbBeautifierWorkbenchAddin *self,
state->config_file = g_file_dup (entry->file);
state->lang_id = g_strdup (lang_id);
+ 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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]