- [x] file paths for :source and :save
- [x] search phrases
- [x] settings
- - [ ] url handler
+ - [x] url handler
- [x] url history
- [ ] HSTS
- [ ] auto-response-header
- [x] default zoom
- [x] yanking
- [x] keymapping
- - [ ] URL handler
+ - [x] URL handler
- [x] shortcuts
- [ ] autocommands and augroups
3. documentation
.BI ":bmr [" URI ]
Removes all bookmarks for given \fIURI\fP or, if not given, the current opened
page.
+.SS Handlers
+Handlers allow specifying external scripts to handle alternative URI methods.
+.TP
+.BI ":handler-add " "handler" "=" "cmd"
+Adds a handler to direct \fIhandler\fP links to the external \fIcmd\fP.
+The \fIcmd\fP can contain one placeholder `%s` that will be filled by the
+full URI given when the command is called.
+.RS
+.P
+Examples:
+.PD 0
+.IP ":handler-add mailto=urxvt -e mutt %s"
+to start email client for mailto links.
+.IP ":handler-add magnet=xdg-open %s"
+to open magnet links with xdg-open.
+.IP ":handler-add ftp=urxvt -e wget %s -P ~/ftp-downloads"
+to handle ftp downloads via wget.
+.PD
+.RE
+.TP
+.BI ":handler-remove " "handler"
+Remove the handler for the given URI \fIhandler\fP.
.SS Shortcuts
Shortcuts allow the opening of an URI built up from a named template with additional
parameters.
#include "completion.h"
#include "config.h"
#include "ex.h"
+#include "handler.h"
#include "history.h"
#include "main.h"
#include "map.h"
static VbCmdResult ex_handlers(Client *c, const ExArg *arg)
{
- /* TODO no implemented yet */
- return CMD_SUCCESS;
+ char *p;
+ gboolean res = FALSE;
+
+ switch (arg->code) {
+ case EX_HANDADD:
+ if (arg->rhs->len && (p = strchr(arg->rhs->str, '='))) {
+ *p++ = '\0';
+ res = handler_add(c, arg->rhs->str, p);
+ }
+ break;
+
+ case EX_HANDREM:
+ res = handler_remove(c, arg->rhs->str);
+ break;
+
+ default:
+ break;
+ }
+
+ return res ? CMD_SUCCESS : CMD_ERROR;
}
static VbCmdResult ex_shortcut(Client *c, const ExArg *arg)
break;
case EX_HANDREM:
- /* TODO fill handler completion */
+ found = handler_fill_completion(c, store, token);
break;
case EX_SAVE: /* Fallthrough */
--- /dev/null
+/**
+ * vimb - a webkit based vim like browser.
+ *
+ * Copyright (C) 2012-2017 Daniel Carl
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ */
+
+#include <string.h>
+
+#include "main.h"
+#include "handler.h"
+#include "util.h"
+
+extern struct Vimb vb;
+
+static char *handler_lookup(Client *c, const char *uri);
+
+void handler_init(Client *c)
+{
+ c->handlers.table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+}
+
+void handler_cleanup(Client *c)
+{
+ if (c->handlers.table) {
+ g_hash_table_destroy(c->handlers.table);
+ c->handlers.table = NULL;
+ }
+}
+
+gboolean handler_add(Client *c, const char *key, const char *cmd)
+{
+ g_hash_table_insert(c->handlers.table, g_strdup(key), g_strdup(cmd));
+
+ return true;
+}
+
+gboolean handler_remove(Client *c, const char *key)
+{
+ return g_hash_table_remove(c->handlers.table, key);
+}
+
+gboolean handler_handle_uri(Client *c, const char *uri)
+{
+ char *handler, *cmd;
+ GError *error = NULL;
+ gboolean res;
+
+ if (!(handler = handler_lookup(c, uri))) {
+ return FALSE;
+ }
+
+ cmd = g_strdup_printf(handler, uri);
+ if (!g_spawn_command_line_async(cmd, &error)) {
+ g_warning("Can't run '%s': %s", cmd, error->message);
+ g_clear_error(&error);
+ res = FALSE;
+ } else {
+ res = TRUE;
+ }
+
+ g_free(cmd);
+ return res;
+}
+
+gboolean handler_fill_completion(Client *c, GtkListStore *store, const char *input)
+{
+ GList *src = g_hash_table_get_keys(c->handlers.table);
+ gboolean found = util_fill_completion(store, input, src);
+ g_list_free(src);
+
+ return found;
+}
+
+static char *handler_lookup(Client *c, const char *uri)
+{
+ char *p, *schema, *handler = NULL;
+
+ if ((p = strchr(uri, ':'))) {
+ schema = g_strndup(uri, p - uri);
+ handler = g_hash_table_lookup(c->handlers.table, schema);
+ g_free(schema);
+ }
+
+ return handler;
+}
+
--- /dev/null
+/**
+ * vimb - a webkit based vim like browser.
+ *
+ * Copyright (C) 2012-2017 Daniel Carl
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ */
+
+#ifndef _HANDLERS_H
+#define _HANDLERS_H
+
+void handler_init(Client *c);
+void handler_cleanup(Client *c);
+gboolean handler_add(Client *c, const char *key, const char *cmd);
+gboolean handler_remove(Client *c, const char *key);
+gboolean handler_handle_uri(Client *c, const char *uri);
+gboolean handler_fill_completion(Client *c, GtkListStore *store, const char *input);
+
+#endif /* end of include guard: _HANDLERS_H */
+
#include "config.h"
#include "ex.h"
#include "ext-proxy.h"
+#include "handler.h"
#include "input.h"
#include "js.h"
#include "main.h"
map_cleanup(c);
register_cleanup(c);
setting_cleanup(c);
+ handler_cleanup(c);
g_slice_free(Client, c);
/* initialize the settings */
setting_init(c);
+ /* initialize the url handlers */
+ handler_init(c);
+
/* start client in normal mode */
vb_enter(c, 'n');
static gboolean on_webview_decide_policy(WebKitWebView *webview,
WebKitPolicyDecision *dec, WebKitPolicyDecisionType type, Client *c)
{
- guint status;
+ guint status, button, mod;
WebKitNavigationAction *a;
WebKitURIRequest *req;
WebKitURIResponse *res;
switch (type) {
case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION:
- a = webkit_navigation_policy_decision_get_navigation_action(WEBKIT_NAVIGATION_POLICY_DECISION(dec));
- req = webkit_navigation_action_get_request(a);
+ a = webkit_navigation_policy_decision_get_navigation_action(WEBKIT_NAVIGATION_POLICY_DECISION(dec));
+ req = webkit_navigation_action_get_request(a);
+ button = webkit_navigation_action_get_mouse_button(a);
+ mod = webkit_navigation_action_get_modifiers(a);
- if (webkit_navigation_action_get_navigation_type(a) == WEBKIT_NAVIGATION_TYPE_LINK_CLICKED) {
- if (webkit_navigation_action_get_mouse_button(a) == 2
- || (webkit_navigation_action_get_mouse_button(a) == 1
- && webkit_navigation_action_get_modifiers(a) & GDK_CONTROL_MASK)) {
- webkit_policy_decision_ignore(dec);
- spawn_new_instance(webkit_uri_request_get_uri(req), TRUE);
- return TRUE;
- }
+ /* Try to handle with specific protocol handler. */
+ if (handler_handle_uri(c, webkit_uri_request_get_uri(req))) {
+ webkit_policy_decision_ignore(dec);
+ return TRUE;
+ }
+ if (webkit_navigation_action_get_navigation_type(a) == WEBKIT_NAVIGATION_TYPE_LINK_CLICKED
+ && (button == 2 || (button == 1 && mod & GDK_CONTROL_MASK))) {
+
+ webkit_policy_decision_ignore(dec);
+ spawn_new_instance(webkit_uri_request_get_uri(req), TRUE);
+ return TRUE;
}
return FALSE;
GHashTable *table;
char *fallback; /* default shortcut to use if none given in request */
} shortcut;
+ struct {
+ GHashTable *table; /* holds the protocol handlers */
+ } handlers;
};
struct Vimb {