1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-20 22:07:58 +01:00

Add tests for dead help links. Fix some minor bugs. Show error when trying to modify a builtin group rather than failing silently.

This commit is contained in:
Kris Maglione
2011-02-21 16:22:30 -05:00
parent d62c93aef0
commit 234f50bce8
18 changed files with 92 additions and 50 deletions

View File

@@ -188,6 +188,7 @@ Dactyl.prototype = {
return redirect("dactyl://help/" + tag, uri); return redirect("dactyl://help/" + tag, uri);
if (tag in this.HELP_TAGS) if (tag in this.HELP_TAGS)
return redirect("dactyl://help/" + this.HELP_TAGS[tag] + "#" + tag.replace(/#/g, encodeURIComponent), uri); return redirect("dactyl://help/" + this.HELP_TAGS[tag] + "#" + tag.replace(/#/g, encodeURIComponent), uri);
break;
case "locale": case "locale":
return makeChannel(["resource://dactyl-locale", config.locale, path].join("/"), uri); return makeChannel(["resource://dactyl-locale", config.locale, path].join("/"), uri);
case "locale-local": case "locale-local":
@@ -228,7 +229,7 @@ function StringChannel(data, contentType, uri) {
} }
function XMLChannel(uri, contentType) { function XMLChannel(uri, contentType) {
let channel = services.io.newChannelFromURI(uri); var channel = services.io.newChannelFromURI(uri);
try { try {
var channelStream = channel.open(); var channelStream = channel.open();
} }

View File

@@ -6,16 +6,20 @@
function checkFragment() { function checkFragment() {
document.title = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "title")[0].textContent; document.title = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "title")[0].textContent;
var frag = document.location.hash.substr(1);
var elem = document.getElementById(frag);
function action() { function action() {
content.scrollTo(0, content.scrollY + elem.getBoundingClientRect().top - 10); // 10px context content.scrollTo(0, content.scrollY + elem.getBoundingClientRect().top - 10); // 10px context
} }
var frag = document.location.hash.substr(1);
if (frag) {
var elem = document.getElementById(frag);
if (elem) { if (elem) {
action(); action();
setTimeout(action, 10); setTimeout(action, 10);
} }
} }
}
document.addEventListener("load", checkFragment, true); document.addEventListener("load", checkFragment, true);
document.addEventListener("hashChange", checkFragment, true); document.addEventListener("hashChange", checkFragment, true);

View File

@@ -295,7 +295,10 @@
<xsl:template name="linkify-tag"> <xsl:template name="linkify-tag">
<xsl:param name="contents" select="text()"/> <xsl:param name="contents" select="text()"/>
<xsl:variable name="tag" select="$contents"/> <xsl:variable name="tag" select="$contents"/>
<a href="dactyl://help-tag/{$tag}" style="color: inherit;"> <a style="color: inherit;">
<xsl:if test="@link != 'false'">
<xsl:attribute name="href">dactyl://help-tag/<xsl:value-of select="$tag"/></xsl:attribute>
</xsl:if>
<xsl:if test="contains(ancestor::*/@document-tags, concat(' ', $tag, ' '))"> <xsl:if test="contains(ancestor::*/@document-tags, concat(' ', $tag, ' '))">
<xsl:attribute name="href">#<xsl:value-of select="$tag"/></xsl:attribute> <xsl:attribute name="href">#<xsl:value-of select="$tag"/></xsl:attribute>
</xsl:if> </xsl:if>
@@ -370,6 +373,7 @@
<xsl:template match="dactyl:link" mode="help-2"> <xsl:template match="dactyl:link" mode="help-2">
<a> <a>
<xsl:choose> <xsl:choose>
<xsl:when test="not(@topic)"/>
<xsl:when test="regexp:match(@topic, '^([a-zA-Z]*:|[^/]*#|/)', '')"> <xsl:when test="regexp:match(@topic, '^([a-zA-Z]*:|[^/]*#|/)', '')">
<xsl:attribute name="href"><xsl:value-of select="@topic"/></xsl:attribute> <xsl:attribute name="href"><xsl:value-of select="@topic"/></xsl:attribute>
</xsl:when> </xsl:when>
@@ -468,7 +472,12 @@
<html:span style="display: inline-block;"> <html:span style="display: inline-block;">
<ex>:set</ex> <ex>:set</ex>
<xsl:text> </xsl:text> <xsl:text> </xsl:text>
<link topic="'{@opt}'"><hl key="HelpOpt"><xsl:value-of select="@opt"/></hl></link> <link>
<xsl:if test="@link != 'false'">
<xsl:attribute name="topic">'<xsl:value-of select="@opt"/>'</xsl:attribute>
</xsl:if>
<hl key="HelpOpt"><xsl:value-of select="@opt"/></hl>
</link>
<xsl:choose> <xsl:choose>
<xsl:when test="@op and @op != ''"><xsl:value-of select="@op"/></xsl:when> <xsl:when test="@op and @op != ''"><xsl:value-of select="@op"/></xsl:when>
<xsl:otherwise>=</xsl:otherwise> <xsl:otherwise>=</xsl:otherwise>
@@ -482,7 +491,7 @@
<xsl:template match="dactyl:set" mode="help-2"> <xsl:template match="dactyl:set" mode="help-2">
<xsl:variable name="nodes"> <xsl:variable name="nodes">
<code xmlns="&xmlns.dactyl;"> <code xmlns="&xmlns.dactyl;">
<se opt="{@opt}" op="{@op}"> <se opt="{@opt}" op="{@op}" link="{@link}">
<xsl:copy-of select="@*|node()"/> <xsl:copy-of select="@*|node()"/>
</se> </se>
</code> </code>

View File

@@ -181,7 +181,7 @@
<ul> <ul>
<li><ex>:abbreviate</ex></li> <li><ex>:abbreviate</ex></li>
<li><ex>:autocmd</ex></li> <li><ex>:autocmd</ex></li>
<li><ex>:cabbrev</ex></li> <li><ex>:cabbreviate</ex></li>
<li><ex>:cmap</ex></li> <li><ex>:cmap</ex></li>
<li><ex>:cnoremap</ex></li> <li><ex>:cnoremap</ex></li>
<li><ex>:command</ex></li> <li><ex>:command</ex></li>
@@ -195,7 +195,7 @@
<li><ex>:elseif</ex></li> <li><ex>:elseif</ex></li>
<li><ex>:execute</ex></li> <li><ex>:execute</ex></li>
<li><ex>:highlight</ex></li> <li><ex>:highlight</ex></li>
<li><ex>:iabbrev</ex></li> <li><ex>:iabbreviate</ex></li>
<li><ex>:if</ex></li> <li><ex>:if</ex></li>
<li><ex>:imap</ex></li> <li><ex>:imap</ex></li>
<li><ex>:inoremap</ex></li> <li><ex>:inoremap</ex></li>
@@ -286,8 +286,8 @@
form and a long form, such as <em>-name</em> and <em>-n</em>. Most options form and a long form, such as <em>-name</em> and <em>-n</em>. Most options
accept arguments, which come after the option separated by either a space accept arguments, which come after the option separated by either a space
or an equal sign. For instance, the following three forms, or an equal sign. For instance, the following three forms,
<ex>-name=<str>foo</str></ex>, <ex>-name <str>foo</str></ex>, and <em>-name=<str>foo</str></em>, <em>-name <str>foo</str></em>, and
<ex>-n <str>foo</str></ex>, are all acceptable and entirely equivalent. <em>-n <str>foo</str></em>, are all acceptable and entirely equivalent.
</p> </p>
</document> </document>

View File

@@ -41,7 +41,7 @@
special meanings in QuickHint mode: special meanings in QuickHint mode:
</p> </p>
<dl> <dl>
<dt><k name="Return"/></dt> <dt><k name="CR"/></dt>
<dd>Selects the first highlighted element, or that <dd>Selects the first highlighted element, or that
focused by <k name="Tab"/>.</dd> focused by <k name="Tab"/>.</dd>

View File

@@ -21,7 +21,7 @@
navigation, and tool bars by default. If you find it uncomfortable to work navigation, and tool bars by default. If you find it uncomfortable to work
without them, you can re-enable them by typing without them, you can re-enable them by typing
</p> </p>
<set opt="guioptions" op="+="><str delim="">mT</str><k name="Return"/></set> <set opt="guioptions" op="+="><str delim="">mT</str><k name="CR"/></set>
<p> <p>
If you have trouble remembering commands or keyboard shortcuts, you can If you have trouble remembering commands or keyboard shortcuts, you can
bring up this help page at any time by typing <ex>:help</ex> or bring up this help page at any time by typing <ex>:help</ex> or

View File

@@ -27,7 +27,7 @@
Key mappings are the most basic means &dactyl.appName; provides Key mappings are the most basic means &dactyl.appName; provides
for altering the actions of key presses. Each key mapping is for altering the actions of key presses. Each key mapping is
associated with a mode, such as <link topic="insert-mode">insert</link>, associated with a mode, such as <link topic="insert-mode">insert</link>,
<link topic="normal-mode">normal</link>, or <link>normal</link>, or
<link topic="command-line-mode">command-line</link>, and only <link topic="command-line-mode">command-line</link>, and only
has effect when that mode is active. Although each mode has a has effect when that mode is active. Although each mode has a
full suite of internal mappings, they may be easily augmented, full suite of internal mappings, they may be easily augmented,
@@ -277,7 +277,7 @@
expected. expected.
</li> </li>
<li> <li>
<k name="Return"/> or <k name="CR"/> represent the carriage <k name="Return" link="false"/> or <k name="CR"/> represent the carriage
return key. return key.
</li> </li>
<li><k name="BS"/> represents the backspace key.</li> <li><k name="BS"/> represents the backspace key.</li>

View File

@@ -158,11 +158,11 @@
<p style="text-align: left;"> <p style="text-align: left;">
If the option is a list, the given values are toggled. Given, If the option is a list, the given values are toggled. Given,
<se opt="opt"><str delim="">foo</str>,<str delim="">bar</str></se> <se opt="opt" link="false"><str delim="">foo</str>,<str delim="">bar</str></se>
then, then,
<se opt="opt" op="!="><str delim="">foo</str>,<str delim="">baz</str></se> <se opt="opt" op="!=" link="false"><str delim="">foo</str>,<str delim="">baz</str></se>
has the same result as has the same result as
<se opt="opt"><str delim="">bar</str>,<str delim="">baz</str></se> <se opt="opt" link="false"><str delim="">bar</str>,<str delim="">baz</str></se>
</p> </p>
<p> <p>
@@ -690,8 +690,8 @@
<dl dt="width: 6em;"> <dl dt="width: 6em;">
<dt>0</dt> <dd>Follow the first hint as soon as typed text uniquely identifies it.</dd> <dt>0</dt> <dd>Follow the first hint as soon as typed text uniquely identifies it.</dd>
<dt>1</dt> <dd>Follow the selected hint on <k name="Return"/>.</dd> <dt>1</dt> <dd>Follow the selected hint on <k name="CR"/>.</dd>
<dt>2</dt> <dd>Follow the selected hint on <k name="Return"/> only if it's been <k name="Tab" mode="c"/>-selected.</dd> <dt>2</dt> <dd>Follow the selected hint on <k name="CR"/> only if it's been <k name="Tab" mode="c"/>-selected.</dd>
</dl> </dl>
</description> </description>
</item> </item>
@@ -875,7 +875,7 @@
hint. The timeout is measured since the last time a key listed in hint. The timeout is measured since the last time a key listed in
<o>hintkeys</o> was pressed. It has no effect when narrowing hints <o>hintkeys</o> was pressed. It has no effect when narrowing hints
by typing part of their text. Set to 0 (the default) to only follow by typing part of their text. Set to 0 (the default) to only follow
hints after pressing <k name="Return"/> or when the hint is unique. hints after pressing <k name="CR"/> or when the hint is unique.
</p> </p>
</description> </description>
</item> </item>
@@ -1131,7 +1131,7 @@
shift. shift.
</p> </p>
<example><set opt="passkeys" op="+="><str delim="">mail.google.com</str>:<str delim="">jk&lt;Return></str>,<str delim="">gi</str></set></example> <example><set opt="passkeys" op="+="><str delim="">mail.google.com</str>:<str delim="">jk&lt;CR></str>,<str delim="">gi</str></set></example>
<p> <p>
More subtle and complex pass through can be achieved More subtle and complex pass through can be achieved

View File

@@ -276,7 +276,7 @@
In addition to its own JavaScript context, each script is executed In addition to its own JavaScript context, each script is executed
with its own default <link topic="groups">group</link> into which with its own default <link topic="groups">group</link> into which
its styles, mappings, commands, and autocommands are placed. This its styles, mappings, commands, and autocommands are placed. This
means that commands such as <ex>:comclear!</ex> can be issued means that commands such as <ex>:delcommand!</ex> can be issued
without fear of trampling other user-defined mappings. The command without fear of trampling other user-defined mappings. The command
<ex>:group! default</ex> can be issued to clear all such items at <ex>:group! default</ex> can be issued to clear all such items at
once, and should be placed at the head of most scripts to prevent once, and should be placed at the head of most scripts to prevent

View File

@@ -82,7 +82,7 @@
<dt>FrameIndicator</dt> <dd>The indicator shown when a new frame is selected</dd> <dt>FrameIndicator</dt> <dd>The indicator shown when a new frame is selected</dd>
<dt>Function</dt> <dd>A JavaScript Function object</dd> <dt>Function</dt> <dd>A JavaScript Function object</dd>
<dt>Hint</dt> <dd>A hint indicator. See <ex>:help hints</ex></dd> <dt>Hint</dt> <dd>A hint indicator. See <ex>:help hints</ex></dd>
<dt>HintActive</dt> <dd>The hint element of link which will be followed by <k name="Return"/></dd> <dt>HintActive</dt> <dd>The hint element of link which will be followed by <k name="CR"/></dd>
<dt>HintElem</dt> <dd>The hintable element</dd> <dt>HintElem</dt> <dd>The hintable element</dd>
<dt>HintImage</dt> <dd>The indicator which floats above hinted images</dd> <dt>HintImage</dt> <dd>The indicator which floats above hinted images</dd>
<dt>Indicator</dt> <dd>The <em>#</em> and <em>%</em> in the <ex>:buffers</ex> list</dd> <dt>Indicator</dt> <dd>The <em>#</em> and <em>%</em> in the <ex>:buffers</ex> list</dd>

View File

@@ -43,7 +43,7 @@
<dl dt="width: 6em;"> <dl dt="width: 6em;">
<dt><hl key="Indicator">%</hl></dt><dd>The current buffer</dd> <dt><hl key="Indicator">%</hl></dt><dd>The current buffer</dd>
<dt><hl key="Indicator">#</hl></dt><dd>The alternate buffer for <ex>:e #</ex> and <k name="C-^"/></dd> <dt><hl key="Indicator">#</hl></dt><dd>The alternate buffer for <ex>:buffer #</ex> and <k name="C-^"/></dd>
</dl> </dl>
</description> </description>
</item> </item>

View File

@@ -229,9 +229,9 @@ var Addon = Class("Addon", {
if (node.update && node.update !== callee) if (node.update && node.update !== callee)
node.update(); node.update();
let event = this.document.createEvent("Events"); let event = this.list.document.createEvent("Events");
event.initEvent("dactyl-commandupdate", true, false); event.initEvent("dactyl-commandupdate", true, false);
this.document.dispatchEvent(event); this.list.document.dispatchEvent(event);
} }
}); });
@@ -261,9 +261,9 @@ var AddonList = Class("AddonList", {
this.ready = false; this.ready = false;
AddonManager.getAddonsByTypes(types, this.closure(function (addons) { AddonManager.getAddonsByTypes(types, this.closure(function (addons) {
addons.forEach(this.closure.addAddon); this._addons = addons;
this.ready = true; if (this.document)
this.update(); this._init();
})); }));
AddonManager.addAddonListener(this); AddonManager.addAddonListener(this);
}, },
@@ -271,6 +271,12 @@ var AddonList = Class("AddonList", {
AddonManager.removeAddonListener(this); AddonManager.removeAddonListener(this);
}, },
_init: function _init() {
this._addons.forEach(this.closure.addAddon);
this.ready = true;
this.update();
},
message: Class.memoize(function () { message: Class.memoize(function () {
XML.ignoreWhitespace = true; XML.ignoreWhitespace = true;
@@ -284,6 +290,9 @@ var AddonList = Class("AddonList", {
</tr> </tr>
</table>, this.document, this.nodes); </table>, this.document, this.nodes);
if (this._addons)
this._init();
return this.nodes.list; return this.nodes.list;
}), }),

