summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLeonardo Taccari <iamleot@gmail.com>2018-10-19 13:04:41 +0200
committerLeonardo Taccari <iamleot@gmail.com>2018-10-25 00:09:42 +0200
commit51949de98cba926ff9ae0d08d95ef795612472ec (patch)
treed991f7f4fd9c1f7421f75bb763adcdb7ec333e95 /src
parenta40526042e9c1a26982a5eb504dd78d34dde649a (diff)
Add command_spawn_editor() and implement normal_view_source()
- Add a command_spawn_editor() to asynchronously spawn editor - Adjust input_editor_formfiller() to use command_spawn_editor() - Add support to view the source of the current page via the editor (`gf' command).
Diffstat (limited to 'src')
-rw-r--r--src/command.c103
-rw-r--r--src/command.h3
-rw-r--r--src/input.c123
-rw-r--r--src/normal.c24
4 files changed, 163 insertions, 90 deletions
diff --git a/src/command.c b/src/command.c
index 118881f..344a06d 100644
--- a/src/command.c
+++ b/src/command.c
@@ -30,8 +30,18 @@
#endif
#include "command.h"
#include "history.h"
+#include "util.h"
#include "main.h"
+typedef struct {
+ Client *c;
+ char *file;
+ gpointer *data;
+ PostEditFunc func;
+} EditorData;
+
+static void resume_editor(GPid pid, int status, gpointer edata);
+
/**
* Start/perform/stop searching in webview.
*
@@ -260,3 +270,96 @@ gboolean command_queue(Client *c, const Arg *arg)
return res;
}
#endif
+
+/**
+ * Asynchronously spawn editor.
+ *
+ * @posteditfunc: If not NULL posteditfunc is called and the following arguments
+ * are passed:
+ * - const char *text: text contents of the temporary file (or
+ * NULL)
+ * - Client *c: current client passed to command_spawn_editor()
+ * - gpointer data: pointer that can be used for any local
+ * purposes
+ * @data: Generic pointer used to pass data to posteditfunc
+ */
+gboolean command_spawn_editor(Client *c, const Arg *arg,
+ PostEditFunc posteditfunc, gpointer data)
+{
+ char **argv = NULL, *file_path = NULL;
+ char *command = NULL;
+ int argc;
+ GPid pid;
+ gboolean success;
+ char *editor_command;
+ GError *error = NULL;
+
+ /* get the editor command */
+ editor_command = GET_CHAR(c, "editor-command");
+ if (!editor_command || !*editor_command) {
+ vb_echo(c, MSG_ERROR, TRUE, "No editor-command configured");
+ return FALSE;
+ }
+
+ /* create a temp file to pass text in/to editor */
+ if (!util_create_tmp_file(arg->s, &file_path)) {
+ goto error;
+ }
+
+ /* spawn editor */
+ command = g_strdup_printf(editor_command, file_path);
+ if (!g_shell_parse_argv(command, &argc, &argv, NULL)) {
+ g_critical("Could not parse editor-command '%s'", command);
+ goto error;
+ }
+
+ success = g_spawn_async(
+ NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL, NULL, &pid, &error
+ );
+
+ if (!success) {
+ g_warning("Could not spawn editor-command: %s", error->message);
+ g_error_free(error);
+ goto error;
+ }
+ g_strfreev(argv);
+
+ EditorData *ed = g_slice_new0(EditorData);
+ ed->file = file_path;
+ ed->c = c;
+ ed->data = data;
+ ed->func = posteditfunc;
+
+ g_child_watch_add(pid, resume_editor, ed);
+
+ return TRUE;
+
+error:
+ unlink(file_path);
+ g_free(file_path);
+ g_strfreev(argv);
+ return FALSE;
+}
+
+static void resume_editor(GPid pid, int status, gpointer edata)
+{
+ char *text = NULL;
+ EditorData *ed = edata;
+
+ g_assert(pid);
+ g_assert(ed);
+ g_assert(ed->c);
+ g_assert(ed->file);
+
+ if (ed->func != NULL) {
+ text = util_get_file_contents(ed->file, NULL);
+ ed->func(text, ed->c, ed->data);
+ g_free(text);
+ }
+
+ unlink(ed->file);
+ g_free(ed->file);
+ g_slice_free(EditorData, ed);
+ g_spawn_close_pid(pid);
+}
diff --git a/src/command.h b/src/command.h
index c3f8b68..3a49a63 100644
--- a/src/command.h
+++ b/src/command.h
@@ -43,11 +43,14 @@ enum {
};
#endif
+typedef void (*PostEditFunc)(const char *, Client *, gpointer);
+
gboolean command_search(Client *c, const Arg *arg, bool commit);
gboolean command_yank(Client *c, const Arg *arg, char buf);
gboolean command_save(Client *c, const Arg *arg);
#ifdef FEATURE_QUEUE
gboolean command_queue(Client *c, const Arg *arg);
#endif
+gboolean command_spawn_editor(Client *c, const Arg *arg, PostEditFunc posteditfunc, gpointer data);
#endif /* end of include guard: _COMMAND_H */
diff --git a/src/input.c b/src/input.c
index ac6db07..56e2676 100644
--- a/src/input.c
+++ b/src/input.c
@@ -22,6 +22,7 @@
#include <string.h>
#include "ascii.h"
+#include "command.h"
#include "config.h"
#include "input.h"
#include "main.h"
@@ -31,13 +32,11 @@
#include "ext-proxy.h"
typedef struct {
- Client *c;
- char *file;
char *element_id;
unsigned long element_map_key;
-} EditorData;
+} ElementEditorData;
-static void resume_editor(GPid pid, int status, EditorData *data);
+static void input_editor_formfiller(const char *text, Client *c, gpointer data);
/**
* Function called when vimb enters the input mode.
@@ -111,25 +110,15 @@ VbResult input_keypress(Client *c, int key)
VbResult input_open_editor(Client *c)
{
static unsigned long element_map_key = 0;
- char *element_id = NULL, *command = NULL;
- char **argv = NULL, *file_path = NULL;
- const char *text = NULL, *id = NULL, *editor_command;
- int argc;
- GPid pid;
+ char *element_id = NULL;
+ char *text = NULL, *id = NULL;
gboolean success;
GVariant *jsreturn;
GVariant *idreturn;
- GError *error = NULL;
+ ElementEditorData *data = NULL;
g_assert(c);
- /* get the editor command */
- editor_command = GET_CHAR(c, "editor-command");
- if (!editor_command || !*editor_command) {
- vb_echo(c, MSG_ERROR, TRUE, "No editor-command configured");
- return RESULT_ERROR;
- }
-
/* get the selected input element */
jsreturn = ext_proxy_eval_script_sync(c, "vimb_input_mode_element.value");
g_variant_get(jsreturn, "(bs)", &success, &text);
@@ -150,96 +139,54 @@ VbResult input_open_editor(Client *c)
element_id = g_strdup(id);
}
- /* create a temp file to pass text to and from editor */
- if (!util_create_tmp_file(text, &file_path)) {
- goto error;
- }
-
- /* spawn editor */
- command = g_strdup_printf(editor_command, file_path);
- if (!g_shell_parse_argv(command, &argc, &argv, NULL)) {
- g_critical("Could not parse editor-command '%s'", command);
- goto error;
- }
+ data = g_slice_new0(ElementEditorData);
+ data->element_id = element_id;
+ data->element_map_key = element_map_key;
- success = g_spawn_async(
- NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
- NULL, NULL, &pid, &error
- );
+ if (command_spawn_editor(c, &((Arg){0, text}), input_editor_formfiller, data)) {
+ /* disable the active element */
+ ext_proxy_lock_input(c, element_id);
- if (!success) {
- g_warning("Could not spawn editor-command: %s", error->message);
- g_error_free(error);
- goto error;
+ return RESULT_COMPLETE;
}
- g_strfreev(argv);
-
- /* disable the active element */
- ext_proxy_lock_input(c, element_id);
-
- /* watch the editor process */
- EditorData *data = g_slice_new0(EditorData);
- data->file = file_path;
- data->c = c;
- data->element_id = element_id;
- data->element_map_key = element_map_key;
- g_child_watch_add(pid, (GChildWatchFunc)resume_editor, data);
-
- return RESULT_COMPLETE;
-
-error:
- unlink(file_path);
- g_free(file_path);
- g_strfreev(argv);
g_free(element_id);
+ g_slice_free(ElementEditorData, data);
return RESULT_ERROR;
}
-static void resume_editor(GPid pid, int status, EditorData *data)
+static void input_editor_formfiller(const char *text, Client *c, gpointer data)
{
- char *text, *escaped;
+ char *escaped;
char *jscode;
char *jscode_enable;
+ ElementEditorData *eed = (ElementEditorData *)data;
- g_assert(pid);
- g_assert(data);
- g_assert(data->c);
- g_assert(data->file);
-
- if (status == 0) {
- /* get the text the editor stored */
- text = util_get_file_contents(data->file, NULL);
-
- if (text) {
- escaped = util_strescape(text, NULL);
+ if (text) {
+ escaped = util_strescape(text, NULL);
- /* put the text back into the element */
- if (data->element_id && strlen(data->element_id) > 0) {
- jscode = g_strdup_printf("document.getElementById(\"%s\").value=\"%s\"", data->element_id, escaped);
- } else {
- jscode = g_strdup_printf("vimb_editor_map.get(\"%lu\").value=\"%s\"", data->element_map_key, escaped);
- }
+ /* put the text back into the element */
+ if (eed->element_id && strlen(eed->element_id) > 0) {
+ jscode = g_strdup_printf("document.getElementById(\"%s\").value=\"%s\"", eed->element_id, escaped);
+ } else {
+ jscode = g_strdup_printf("vimb_editor_map.get(\"%lu\").value=\"%s\"", eed->element_map_key, escaped);
+ }
- ext_proxy_eval_script(data->c, jscode, NULL);
+ ext_proxy_eval_script(c, jscode, NULL);
- g_free(jscode);
- g_free(escaped);
- g_free(text);
- }
+ g_free(jscode);
+ g_free(escaped);
}
- if (data->element_id && strlen(data->element_id) > 0) {
- ext_proxy_unlock_input(data->c, data->element_id);
+ if (eed->element_id && strlen(eed->element_id) > 0) {
+ ext_proxy_unlock_input(c, eed->element_id);
} else {
jscode_enable = g_strdup_printf(JS_FOCUS_EDITOR_MAP_ELEMENT,
- data->element_map_key, data->element_map_key);
- ext_proxy_eval_script(data->c, jscode_enable, NULL);
+ eed->element_map_key, eed->element_map_key);
+ ext_proxy_eval_script(c, jscode_enable, NULL);
g_free(jscode_enable);
}
- g_unlink(data->file);
- g_free(data->file);
- g_free(data->element_id);
- g_slice_free(EditorData, data);
- g_spawn_close_pid(pid);
+
+ g_free(eed->element_id);
+ g_slice_free(ElementEditorData, eed);
}
diff --git a/src/normal.c b/src/normal.c
index 02ba27b..689bf1b 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -74,6 +74,7 @@ static VbResult normal_search(Client *c, const NormalCmdInfo *info);
static VbResult normal_search_selection(Client *c, const NormalCmdInfo *info);
static VbResult normal_view_inspector(Client *c, const NormalCmdInfo *info);
static VbResult normal_view_source(Client *c, const NormalCmdInfo *info);
+static void normal_view_source_loaded(WebKitWebResource *resource, GAsyncResult *res, Client *c);
static VbResult normal_yank(Client *c, const NormalCmdInfo *info);
static VbResult normal_zoom(Client *c, const NormalCmdInfo *info);
@@ -446,7 +447,7 @@ static VbResult normal_g_cmd(Client *c, const NormalCmdInfo *info)
return normal_view_inspector(c, info);
case 'f':
- normal_view_source(c, info);
+ return normal_view_source(c, info);
case 'g':
return normal_scroll(c, info);
@@ -743,10 +744,29 @@ static VbResult normal_view_inspector(Client *c, const NormalCmdInfo *info)
static VbResult normal_view_source(Client *c, const NormalCmdInfo *info)
{
- /* TODO the source mode isn't supported anymore use external editor for this */
+ WebKitWebResource *resource;
+
+ if ((resource = webkit_web_view_get_main_resource(c->webview)) == NULL) {
+ return RESULT_ERROR;
+ }
+
+ webkit_web_resource_get_data(resource, NULL,
+ (GAsyncReadyCallback)normal_view_source_loaded, c);
+
return RESULT_COMPLETE;
}
+static void normal_view_source_loaded(WebKitWebResource *resource,
+ GAsyncResult *res, Client *c)
+{
+ gsize length;
+ guchar *text = NULL;
+
+ text = webkit_web_resource_get_data_finish(resource, res, &length, NULL);
+ command_spawn_editor(c, &((Arg){0, (char *)text}), NULL, NULL);
+ g_free(text);
+}
+
static VbResult normal_yank(Client *c, const NormalCmdInfo *info)
{
Arg a = {info->key == 'Y' ? COMMAND_YANK_SELECTION : COMMAND_YANK_URI};