1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-21 11:57:59 +01:00

Add 'linenumbers'.

This commit is contained in:
Kris Maglione
2011-09-27 01:21:29 -04:00
parent 0f9cb3100b
commit c90629c71f
10 changed files with 128 additions and 45 deletions

View File

@@ -1841,7 +1841,15 @@ var Buffer = Module("buffer", {
mappings.add([modes.NORMAL], ["G", "<End>", "<scroll-bottom>"],
"Go to the end of the document",
function (args) { buffer.scrollToPercent(null, args.count != null ? args.count : 100); },
function (args) {
if (args.count)
var elem = options.get("linenumbers").getLine(buffer.focusedFrame.document,
args.count);
if (elem)
elem.scrollIntoView(true);
else
buffer.scrollToPercent(null, args.count != null ? args.count : 100);
},
{ count: true });
mappings.add([modes.NORMAL], ["%", "<scroll-percent>"],
@@ -2132,6 +2140,52 @@ var Buffer = Module("buffer", {
&& Object.keys(value).every(function (v) v.length == 1)
});
options.add(["linenumbers", "ln"],
"Patterns used to determine line numbers used by G",
"sitemap", {
"code.google.com": '#nums [id^="nums_table"] a[href^="#"]',
"github.com": '.line_numbers>*',
"mxr.mozilla.org": 'a.l',
"pastebin.com": '#code_frame>div>ol>li'
},
{
getLine: function getLine(doc, line) {
let uri = util.newURI(doc.documentURI);
for (let filter in values(this.value))
if (filter(uri, doc)) {
if (/^func:/.test(filter.result))
var res = dactyl.userEval("(" + Option.dequote(filter.result.substr(5)) + ")")(doc, line);
else
res = iter.nth(filter.matcher(doc),
function (elem) (elem.nodeValue || elem.textContent).trim() == line && DOM(elem).display != "none",
0)
|| iter.nth(filter.matcher(doc), util.identity, line - 1);
if (res)
break;
}
return res;
},
keepQuotes: true,
setter: function (vals) {
for (let value in values(vals))
if (!/^func:/.test(value.result))
value.matcher = DOM.compileMatcher(Option.splitList(value.result));
return vals;
},
validate: function validate(values) {
return this.testValues(values, function (value) {
if (/^func:/.test(value))
return callable(dactyl.userEval("(" + Option.dequote(value.substr(5)) + ")"));
else
return DOM.testMatcher(value);
});
}
});
options.add(["nextpattern"],
"Patterns to use when guessing the next page in a document sequence",
"regexplist", UTF8(/'\bnext\b',^>$,^(>>|»)$,^(>|»),(>|»)$,'\bmore\b'/.source),

View File

@@ -111,20 +111,7 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
}
},
/** @property {string} The name of the current user profile. */
profileName: Class.Memoize(function () {
// NOTE: services.profile.selectedProfile.name doesn't return
// what you might expect. It returns the last _actively_ selected
// profile (i.e. via the Profile Manager or -P option) rather than the
// current profile. These will differ if the current process was run
// without explicitly selecting a profile.
let dir = services.directory.get("ProfD", Ci.nsIFile);
for (let prof in iter(services.profile.profiles))
if (prof.QueryInterface(Ci.nsIToolkitProfile).rootDir.path === dir.path)
return prof.name;
return "unknown";
}),
profileName: deprecated("config.profileName", { get: function profileName() config.profileName }),
/**
* @property {Modes.Mode} The current main mode.

View File

@@ -134,7 +134,9 @@
<description>
<p>
Go to the end of the document. With <oa>count</oa>,
behaves exactly the same as <oa>gg</oa>.
go to the <oa>count</oa>th line as determined by <o>linenumbers</o>,
or to the <oa>count</oa>th percent of the document if the line number
can't be determined.
</p>
</description>
</item>

View File

@@ -1034,6 +1034,25 @@
</description>
</item>
<item>
<tags>'ln' 'linenumbers'</tags>
<spec>'linenumbers' 'ln'</spec>
<type>&option.linenumbers.type;</type>
<default>&option.linenumbers.default;</default>
<description>
<p>
Patterns used to determine line numbers used by <k>G</k>. May be
either a selector expression as accepted by <o>hinttags</o>, in
which case the first matching element whose text content is equal to
the desired line number is used or the <oa>count</oa>th element
failing that, or the string <str delim="'">func:</str> followed by a
function which, given arguments for the document and desired line
number must return the target element.
</p>
</description>
</item>
<item>
<tags>'lpl' 'loadplugins'</tags>
<spec>'loadplugins' 'lpl'</spec>

View File

@@ -122,7 +122,12 @@ if (!Object.keys)
let getGlobalForObject = Cu.getGlobalForObject || function (obj) obj.__parent__;
let jsmodules = {};
let jsmodules = {
lazyRequire: function lazyRequire(module, names, target) {
for each (let name in names)
memoize(target || this, name, function (name) require(module)[name]);
}
};
let use = {};
let loaded = {};
let currentModule;
@@ -229,6 +234,8 @@ defineModule("base", {
]
}, this);
this.lazyRequire("messages", ["_", "Messages"]);
/**
* Returns a list of all of the top-level properties of an object, by
* way of the debugger.
@@ -325,7 +332,7 @@ deprecated.warn = function warn(func, name, alternative, frame) {
let filename = util.fixURI(frame.filename || "unknown");
if (!Set.add(func.seenCaller, filename))
util.dactyl(func).warn([util.urlPath(filename), frame.lineNumber, " "].join(":")
+ require("messages")._("warn.deprecated", name, alternative));
+ _("warn.deprecated", name, alternative));
}
/**
@@ -1242,7 +1249,7 @@ var StructBase = Class("StructBase", Array, {
localize: function localize(key, defaultValue) {
let i = this.prototype.members[key];
Object.defineProperty(this.prototype, i, require("messages").Messages.Localized(defaultValue).init(key, this.prototype));
Object.defineProperty(this.prototype, i, Messages.Localized(defaultValue).init(key, this.prototype));
return this;
}
});

View File

@@ -13,6 +13,10 @@ defineModule("config", {
require: ["dom", "protocol", "services", "storage", "util", "template"]
}, this);
this.lazyRequire("addons", ["AddonManager"]);
this.lazyRequire("highlight", ["highlight"]);
this.lazyRequire("messages", ["_"]);
function AboutHandler() {}
AboutHandler.prototype = {
get classDescription() "About " + config.appName + " Page",
@@ -102,9 +106,6 @@ var ConfigBase = Class("ConfigBase", {
},
loadStyles: function loadStyles(force) {
const { highlight } = require("highlight");
const { _ } = require("messages");
highlight.styleableChrome = this.styleableChrome;
highlight.loadCSS(this.CSS.replace(/__MSG_(.*?)__/g, function (m0, m1) _(m1)));
@@ -145,7 +146,7 @@ var ConfigBase = Class("ConfigBase", {
addon: Class.Memoize(function () {
return (JSMLoader.bootstrap || {}).addon ||
require("addons").AddonManager.getAddonByID(this.addonID);
AddonManager.getAddonByID(this.addonID);
}),
/**
@@ -311,6 +312,21 @@ var ConfigBase = Class("ConfigBase", {
return (/pre-hg\d+-(\S*)/.exec(this.version) || [])[1];
}),
/** @property {string} The name of the current user profile. */
profileName: Class.Memoize(function () {
// NOTE: services.profile.selectedProfile.name doesn't return
// what you might expect. It returns the last _actively_ selected
// profile (i.e. via the Profile Manager or -P option) rather than the
// current profile. These will differ if the current process was run
// without explicitly selecting a profile.
let dir = services.directory.get("ProfD", Ci.nsIFile);
for (let prof in iter(services.profile.profiles))
if (prof.QueryInterface(Ci.nsIToolkitProfile).rootDir.path === dir.path)
return prof.name;
return "unknown";
}),
/** @property {string} The Dactyl version string. */
version: Class.Memoize(function () {
if (this.VCSPath)
@@ -375,7 +391,6 @@ var ConfigBase = Class("ConfigBase", {
helpStyles: /^(Help|StatusLine|REPL)|^(Boolean|Dense|Indicator|MoreMsg|Number|Object|Logo|Key(word)?|String)$/,
styleHelp: function styleHelp() {
if (!this.helpStyled) {
const { highlight } = require("highlight");
for (let k in keys(highlight.loaded))
if (this.helpStyles.test(k))
highlight.loaded[k] = true;
@@ -1064,7 +1079,6 @@ config.INIT = update(Object.create(config.INIT), config.INIT, {
let img = window.Image();
img.src = this.logo || "resource://dactyl-local-content/logo.png";
img.onload = util.wrapCallback(function () {
const { highlight } = require("highlight");
highlight.loadCSS(<>{"!Logo {"}
display: inline-block;
background: url({img.src});

View File

@@ -1324,7 +1324,7 @@ var DOM = Class("DOM", {
yield elem;
if (matcher.css)
for (let [, elem] in iter(node.querySelectorAll(matcher.css)))
for (let [, elem] in iter(util.withProperErrors("querySelectorAll", node, matcher.css)))
yield elem;
}, {
css: css.join(", "),
@@ -1343,13 +1343,15 @@ var DOM = Class("DOM", {
validateMatcher: function validateMatcher(list) {
let evaluator = services.XPathEvaluator();
let node = services.XMLDocument();
return this.testValues(list, function (value) {
if (/^xpath:/.test(value))
evaluator.createExpression(value.substr(6), DOM.XPath.resolver);
else
node.querySelector(value);
return true;
});
return this.testValues(list, this.closure.testMatcher);
},
testMatcher: function testMatcher(value) {
if (/^xpath:/.test(value))
evaluator.createExpression(value.substr(6), DOM.XPath.resolver);
else
node.querySelector(value);
return true;
},
/**

View File

@@ -12,8 +12,6 @@ defineModule("finder", {
function equals(a, b) XPCNativeWrapper(a) == XPCNativeWrapper(b);
try {
/** @instance rangefinder */
var RangeFinder = Module("rangefinder", {
Local: function (dactyl, modules, window) ({
@@ -265,7 +263,6 @@ var RangeFinder = Module("rangefinder", {
},
options: function (dactyl, modules, window) {
const { options, rangefinder } = modules;
const { prefs } = require("prefs");
options.add(["hlfind", "hlf"],
"Highlight all /find pattern matches on the current page after submission",
@@ -844,9 +841,8 @@ var RangeFind = Class("RangeFind", {
}
});
} catch(e){ if (typeof e === "string") e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }
// catch(e){ if (typeof e === "string") e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }
endModule();
// vim: set fdm=marker sw=4 ts=4 et ft=javascript:

View File

@@ -7,9 +7,11 @@
Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("storage", {
exports: ["File", "Storage", "storage"],
require: ["services", "util"]
require: ["config", "services", "util"]
}, this);
this.lazyRequire("io", ["IO"]);
var win32 = /^win(32|nt)$/i.test(services.runtime.OS);
var myObject = JSON.parse("{}").constructor;
@@ -169,6 +171,10 @@ var Storage = Module("Storage", {
this.observers = {};
},
infoPath: Class.Memoize(function ()
File(IO.runtimePath.replace(/,.*/, ""))
.child("info").child(config.profileName)),
exists: function exists(name) this.infoPath.child(name).exists(),
newObject: function newObject(key, constructor, params) {
@@ -270,12 +276,6 @@ var Storage = Module("Storage", {
skipXpcom: function skipXpcom(key, val) val instanceof Ci.nsISupports ? null : val
}
}, {
init: function init(dactyl, modules) {
init.superapply(this, arguments);
storage.infoPath = File(modules.IO.runtimePath.replace(/,.*/, ""))
.child("info").child(dactyl.profileName);
},
cleanup: function (dactyl, modules, window) {
overlay.setData(window, "storage-refs", null);
this.removeDeadObservers();

View File

@@ -80,6 +80,7 @@
- It's now possible to map keys in many more modes, including
Hint, Multi-line Output, and Menu. [b4]
- <C-o> and <C-i> now behave more like Vim. [b8]
- n_G now uses 'linenumbers' to determine destination if possible. [b8]
- Add n_s and n_S. [b8]
- Added Operator mode for motion maps, per Vim. [b8]
- Added site-specific mapping groups and related command
@@ -211,6 +212,7 @@
- 'complete' now defaults to "slf" but file completion only
triggers when the URL begins as above. [b1]
- Added 'jumptags' option. [b7]
- Added 'linenumbers' option. [b8]
- Added 's' flag to 'pageinfo' and changed default value. [b7]
- Added 'passkeys' option. [b3]
- Added 'passunknown' option. [b7]