View File

@@ -463,6 +463,11 @@ var Contexts = Module("contexts", {
if (args.context) if (args.context)
args.context.group = group; args.context.group = group;
util.assert(!group.builtin ||
!["-description", "-locations", "-nopersist"]
.some(function (arg) set.has(args.explicitOpts, arg)),
"Cannot modify builtin group");
}, },
{ {
argCount: "?", argCount: "?",

View File

@@ -73,8 +73,10 @@ var JavaScript = Module("javascript", {
let seen = isinstance(obj, ["Sandbox"]) ? set(JavaScript.magicalNames) : {}; let seen = isinstance(obj, ["Sandbox"]) ? set(JavaScript.magicalNames) : {};
let globals = values(toplevel && this.window === obj ? this.globalNames : []); let globals = values(toplevel && this.window === obj ? this.globalNames : []);
if (toplevel && "wrappedJSObject" in obj)
if (toplevel && isObject(obj) && "wrappedJSObject" in obj)
yield "wrappedJSObject"; yield "wrappedJSObject";
for (let key in iter(globals, properties(obj, !toplevel, true))) for (let key in iter(globals, properties(obj, !toplevel, true)))
if (!set.add(seen, key)) if (!set.add(seen, key))
yield key; yield key;

View File

@@ -1,16 +1,8 @@
function module(uri) { var utils = {}; Components.utils.import(/([^ ]+\/)[^\/]+$/.exec(Components.stack.filename)[1] + "utils.jsm", utils);
if (!/^[a-z-]+:/.exec(uri))
uri = /([^ ]+\/)[^\/]+$/.exec(Components.stack.filename)[1] + uri + ".jsm";
let obj = {};
Components.utils.import(uri, obj);
return obj;
}
var EXPORTED_SYMBOLS = ["Controller"]; var EXPORTED_SYMBOLS = ["Controller"];
var utils = module("utils"); const { module, NS } = utils;
const { NS } = utils;
var elementslib = module("resource://mozmill/modules/elementslib.js"); var elementslib = module("resource://mozmill/modules/elementslib.js");
var frame = module("resource://mozmill/modules/frame.js"); var frame = module("resource://mozmill/modules/frame.js");

View File

@@ -1,7 +1,11 @@
const { module } = require("utils"); const utils = require("utils");
const { module } = utils;
var jumlib = module("resource://mozmill/modules/jum.js"); var jumlib = module("resource://mozmill/modules/jum.js");
var dactyllib = module("dactyl"); var dactyllib = module("dactyl");
const { Services } = module("resource://gre/modules/Services.jsm");
var setupModule = function (module) { var setupModule = function (module) {
controller = mozmill.getBrowserController(); controller = mozmill.getBrowserController();
dactyl = new dactyllib.Controller(controller); dactyl = new dactyllib.Controller(controller);
@@ -15,8 +19,15 @@ var setupTest = function (test) {
dactyl.runViCommand([["VK_ESCAPE"]]); dactyl.runViCommand([["VK_ESCAPE"]]);
}; };
function urlTarget(url) Services.io.newChannel(url, null, null).name;
__defineGetter__("doesNotExist", function () {
delete this.doesNotExist;
return this.doesNotExist = urlTarget("dactyl://help-tag/non-existent-help-tag-url-thingy");
});
const HELP_FILES = ["all", "tutorial", "intro", "starting", "browsing", const HELP_FILES = ["all", "tutorial", "intro", "starting", "browsing",
"buffer", "cmdline", "insert", "options", "pattern", "tabs", "hints", "buffer", "cmdline", "editing", "options", "pattern", "tabs", "hints",
"map", "eval", "marks", "repeat", "autocommands", "print", "gui", "map", "eval", "marks", "repeat", "autocommands", "print", "gui",
"styling", "message", "privacy", "developer", "various", "plugins", "faq", "styling", "message", "privacy", "developer", "various", "plugins", "faq",
"versions", "index"]; "versions", "index"];
@@ -56,6 +67,14 @@ var testExHelpCommand_PageTagArg_OpensHelpPageContainingTag = function () {
HELP_COMMAND: function () { dactyl.runExCommand("help " + tag); }, HELP_COMMAND: function () { dactyl.runExCommand("help " + tag); },
EXPECTED_HELP_TAG: tag EXPECTED_HELP_TAG: tag
}); });
let links = controller.tabs.activeTab.querySelectorAll("a[href^='dactyl:']");
let missing = Array.filter(links, function (link) urlTarget(link.href) === doesNotExist)
.map(function (link) link.textContent + " -> " + link.href);
utils.assertEqual("testHelpCommands.assertNoDeadLinks", 0, missing.length,
"Found dead links in " + tag + ": " + missing.join(", "));
} }
}; };

