summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Carl <danielcarl@gmx.de>2013-10-27 23:42:45 +0100
committerDaniel Carl <danielcarl@gmx.de>2013-10-27 23:48:52 +0100
commit81aa3cfc503a98f670b86db51de80660c3b96008 (patch)
tree64718f36870207a5e299d646d17f26d607f9c7ad
parent1a49e669384c91a3e5ad38a09b9058f52527669b (diff)
Added new ]] and [[ commands.
These commands allow to open next/previous page by regex pattern configured using new settings 'previouspattern' and 'nextpattern'.
-rw-r--r--doc/vimb.116
-rw-r--r--src/default.h2
-rw-r--r--src/hints.c14
-rw-r--r--src/hints.h1
-rw-r--r--src/hints.js59
-rw-r--r--src/main.h2
-rw-r--r--src/normal.c20
-rw-r--r--src/setting.c16
8 files changed, 122 insertions, 8 deletions
diff --git a/doc/vimb.1 b/doc/vimb.1
index 5603656..247a187 100644
--- a/doc/vimb.1
+++ b/doc/vimb.1
@@ -167,6 +167,12 @@ Scroll page \fIN\fP steps down.
.TP
.BI [ N ]k
Scroll page \fIN\fP steps up.
+.TP
+.BI [ N ]]\-]
+Follow the last \fIN\fPth link matching `nextpattern'.
+.TP
+.BI [ N ][\-[
+Follow the last \fIN\fPth link matching `previouspattern'.
.SS Hinting
The hinting is the way to do what you would do with the mouse in common
mouse-driven browsers. Open URI, yank URI, save page and so on. If the hinting
@@ -696,6 +702,16 @@ Font user in inputbox if error is shown.
.B input-font-normal (string)
Font used for inputbox.
.TP
+.B nextpattern (string)
+Patterns to use when guessing the next page in a document. Each pattern is
+successively tested against each link in the page beginning from the last
+link. Default "'\\bnext\\b','^(>|>>|»)$','^(>|>>|»)','(>|>>|»)$','\\bmore\\b'"
+.TP
+.B previouspattern (string)
+Patterns to use when guessing the previous page in a document. Each pattern is
+successively tested against each link in the page beginning from the last
+link. Default "\\bprev|previous\\b','^(<|<<|«)$','^(<|<<|«)','(<|<<|«)$'"
+.TP
.B proxy (bool)
Indicates if the environment variable `http_proxy' is evaluated.
.TP
diff --git a/src/default.h b/src/default.h
index 944c7e7..8b97abf 100644
--- a/src/default.h
+++ b/src/default.h
@@ -67,6 +67,8 @@ static char *default_config[] = {
"set insecure-content-run=off",
#endif
"set timeoutlen=1000",
+ "set previouspattern='\\bprev\\|previous\\b','^(<\\|<<\\|«)$','^(<\\|<<\\|«)','(<\\|<<\\|«)$'",
+ "set nextpattern='\\bnext\\b','^(>\\|>>\\|»)$','^(>\\|>>\\|»)','(>\\|>>\\|»)$','\\bmore\\b'",
NULL
};
diff --git a/src/hints.c b/src/hints.c
index b2d659b..fe7cda1 100644
--- a/src/hints.c
+++ b/src/hints.c
@@ -158,8 +158,22 @@ void hints_fire(void)
g_free(js);
}
+void hints_follow_link(const gboolean back, int count)
+{
+ char *pattern = back ? vb.config.prevpattern : vb.config.nextpattern;
+ char *js = g_strdup_printf(
+ "%s.followLink('%s', [%s], %d);", HINT_VAR,
+ back ? "prev" : "next",
+ pattern,
+ count
+ );
+ run_script(js);
+ g_free(js);
+}
+
static void run_script(char *js)
{
+ PRINT_DEBUG("%s", js);
char mode, *value = NULL;
gboolean success = vb_eval_script(
diff --git a/src/hints.h b/src/hints.h
index f721883..386e7ca 100644
--- a/src/hints.h
+++ b/src/hints.h
@@ -27,6 +27,7 @@ VbResult hints_keypress(int key);
void hints_create(const char *input);
void hints_update(int num);
void hints_fire(void);
+void hints_follow_link(const gboolean back, int count);
void hints_clear(void);
void hints_focus_next(const gboolean back);
diff --git a/src/hints.js b/src/hints.js
index 55a79b5..1beea66 100644
--- a/src/hints.js
+++ b/src/hints.js
@@ -392,6 +392,53 @@ var VbHint = (function(){
}
}
+ /* follow the count last link on pagematching the given pattern */
+ function followLink(rel, pattern, count) {
+ /* returns array of matching elements */
+ function followFrame(frame) {
+ var i, p, reg, res = [],
+ elems = frame.document.getElementsByTagName("a");
+
+ /* first match links by rel attribute */
+ for (i = elems.length - 1; i >= 0; i--) {
+ if (elems[i].rel.toLowerCase() === rel) {
+ res.push(elems[i]);
+ elems.splice(i, 1);
+ }
+ }
+ /* match each pattern successively against each link in the page */
+ for (p = 0; p < pattern.length; p++) {
+ reg = pattern[p];
+ /* begin with the last link on page */
+ for (i = elems.length - 1; i >= 0; i--) {
+ if (elems[i].innerText.match(reg)) {
+ res.push(elems[i]);
+ }
+ }
+ }
+ return res;
+ }
+ var i, j, elems, frames = allFrames(window);
+ for (i = 0; i < frames.length; i++) {
+ elems = followFrame(frames[i]);
+ for (j = 0; j < elems.length; j++) {
+ if (--count == 0) {
+ open(elems[j], false);
+ return "DONE:";
+ }
+ }
+ }
+ return "NONE:";
+ }
+
+ function allFrames(win) {
+ var i, f, frames = [win];
+ for (i = 0; i < win.frames.length; i++) {
+ frames.push(win.frames[i].frameElement);
+ }
+ return frames;
+ }
+
/* the api */
return {
init: function init(prefix, maxHints) {
@@ -423,11 +470,13 @@ var VbHint = (function(){
config.usage = map[prefix][1];
}
},
- create: create,
- update: update,
- clear: clear,
- fire: fire,
- focus: focus
+ create: create,
+ update: update,
+ clear: clear,
+ fire: fire,
+ focus: focus,
+ /* not really hintings but uses similar logic */
+ followLink: followLink
};
})();
Object.freeze(VbHint);
diff --git a/src/main.h b/src/main.h
index e79e0a9..7b65589 100644
--- a/src/main.h
+++ b/src/main.h
@@ -282,6 +282,8 @@ typedef struct {
guint timeoutlen; /* timeout for ambiguous mappings */
gboolean strict_focus;
GHashTable *headers; /* holds user defined header appended to requests */
+ char *nextpattern; /* regex patter nfor prev link matching */
+ char *prevpattern; /* regex patter nfor next link matching */
} Config;
typedef struct {
diff --git a/src/normal.c b/src/normal.c
index 26e4dc5..b55160b 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -61,6 +61,7 @@ static VbResult normal_navigate(const NormalCmdInfo *info);
static VbResult normal_open_clipboard(const NormalCmdInfo *info);
static VbResult normal_open(const NormalCmdInfo *info);
static VbResult normal_pass(const NormalCmdInfo *info);
+static VbResult normal_prevnext(const NormalCmdInfo *info);
static VbResult normal_queue(const NormalCmdInfo *info);
static VbResult normal_quit(const NormalCmdInfo *info);
static VbResult normal_scroll(const NormalCmdInfo *info);
@@ -165,9 +166,9 @@ static struct {
/* X 0x58 */ {NULL},
/* Y 0x59 */ {normal_yank},
/* Z 0x5a */ {NULL},
-/* [ 0x5b */ {NULL},
+/* [ 0x5b */ {normal_prevnext},
/* \ 0x5c */ {NULL},
-/* ] 0x5d */ {NULL},
+/* ] 0x5d */ {normal_prevnext},
/* ^ 0x5e */ {NULL},
/* _ 0x5f */ {NULL},
/* ` 0x60 */ {NULL},
@@ -243,7 +244,7 @@ VbResult normal_keypress(int key)
info.phase = PHASE_COMPLETE;
} else if (info.phase == PHASE_START && isdigit(key)) {
info.count = info.count * 10 + key - '0';
- } else if (strchr(";zg", (char)key)) {
+ } else if (strchr(";zg[]", (char)key)) {
/* handle commands that needs additional char */
info.phase = PHASE_KEY2;
info.cmd = key;
@@ -546,6 +547,19 @@ static VbResult normal_pass(const NormalCmdInfo *info)
return RESULT_COMPLETE;
}
+static VbResult normal_prevnext(const NormalCmdInfo *info)
+{
+ int count = info->count ? info->count : 1;
+ if (info->ncmd == ']') {
+ hints_follow_link(false, count);
+ } else if (info->ncmd == '[') {
+ hints_follow_link(true, count);
+ } else {
+ return RESULT_ERROR;
+ }
+ return RESULT_COMPLETE;
+}
+
static VbResult normal_queue(const NormalCmdInfo *info)
{
command_queue(&((Arg){COMMAND_QUEUE_POP}));
diff --git a/src/setting.c b/src/setting.c
index 994b24c..f2082b3 100644
--- a/src/setting.c
+++ b/src/setting.c
@@ -47,6 +47,7 @@ static gboolean history_max_items(const Setting *s, const SettingType type);
static gboolean editor_command(const Setting *s, const SettingType type);
static gboolean timeoutlen(const Setting *s, const SettingType type);
static gboolean headers(const Setting *s, const SettingType type);
+static gboolean nextpattern(const Setting *s, const SettingType type);
static Setting default_settings[] = {
/* webkit settings */
@@ -111,6 +112,8 @@ static Setting default_settings[] = {
{NULL, "history-max-items", TYPE_INTEGER, history_max_items, {0}},
{NULL, "editor-command", TYPE_CHAR, editor_command, {0}},
{NULL, "header", TYPE_CHAR, headers, {0}},
+ {NULL, "nextpattern", TYPE_CHAR, nextpattern, {0}},
+ {NULL, "previouspattern", TYPE_CHAR, nextpattern, {0}},
};
void setting_init(void)
@@ -775,3 +778,16 @@ static gboolean headers(const Setting *s, const SettingType type)
return true;
}
+
+static gboolean nextpattern(const Setting *s, const SettingType type)
+{
+ if (type == SETTING_GET) {
+ print_value(s, s->name[0] == 'n' ? vb.config.nextpattern : vb.config.prevpattern);
+ } else if (*s->name == 'n') {
+ OVERWRITE_STRING(vb.config.nextpattern, s->arg.s);
+ } else {
+ OVERWRITE_STRING(vb.config.prevpattern, s->arg.s);
+ }
+
+ return true;
+}