1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-20 17:47:59 +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);
if (tag in this.HELP_TAGS)
return redirect("dactyl://help/" + this.HELP_TAGS[tag] + "#" + tag.replace(/#/g, encodeURIComponent), uri);
break;
case "locale":
return makeChannel(["resource://dactyl-locale", config.locale, path].join("/"), uri);
case "locale-local":
@@ -228,7 +229,7 @@ function StringChannel(data, contentType, uri) {
}
function XMLChannel(uri, contentType) {
let channel = services.io.newChannelFromURI(uri);
var channel = services.io.newChannelFromURI(uri);
try {
var channelStream = channel.open();
}

View File

@@ -6,16 +6,20 @@
function checkFragment() {
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() {
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) {
action();
setTimeout(action, 10);
}
}
}
document.addEventListener("load", checkFragment, true);
document.addEventListener("hashChange", checkFragment, true);

View File

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

View File

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

View File

@@ -41,7 +41,7 @@
special meanings in QuickHint mode:
</p>
<dl>
<dt><k name="Return"/></dt>
<dt><k name="CR"/></dt>
<dd>Selects the first highlighted element, or that
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
without them, you can re-enable them by typing
</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>
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

View File

@@ -27,7 +27,7 @@
Key mappings are the most basic means &dactyl.appName; provides
for altering the actions of key presses. Each key mapping is
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
has effect when that mode is active. Although each mode has a
full suite of internal mappings, they may be easily augmented,
@@ -277,7 +277,7 @@
expected.
</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.
</li>
<li><k name="BS"/> represents the backspace key.</li>

View File

@@ -158,11 +158,11 @@
<p style="text-align: left;">
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,
<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
<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>
@@ -690,8 +690,8 @@
<dl dt="width: 6em;">
<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>2</dt> <dd>Follow the selected hint on <k name="Return"/> only if it's been <k name="Tab" mode="c"/>-selected.</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="CR"/> only if it's been <k name="Tab" mode="c"/>-selected.</dd>
</dl>
</description>
</item>
@@ -875,7 +875,7 @@
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
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>
</description>
</item>
@@ -1131,7 +1131,7 @@
shift.
</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>
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
with its own default <link topic="groups">group</link> into which
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
<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

View File

@@ -82,7 +82,7 @@
<dt>FrameIndicator</dt> <dd>The indicator shown when a new frame is selected</dd>
<dt>Function</dt> <dd>A JavaScript Function object</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>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>

View File

@@ -43,7 +43,7 @@
<dl dt="width: 6em;">
<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>
</description>
</item>

View File

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

View File

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

View File

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

View File

@@ -1,16 +1,8 @@
function module(uri) {
if (!/^[a-z-]+:/.exec(uri))
uri = /([^ ]+\/)[^\/]+$/.exec(Components.stack.filename)[1] + uri + ".jsm";
let obj = {};
Components.utils.import(uri, obj);
return obj;
}
var utils = {}; Components.utils.import(/([^ ]+\/)[^\/]+$/.exec(Components.stack.filename)[1] + "utils.jsm", utils);
var EXPORTED_SYMBOLS = ["Controller"];
var utils = module("utils");
const { NS } = utils;
const { module, NS } = utils;
var elementslib = module("resource://mozmill/modules/elementslib.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 dactyllib = module("dactyl");
const { Services } = module("resource://gre/modules/Services.jsm");
var setupModule = function (module) {
controller = mozmill.getBrowserController();
dactyl = new dactyllib.Controller(controller);
@@ -15,8 +19,15 @@ var setupTest = function (test) {
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",
"buffer", "cmdline", "insert", "options", "pattern", "tabs", "hints",
"buffer", "cmdline", "editing", "options", "pattern", "tabs", "hints",
"map", "eval", "marks", "repeat", "autocommands", "print", "gui",
"styling", "message", "privacy", "developer", "various", "plugins", "faq",
"versions", "index"];
@@ -56,6 +67,14 @@ var testExHelpCommand_PageTagArg_OpensHelpPageContainingTag = function () {
HELP_COMMAND: function () { dactyl.runExCommand("help " + 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) {
if (!/^[a-z-]+:/.exec(uri))
uri = /([^ ]+\/)[^\/]+$/.exec(Components.stack.filename)[1] + uri + ".jsm";
uri = /([^ ]+\/)[^\/]+$/.exec(Components.stack.caller.filename)[1] + uri + ".jsm";
let obj = {};
Components.utils.import(uri, obj);

View File

@@ -26,11 +26,12 @@
regain these by issuing the command
</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>
where <k name="CR"/> represents pressing the <k name="Enter"/> or <k name="Return"/> key.
If you're a veteran Vim user, this may look familiar. It should.
where <k name="CR"/> represents pressing the <k name="Enter" link="false"/>
or <k name="Return" link="false"/> key. If you're a veteran Vim user, this
may look familiar. It should.
</p>
<p>
@@ -143,7 +144,7 @@
</dl>
<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.
</p>