View File

@@ -5,7 +5,7 @@ const Ci = Components.interfaces;
function module(uri) { function module(uri) {
if (!/^[a-z-]+:/.exec(uri)) if (!/^[a-z-]+:/.exec(uri))
uri = /([^ ]+\/)[^\/]+$/.exec(Components.stack.filename)[1] + uri + ".jsm"; uri = /([^ ]+\/)[^\/]+$/.exec(Components.stack.caller.filename)[1] + uri + ".jsm";
let obj = {}; let obj = {};
Components.utils.import(uri, obj); Components.utils.import(uri, obj);

View File

@@ -26,11 +26,12 @@
regain these by issuing the command regain these by issuing the command
</p> </p>
<set opt="go+"><str delim="">mTB</str><k name="CR"/></set> <set opt="go" op="+="><str delim="">mTB</str><k name="CR"/></set>
<p> <p>
where <k name="CR"/> represents pressing the <k name="Enter"/> or <k name="Return"/> key. where <k name="CR"/> represents pressing the <k name="Enter" link="false"/>
If you're a veteran Vim user, this may look familiar. It should. or <k name="Return" link="false"/> key. If you're a veteran Vim user, this
may look familiar. It should.
</p> </p>
<p> <p>
@@ -143,7 +144,7 @@
</dl> </dl>
<p> <p>
Your standard buttons (<k name="Up"/>/<k name="Down"/>/<k name="PgUp"/>/<k name="PgDn"/>) will Your standard buttons (<k name="Up"/>/<k name="Down"/>/<k name="PageUp"/>/<k name="PageDown"/>) will
also work as expected. also work as expected.
</p> </p>