diff --git a/AUTHORS b/AUTHORS index 92e76916..4febaaf8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -15,4 +15,5 @@ Patches: * Hannes Rist (:set titlestring support) * Nikolai Weibull ($VIMPERATOR_HOME) * Joseph Xu (supporting multiple top level windows better) + * Raimon Grau Cusc'o (document relationship navigation - ]n, ]p) diff --git a/NEWS b/NEWS index 4e88c6e0..274814e8 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,8 @@ read up the new help for the f, F and ; commands for details removed the following hint options: 'hintchars' 'maxhints' added the following hint options: 'hinttimeout' + * added ]n and ]p to navigate to the next/previous document based on + the regexp specified in 'nextpattern' and 'previouspattern' (thanks kidd) * abbreviations for text fields (:abbr etc.) (thanks calmar) * you can edit textfields with Ctrl-i now using an external editor (thanks to Joseph Xu) * :open, :bmarks, etc. filter on space separated tokens now, so you can @@ -24,7 +26,7 @@ * support for * and # mappings to search for the text selection or the text under the cursor * Escape finally clears any selection made in the document * initial start of caret mode. Start with 'i', stop with Escape; - * many small bug fixes and enhancments + * many small bug fixes and enhancements 2007-10-11: * version 0.5.2 diff --git a/content/buffers.js b/content/buffers.js index fd586662..5db25158 100644 --- a/content/buffers.js +++ b/content/buffers.js @@ -658,7 +658,7 @@ vimperator.Buffer = function () //{{{ var lastModVerbose = new Date(window.content.document.lastModified).toLocaleString(); var lastMod = new Date(window.content.document.lastModified).toLocaleFormat("%x %X"); // FIXME: probably unportable across differnet language versions - if (lastModVerbose == "Invalid Date" || new Date(window.content.document.lastModified).getFullYear() == 1970) + if (lastModVerbose == "Invalid Date" || new Date(window.content.document.lastModified).getFullYear() == 1970) lastModVerbose = lastMod = null; // Ctrl-g single line output @@ -769,8 +769,43 @@ vimperator.Buffer = function () //{{{ } } vimperator.echo(pageInfoText, vimperator.commandline.FORCE_MULTILINE); - } + }, + followDocumentRelation: function (relation) + { + var regexps; + var relText; + var patternText; + switch (relation) + { + case "next": + regexps = vimperator.options["nextpattern"].split(","); + relText = "next"; + break; + case "previous": + //TODO: accept prev\%[ious] + regexps = vimperator.options["previouspattern"].split(","); + relText = "previous"; + break; + default: vimperator.echoerr("bad relation"); + } + + relText = new RegExp(relText); + var elems = window.content.document.getElementsByTagName('a'); + for (pattern = 0; pattern < regexps.length; pattern++) + { + patternText = new RegExp(regexps[pattern]); + for (i = 0; i < elems.length; i++) + { + if (patternText.test(elems[i].text) || relText.test(elems[i].rel) ) + { + vimperator.buffer.followLink(elems[i],vimperator.CURRENT_TAB); + return; + } + } + } + vimperator.beep(); + } }; //}}} }; //}}} diff --git a/content/mappings.js b/content/mappings.js index 8a08cf05..b9043e45 100644 --- a/content/mappings.js +++ b/content/mappings.js @@ -414,6 +414,22 @@ vimperator.Mappings = function () //{{{ flags: vimperator.Mappings.flags.COUNT } )); + addDefaultMap(new vimperator.Map([vimperator.modes.NORMAL], ["]n"], + function (count) {vimperator.buffer.followDocumentRelation("next");}, + { + short_help: "go to 'next' or '>' if it exists. Beep otherwise.", + help: "Opens link labeled with next or >. Useful when browsing forums or documentation. Change nextpattern to modify its behaviour. It follows relations between files too.", + flags: vimperator.Mappings.flags.COUNT + } + )); + addDefaultMap(new vimperator.Map([vimperator.modes.NORMAL], ["]p"], + function (count) {vimperator.buffer.followDocumentRelation("previous");}, + { + short_help: "go to 'prev', 'previous' or '<' if it exists. Beep otherwise.", + help: "Opens link labeled with prev, previous or <. Useful when browsing forums or documentation. Change nextpattern to modify its behaviour. It follows relations between files too.", + flags: vimperator.Mappings.flags.COUNT + } + )); addDefaultMap(new vimperator.Map([vimperator.modes.NORMAL], ["b"], function () { vimperator.commandline.open(":", "buffer! ", vimperator.modes.EX); }, { diff --git a/content/options.js b/content/options.js index fc47e435..b9702b16 100644 --- a/content/options.js +++ b/content/options.js @@ -768,6 +768,22 @@ vimperator.Options = function () //{{{ validator: function (value) { return /^(sort|)$/.test(value); } } )); + this.add(new vimperator.Option(["nextpattern"], "stringlist", + { + short_help: "String to search when looking for 'next' page in document relation", + help: "Change it to make it look for another string in links when pressing ]n
" + + "This value is case insensitive", + default_value: "\\bnext,^>$" + } + )); + this.add(new vimperator.Option(["previouspattern"], "stringlist", + { + short_help: "String to search when looking for 'prev' page in document relation", + help: "Change it to make it look for another string in links when pressing ]p
" + + "This value is case insensitive", + default_value: "\\bprev,previous\\b,^<$" + } + )); //}}} // we start with an "empty" GUI so that no toolbars or tabbar is shown if the user