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

Merge branch 'master' into vimperator-2.1

Conflicts:
	common/content/io.js
	common/content/style.js
This commit is contained in:
Kris Maglione
2009-01-07 00:26:37 -05:00
54 changed files with 1801 additions and 1013 deletions

4
.gitignore vendored
View File

@@ -2,3 +2,7 @@
*/locale/*/*.html
*/chrome
*~
.*.swp
.*.swo
.swp
.DS_Store

148
HACKING Normal file
View File

@@ -0,0 +1,148 @@
= Hacking =
If you've taken to hacking Vimperator source code, we hope that you'll share
your changes. In case you do, please keep the following in mind, and we'll be
happy to accept your patches.
== Documentation ==
First of all, all new features and all user-visible changes to existing
features need to be documented. That means editing the appropriate help files
and adding a NEWS entry where appropriate. When editing the NEWS file, you
should add your change to the top of the list of changes. If your change
alters an interface (key binding, command) and is likely to cause trouble,
prefix it with 'IMPORTANT:', otherwise, place it below the other 'IMPORTANT'
entries. If you're not sure if your change merits a news entry, or if it's
important, please ask.
== Coding Style ==
In general: Just look at the existing source code!
We try to be quite consistent, but of course, that's not always possible.
=== The most important style issues are: ===
* Use 4 spaces to indent things, no tabs, not 2, nor 8 spaces. If you use Vim,
this should be taken care of automatically by the modeline (like the
one below).
* No trailing whitespace.
* Use " for enclosing strings instead of ', unless using ' avoids escaping of lots of "
Example: alert("foo") instead of alert('foo');
* Exactly one space after if/for/while/catch etc. and after a comma, but none
after a parenthesis or after a function call:
for (pre; condition; post)
but:
alert("foo");
* Opening curly brackets { must be on a new line, unless it is used in a closure:
function myFunction ()
{
if (foo)
{
baz = false;
return bar;
}
else
{
return baz;
}
}
but:
setTimeout(function () {
...
});
* No braces for one-line conditional statements:
Right:
if (foo)
frob();
else
unfrob();
* Prefer lambda-style functions where suitable:
Right: list.filter(function (elem) elem.good != elem.BAD);
Wrong: list.filter(function (elem) { return elem.good != elem.BAD });
* Anonymous function definitions should be formatted with a space after the
keyword "function". Example: function () {}, not function() {}.
* Prefer the use of let over var i.e. only use var when required.
For more details, see
https://developer.mozilla.org/en/New_in_JavaScript_1.7#Block_scope_with_let
* Reuse common local variable names E.g. "elem" is generally used for element,
"win" for windows etc.
* Prefer // over /* */ comments (exceptions for big comments are usually OK)
Right: if (HACK) // TODO: remove hack
Wrong: if (HACK) /* TODO: remove hack */
Documentation comment blocks use /** ... */
* Only wrap lines if it makes the code obviously clearer. Lines longer than 132
characters should probably be broken up rather than wrapped anyway.
* Use UNIX new lines (\n), not windows (\r\n) or old Mac ones (\r)
* Use Iterators, Array#forEach, or for (let i = 0; i < ary.length; i++)
to iterate over arrays. for (let i in ary) and for each (let i in ary)
include members in an Array.prototype, which some extensions alter.
Right:
for (let [,elem] in Iterator(ary))
for (let [k, v] in Iterator(obj))
ary.forEach(function (elem) { ...
Wrong:
for each (let elem in ary)
The exceptions to this rule are for objects with __iterator__ set,
and for XML objects (see README.E4X).
* Avoid using 'new' with constructors where possible, and use [] and
{} rather than new Array/new Object.
Right:
RegExp("^" + foo + "$")
Function(code)
new Date
Wrong:
new RegExp("^" + foo + "$")
new Function(code)
Date() // Right if you want a string-representation of the date
NOTE by mst: That one is debateable, actually I like the "new" as one
immediately sees that a new object of a class is created which is not
so obvious by var x = CompletionContext(); which could also mean that
CompletionContext() could return a cached object. What's thesnowdog's
opinion and why do you, Kris, think it's better/cleaner?
I don't think it's better/cleaner, it just seemed to be a consensus.
--Kris
I don't like unnecessary use of 'new', I don't like 'new'. --djk
== Testing/Optimization ==
TODO: Add some information here about testing/validation/etc.
Information about how/when to use :regressions might be nice.
Additionally, maybe there should be some benchmark information here --
something to let a developer know what's "too" slow...? Or general
guidelines about optimization?
== Source Code Management ==
TODO: Document the existence of remote branches and discuss when and how
to push to them. At least provide an index so that devs know where
to look if an old branch needs to be maintained or a feature needs
to be added to a new branch. Keep in mind that git is not the most
intuitive SCM.
I don't agree. git is about as intuitive as any other SCM, but,
regardless, it's by far one of the most popular. There are
countless git walkthroughs, FAQs, tips pages (not to mention 'git
help') that I don't see the need to duplicate them here. As for
branches, 'git branch' should be sufficient, and, if not, there's
a list on gitweb.
--Kris
# vim: set fdm=marker sw=4 ts=4 et ai:

View File

@@ -32,7 +32,7 @@ const Point = new Struct("x", "y");
/**
* A class to manage the primary web content buffer. The name comes
* from vim's term, 'buffer', which signifies instances of open
* from Vim's term, 'buffer', which signifies instances of open
* files.
* @instance buffer
*/
@@ -41,7 +41,8 @@ function Buffer() //{{{
////////////////////////////////////////////////////////////////////////////////
////////////////////// PRIVATE SECTION /////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
/* FIXME: This doesn't belong here. */
// FIXME: This doesn't belong here.
let mainWindowID = config.mainWindowID || "main-window";
let fontSize = util.computedStyle(document.getElementById(mainWindowID)).fontSize;
@@ -197,7 +198,7 @@ function Buffer() //{{{
{
if (mappings.repeat)
{
for (let i in util.interruptableRange(0, Math.max(count, 1), 100))
for (let i in util.interruptibleRange(0, Math.max(count, 1), 100))
mappings.repeat();
}
},
@@ -330,7 +331,7 @@ function Buffer() //{{{
"//xhtml:input[not(@type) or @type='text' or @type='password'] | //xhtml:textarea[not(@disabled) and not(@readonly)]"
);
for (match in matches)
for (let match in matches)
{
let computedStyle = util.computedStyle(match);
if (computedStyle.visibility != "hidden" && computedStyle.display != "none")
@@ -339,11 +340,7 @@ function Buffer() //{{{
if (elements.length > 0)
{
if (count > elements.length)
count = elements.length;
else if (count < 1)
count = 1;
count = Math.min(Math.max(count, 1), elements.length);
elements[count - 1].focus();
}
else
@@ -482,7 +479,7 @@ function Buffer() //{{{
if (arg && (liberator.has("Win32") || arg[0] != ">"))
return liberator.echoerr("E488: Trailing characters");
options.temporaryContext(function () {
options.withContext(function () {
if (arg)
{
options.setPref("print.print_to_file", "true");
@@ -570,12 +567,9 @@ function Buffer() //{{{
let file = io.getFile(filename);
if (file.exists() && !args.bang)
{
liberator.echoerr("E13: File exists (add ! to override)");
return;
}
return void liberator.echoerr("E13: File exists (add ! to override)");
chosenData = { file: file, uri: makeURI(doc.location.href, doc.characterSet) };
chosenData = { file: file, uri: window.makeURI(doc.location.href, doc.characterSet) };
}
// if browser.download.useDownloadDir = false then the "Save As"
@@ -682,7 +676,7 @@ function Buffer() //{{{
if (!isFeed)
{
let type = data.type && data.type.toLowerCase();
var type = data.type && data.type.toLowerCase();
type = type.replace(/^\s+|\s*(?:;.*)?$/g, "");
isFeed = (type == "application/rss+xml" || type == "application/atom+xml");
@@ -817,8 +811,8 @@ function Buffer() //{{{
return {
/**
* The alternative stylesheets for the current buffer. Only
* returns stylesheets for the 'screen' media type.
* @property {Array} The alternative style sheets for the current
* buffer. Only returns style sheets for the 'screen' media type.
*/
get alternateStyleSheets()
{
@@ -836,7 +830,8 @@ function Buffer() //{{{
get pageInfo() pageInfo,
/**
* Returns whether the buffer is loaded. Values may be:
* @property {number} A value indicating whether the buffer is loaded.
* Values may be:
* 0 - Loading.
* 1 - Fully loaded.
* 2 - Load failed.
@@ -854,8 +849,8 @@ function Buffer() //{{{
},
/**
* The last focused input field in the buffer. Used by the
* "gi" key binding.
* @property {Object} The last focused input field in the buffer. Used
* by the "gi" key binding.
*/
get lastInputField()
{
@@ -870,21 +865,24 @@ function Buffer() //{{{
},
/**
* The current top-level document's URL.
* @property {string} The current top-level document's URL.
*/
get URL()
{
return window.content.document.location.href;
},
/**
* @property {number} The buffer's height in pixels.
*/
get pageHeight()
{
return window.content.innerHeight;
},
/**
* The current browser's text zoom level, as a percentage with
* 100 as 'normal'. Only affects text size.
* @property {number} The current browser's text zoom level, as a
* percentage with 100 as 'normal'. Only affects text size.
*/
get textZoom()
{
@@ -896,9 +894,9 @@ function Buffer() //{{{
},
/**
* The current browser's text zoom level, as a percentage with
* 100 as 'normal'. Affects text size, as well as image size
* and block size.
* @property {number} The current browser's text zoom level, as a
* percentage with 100 as 'normal'. Affects text size, as well as
* image size and block size.
*/
get fullZoom()
{
@@ -910,7 +908,7 @@ function Buffer() //{{{
},
/**
* The current document's title.
* @property {string} The current document's title.
*/
get title()
{
@@ -918,6 +916,7 @@ function Buffer() //{{{
},
/**
* Adds a new section to the page information output.
*
* @param {string} option The section's value in 'pageinfo'.
* @param {string} title The heading for this section's
@@ -972,6 +971,8 @@ function Buffer() //{{{
* positioned in.
*
* NOTE: might change the selection
*
* @returns {string}
*/
// FIXME: getSelection() doesn't always preserve line endings, see:
// https://www.mozdev.org/bugs/show_bug.cgi?id=19303
@@ -1026,9 +1027,8 @@ function Buffer() //{{{
},
/**
* Try to guess links the like of "next" and "prev". Though it
* has a singularly horrendous name, it turns out to be quite
* useful.
* Tries to guess links the like of "next" and "prev". Though it has a
* singularly horrendous name, it turns out to be quite useful.
*
* @param {string} rel The relationship to look for. Looks for
* links with matching @rel or @rev attributes, and,
@@ -1083,12 +1083,12 @@ function Buffer() //{{{
return false;
}
let retVal = followFrame(window.content);
if (!retVal)
// only loop through frames if the main content didnt match
retVal = Array.some(window.content.frames, followFrame);
let ret = followFrame(window.content);
if (!ret)
// only loop through frames if the main content didn't match
ret = Array.some(window.content.frames, followFrame);
if (!retVal)
if (!ret)
liberator.beep();
},
@@ -1125,7 +1125,7 @@ function Buffer() //{{{
case liberator.NEW_TAB:
case liberator.NEW_BACKGROUND_TAB:
ctrlKey = true;
shiftKey = (where == liberator.NEW_BACKGROUND_TAB);
shiftKey = (where != liberator.NEW_BACKGROUND_TAB);
break;
case liberator.NEW_WINDOW:
shiftKey = true;
@@ -1147,13 +1147,19 @@ function Buffer() //{{{
},
/**
* The current document's selection controller.
* @property {Object} The current document's selection controller.
*/
get selectionController() getBrowser().docShell
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsISelectionDisplay)
.QueryInterface(Ci.nsISelectionController),
/**
* Saves a page link to disk.
*
* @param {Object} elem The page link to save.
* @param {boolean} skipPrompt Whether to open the "Save Link As..." dialog
*/
saveLink: function (elem, skipPrompt)
{
let doc = elem.ownerDocument;
@@ -1229,7 +1235,13 @@ function Buffer() //{{{
win.scrollByPages(pages);
},
scrollByScrollSize: function (count, direction)
/**
* Scrolls the buffer vertically <b>count</b> * 'scroll' rows.
*
* @param {number} count The multiple of 'scroll' lines to scroll.
* @param {number} direction The direction to scroll, down if 1 and up if -1.
*/
scrollByScrollSize: function (count, direction) // XXX: boolean
{
if (count > 0)
options["scroll"] = count;
@@ -1244,7 +1256,9 @@ function Buffer() //{{{
},
/**
* Scrolls the current buffer vertically to <b>percentage</b>
* Scrolls the current buffer vertically to <b>percentage</b>.
*
* @param {number} percentage The page percentile to scroll the buffer to.
*/
scrollToPercentile: function (percentage)
{
@@ -1279,9 +1293,16 @@ function Buffer() //{{{
},
// TODO: allow callback for filtering out unwanted frames? User defined?
/**
* Shifts the focus to another frame within the buffer. Each buffer
* contains at least one frame.
*
* @param {number} count The number of frames to skip through.
* @param {boolean} forward The direction of motion.
*/
shiftFrameFocus: function (count, forward)
{
if (!window.content.document instanceof HTMLDocument)
if (!(window.content.document instanceof HTMLDocument))
return;
count = Math.max(count, 1);
@@ -1357,11 +1378,23 @@ function Buffer() //{{{
// similar to pageInfo
// TODO: print more useful information, just like the DOM inspector
/**
* Displays information about the specified element.
*
* @param {Object} elem
*/
showElementInfo: function (elem)
{
liberator.echo(<>Element:<br/>{util.objectToString(elem, true)}</>, commandline.FORCE_MULTILINE);
},
/**
* Displays information about the current buffer.
*
* @param {boolean} verbose Display more verbose information.
* @param {string} sections A string limiting the displayed sections.
* @default The value of 'pageinfo'.
*/
showPageInfo: function (verbose, sections)
{
// Ctrl-g single line output
@@ -1391,6 +1424,9 @@ function Buffer() //{{{
liberator.echo(list, commandline.FORCE_MULTILINE);
},
/**
* Opens a viewer to inspect the source of the currently selected range.
*/
viewSelectionSource: function ()
{
// copied (and tuned somebit) from browser.jar -> nsContextMenu.js
@@ -1411,6 +1447,15 @@ function Buffer() //{{{
docUrl, docCharset, reference, "selection");
},
/**
* Opens a viewer to inspect the source of the current buffer or the
* specified <b>url</b>. Either the default viewer or the configured
* external editor is used.
*
* @param {string} url The URL of the source.
* @default The current buffer.
* @param {boolean} useExternalEditor View the source in the external editor.
*/
viewSource: function (url, useExternalEditor)
{
url = url || buffer.URL;
@@ -1421,11 +1466,23 @@ function Buffer() //{{{
liberator.open("view-source:" + url);
},
/**
* Increases the zoom level of the current buffer.
*
* @param {number} steps The number of zoom levels to jump.
* @param {boolean} fullZoom Whether to use full zoom or text zoom.
*/
zoomIn: function (steps, fullZoom)
{
bumpZoomLevel(steps, fullZoom);
},
/**
* Decreases the zoom level of the current buffer.
*
* @param {number} steps The number of zoom levels to jump.
* @param {boolean} fullZoom Whether to use full zoom or text zoom.
*/
zoomOut: function (steps, fullZoom)
{
bumpZoomLevel(-steps, fullZoom);
@@ -1443,8 +1500,8 @@ function Marks() //{{{
////////////////////// PRIVATE SECTION /////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
var localMarks = storage.newMap('local-marks', true);
var urlMarks = storage.newMap('url-marks', true);
var localMarks = storage.newMap("local-marks", true);
var urlMarks = storage.newMap("url-marks", true);
var pendingJumps = [];
var appContent = document.getElementById("appcontent");
@@ -1471,7 +1528,7 @@ function Marks() //{{{
return name + ", " + mark.location +
", (" + Math.round(mark.position.x * 100) +
"%, " + Math.round(mark.position.y * 100) + "%)" +
(('tab' in mark) ? ", tab: " + tabs.index(mark.tab) : "");
(("tab" in mark) ? ", tab: " + tabs.index(mark.tab) : "");
}
function removeLocalMark(mark)

View File

@@ -28,14 +28,14 @@ the terms of any one of the MPL, the GPL or the LGPL.
/** @scope modules */
// Do NOT create instances of this class yourself, use the helper method
// commands.add() instead
/**
* A class representing EX commands. Instances are created by
* A class representing Ex commands. Instances are created by
* the {@link Commands} class.
*
* @private
*/
// Do NOT create instances of this class yourself, use the helper method
// commands.add() instead
function Command(specs, description, action, extraInfo) //{{{
{
if (!specs || !action)
@@ -86,7 +86,7 @@ function Command(specs, description, action, extraInfo) //{{{
/** @property {string[]} All of this command's long names, e.g., "command" */
this.longNames = expandedSpecs.longNames;
/** @property {string} The command's cannonical name. */
/** @property {string} The command's canonical name. */
this.name = this.longNames[0];
/** @property {string[]} All of this command's long and short names. */
this.names = expandedSpecs.names; // return all command name aliases
@@ -112,7 +112,7 @@ function Command(specs, description, action, extraInfo) //{{{
* arguments begin. For instance, with a value of 2, all arguments
* starting with the third are parsed as a single string, with all
* quoting characters passed literally. This is especially useful for
* commands which take key mappings or ex command lines as
* commands which take key mappings or Ex command lines as
* arguments.
*/
this.literal = extraInfo.literal == null ? null : extraInfo.literal;
@@ -133,7 +133,7 @@ function Command(specs, description, action, extraInfo) //{{{
this.isUserCommand = extraInfo.isUserCommand || false;
/**
* @property {string} For commands defined via :command, contains
* the EX command line to be executed upon invocation.
* the Ex command line to be executed upon invocation.
*/
this.replacementText = extraInfo.replacementText || null;
};
@@ -148,7 +148,7 @@ Command.prototype = {
* @param {boolean} bang @deprecated Whether this command was
* executed with a trailing !.
* @param {number} count @deprecated Whether this command was
* executed a leading count.
* executed with a leading count.
* @param modifiers Any modifiers to be passed to
* {@link action}
*/
@@ -189,6 +189,7 @@ Command.prototype = {
* Returns whether this command may be invoked via <b>name</b>.
*
* @param {string} name
* @returns {boolean}
*/
hasName: function (name)
{
@@ -214,7 +215,7 @@ Command.prototype = {
* purposes.
* @param {Object} extra Extra keys to be spliced into the
* returned Args object.
* @returns Args
* @returns {Args}
* @see Commands#parseArgs
*/
parseArgs: function (args, complete, extra) commands.parseArgs(args, this.options, this.argCount, false, this.literal, complete, extra)
@@ -306,7 +307,7 @@ function Commands() //{{{
completion.setFunctionCompleter(commands.get, [function () ([c.name, c.description] for (c in commands))]);
});
var commandManager = {
const self = {
// FIXME: remove later, when our option handler is better
OPTION_ANY: 0, // can be given no argument or an argument of any type,
@@ -717,27 +718,18 @@ function Commands() //{{{
return args;
},
// return [null, null, null, null, heredoc_tag || false];
// [count, cmd, special, args] = match;
parseCommand: function (str, tag)
parseCommand: function (str)
{
// remove comments
str.replace(/\s*".*$/, "");
if (tag) // we already have a multiline heredoc construct
{
if (str == tag)
return [null, null, null, null, false];
else
return [null, null, null, str, tag];
}
// 0 - count, 1 - cmd, 2 - special, 3 - args, 4 - heredoc tag
// 0 - count, 1 - cmd, 2 - special, 3 - args
let matches = str.match(/^:*(\d+|%)?([a-zA-Z]+|!)(!)?(?:\s*(.*?))?$/);
//var matches = str.match(/^:*(\d+|%)?([a-zA-Z]+|!)(!)?(?:\s*(.*?)\s*)?$/);
if (!matches)
return [null, null, null, null, null];
let [, count, cmd, special, args, heredoc] = matches;
return [null, null, null, null];
let [, count, cmd, special, args] = matches;
// parse count
if (count)
@@ -745,14 +737,7 @@ function Commands() //{{{
else
count = this.COUNT_NONE;
if (args)
{
tag = args.match(/<<\s*(\w+)\s*$/);
if (tag && tag[1])
heredoc = tag[1];
}
return [count, cmd, !!special, args || "", heredoc];
return [count, cmd, !!special, args || ""];
},
get complQuote() complQuote,
@@ -769,7 +754,7 @@ function Commands() //{{{
{
return str.replace(/<((?:q-)?)([a-zA-Z]+)?>/g, function (match, quote, token)
{
if (token == "lt") // Don't quote, as in vim (but, why so in vim? You'd think people wouldn't say <q-lt> if they didn't want it)
if (token == "lt") // Don't quote, as in Vim (but, why so in Vim? You'd think people wouldn't say <q-lt> if they didn't want it)
return "<";
let res = tokens[token];
if (res == undefined) // Ignore anything undefined
@@ -811,7 +796,7 @@ function Commands() //{{{
// TODO: Vim allows commands to be defined without {rep} if there are {attr}s
// specified - useful?
commandManager.add(["com[mand]"],
self.add(["com[mand]"],
"List and define commands",
function (args)
{
@@ -918,13 +903,13 @@ function Commands() //{{{
bang: true,
completer: function (context) completion.userCommand(context),
options: [
[["-nargs"], commandManager.OPTION_STRING,
[["-nargs"], self.OPTION_STRING,
function (arg) /^[01*?+]$/.test(arg), ["0", "1", "*", "?", "+"]],
[["-bang"], commandManager.OPTION_NOARG],
[["-count"], commandManager.OPTION_NOARG],
[["-complete"], commandManager.OPTION_STRING,
[["-bang"], self.OPTION_NOARG],
[["-count"], self.OPTION_NOARG],
[["-complete"], self.OPTION_STRING,
function (arg) arg in completeOptionMap || /custom,\w+/.test(arg),
function (context) [[k, ''] for ([k, v] in Iterator(completeOptionMap))]]
function (context) [[k, ""] for ([k, v] in Iterator(completeOptionMap))]]
],
literal: 1,
serial: function () [
@@ -945,7 +930,7 @@ function Commands() //{{{
]
});
commandManager.add(["comc[lear]"],
self.add(["comc[lear]"],
"Delete all user-defined commands",
function ()
{
@@ -953,7 +938,7 @@ function Commands() //{{{
},
{ argCount: "0" });
commandManager.add(["delc[ommand]"],
self.add(["delc[ommand]"],
"Delete the specified user-defined command",
function (args)
{
@@ -971,7 +956,7 @@ function Commands() //{{{
//}}}
return commandManager;
return self;
}; //}}}

View File

@@ -66,7 +66,8 @@ function CompletionContext(editor, name, offset) //{{{
self.contexts[name] = this;
/**
* @property {CompletionContext} This context's parent. {null} when this is a top-level context.
* @property {CompletionContext} This context's parent. {null} when
* this is a top-level context.
*/
self.parent = parent;
@@ -111,6 +112,12 @@ function CompletionContext(editor, name, offset) //{{{
this.editor = editor;
this.compare = function (a, b) String.localeCompare(a.text, b.text);
/**
* @property {function} This function is called when we close
* a completion window with Esc or Ctrl-c. Usually this callback
* is only needed for long, asynchronous completions
*/
this.cancel = null;
/**
* @property {function} The function used to filter the results.
* @default Selects all results which match every predicate in the
@@ -141,16 +148,18 @@ function CompletionContext(editor, name, offset) //{{{
}];
/**
* @property {boolean} Specifies whether this context results must
* match the filter at the begining of the string.
* match the filter at the beginning of the string.
* @default true
*/
this.anchored = true;
/**
* @property {Object} A map of all contexts, keyed on their names.
* Names are assigned when a context is forked, with its specified
* name appended, after a '/', to its parent's name.
* name appended, after a '/', to its parent's name. May
* contain inactive contexts. For active contexts, see
* {@link #contextList}.
*/
this.contexts = { name: this };
this.contexts = { "/": this };
/**
* @property {Object} A mapping of keys, for {@link #getKey}. Given
* { key: value }, getKey(item, key) will return values as such:
@@ -159,7 +168,7 @@ function CompletionContext(editor, name, offset) //{{{
*/
this.keys = { text: 0, description: 1, icon: "icon" };
/**
* @property {number} This context's offset from the begining of
* @property {number} This context's offset from the beginning of
* {@link #editor}'s value.
*/
this.offset = offset || 0;
@@ -519,6 +528,15 @@ CompletionContext.prototype = {
this._filter = this._filter.substr(count);
},
cancelAll: function ()
{
for (let [,context] in Iterator(this.contextList))
{
if (context.cancel)
context.cancel();
}
},
/**
* Gets a key from {@link #cache}, setting it to <b>defVal</b> if it
* doesn't already exists.
@@ -622,6 +640,11 @@ CompletionContext.prototype = {
for (let type in this.selectionTypes)
this.highlight(0, 0, type);
/**
* @property {[CompletionContext]} A list of active
* completion contexts, in the order in which they were
* instantiated.
*/
this.contextList = [];
this.offset = 0;
this.process = [];
@@ -631,6 +654,8 @@ CompletionContext.prototype = {
this.updateAsync = false;
this.waitingForTab = false;
this.cancelAll();
if (this.editor)
{
this.value = this.editor.selection.focusNode.textContent;
@@ -653,7 +678,7 @@ CompletionContext.prototype = {
/**
* Wait for all subcontexts to complete.
*
* @param {boolean} interruptable When true, the call may be interrupted
* @param {boolean} interruptible When true, the call may be interrupted
* via <C-c>. In this case, "Interrupted" may be thrown.
* @param {number} timeout The maximum time, in milliseconds, to wait.
*/
@@ -682,10 +707,10 @@ function Completion() //{{{
const OFFSET = 0, CHAR = 1, STATEMENTS = 2, DOTS = 3, FULL_STATEMENTS = 4, COMMA = 5, FUNCTIONS = 6;
let stack = [];
let functions = [];
let top = []; /* The element on the top of the stack. */
let last = ""; /* The last opening char pushed onto the stack. */
let lastNonwhite = ""; /* Last non-whitespace character we saw. */
let lastChar = ""; /* Last character we saw, used for \ escaping quotes. */
let top = []; // The element on the top of the stack.
let last = ""; // The last opening char pushed onto the stack.
let lastNonwhite = ""; // Last non-whitespace character we saw.
let lastChar = ""; // Last character we saw, used for \ escaping quotes.
let compl = [];
let str = "";
@@ -732,11 +757,10 @@ function Completion() //{{{
return iterator;
}
/* Search the object for strings starting with @key.
* If @last is defined, key is a quoted string, it's
* wrapped in @last after @offset characters are sliced
* off of it and it's quoted.
*/
// Search the object for strings starting with @key.
// If @last is defined, key is a quoted string, it's
// wrapped in @last after @offset characters are sliced
// off of it and it's quoted.
this.objectKeys = function objectKeys(obj)
{
// Things we can dereference
@@ -808,11 +832,10 @@ function Completion() //{{{
}
}
/* Get an element from the stack. If @n is negative,
* count from the top of the stack, otherwise, the bottom.
* If @m is provided, return the @mth value of element @o
* of the stack entey at @n.
*/
// Get an element from the stack. If @n is negative,
// count from the top of the stack, otherwise, the bottom.
// If @m is provided, return the @mth value of element @o
// of the stack entey at @n.
let get = function get(n, m, o)
{
let a = stack[n >= 0 ? n : stack.length + n];
@@ -826,7 +849,7 @@ function Completion() //{{{
function buildStack(filter)
{
let self = this;
/* Push and pop the stack, maintaining references to 'top' and 'last'. */
// Push and pop the stack, maintaining references to 'top' and 'last'.
let push = function push(arg)
{
top = [i, arg, [i], [], [], [], []];
@@ -854,7 +877,7 @@ function Completion() //{{{
return ret;
}
let i = 0, c = ""; /* Current index and character, respectively. */
let i = 0, c = ""; // Current index and character, respectively.
// Reuse the old stack.
if (str && filter.substr(0, str.length) == str)
@@ -870,11 +893,10 @@ function Completion() //{{{
push("#root");
}
/* Build a parse stack, discarding entries as opening characters
* match closing characters. The stack is walked from the top entry
* and down as many levels as it takes us to figure out what it is
* that we're completing.
*/
// Build a parse stack, discarding entries as opening characters
// match closing characters. The stack is walked from the top entry
// and down as many levels as it takes us to figure out what it is
// that we're completing.
str = filter;
let length = str.length;
for (; i < length; lastChar = c, i++)
@@ -906,7 +928,7 @@ function Completion() //{{{
switch (c)
{
case "(":
/* Function call, or if/while/for/... */
// Function call, or if/while/for/...
if (/[\w$]/.test(lastNonwhite))
{
functions.push(i);
@@ -927,7 +949,7 @@ function Completion() //{{{
break;
case ")": pop("("); break;
case "]": pop("["); break;
case "}": pop("{"); /* Fallthrough */
case "}": pop("{"); // Fallthrough
case ";":
top[FULL_STATEMENTS].push(i);
break;
@@ -972,7 +994,7 @@ function Completion() //{{{
this.context.getCache("eval", Object);
this.context.getCache("evalContext", function () ({ __proto__: userContext }));
/* Okay, have parse stack. Figure out what we're completing. */
// Okay, have parse stack. Figure out what we're completing.
// Find any complete statements that we can eval before we eval our object.
// This allows for things like: let doc = window.content.document; let elem = doc.createElement...; elem.<Tab>
@@ -1039,7 +1061,7 @@ function Completion() //{{{
cacheKey = null;
let obj = [[cache.evalContext, "Local Variables"], [userContext, "Global Variables"],
[modules, "modules"], [window, "window"]]; // Default objects;
/* Is this an object dereference? */
// Is this an object dereference?
if (dot < statement) // No.
dot = statement - 1;
else // Yes. Set the object to the string before the dot.
@@ -1073,7 +1095,7 @@ function Completion() //{{{
compl = function (context, obj)
{
context.process = [null, function highlight(item, v) template.highlight(v, true)];
// Sort in a logical fasion for object keys:
// Sort in a logical fashion for object keys:
// Numbers are sorted as numbers, rather than strings, and appear first.
// Constants are unsorted, and appear before other non-null strings.
// Other strings are sorted in the default manner.
@@ -1112,11 +1134,11 @@ function Completion() //{{{
// Otherwise, do nothing.
if (last == "'" || last == '"')
{
/*
* str = "foo[bar + 'baz"
* obj = "foo"
* key = "bar + ''"
*/
//
// str = "foo[bar + 'baz"
// obj = "foo"
// key = "bar + ''"
//
// The top of the stack is the sting we're completing.
// Wrap it in its delimiters and eval it to process escape sequences.
@@ -1133,21 +1155,20 @@ function Completion() //{{{
return this.eval(key);
}
/* Is this an object accessor? */
// Is this an object accessor?
if (get(-2)[CHAR] == "[") // Are we inside of []?
{
/* Stack:
* [-1]: "...
* [-2]: [...
* [-3]: base statement
*/
// Stack:
// [-1]: "...
// [-2]: [...
// [-3]: base statement
// Yes. If the [ starts at the begining of a logical
// Yes. If the [ starts at the beginning of a logical
// statement, we're in an array literal, and we're done.
if (get(-3, 0, STATEMENTS) == get(-2)[OFFSET])
return;
// Begining of the statement upto the opening [
// Beginning of the statement upto the opening [
let obj = getObj(-3, get(-2)[OFFSET]);
return complete.call(this, obj, getKey(), null, string, last);
@@ -1156,11 +1177,10 @@ function Completion() //{{{
// Is this a function call?
if (get(-2)[CHAR] == "(")
{
/* Stack:
* [-1]: "...
* [-2]: (...
* [-3]: base statement
*/
// Stack:
// [-1]: "...
// [-2]: (...
// [-3]: base statement
// Does the opening "(" mark a function call?
if (get(-3, 0, FUNCTIONS) != get(-2)[OFFSET])
@@ -1209,15 +1229,15 @@ function Completion() //{{{
return;
}
/*
* str = "foo.bar.baz"
* obj = "foo.bar"
* key = "baz"
*
* str = "foo"
* obj = [modules, window]
* key = "foo"
*/
//
// str = "foo.bar.baz"
// obj = "foo.bar"
// key = "baz"
//
// str = "foo"
// obj = [modules, window]
// key = "foo"
//
let [offset, obj, key] = getObjKey(-1);
@@ -1230,7 +1250,7 @@ function Completion() //{{{
}
if (!/^(?:[a-zA-Z_$][\w$]*)?$/.test(key))
return; /* Not a word. Forget it. Can this even happen? */
return; // Not a word. Forget it. Can this even happen?
try
{ // FIXME
@@ -1250,7 +1270,7 @@ function Completion() //{{{
////////////////////// PUBLIC SECTION //////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
let self = {
const self = {
setFunctionCompleter: function setFunctionCompleter(funcs, completers)
{
@@ -1338,6 +1358,7 @@ function Completion() //{{{
context.completions = config.autocommands;
},
// TODO: shouldn't these app-specific completers be moved to config.js? --djk
bookmark: function bookmark(context, tags, extra)
{
context.title = ["Bookmark", "Title"];
@@ -1552,13 +1573,15 @@ function Completion() //{{{
location: function location(context)
{
if (!services.get("autoCompleteSearch"))
return
return;
context.anchored = false;
context.title = ["Smart Completions"];
context.keys.icon = 2;
context.incomplete = true;
context.hasItems = context.completions.length > 0; // XXX
context.filterFunc = null;
context.cancel = function () services.get("autoCompleteSearch").stopSearch();
context.compare = null;
let timer = new Timer(50, 100, function (result) {
context.incomplete = result.searchResult >= result.RESULT_NOMATCH_ONGOING;
@@ -1627,9 +1650,8 @@ function Completion() //{{{
let completions = completer(context);
if (!completions)
return;
/* Not vim compatible, but is a significant enough improvement
* that it's worth breaking compatibility.
*/
// Not Vim compatible, but is a significant enough improvement
// that it's worth breaking compatibility.
if (newValues instanceof Array)
{
completions = completions.filter(function (val) newValues.indexOf(val[0]) == -1);

View File

@@ -217,7 +217,7 @@ function Editor() //{{{
var myModes = [modes.INSERT, modes.COMMAND_LINE];
/* KEYS COUNT CARET TEXTAREA VISUAL_TEXTAREA */
// KEYS COUNT CARET TEXTAREA VISUAL_TEXTAREA
addMovementMap(["k", "<Up>"], true, "lineMove", false, "cmd_linePrevious", selectPreviousLine);
addMovementMap(["j", "<Down>", "<Return>"], true, "lineMove", true, "cmd_lineNext", selectNextLine);
addMovementMap(["h", "<Left>", "<BS>"], true, "characterMove", false, "cmd_charPrevious", "cmd_selectCharPrevious");
@@ -371,10 +371,14 @@ function Editor() //{{{
{ flags: Mappings.flags.COUNT });
// visual mode
mappings.add([modes.CARET, modes.TEXTAREA, modes.VISUAL],
mappings.add([modes.CARET, modes.TEXTAREA],
["v"], "Start visual mode",
function (count) { modes.set(modes.VISUAL, liberator.mode); });
mappings.add([modes.VISUAL],
["v"], "End visual mode",
function (count) { events.onEscape() });
mappings.add([modes.TEXTAREA],
["V"], "Start visual line mode",
function (count)
@@ -557,9 +561,9 @@ function Editor() //{{{
unselectText: function ()
{
let elt = window.document.commandDispatcher.focusedElement;
if (elt && elt.selectionEnd)
elt.selectionEnd = elt.selectionStart;
let elem = window.document.commandDispatcher.focusedElement;
if (elem && elem.selectionEnd)
elem.selectionEnd = elem.selectionStart;
},
selectedText: function ()
@@ -570,20 +574,20 @@ function Editor() //{{{
pasteClipboard: function ()
{
let elt = window.document.commandDispatcher.focusedElement;
let elem = window.document.commandDispatcher.focusedElement;
if (elt.setSelectionRange && util.readFromClipboard())
if (elem.setSelectionRange && util.readFromClipboard())
// readFromClipboard would return 'undefined' if not checked
// dunno about .setSelectionRange
{
let rangeStart = elt.selectionStart; // caret position
let rangeEnd = elt.selectionEnd;
let tempStr1 = elt.value.substring(0, rangeStart);
let rangeStart = elem.selectionStart; // caret position
let rangeEnd = elem.selectionEnd;
let tempStr1 = elem.value.substring(0, rangeStart);
let tempStr2 = util.readFromClipboard();
let tempStr3 = elt.value.substring(rangeEnd);
elt.value = tempStr1 + tempStr2 + tempStr3;
elt.selectionStart = rangeStart + tempStr2.length;
elt.selectionEnd = elt.selectionStart;
let tempStr3 = elem.value.substring(rangeEnd);
elem.value = tempStr1 + tempStr2 + tempStr3;
elem.selectionStart = rangeStart + tempStr2.length;
elem.selectionEnd = elem.selectionStart;
}
},
@@ -709,7 +713,7 @@ function Editor() //{{{
// This function will move/select up to given "pos"
// Simple setSelectionRange() would be better, but we want to maintain the correct
// order of selectionStart/End (a firefox bug always makes selectionStart <= selectionEnd)
// order of selectionStart/End (a Firefox bug always makes selectionStart <= selectionEnd)
// Use only for small movements!
moveToPosition: function (pos, forward, select)
{
@@ -809,7 +813,7 @@ function Editor() //{{{
}
args.push(path);
liberator.callFunctionInThread(null, io.run, args.shift(), args, true);
liberator.callFunctionInThread(null, io.run, io.expandPath(args.shift()), args, true);
},
// TODO: clean up with 2 functions for textboxes and currentEditor?
@@ -900,7 +904,7 @@ function Editor() //{{{
//
// if filter == ! remove all and add it as only END
//
// variant 1: rhs matches anywere in loop
// variant 1: rhs matches anywhere in loop
//
// 1 mod matches anywhere in loop
// a) simple replace and
@@ -913,7 +917,7 @@ function Editor() //{{{
// (b) a ! is there. do nothing END)
//
// variant 2: rhs matches *no*were in loop and filter is c or i
// everykind of current combo is possible to 1 {c,i,!} or two {c and i}
// every kind of current combo is possible to 1 {c,i,!} or two {c and i}
//
// 1 mod is ! split into two i + c END
// 1 not !: opposite mode (first), add/change 'second' and END

View File

@@ -4,7 +4,7 @@ catch (e)
{
__liberator_eval_error = e;
}
// Important: The eval statement *must* remain on the first line
// IMPORTANT: The eval statement *must* remain on the first line
// in order for line numbering in any errors to remain correct.
//
// vim: set fdm=marker sw=4 ts=4 et:

View File

@@ -37,13 +37,12 @@ function AutoCommands() //{{{
////////////////////// PRIVATE SECTION /////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
const AutoCommand = new Struct("event", "pattern", "command");
var store = [];
var lastFocus = null;
function matchAutoCmd(autoCmd, event, regex)
{
return (!event || autoCmd.event == event) &&
(!regex || autoCmd.pattern.source == regex);
return (!event || autoCmd.event == event) && (!regex || autoCmd.pattern.source == regex);
}
/////////////////////////////////////////////////////////////////////////////}}}
@@ -72,6 +71,7 @@ function AutoCommands() //{{{
{
let [event, regex, cmd] = args;
let events = null;
if (event)
{
// NOTE: event can only be a comma separated list for |:au {event} {pat} {cmd}|
@@ -96,6 +96,7 @@ function AutoCommands() //{{{
{
if (event == "*")
event = null;
if (args.bang)
{
// TODO: "*" only appears to work in Vim when there is a {group} specified
@@ -181,6 +182,16 @@ function AutoCommands() //{{{
__iterator__: function () util.Array.iterator(store),
/**
* Adds a new autocommand. <b>cmd</b> will be executed when one of the
* specified <b>events</b> occurs and the URL of the applicable buffer
* matches <b>regex</b>.
*
* @param {Array} events The array of event names for which this
* autocommand should be executed.
* @param {string} regex The URL pattern to match against the buffer URL
* @param {string} cmd The Ex command to run
*/
add: function (events, regex, cmd)
{
if (typeof events == "string")
@@ -188,20 +199,43 @@ function AutoCommands() //{{{
events = events.split(",");
liberator.log("DEPRECATED: the events list arg to autocommands.add() should be an array of event names");
}
events.forEach(function (event)
store.push({ event: event, pattern: RegExp(regex), command: cmd }));
events.forEach(function (event) {
store.push(new AutoCommand(event, RegExp(regex), cmd));
});
},
/**
* Returns all autocommands with a matching <b>event</b> and
* <b>regex</b>.
*
* @param {string} event The event name filter.
* @param {string} regex The URL pattern filter.
* @returns {AutoCommand[]}
*/
get: function (event, regex)
{
return store.filter(function (autoCmd) matchAutoCmd(autoCmd, event, regex));
},
/**
* Deletes all autocommands with a matching <b>event</b> and
* <b>regex</b>.
*
* @param {string} event The event name filter.
* @param {string} regex The URL pattern filter.
*/
remove: function (event, regex)
{
store = store.filter(function (autoCmd) !matchAutoCmd(autoCmd, event, regex));
},
/**
* Lists all autocommands with a matching <b>event</b> and
* <b>regex</b>.
*
* @param {string} event The event name filter.
* @param {string} regex The URL pattern filter.
*/
list: function (event, regex)
{
let cmds = {};
@@ -237,6 +271,14 @@ function AutoCommands() //{{{
commandline.echo(list, commandline.HL_NORMAL, commandline.FORCE_MULTILINE);
},
/**
* Triggers the execution of all autocommands registered for
* <b>event</b>. A map of <b>args</b> is passed to each autocommand
* when it is being executed.
*
* @param {string} event The event to fire.
* @param {Object} args The args to pass to each autocommand.
*/
trigger: function (event, args)
{
if (options.get("eventignore").has("all", event))
@@ -273,7 +315,7 @@ function AutoCommands() //{{{
}
else
{
liberator.execute(commands.replaceTokens(autoCmd.command, args));
liberator.execute(commands.replaceTokens(autoCmd.command, args), null, true);
}
}
}
@@ -295,10 +337,12 @@ function Events() //{{{
var fullscreen = window.fullScreen;
var lastFocus = null;
var inputBufferLength = 0; // count the number of keys in v.input.buffer (can be different from v.input.buffer.length)
var skipMap = false; // while feeding the keys (stored in v.input.buffer | no map found) - ignore mappings
var macros = storage.newMap('macros', true);
var macros = storage.newMap("macros", true);
var currentMacro = "";
var lastMacro = "";
@@ -457,14 +501,14 @@ function Events() //{{{
function isFormElemFocused()
{
let elt = window.document.commandDispatcher.focusedElement;
if (elt == null)
let elem = window.document.commandDispatcher.focusedElement;
if (elem == null)
return false;
try
{ // sometimes the elt doesn't have .localName
let tagname = elt.localName.toLowerCase();
let type = elt.type.toLowerCase();
{ // sometimes the elem doesn't have .localName
let tagname = elem.localName.toLowerCase();
let type = elem.type.toLowerCase();
if ((tagname == "input" && (type != "image")) ||
tagname == "textarea" ||
@@ -524,7 +568,7 @@ function Events() //{{{
{
// hacky way to get rid of "Transfering data from ..." on sites with frames
// when you click on a link inside a frameset, because asyncUpdateUI
// is not triggered there (firefox bug?)
// is not triggered there (Firefox bug?)
setTimeout(statusline.updateUrl, 10);
return;
}
@@ -568,7 +612,7 @@ function Events() //{{{
{
try
{
eventManager[method](event);
self[method](event);
}
catch (e)
{
@@ -587,7 +631,6 @@ function Events() //{{{
// load all macros inside ~/.vimperator/macros/
// setTimeout needed since io. is loaded after events.
setTimeout (function () {
// FIXME: largely duplicated for loading plugins
try
{
let dirs = io.getRuntimeDirectories("macros");
@@ -715,7 +758,7 @@ function Events() //{{{
////////////////////// PUBLIC SECTION //////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
var eventManager = {
const self = {
feedingKeys: false,
@@ -805,7 +848,7 @@ function Events() //{{{
{
if (lastMacro.length == 1)
// TODO: ignore this like Vim?
liberator.echoerr("Exxx: Register " + lastMacro + " not set");
liberator.echoerr("Exxx: Register '" + lastMacro + "' not set");
else
liberator.echoerr("Exxx: Named macro '" + lastMacro + "' not set");
}
@@ -832,12 +875,18 @@ function Events() //{{{
}
},
// This method pushes keys into the event queue from liberator
// it is similar to vim's feedkeys() method, but cannot cope with
// 2 partially-fed strings, you have to feed one parsable string
//
// @param keys: a string like "2<C-f>" to pass
// if you want < to be taken literally, prepend it with a \\
/**
* Pushes keys into the event queue from liberator it is similar to
* Vim's feedkeys() method, but cannot cope with 2 partially-fed
* strings, you have to feed one parsable string.
*
* @param {string} keys A string like "2<C-f>" to pass if you want "<"
* to be taken literally, prepend it with a "\\".
* @param {boolean} noremap Allow recursive mappings.
* @param {boolean} silent Whether the command should be echoed to the
* command-line.
* @returns {boolean}
*/
feedkeys: function (keys, noremap, silent)
{
let doc = window.document;
@@ -965,7 +1014,7 @@ function Events() //{{{
if (event.metaKey)
modifier += "M-";
if (event.type == "keypress")
if (/^key/.test(event.type))
{
if (event.charCode == 0)
{
@@ -1043,8 +1092,9 @@ function Events() //{{{
if (buffer.loaded == 1)
return true;
const maxWaitTime = 25;
let start = Date.now();
let end = start + 25000; // maximum time to wait - TODO: add option
let end = start + (maxWaitTime * 1000); // maximum time to wait - TODO: add option
let now;
while (now = Date.now(), now < end)
{
@@ -1061,14 +1111,14 @@ function Events() //{{{
break;
}
else
liberator.echomsg("Waiting for page to load...");
liberator.echo("Waiting for page to load...", commandline.DISALLOW_MULTILINE);
}
modes.show();
// TODO: allow macros to be continued when page does not fully load with an option
let ret = (buffer.loaded == 1);
if (!ret)
liberator.echoerr("Page did not load completely in " + ms + " milliseconds. Macro stopped.");
liberator.echoerr("Page did not load completely in " + maxWaitTime + " seconds. Macro stopped.");
liberator.dump("done waiting: " + ret);
// sometimes the input widget had focus when replaying a macro
@@ -1078,10 +1128,10 @@ function Events() //{{{
return ret;
},
// argument "event" is delibarately not used, as i don't seem to have
// argument "event" is deliberately not used, as i don't seem to have
// access to the real focus target
//
// the ugly wantsModeReset is needed, because firefox generates a massive
// the ugly wantsModeReset is needed, because Firefox generates a massive
// amount of focus changes for things like <C-v><C-k> (focusing the search field)
onFocusChange: function (event)
{
@@ -1128,7 +1178,7 @@ function Events() //{{{
if (config.name == "Muttator")
{
// we switch to -- MESSAGE -- mode for muttator, when the main HTML widget gets focus
// we switch to -- MESSAGE -- mode for Muttator, when the main HTML widget gets focus
if (hasHTMLDocument(win) || elem instanceof HTMLAnchorElement)
{
if (config.isComposeWindow)
@@ -1334,7 +1384,7 @@ function Events() //{{{
return false;
}
// XXX: ugly hack for now pass certain keys to firefox as they are without beeping
// XXX: ugly hack for now pass certain keys to Firefox as they are without beeping
// also fixes key navigation in combo boxes, submitting forms, etc.
// FIXME: breaks iabbr for now --mst
if ((config.name == "Vimperator" && liberator.mode == modes.NORMAL)
@@ -1373,7 +1423,7 @@ function Events() //{{{
return false;
}
// others are left to generate the 'input' event or handled by firefox
// others are left to generate the 'input' event or handled by Firefox
return;
}
}
@@ -1503,7 +1553,7 @@ function Events() //{{{
if (key != "<Esc>" && key != "<C-[>")
{
// allow key to be passed to firefox if we can't handle it
// allow key to be passed to Firefox if we can't handle it
stop = false;
if (liberator.mode == modes.COMMAND_LINE)
@@ -1673,7 +1723,7 @@ function Events() //{{{
}
}; //}}}
window.XULBrowserWindow = eventManager.progressListener;
window.XULBrowserWindow = self.progressListener;
window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
@@ -1682,21 +1732,21 @@ function Events() //{{{
.XULBrowserWindow = window.XULBrowserWindow;
try
{
getBrowser().addProgressListener(eventManager.progressListener, Ci.nsIWebProgress.NOTIFY_ALL);
getBrowser().addProgressListener(self.progressListener, Ci.nsIWebProgress.NOTIFY_ALL);
}
catch (e) {}
eventManager.prefObserver.register();
self.prefObserver.register();
liberator.registerObserver("shutdown", function () {
eventManager.destroy();
eventManager.prefObserver.unregister();
self.destroy();
self.prefObserver.unregister();
});
window.addEventListener("keypress", wrapListener("onKeyPress"), true);
window.addEventListener("keydown", wrapListener("onKeyUpOrDown"), true);
window.addEventListener("keyup", wrapListener("onKeyUpOrDown"), true);
return eventManager;
return self;
}; //}}}

View File

@@ -108,7 +108,7 @@ function Search() //{{{
// strip case-sensitive modifiers
pattern = pattern.replace(/(\\)?\\[cC]/g, function ($0, $1) { return $1 ? $0 : ""; });
// remove any modifer escape \
// remove any modifier escape \
pattern = pattern.replace(/\\(\\[cClL])/g, "$1");
searchString = pattern;
@@ -440,7 +440,7 @@ function Search() //{{{
// TODO: code to reposition the document to the place before search started
},
// FIXME: thunderbird incompatible
// FIXME: Thunderbird incompatible
// this is not dependent on the value of 'hlsearch'
highlight: function (text)
{
@@ -469,7 +469,6 @@ function Search() //{{{
// highlighted
getBrowser().fastFind.collapseSelection();
}
};
//}}}
}; //}}}

View File

@@ -9,3 +9,4 @@ let url = page ? "chrome://liberator/locale/" + page : content.history.previous;
win.getBrowser().loadURIWithFlags(url, Components.interfaces.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY, null, null, null);
// vim: set fdm=marker sw=4 ts=4 et:

View File

@@ -47,7 +47,7 @@ function Hints() //{{{
var hintNumber = 0; // only the numerical part of the hint
var usedTabKey = false; // when we used <Tab> to select an element
var prevInput = ""; // record previous user input type, "text" || "number"
var extendedhintCount; // for the count arugument of Mode#action (extended hint only)
var extendedhintCount; // for the count argument of Mode#action (extended hint only)
// hints[] = [elem, text, span, imgspan, elem.style.backgroundColor, elem.style.color]
var pageHints = [];
@@ -65,24 +65,42 @@ function Hints() //{{{
function extended() options.extendedhinttags;
const hintModes = {
";": Mode("Focus hint", function (elem) buffer.focusElement(elem), extended),
"?": Mode("Show information for hint", function (elem) buffer.showElementInfo(elem), extended),
s: Mode("Save hint", function (elem) buffer.saveLink(elem, true)),
a: Mode("Save hint with prompt", function (elem) buffer.saveLink(elem, false)),
f: Mode("Focus frame", function (elem) elem.ownerDocument.defaultView.focus(), function () "//body | //xhtml:body"),
s: Mode("Save hint", function (elem) buffer.saveLink(elem, true)),
o: Mode("Follow hint", function (elem) buffer.followLink(elem, liberator.CURRENT_TAB)),
t: Mode("Follow hint in a new tab", function (elem) buffer.followLink(elem, liberator.NEW_TAB)),
b: Mode("Follow hint in a background tab", function (elem) buffer.followLink(elem, liberator.NEW_BACKGROUND_TAB)),
v: Mode("View hint source", function (elem, loc) buffer.viewSource(loc, false), extended),
V: Mode("View hint source", function (elem, loc) buffer.viewSource(loc, true), extended),
w: Mode("Follow hint in a new window", function (elem) buffer.followLink(elem, liberator.NEW_WINDOW), extended),
"?": Mode("Show information for hint", function (elem) buffer.showElementInfo(elem), extended),
O: Mode("Open location based on hint", function (elem, loc) commandline.open(":", "open " + loc, modes.EX)),
T: Mode("Open new tab based on hint", function (elem, loc) commandline.open(":", "tabopen " + loc, modes.EX)),
W: Mode("Open new window based on hint", function (elem, loc) commandline.open(":", "winopen " + loc, modes.EX)),
F: Mode("Follow hint sequence in tabs", hintSequenceElement),
O: Mode("Preselect hint in an :open query", function (elem, loc) commandline.open(":", "open " + loc, modes.EX)),
T: Mode("Preselect hint in a :tabopen query", function (elem, loc) commandline.open(":", "tabopen " + loc, modes.EX)),
W: Mode("Preselect hint in a :winopen query", function (elem, loc) commandline.open(":", "winopen " + loc, modes.EX)),
v: Mode("View hint source", function (elem, loc) buffer.viewSource(loc, false), extended),
V: Mode("View hint source in external editor", function (elem, loc) buffer.viewSource(loc, true), extended),
y: Mode("Yank hint location", function (elem, loc) util.copyToClipboard(loc, true)),
Y: Mode("Yank hint description", function (elem) util.copyToClipboard(elem.textContent || "", true), extended)
};
// Used to open multiple hints
function hintSequenceElement(elem)
{
// Want to always open sequence hints in background
// (remember: NEW_BACKGROUND_TAB and NEW_TAB semantics assume
// that loadInBackground=true)
if (options.getPref("browser.tabs.loadInBackground"))
buffer.followLink(elem, liberator.NEW_BACKGROUND_TAB);
else
buffer.followLink(elem, liberator.NEW_TAB);
// Move to next element in sequence
// TODO: Maybe we find a *simple* way to keep the hints displayed rather than
// showing them again, or is this short flash actually needed as a "usability
// feature"? --mst
hints.show("F");
}
// reset all important variables
function reset()
{
@@ -209,7 +227,7 @@ function Hints() //{{{
let scrollY = doc.defaultView.scrollY;
inner:
for (let i in (util.interruptableRange(start, end + 1, 500)))
for (let i in (util.interruptibleRange(start, end + 1, 500)))
{
let hint = pageHints[i];
[elem, text, span, imgspan] = hint;
@@ -340,7 +358,7 @@ function Hints() //{{{
removeHints(timeout);
if (timeout == 0)
// force a possible mode change, based on wheter an input field has focus
// force a possible mode change, based on whether an input field has focus
events.onFocusChange();
setTimeout(function () {
if (modes.extended & modes.HINTS)

View File

@@ -108,10 +108,10 @@ function IO() //{{{
function joinPaths(head, tail)
{
let path = ioManager.getFile(head);
let path = self.getFile(head);
try
{
path.appendRelativePath(ioManager.expandPath(tail, true)); // FIXME: should only expand env vars and normalise path separators
path.appendRelativePath(self.expandPath(tail, true)); // FIXME: should only expand env vars and normalise path separators
if (path.exists() && path.normalize)
path.normalize();
}
@@ -379,14 +379,14 @@ function IO() //{{{
liberator.registerObserver("load_completion", function ()
{
completion.setFunctionCompleter([ioManager.getFile, ioManager.expandPath],
completion.setFunctionCompleter([self.getFile, self.expandPath],
[function (context, obj, args) {
context.quote[2] = "";
completion.file(context, true);
}]);
});
var ioManager = {
const self = {
MODE_RDONLY: 0x01,
MODE_WRONLY: 0x02,
@@ -405,7 +405,7 @@ function IO() //{{{
// Firefox's CWD - see // https://bugzilla.mozilla.org/show_bug.cgi?id=280953
getCurrentDirectory: function ()
{
let dir = ioManager.getFile(cwd.path);
let dir = self.getFile(cwd.path);
// NOTE: the directory could have been deleted underneath us so
// fallback to Firefox's CWD
@@ -425,7 +425,7 @@ function IO() //{{{
}
else
{
let dir = ioManager.getFile(newdir);
let dir = self.getFile(newdir);
if (!dir.exists() || !dir.isDirectory())
{
@@ -436,7 +436,7 @@ function IO() //{{{
[cwd, oldcwd] = [dir, this.getCurrentDirectory()];
}
return ioManager.getCurrentDirectory();
return self.getCurrentDirectory();
},
getRuntimeDirectories: function (specialDirectory)
@@ -482,10 +482,10 @@ function IO() //{{{
}
else
{
let expandedPath = ioManager.expandPath(path);
let expandedPath = self.expandPath(path);
if (!isAbsolutePath(expandedPath) && !noCheckPWD)
file = joinPaths(ioManager.getCurrentDirectory().path, expandedPath);
file = joinPaths(self.getCurrentDirectory().path, expandedPath);
else
file.initWithPath(expandedPath);
}
@@ -502,7 +502,7 @@ function IO() //{{{
switch (EXTENSION_NAME)
{
case "muttator":
tmpName = "mutt-ator-mail"; // to allow vim to :set ft=mail automatically
tmpName = "mutt-ator-mail"; // to allow Vim to :set ft=mail automatically
break;
case "vimperator":
try
@@ -529,7 +529,7 @@ function IO() //{{{
readDirectory: function (file, sort)
{
if (typeof file == "string")
file = ioManager.getFile(file);
file = self.getFile(file);
else if (!(file instanceof Ci.nsILocalFile))
throw Cr.NS_ERROR_INVALID_ARG; // FIXME: does not work as expected, just shows undefined: undefined
@@ -543,11 +543,12 @@ function IO() //{{{
array.push(entry.QueryInterface(Ci.nsIFile));
}
if (sort)
return array.sort(function (a, b) b.isDirectory() - a.isDirectory() || String.localeCompare(a.path, b.path));
array.sort(function (a, b) b.isDirectory() - a.isDirectory() || String.localeCompare(a.path, b.path));
return array;
}
else
return []; // XXX: or should it throw an error, probably yes?
// Yes --djk
},
// file is either a full pathname or an instance of file instanceof nsILocalFile
@@ -559,7 +560,7 @@ function IO() //{{{
let toCharset = "UTF-8";
if (typeof file == "string")
file = ioManager.getFile(file);
file = self.getFile(file);
else if (!(file instanceof Ci.nsILocalFile))
throw Cr.NS_ERROR_INVALID_ARG; // FIXME: does not work as expected, just shows undefined: undefined
@@ -587,14 +588,14 @@ function IO() //{{{
let charset = "UTF-8"; // Can be any character encoding name that Mozilla supports
if (typeof file == "string")
file = ioManager.getFile(file);
file = self.getFile(file);
else if (!(file instanceof Ci.nsILocalFile))
throw Cr.NS_ERROR_INVALID_ARG; // FIXME: does not work as expected, just shows undefined: undefined
if (mode == ">>")
mode = ioManager.MODE_WRONLY | ioManager.MODE_CREATE | ioManager.MODE_APPEND;
mode = self.MODE_WRONLY | self.MODE_CREATE | self.MODE_APPEND;
else if (!mode || mode == ">")
mode = ioManager.MODE_WRONLY | ioManager.MODE_CREATE | ioManager.MODE_TRUNCATE;
mode = self.MODE_WRONLY | self.MODE_CREATE | self.MODE_TRUNCATE;
if (!perms)
perms = 0644;
@@ -616,12 +617,12 @@ function IO() //{{{
if (isAbsolutePath(program))
{
file = ioManager.getFile(program, true);
file = self.getFile(program, true);
}
else
{
let dirs = services.get("environment").get("PATH").split(WINDOWS ? ";" : ":");
// Windows tries the cwd first TODO: desirable?
// Windows tries the CWD first TODO: desirable?
if (WINDOWS)
dirs = [io.getCurrentDirectory().path].concat(dirs);
@@ -693,9 +694,9 @@ lookup:
}
if (res > 0) // FIXME: Is this really right? Shouldn't we always show both?
var output = ioManager.readFile(stderr) + "\nshell returned " + res;
var output = self.readFile(stderr) + "\nshell returned " + res;
else
output = ioManager.readFile(stdout);
output = self.readFile(stdout);
// if there is only one \n at the end, chop it off
if (output && output.indexOf("\n") == output.length - 1)
@@ -740,15 +741,15 @@ lookup:
return found;
},
// files which end in .js are sourced as pure javascript files,
// files which end in .js are sourced as pure JavaScript files,
// no need (actually forbidden) to add: js <<EOF ... EOF around those files
source: function (filename, silent)
{
let wasSourcing = ioManager.sourcing;
let wasSourcing = self.sourcing;
try
{
var file = ioManager.getFile(filename);
ioManager.sourcing = {
var file = self.getFile(filename);
self.sourcing = {
file: file.path,
line: 0
};
@@ -770,10 +771,10 @@ lookup:
liberator.echomsg("sourcing " + filename.quote(), 2);
let str = ioManager.readFile(file);
let str = self.readFile(file);
let uri = ioService.newFileURI(file);
// handle pure javascript files specially
// handle pure JavaScript files specially
if (/\.js$/.test(filename))
{
try
@@ -797,7 +798,7 @@ lookup:
{
let heredoc = "";
let heredocEnd = null; // the string which ends the heredoc
let lines = str.split("\n");
let lines = str.split(/\r\n|[\r\n]/);
for (let [i, line] in Iterator(lines))
{
@@ -816,7 +817,7 @@ lookup:
}
else
{
ioManager.sourcing.line = i + 1;
self.sourcing.line = i + 1;
// skip line comments and blank lines
line = line.replace(/\r$/, "");
@@ -891,7 +892,7 @@ lookup:
}
finally
{
ioManager.sourcing = wasSourcing;
self.sourcing = wasSourcing;
}
},
@@ -911,7 +912,7 @@ lookup:
}
}; //}}}
return ioManager;
return self;
}; //}}}
@@ -921,8 +922,16 @@ IO.PATH_SEP = (function () {
return file.path[0];
})();
IO.__defineGetter__("runtimePath", function () services.get("environment").get(config.name.toUpperCase() + "_RUNTIME") ||
"~/" + (liberator.has("Win32") ? "" : ".") + config.name.toLowerCase());
IO.__defineGetter__("runtimePath", function () {
const rtpvar = config.name.toUpperCase() + "_RUNTIME";
let rtp = services.get("environment").get(rtpvar);
if (!rtp)
{
rtp = "~/" + (liberator.has("Win32") ? "" : ".") + config.name.toLowerCase();
services.get("environment").set(rtpvar, rtp);
}
return rtp;
});
IO.expandPath = function (path, relative)
{
@@ -947,7 +956,7 @@ IO.expandPath = function (path, relative)
// Try $HOME first, on all systems
let home = services.get("environment").get("HOME");
// Windows has its own ideosyncratic $HOME variables.
// Windows has its own idiosyncratic $HOME variables.
if (!home && WINDOWS)
home = services.get("environment").get("USERPROFILE") ||
services.get("environment").get("HOMEDRIVE") + services.get("environment").get("HOMEPATH");

View File

@@ -57,11 +57,14 @@ const liberator = (function () //{{{
run: function () { this.func.apply(this.self, this.args); }
};
var callbacks = [];
var observers = [];
const callbacks = {};
const observers = {};
function registerObserver(type, callback)
{
observers.push([type, callback]);
if (!(type in observers))
observers[type] = [];
observers[type].push(callback);
}
let nError = 0;
@@ -83,7 +86,7 @@ const liberator = (function () //{{{
}
}
// Only general options are added here, which are valid for all vimperator like extensions
// Only general options are added here, which are valid for all Vimperator like extensions
registerObserver("load_options", function ()
{
options.add(["errorbells", "eb"],
@@ -364,7 +367,7 @@ const liberator = (function () //{{{
"Run a JavaScript command through eval()",
function (args)
{
if (args.bang) // open javascript console
if (args.bang) // open JavaScript console
{
liberator.open("chrome://global/content/console.xul",
(options["newtab"] && options.get("newtab").has("all", "javascript"))
@@ -449,7 +452,7 @@ const liberator = (function () //{{{
let each, eachUnits, totalUnits;
let total = 0;
for (let i in util.interruptableRange(0, count, 500))
for (let i in util.interruptibleRange(0, count, 500))
{
let now = Date.now();
method();
@@ -605,6 +608,11 @@ const liberator = (function () //{{{
// ###VERSION### and ###DATE### are replaced by the Makefile
version: "###VERSION### (created: ###DATE###)",
// NOTE: services.get("profile").selectedProfile.name is not rightness.
// If default profile Firefox runs without arguments,
// then selectedProfile returns last selected profile! (not current one!)
profileName: services.get("directory").get("ProfD", Ci.nsIFile).leafName.replace(/^.+?\./, ""),
// TODO: move to events.js?
input: {
buffer: "", // partial command storage
@@ -622,19 +630,15 @@ const liberator = (function () //{{{
// TODO: move to ui.js?
registerCallback: function (type, mode, func)
{
// TODO: check if callback is already registered
callbacks.push([type, mode, func]);
if (!(type in callbacks))
callbacks[type] = {};
callbacks[type][mode] = func;
},
triggerCallback: function (type, mode, data)
{
// liberator.dump("type: " + type + " mode: " + mode + "data: " + data + "\n");
for (let i = 0; i < callbacks.length; i++)
{
let [thistype, thismode, thisfunc] = callbacks[i];
if (mode == thismode && type == thistype)
return thisfunc.call(this, data);
}
if (callbacks[type] && callbacks[type][mode])
return callbacks[type][mode].call(this, data);
return false;
},
@@ -642,16 +646,14 @@ const liberator = (function () //{{{
unregisterObserver: function (type, callback)
{
observers = observers.filter(function ([t, c]) t != type || c != callback);
if (type in observers)
observers[type] = observers[type].filter(function (c) c != callback);
},
triggerObserver: function (type)
{
for (let [,[thistype, callback]] in Iterator(observers))
{
if (thistype == type)
callback.apply(null, Array.slice(arguments, 1));
}
for (let [,fn] in Iterator(observers[type] || []))
fn.apply(null, Array.slice(arguments, 1));
},
beep: function ()
@@ -988,27 +990,17 @@ const liberator = (function () //{{{
loadPlugins: function ()
{
// FIXME: largely duplicated for loading macros
try
function sourceDirectory(dir)
{
let dirs = io.getRuntimeDirectories("plugin");
if (dirs.length == 0)
if (!dir.isReadable())
{
liberator.log("No user plugin directory found", 3);
liberator.echoerr("E484: Can't open file " + dir.path);
return;
}
for (let [,dir] in Iterator(dirs))
{
// TODO: search plugins/**/* for plugins
liberator.echomsg('Searching for "plugin/*.{js,vimp}" in ' + dir.path.quote(), 2);
liberator.log("Sourcing plugin directory: " + dir.path + "...", 3);
let files = io.readDirectory(dir.path, true);
files.forEach(function (file) {
if (!file.isDirectory() && /\.(js|vimp)$/i.test(file.path) && !(file.path in liberator.pluginFiles))
io.readDirectory(dir.path, true).forEach(function (file) {
if (file.isFile() && /\.(js|vimp)$/i.test(file.path) && !(file.path in liberator.pluginFiles))
{
try
{
@@ -1020,17 +1012,31 @@ const liberator = (function () //{{{
liberator.reportError(e);
}
}
else if (file.isDirectory())
{
sourceDirectory(file);
}
});
}
}
catch (e)
let dirs = io.getRuntimeDirectories("plugin");
if (dirs.length == 0)
{
// thrown if directory does not exist
liberator.log("Error sourcing plugin directory: " + e, 9);
liberator.log("No user plugin directory found", 3);
return;
}
liberator.echomsg('Searching for "plugin/**/*.{js,vimp}" in '
+ [dir.path.replace(/.plugin$/, "") for each (dir in dirs)].join(",").quote(), 2);
dirs.forEach(function (dir) {
liberator.echomsg("Searching for " + (dir.path + "/**/*.{js,vimp}").quote(), 3);
sourceDirectory(dir);
});
},
// logs a message to the javascript error console
// logs a message to the JavaScript error console
// if msg is an object, it is beautified
// TODO: add proper level constants
log: function (msg, level)
@@ -1049,20 +1055,24 @@ const liberator = (function () //{{{
if (typeof msg == "object")
msg = util.objectToString(msg, false);
const consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
consoleService.logStringMessage(config.name.toLowerCase() + ": " + msg);
services.get("console").logStringMessage(config.name.toLowerCase() + ": " + msg);
},
// open one or more URLs
//
// @param urls: either a string or an array of urls
// The array can look like this:
// ["url1", "url2", "url3", ...] or:
// [["url1", postdata1], ["url2", postdata2], ...]
// @param where: if ommited, CURRENT_TAB is assumed
// but NEW_TAB is set when liberator.forceNewTab is true.
// @param force: Don't prompt whether to open more than 20 tabs.
// @returns true when load was initiated, or false on error
/**
* Opens one or more URLs. Returns true when load was initiated, or
* false on error.
*
* @param {FIXME} urls Either a URL string or an array of URLs.
* The array can look like this:
* ["url1", "url2", "url3", ...]
* or:
* [["url1", postdata1], ["url2", postdata2], ...]
* @param {number} where If ommited, CURRENT_TAB is assumed but NEW_TAB
* is set when liberator.forceNewTab is true.
* @param {boolean} force Don't prompt whether to open more than 20
* tabs.
* @returns {boolean}
*/
open: function (urls, where, force)
{
// convert the string to an array of converted URLs
@@ -1083,6 +1093,8 @@ const liberator = (function () //{{{
if (urls.length == 0)
return false;
let browser = window.getBrowser();
function open(urls, where)
{
let url = Array.concat(urls)[0];
@@ -1092,7 +1104,7 @@ const liberator = (function () //{{{
switch (where)
{
case liberator.CURRENT_TAB:
getBrowser().loadURIWithFlags(url, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, postdata);
browser.loadURIWithFlags(url, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, postdata);
break;
case liberator.NEW_BACKGROUND_TAB:
@@ -1100,21 +1112,21 @@ const liberator = (function () //{{{
if (!liberator.has("tabs"))
return open(urls, liberator.NEW_WINDOW);
let tab = getBrowser().addTab(url, null, null, postdata);
if (where == liberator.NEW_TAB)
getBrowser().selectedTab = tab;
options.withContext(function () {
options.setPref("browser.tabs.loadInBackground", true);
browser.loadOneTab(url, null, null, postdata, where == liberator.NEW_BACKGROUND_TAB);
});
break;
case liberator.NEW_WINDOW:
window.open();
services.get("windowMediator").getMostRecentWindow("navigator:browser")
.loadURI(url, null, postdata);
let win = services.get("windowMediator").getMostRecentWindow("navigator:browser");
win.loadURI(url, null, postdata);
browser = win.getBrowser();
break;
default:
liberator.echoerr("Exxx: Invalid 'where' directive in liberator.open(...)");
return false;
throw Error("Invalid 'where' directive in liberator.open(...)");
}
}
@@ -1123,7 +1135,7 @@ const liberator = (function () //{{{
else if (!where)
where = liberator.CURRENT_TAB;
for (let [i, url] in Iterator(urls))
for (let [,url] in Iterator(urls))
{
open(url, where);
where = liberator.NEW_BACKGROUND_TAB;
@@ -1227,7 +1239,7 @@ const liberator = (function () //{{{
let infoPath = services.create("file");
infoPath.initWithPath(IO.expandPath(IO.runtimePath.replace(/,.*/, "")));
infoPath.append("info");
infoPath.append(services.get("profile").selectedProfile.name);
infoPath.append(liberator.profileName);
storage.infoPath = infoPath;
}
catch (e)
@@ -1235,8 +1247,6 @@ const liberator = (function () //{{{
liberator.reportError(e);
}
liberator.triggerObserver("load");
// commands must always be the first module to be initialized
loadModule("commands", Commands);
loadModule("options", Options);
@@ -1254,6 +1264,8 @@ const liberator = (function () //{{{
if (config.init)
config.init();
liberator.triggerObserver("load");
liberator.log("All modules loaded", 3);
// first time intro message
@@ -1404,6 +1416,21 @@ const liberator = (function () //{{{
window.liberator = liberator;
// FIXME: Ugly, etc.
window.addEventListener("liberatorHelpLink", function (event) {
let elem = event.target;
liberator.dump(String(elem));
if (/^(option|mapping|command)$/.test(elem.className))
var tag = elem.textContent.replace(/\s.*/, "");
if (elem.className == "command")
tag = tag.replace(/\[.*?\]/g, "");
if (tag)
var page = liberator.findHelp(tag);
if (page)
elem.href = "chrome://liberator/locale/" + page;
},
true, true);
// called when the chrome is fully loaded and before the main window is shown
window.addEventListener("load", liberator.startup, false);
window.addEventListener("unload", liberator.shutdown, false);

View File

@@ -85,6 +85,7 @@ the terms of any one of the MPL, the GPL or the LGPL.
<label class="plain" id="liberator-commandline-prompt" flex="0" crop="end" value="" collapsed="true"/>
<textbox class="plain" id="liberator-commandline-command" flex="1" type="timed" timeout="100"
oninput="liberator.modules.commandline.onEvent(event);"
onkeyup="liberator.modules.commandline.onEvent(event);"
onfocus="liberator.modules.commandline.onEvent(event);"
onblur="liberator.modules.commandline.onEvent(event);"/>
</hbox>

View File

@@ -283,7 +283,7 @@ function Mappings() //{{{
// FIXME:
Mappings.flags = {
ALLOW_EVENT_ROUTING: 1 << 0, // if set, return true inside the map command to pass the event further to firefox
ALLOW_EVENT_ROUTING: 1 << 0, // if set, return true inside the map command to pass the event further to Firefox
MOTION: 1 << 1,
COUNT: 1 << 2,
ARGUMENT: 1 << 3

View File

@@ -126,7 +126,8 @@ const modes = (function () //{{{
////////////////////// PUBLIC SECTION //////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
var self = {
const self = {
NONE: 0,
__iterator__: function () util.Array.iterator(this.all),

View File

@@ -125,7 +125,7 @@ Option.prototype = {
aValue = this.globalvalue;
if (this.getter)
this.getter.call(this, aValue);
return this.getter.call(this, aValue);
return aValue;
},
@@ -393,167 +393,7 @@ function Options() //{{{
}
}
//
// firefox preferences which need to be changed to work well with vimperator
//
// work around firefox popup blocker
// TODO: Make this work like safeSetPref
var popupAllowedEvents = loadPreference("dom.popup_allowed_events", "change click dblclick mouseup reset submit");
if (!/keypress/.test(popupAllowedEvents))
{
storePreference("dom.popup_allowed_events", popupAllowedEvents + " keypress");
liberator.registerObserver("shutdown", function ()
{
if (loadPreference("dom.popup_allowed_events", "")
== popupAllowedEvents + " keypress")
storePreference("dom.popup_allowed_events", popupAllowedEvents);
});
}
// safeSetPref might try to echomsg. Need commandline.
liberator.registerObserver("load_commandline", function () {
// TODO: maybe reset in .destroy()?
// TODO: move to buffer.js
// we have our own typeahead find implementation
options.safeSetPref("accessibility.typeaheadfind.autostart", false);
options.safeSetPref("accessibility.typeaheadfind", false); // actually the above setting should do it, but has no effect in firefox
});
// start with saved session
storePreference("browser.startup.page", 3);
/////////////////////////////////////////////////////////////////////////////}}}
////////////////////// COMMANDS ////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
commands.add(["let"],
"Set or list a variable",
function (args)
{
args = args.string;
if (!args)
{
let str =
<table>
{
template.map(liberator.globalVariables, function ([i, value]) {
let prefix = typeof value == "number" ? "#" :
typeof value == "function" ? "*" :
" ";
return <tr>
<td style="width: 200px;">{i}</td>
<td>{prefix}{value}</td>
</tr>
})
}
</table>;
if (str.*.length())
liberator.echo(str, commandline.FORCE_MULTILINE);
else
liberator.echomsg("No variables found");
return;
}
let matches;
// 1 - type, 2 - name, 3 - +-., 4 - expr
if (matches = args.match(/([$@&])?([\w:]+)\s*([-+.])?=\s*(.+)/))
{
if (!matches[1])
{
let reference = liberator.variableReference(matches[2]);
if (!reference[0] && matches[3])
{
liberator.echoerr("E121: Undefined variable: " + matches[2]);
return;
}
let expr = liberator.evalExpression(matches[4]);
if (expr === undefined)
{
liberator.echoerr("E15: Invalid expression: " + matches[4]);
return;
}
else
{
if (!reference[0])
{
if (reference[2] == "g")
reference[0] = liberator.globalVariables;
else
return; // for now
}
if (matches[3])
{
if (matches[3] == "+")
reference[0][reference[1]] += expr;
else if (matches[3] == "-")
reference[0][reference[1]] -= expr;
else if (matches[3] == ".")
reference[0][reference[1]] += expr.toString();
}
else
reference[0][reference[1]] = expr;
}
}
}
// 1 - name
else if (matches = args.match(/^\s*([\w:]+)\s*$/))
{
let reference = liberator.variableReference(matches[1]);
if (!reference[0])
{
liberator.echoerr("E121: Undefined variable: " + matches[1]);
return;
}
let value = reference[0][reference[1]];
let prefix = typeof value == "number" ? "#" :
typeof value == "function" ? "*" :
" ";
liberator.echo(reference[1] + "\t\t" + prefix + value);
}
});
commands.add(["setl[ocal]"],
"Set local option",
function (args)
{
commands.get("set").execute(args.string, args.bang, args.count, { scope: options.OPTION_SCOPE_LOCAL });
},
{
bang: true,
count: true,
completer: function (context, args)
{
return commands.get("set").completer(context.filter, args.bang, args.count, { scope: options.OPTION_SCOPE_LOCAL });
},
literal: 0
}
);
commands.add(["setg[lobal]"],
"Set global option",
function (args)
{
commands.get("set").execute(args.string, args.bang, args.count, { scope: options.OPTION_SCOPE_GLOBAL });
},
{
bang: true,
count: true,
completer: function (context, args)
{
return commands.get("set").completer(context.filter, args.bang, args.count, { scope: options.OPTION_SCOPE_GLOBAL });
},
literal: 0
}
);
commands.add(["se[t]"],
"Set an option",
function (args, modifiers)
function setAction(args, modifiers)
{
let bang = args.bang;
if (!args.length)
@@ -675,10 +515,9 @@ function Options() //{{{
liberator.echoerr(res);
}
}
},
{
bang: true,
completer: function (context, args, modifiers)
}
function setCompleter(context, args, modifiers)
{
let filter = context.filter;
@@ -737,6 +576,177 @@ function Options() //{{{
}
completion.optionValue(context, opt.name, opt.operator);
}
//
// Firefox preferences which need to be changed to work well with Vimperator
//
// work around Firefox popup blocker
// TODO: Make this work like safeSetPref
var popupAllowedEvents = loadPreference("dom.popup_allowed_events", "change click dblclick mouseup reset submit");
if (!/keypress/.test(popupAllowedEvents))
{
storePreference("dom.popup_allowed_events", popupAllowedEvents + " keypress");
liberator.registerObserver("shutdown", function ()
{
if (loadPreference("dom.popup_allowed_events", "")
== popupAllowedEvents + " keypress")
storePreference("dom.popup_allowed_events", popupAllowedEvents);
});
}
// safeSetPref might try to echomsg. Need commandline.
liberator.registerObserver("load_commandline", function () {
// TODO: maybe reset in .destroy()?
// TODO: move to buffer.js
// we have our own typeahead find implementation
options.safeSetPref("accessibility.typeaheadfind.autostart", false);
options.safeSetPref("accessibility.typeaheadfind", false); // actually the above setting should do it, but has no effect in Firefox
});
// start with saved session
storePreference("browser.startup.page", 3);
/////////////////////////////////////////////////////////////////////////////}}}
////////////////////// COMMANDS ////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
commands.add(["let"],
"Set or list a variable",
function (args)
{
args = args.string;
if (!args)
{
let str =
<table>
{
template.map(liberator.globalVariables, function ([i, value]) {
let prefix = typeof value == "number" ? "#" :
typeof value == "function" ? "*" :
" ";
return <tr>
<td style="width: 200px;">{i}</td>
<td>{prefix}{value}</td>
</tr>
})
}
</table>;
if (str.*.length())
liberator.echo(str, commandline.FORCE_MULTILINE);
else
liberator.echomsg("No variables found");
return;
}
let matches;
// 1 - type, 2 - name, 3 - +-., 4 - expr
if (matches = args.match(/([$@&])?([\w:]+)\s*([-+.])?=\s*(.+)/))
{
if (!matches[1])
{
let reference = liberator.variableReference(matches[2]);
if (!reference[0] && matches[3])
{
liberator.echoerr("E121: Undefined variable: " + matches[2]);
return;
}
let expr = liberator.evalExpression(matches[4]);
if (expr === undefined)
{
liberator.echoerr("E15: Invalid expression: " + matches[4]);
return;
}
else
{
if (!reference[0])
{
if (reference[2] == "g")
reference[0] = liberator.globalVariables;
else
return; // for now
}
if (matches[3])
{
if (matches[3] == "+")
reference[0][reference[1]] += expr;
else if (matches[3] == "-")
reference[0][reference[1]] -= expr;
else if (matches[3] == ".")
reference[0][reference[1]] += expr.toString();
}
else
reference[0][reference[1]] = expr;
}
}
}
// 1 - name
else if (matches = args.match(/^\s*([\w:]+)\s*$/))
{
let reference = liberator.variableReference(matches[1]);
if (!reference[0])
{
liberator.echoerr("E121: Undefined variable: " + matches[1]);
return;
}
let value = reference[0][reference[1]];
let prefix = typeof value == "number" ? "#" :
typeof value == "function" ? "*" :
" ";
liberator.echo(reference[1] + "\t\t" + prefix + value);
}
});
commands.add(["setl[ocal]"],
"Set local option",
function (args)
{
return setAction(args, { scope: options.OPTION_SCOPE_LOCAL });
},
{
bang: true,
count: true,
completer: function (context, args)
{
return setCompleter(context, args, { scope: options.OPTION_SCOPE_LOCAL });
},
literal: 0
}
);
commands.add(["setg[lobal]"],
"Set global option",
function (args)
{
return setAction(args, { scope: options.OPTION_SCOPE_GLOBAL });
},
{
bang: true,
count: true,
completer: function (context, args)
{
return setCompleter(context, args, { scope: options.OPTION_SCOPE_GLOBAL });
},
literal: 0
}
);
commands.add(["se[t]"],
"Set an option",
function (args)
{
return setAction(args);
},
{
bang: true,
completer: function (context, args)
{
return setCompleter(context, args);
},
serial: function () [
{
@@ -760,7 +770,6 @@ function Options() //{{{
//for (let i = 0, name = names[i]; i < length; name = names[++i])
for (let [,name] in args)
{
let name = args[i];
let reference = liberator.variableReference(name);
if (!reference[0])
{
@@ -857,7 +866,7 @@ function Options() //{{{
isDefault: opt.value == opt.defaultValue,
name: opt.name,
default: opt.defaultValue,
pre: "\u00a0\u00a0", /* Unicode nonbreaking space. */
pre: "\u00a0\u00a0", // Unicode nonbreaking space.
value: <></>
};
@@ -905,7 +914,7 @@ function Options() //{{{
default: loadPreference(pref, null, true),
value: <>={template.highlight(value, true, 100)}</>,
name: pref,
pre: "\u00a0\u00a0" /* Unicode nonbreaking space. */
pre: "\u00a0\u00a0" // Unicode nonbreaking space.
};
yield option;
@@ -982,14 +991,14 @@ function Options() //{{{
setPref: function (name, value)
{
return storePreference(name, value);
storePreference(name, value);
},
resetPref: function (name)
{
try
{
return services.get("pref").clearUserPref(name);
services.get("pref").clearUserPref(name);
}
catch (e)
{
@@ -1017,7 +1026,7 @@ function Options() //{{{
storePreference(k, v);
},
temporaryContext: function (fn, self)
withContext: function (fn, self)
{
try
{

View File

@@ -45,6 +45,7 @@ function Services()
get: function (name) services[name],
create: function (name) classes[name]()
};
self.add("appStartup", "@mozilla.org/toolkit/app-startup;1", Ci.nsIAppStartup);
self.add("autoCompleteSearch", "@mozilla.org/browser/global-history;2", Ci.nsIAutoCompleteSearch);
self.add("browserSearch", "@mozilla.org/browser/search-service;1", Ci.nsIBrowserSearchService);
@@ -55,6 +56,7 @@ function Services()
self.add("extensionManager", "@mozilla.org/extensions/manager;1", Ci.nsIExtensionManager);
self.add("json", "@mozilla.org/dom/json;1", Ci.nsIJSON, "createInstance");
self.add("observer", "@mozilla.org/observer-service;1", Ci.nsIObserverService);
self.add("io", "@mozilla.org/network/io-service;1", Ci.nsIIOService);
self.add("pref", "@mozilla.org/preferences-service;1", [Ci.nsIPrefService, Ci.nsIPrefBranch, Ci.nsIPrefBranch2]);
self.add("profile", "@mozilla.org/toolkit/profile-service;1", Ci.nsIToolkitProfileService);
self.add("sessionStore", "@mozilla.org/browser/sessionstore;1", Ci.nsISessionStore);
@@ -66,8 +68,10 @@ function Services()
self.addClass("file", "@mozilla.org/file/local;1", Ci.nsILocalFile);
self.addClass("find", "@mozilla.org/embedcomp/rangefind;1", Ci.nsIFind);
self.addClass("process", "@mozilla.org/process/util;1", Ci.nsIProcess);
return self;
};
var services = Services();
// vim: set fdm=marker sw=4 ts=4 et:

View File

@@ -72,8 +72,8 @@ Highlights.prototype.CSS = <![CDATA[
Question color: green; background: white; font-weight: bold;
StatusLine color: white; background: black;
StatusLineBroken color: black; background: #FF6060; /* light-red */
StatusLineSecure color: black; background: #B0FF00; /* light-green */
StatusLineBroken color: black; background: #FF6060 /* light-red */
StatusLineSecure color: black; background: #B0FF00 /* light-green */
TabClose
TabIcon
@@ -129,7 +129,7 @@ Highlights.prototype.CSS = <![CDATA[
/**
* A class to manage highlighting rules. The parameters are the
* standard paramaters for any {@link Storage} object.
* standard parameters for any {@link Storage} object.
*
* @author Kris Maglione <maglione.k@gmail.com>
*/
@@ -178,17 +178,22 @@ function Highlights(name, store, serial)
let css = newStyle.replace(/(?:!\s*important\s*)?(?:;?\s*$|;)/g, "!important;")
.replace(";!important;", ";", "g"); // Seeming Spidermonkey bug
if (!/^\s*(?:!\s*important\s*)?;*\s*$/.test(css))
{
css = style.selector + " { " + css + " }";
let error = styles.addSheet(true, style.selector, style.filter, css);
if (error)
return error;
}
style.value = newStyle;
highlight[style.class] = style;
};
/**
* Gets a CSS selector given a highlight group.
*
* @param {string} class
*/
this.selector = function (class)
{
@@ -233,30 +238,28 @@ function Highlights(name, store, serial)
}
/**
* Manages named and unnamed user stylesheets, which apply to both
* Manages named and unnamed user style sheets, which apply to both
* chrome and content pages. The parameters are the standard
* paramaters for any {@link Storage} object.
* parameters for any {@link Storage} object.
*
* @author Kris Maglione <maglione.k@gmail.com>
*/
function Styles(name, store, serial)
{
/* Can't reference liberator or Components inside Styles --
* they're members of the window object, which disappear
* with this window.
*/
// Can't reference liberator or Components inside Styles --
// they're members of the window object, which disappear
// with this window.
const util = modules.util;
const sleep = liberator.sleep;
const storage = modules.storage;
const consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
const ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
const ios = services.get("io");
const sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
const namespace = '@namespace html "' + XHTML + '";\n' +
'@namespace xul "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";\n' +
'@namespace liberator "' + NS.uri + '";\n';
const Sheet = new Struct("name", "sites", "css", "ref");
let cssUri = function (css) "chrome-data:text/css," + encodeURI(css);
let cssUri = function (css) "chrome-data:text/css," + window.encodeURI(css);
let userSheets = [];
let systemSheets = [];
@@ -270,13 +273,12 @@ function Styles(name, store, serial)
this.__defineGetter__("userNames", function () Iterator(userNames));
/**
* Add a new stylesheet.
* Add a new style sheet.
*
* @param {boolean} system Declares whether this is a system or
* user sheet. System sheets are used internally by
* @liberator.
>>>>>>> master:common/content/style.js
* @param {string} name The name given to the stylesheet by
* @param {string} name The name given to the style sheet by
* which it may be later referenced.
* @param {string} filter The sites to which this sheet will
* apply. Can be a domain name or a URL. Any URL ending in
@@ -335,6 +337,12 @@ function Styles(name, store, serial)
/**
* Find sheets matching the parameters. See {@link #addSheet}
* for parameters.
*
* @param {boolean} system
* @param {string} name
* @param {string} filter
* @param {string} css
* @param {number} index
*/
this.findSheets = function (system, name, filter, css, index)
{
@@ -355,10 +363,16 @@ function Styles(name, store, serial)
};
/**
* Remove a stylesheet. See {@link #addSheet} for parameters.
* Remove a style sheet. See {@link #addSheet} for parameters.
* In cases where <b>filter</b> is supplied, the given filters
* are removed from matching sheets. If any remain, the sheet is
* left in place.
*
* @param {boolean} system
* @param {string} name
* @param {string} filter
* @param {string} css
* @param {number} index
*/
this.removeSheet = function (system, name, filter, css, index)
{
@@ -403,9 +417,9 @@ function Styles(name, store, serial)
};
/**
* Register a user stylesheet at the given URI.
* Register a user style sheet at the given URI.
*
* @param {string} uri The UrI of the sheet to register.
* @param {string} uri The URI of the sheet to register.
* @param {boolean} reload Whether to reload any sheets that are
* already registered.
*/
@@ -420,6 +434,8 @@ function Styles(name, store, serial)
/**
* Unregister a sheet at the given URI.
*
* @param {string} uri The URI of the sheet to unregister.
*/
this.unregisterSheet = function (uri)
{
@@ -430,7 +446,9 @@ function Styles(name, store, serial)
// FIXME
/**
* Register an agent stylesheet.
* Register an agent style sheet.
*
* @param {string} uri The URI of the sheet to register.
* @deprecated
*/
this.registerAgentSheet = function (uri)
@@ -441,7 +459,9 @@ function Styles(name, store, serial)
};
/**
* Unregister an agent stylesheet.
* Unregister an agent style sheet.
*
* @param {string} uri The URI of the sheet to unregister.
* @deprecated
*/
this.unregisterAgentSheet = function (uri)
@@ -514,7 +534,6 @@ liberator.registerObserver("load_completion", function ()
liberator.registerObserver("load_commands", function ()
{
// TODO: :colo default needs :hi clear
commands.add(["colo[rscheme]"],
"Load a color scheme",
function (args)
@@ -598,7 +617,7 @@ liberator.registerObserver("load_commands", function ()
});
commands.add(["dels[tyle]"],
"Remove a user stylesheet",
"Remove a user style sheet",
function (args)
{
styles.removeSheet(false, args["-name"], args[0], args.literalArg, args["-index"]);

View File

@@ -44,12 +44,12 @@ function Tabs() //{{{
{
if (!tabmail)
{
tabmail = document.getElementById('tabmail');
tabmail.__defineGetter__('mTabContainer', function () this.tabContainer);
tabmail.__defineGetter__('mTabs', function () this.tabContainer.childNodes);
tabmail.__defineGetter__('mCurrentTab', function () this.tabContainer.selectedItem);
tabmail.__defineGetter__('mStrip', function () this.tabStrip);
tabmail.__defineGetter__('browsers', function () [browser for (browser in Iterator(this.mTabs))] );
tabmail = document.getElementById("tabmail");
tabmail.__defineGetter__("mTabContainer", function () this.tabContainer);
tabmail.__defineGetter__("mTabs", function () this.tabContainer.childNodes);
tabmail.__defineGetter__("mCurrentTab", function () this.tabContainer.selectedItem);
tabmail.__defineGetter__("mStrip", function () this.tabStrip);
tabmail.__defineGetter__("browsers", function () [browser for (browser in Iterator(this.mTabs))] );
}
return tabmail;
};
@@ -123,7 +123,7 @@ function Tabs() //{{{
let tabStrip = tabs.tabStrip;
if (!tabStrip)
return options['showtabline']; // XXX
return options["showtabline"]; // XXX
if (value == 0)
{
@@ -677,9 +677,9 @@ function Tabs() //{{{
return store.options;
},
getLocalStore: function (tab)
getLocalStore: function (tabIndex)
{
let tab = this.getTab(tab);
let tab = this.getTab(tabIndex);
if (!tab.liberatorStore)
tab.liberatorStore = {};
return tab.liberatorStore;
@@ -737,7 +737,7 @@ function Tabs() //{{{
{
if (index != undefined)
return getBrowser().mTabs[index];
else
return getBrowser().mCurrentTab;
},

View File

@@ -7,7 +7,7 @@ const template = {
map: function map(iter, fn, sep, interruptable)
{
if (iter.length) /* Kludge? */
if (iter.length) // FIXME: Kludge?
iter = util.Array.iterator(iter);
let ret = <></>;
let n = 0;
@@ -287,7 +287,7 @@ const template = {
tabular: function tabular(headings, style, iter)
{
/* This might be mind-bogglingly slow. We'll see. */
// TODO: This might be mind-bogglingly slow. We'll see.
// <e4x>
return this.commandOutput(
<table>

View File

@@ -28,7 +28,7 @@ the terms of any one of the MPL, the GPL or the LGPL.
/** @scope modules */
/*
/**
* This class is used for prompting of user input and echoing of messages
*
* it consists of a prompt and command field
@@ -75,6 +75,12 @@ function CommandLine() //{{{
var keepCommand = false;
var lastEcho = null;
/**
* A class for managing the history of an inputField
*
* @param {Object} inputField
* @param {string} mode
*/
function History(inputField, mode)
{
if (!(this instanceof arguments.callee))
@@ -85,27 +91,42 @@ function CommandLine() //{{{
this.reset();
}
History.prototype = {
/**
* Empties the history.
*/
reset: function ()
{
this.index = null;
},
/**
* Permanently save the history
*/
save: function ()
{
let str = this.input.value;
if (/^\s*$/.test(str))
return;
this.store.mutate('filter', function (line) line != str);
this.store.mutate("filter", function (line) line != str);
this.store.push(str);
this.store.truncate(options["history"], true);
},
/**
* Set the current match to val
*
* @param {string} val
*/
replace: function (val)
{
this.input.value = val;
liberator.triggerCallback("change", currentExtendedMode, val);
},
/**
* move up or (if backward) down in the history
*
* @param {boolean} backward
* @param {boolean} matchCurrent XXX: what?
*/
select: function (backward, matchCurrent)
{
// always reset the tab completion if we use up/down keys
@@ -154,6 +175,11 @@ function CommandLine() //{{{
}
};
/**
* A class for tab completions on an input field
*
* @param {Object} input
*/
function Completions(input)
{
if (!(this instanceof arguments.callee))
@@ -326,7 +352,7 @@ function CommandLine() //{{{
{
case this.UP:
if (this.selected == null)
idx = this.items.length - 1;
idx = -2
else
idx = this.selected - 1;
break;
@@ -343,8 +369,8 @@ function CommandLine() //{{{
idx = Math.max(0, Math.min(this.items.length - 1, idx));
break;
}
this.itemList.selectItem(idx);
if (idx < 0 || idx >= this.items.length || idx == null)
if (idx == -1 || this.items.length && idx >= this.items.length || idx == null)
{
// Wrapped. Start again.
this.selected = null;
@@ -352,28 +378,41 @@ function CommandLine() //{{{
}
else
{
// Wait for contexts to complete if necessary.
// FIXME: Need to make idx relative to individual contexts.
let list = this.context.contextList.reverse();
if (idx == -2)
list = list.slice().reverse();
let n = 0;
for (let [,context] in Iterator(list))
{
function done() !(idx >= n + context.items.length || idx == -2 && !context.items.length);
while (context.incomplete && !done())
liberator.threadYield(true, true);
if (done())
break;
n += context.items.length;
}
// See previous FIXME. This will break if new items in
// a previous context come in.
if (idx < 0)
idx = this.items.length - 1;
this.selected = idx;
this.completion = this.items[idx].text;
}
this.itemList.selectItem(idx);
},
tab: function tab(reverse)
{
autocompleteTimer.flush();
// Check if we need to run the completer.
if (this.context.waitingForTab || this.wildIndex == -1)
this.complete(true, true);
if (this.items.length == 0)
{
// No items. Wait for any unfinished completers.
let end = Date.now() + 5000;
while (this.context.incomplete && this.items.length == 0 && Date.now() < end)
liberator.threadYield();
if (this.items.length == 0)
return liberator.beep();
}
switch (this.wildtype.replace(/.*:/, ""))
{
case "":
@@ -392,6 +431,9 @@ function CommandLine() //{{{
break;
}
if (this.items.length == 0)
return void liberator.beep();
if (this.type.list)
completionList.show();
@@ -511,16 +553,28 @@ function CommandLine() //{{{
var multilineRegexp = null;
var multilineCallback = null;
/**
* @private - highlight the messageBox according to group
*/
function setHighlightGroup(group)
{
messageBox.setAttributeNS(NS.uri, "highlight", group);
}
// Whether the command line must be open.
/**
* @private - Determines whether the command line should be visible.
*
* @return {boolean}
*/
function commandShown() modes.main == modes.COMMAND_LINE &&
!(modes.extended & (modes.INPUT_MULTILINE | modes.OUTPUT_MULTILINE));
// sets the prompt - for example, : or /
/**
* @private - set the prompt to val styled with highlightGroup
*
* @param {string} val
* @param {string} highlightGroup
*/
function setPrompt(val, highlightGroup)
{
promptWidget.value = val;
@@ -529,7 +583,11 @@ function CommandLine() //{{{
promptWidget.setAttributeNS(NS.uri, "highlight", highlightGroup || commandline.HL_NORMAL);
}
// sets the command - e.g. 'tabopen', 'open http://example.com/'
/**
* @private - set the command to cmd and move the user's cursor to the end.
*
* @param {string} cmd
*/
function setCommand(cmd)
{
commandWidget.value = cmd;
@@ -537,6 +595,14 @@ function CommandLine() //{{{
commandWidget.selectionEnd = cmd.length;
}
/**
* @private - display a message styled with highlightGroup
* and, if forceSingle is true, ensure it takes only one line.
*
* @param {string} str
* @param {string} highlightGroup
* @param {boolean} forceSingle
*/
function echoLine(str, highlightGroup, forceSingle)
{
setHighlightGroup(highlightGroup);
@@ -552,7 +618,14 @@ function CommandLine() //{{{
echoMultiline(<span highlight="Message">{str}</span>, highlightGroup);
}
// TODO: resize upon a window resize
/**
* Display a multiline message, possible through a "more" like interface
*
* TODO: resize upon a window resize
*
* @param {string} str
* @param {string} highlightGroup
*/
function echoMultiline(str, highlightGroup)
{
let doc = multilineOutputWidget.contentDocument;
@@ -560,11 +633,10 @@ function CommandLine() //{{{
liberator.triggerObserver("echoMultiline", str, highlightGroup);
/* If it's already XML, assume it knows what it's doing.
* Otherwise, white space is significant.
* The problem elsewhere is that E4X tends to insert new lines
* after interpolated data.
*/
// If it's already XML, assume it knows what it's doing.
// Otherwise, white space is significant.
// The problem elsewhere is that E4X tends to insert new lines
// after interpolated data.
XML.ignoreWhitespace = typeof str != "xml";
lastMowOutput = <div class="ex-command-output" style="white-space: nowrap" highlight={highlightGroup}>{template.maybeXML(str)}</div>;
let output = util.xmlToDom(lastMowOutput, doc);
@@ -598,6 +670,10 @@ function CommandLine() //{{{
commandline.updateMorePrompt();
}
/**
* @private - ensure that the Multiline input widget is the
* correct size.
*/
function autosizeMultilineInputWidget()
{
let lines = multilineInputWidget.value.split("\n").length - 1;
@@ -605,7 +681,16 @@ function CommandLine() //{{{
multilineInputWidget.setAttribute("rows", Math.max(lines, 1));
}
// used for the :echo[err] commands
/**
* @private - eval()s a javascript expression
* and returns a string suitable to be echo'd.
*
* If useColor is true, util.objectToString will
* colorize object output.
*
* @param {string} arg
* @param {boolean} useColor
*/
function echoArgumentToString(arg, useColor)
{
if (!arg)
@@ -885,6 +970,9 @@ function CommandLine() //{{{
storage.styles.removeSheet(true, "silent-mode");
},
/**
* XXX: This function is not used!
*/
runSilently: function (fn, self)
{
let wasSilent = this.silent;
@@ -912,6 +1000,16 @@ function CommandLine() //{{{
get message() messageBox.value,
/**
* Changes the command line to display the following prompt (usually ":")
* followed by the command, in the given mode. Valid modes are
* attributes of the "modes" variable, and modes.EX is probably
* a good choice.
*
* @param {string} prompt
* @param {string} cmd
* @param {number} mode
*/
open: function open(prompt, cmd, extendedMode)
{
// save the current prompts, we need it later if the command widget
@@ -936,7 +1034,11 @@ function CommandLine() //{{{
liberator.triggerCallback("change", currentExtendedMode, cmd);
},
// normally used when pressing esc, does not execute a command
/**
* Removes any input from the command line, without executing its
* contents. Removes any "More" windows or other such output.
* Pressing <ESC> in EX mode normally has this effect.
*/
close: function close()
{
let mode = currentExtendedMode;
@@ -946,6 +1048,7 @@ function CommandLine() //{{{
if (history)
history.save();
this.resetCompletions(); // cancels any asynchronous completion still going on, must be before completions = null
completions = null;
history = null;
@@ -969,14 +1072,33 @@ function CommandLine() //{{{
keepCommand = false;
},
/**
* Hide any auto-completion/More-ing that is happening.
*/
hide: function hide()
{
commandlineWidget.collapsed = true;
},
// liberator.echo uses different order of flags as it omits the hightlight group, change v.commandline.echo argument order? --mst
/**
* Output the given string onto the command line coloured
* using the rules according to highlightGroup. If not
* given higlightGroup defaults to commandline.HL_NORMAL
* and other possibe values are at commandline.HL_[A-Z]*.
*
* Flags can be any of:
* commandline.APPEND_TO_MESSAGES (causes message to be added to the messagesHistory)
* commandline.FORCE_SINGLELINE | commandline.DISALLOW_MULTILINE
* commandline.FORCE_MULTILINE
*
* @param {string} str
* @param {string} highlightGroup
* @param {number} flags
*/
echo: function echo(str, highlightGroup, flags)
{
// liberator.echo uses different order of flags as it omits the highlight group, change v.commandline.echo argument order? --mst
if (silent)
return false;
@@ -1021,8 +1143,23 @@ function CommandLine() //{{{
return true;
},
// this will prompt the user for a string
// commandline.input("(s)ave or (o)pen the file?")
/**
* Prompt the user for a string and execute the given
* callback with that as the only argument on <CR>
* extra can have any of the following attributes:
*
* onChange: A function to be called with the current input every time it changes
* completer: A function called with a ?context? when the user tries to tabcomplete
* promptHighlight: The HighlightGroup to use (default commandline.HL_QUESTION, others
* can be found at commandline.HL_[A-Z]*)
*
* This function sets the mode to modes.COMMAND_LINE, and thus popping the mode will
* stop further input from being waited for (useful for stopping onChange)
*
* @param {string} prompt
* @param {function(string)} callback
* @param {Object} extra
*/
input: function input(prompt, callback, extra)
{
extra = extra || {};
@@ -1042,8 +1179,14 @@ function CommandLine() //{{{
completions = Completions(commandWidget.inputField);
},
// reads a multi line input and returns the string once the last line matches
// @param untilRegexp
/**
* Get a multiline input from a user, up to but not including
* the line which matches the given regular expression. Then
* execute the callback with that string as a parameter.
*
* @param {RegExp} untilRegexp
* @param {function(string)} callbackFunc
*/
inputMultiline: function inputMultiline(untilRegexp, callbackFunc)
{
// Kludge.
@@ -1063,6 +1206,13 @@ function CommandLine() //{{{
setTimeout(function () { multilineInputWidget.focus(); }, 10);
},
/**
* Handle events, the come from liberator when liberator.mode = modes.COMMAND_LINE
* but also takes blur/focus/input events raw from #liberator-commandline-command
* in the XUL
*
* @param {Event} event
*/
onEvent: function onEvent(event)
{
let command = this.command;
@@ -1085,7 +1235,7 @@ function CommandLine() //{{{
}
else if (event.type == "input")
{
this.resetCompletions();
//this.resetCompletions(); -> already handled by "keypress" below (hopefully), so don't do it twice
liberator.triggerCallback("change", currentExtendedMode, command);
}
else if (event.type == "keypress")
@@ -1150,11 +1300,18 @@ function CommandLine() //{{{
}
else if (event.type == "keyup")
{
let key = events.toString(event);
if (key == "<Tab>" || key == "<S-Tab>")
tabTimer.flush();
}
},
/**
* Multiline input events, they will come straight from
* #liberator-multiline-input in the XUL.
*
* @param {Event} event
*/
onMultilineInputEvent: function onMultilineInputEvent(event)
{
if (event.type == "keypress")
@@ -1189,8 +1346,16 @@ function CommandLine() //{{{
return true;
},
// FIXME: if 'more' is set and the MOW is not scrollable we should still
// allow a down motion after an up rather than closing
/**
* Handle events when we are in multiline output mode,
* these come from liberator when modes.extended & modes.MULTILINE_OUTPUT
* and also from #liberator-multiline-output in the XUL
*
* FIXME: if 'more' is set and the MOW is not scrollable we should still
* allow a down motion after an up rather than closing
*
* @param {Event} event
*/
onMultilineOutputEvent: function onMultilineOutputEvent(event)
{
let win = multilineOutputWidget.contentWindow;
@@ -1298,7 +1463,7 @@ function CommandLine() //{{{
}
break;
// let firefox handle those to select table cells or show a context menu
// let Firefox handle those to select table cells or show a context menu
case "<C-LeftMouse>":
case "<RightMouse>":
case "<C-S-LeftMouse>":
@@ -1400,6 +1565,15 @@ function CommandLine() //{{{
}
},
/**
* Refresh or remove the prompt that displays when in multiline mode.
* showHelp will cause the possible key-options to be displayed,
* force will cause a display of the default message even if it
* could be at the end of the output.
*
* @param {boolean} force
* @param {boolean} showHelp
*/
updateMorePrompt: function updateMorePrompt(force, showHelp)
{
if (outputContainer.collapsed)
@@ -1417,6 +1591,14 @@ function CommandLine() //{{{
echoLine("Press ENTER or type command to continue", this.HL_QUESTION, true);
},
/**
* Changes the height of the multilineOutputWidget to fit
* its contents, if <b>open</b> is true, it will cause the
* widget to uncollapse, if not it will leave the widget
* closed.
*
* @param {boolean} open
*/
updateOutputHeight: function updateOutputHeight(open)
{
if (!open && outputContainer.collapsed)
@@ -1439,11 +1621,18 @@ function CommandLine() //{{{
outputContainer.collapsed = false;
},
/**
* Disable any active completion functions by calling their cancelFunc's
* Will also remove the completions preview window.
*/
resetCompletions: function resetCompletions()
{
autocompleteTimer.reset();
// liberator.dump("Resetting completions...");
if (completions)
{
completions.context.cancelAll();
completions.wildIndex = -1;
completions.previewClear();
}
@@ -1457,9 +1646,9 @@ function CommandLine() //{{{
/**
* The list which is used for the completion box (and QuickFix window in future)
*
* @param id: the id of the the XUL <iframe> which we want to fill
* it MUST be inside a <vbox> (or any other html element,
* because otherwise setting the height does not work properly
* @param {string} id The id of the XUL <iframe> which we want to fill it
* MUST be inside a <vbox> (or any other html element, because otherwise
* setting the height does not work properly
*/
function ItemList(id) //{{{
{
@@ -1505,7 +1694,7 @@ function ItemList(id) //{{{
minHeight = Math.max(minHeight, divNodes.completions.getBoundingClientRect().bottom);
container.height = minHeight;
if (container.collapsed)
div.style.minWidth = undefined;
div.style.minWidth = "";
// FIXME: Belongs elsewhere.
commandline.updateOutputHeight(false);
}
@@ -1550,10 +1739,10 @@ function ItemList(id) //{{{
}
/**
* uses the entries in "items" to fill the listbox
* does incremental filling to speed up things
* Uses the entries in "items" to fill the listbox and
* does incremental filling to speed up things.
*
* @param offset: start at this index and show maxItems
* @param {number} offset Start at this index and show maxItems
*/
function fill(offset)
{
@@ -1671,7 +1860,7 @@ function ItemList(id) //{{{
// select index, refill list if necessary
selectItem: function selectItem(index)
{
//if (container.collapsed) // fixme
//if (container.collapsed) // FIXME
// return;
//let now = Date.now();
@@ -1773,6 +1962,14 @@ function StatusLine() //{{{
return {
/**
* Update the status bar to indicate how secure the website is
* secure => https:// with valid certificate
* broken => https:// with invalid certificate
* insecure => http://
*
* @param {'secure'|'broken'|'insecure'} type
*/
setClass: function setClass(type)
{
const highlightGroup = {
@@ -1794,7 +1991,14 @@ function StatusLine() //{{{
this.updateBufferPosition();
},
// if "url" is ommited, build a usable string for the URL
/**
* Update which URL is displayed on the status line,
* if url is omitted then buffer.URL is used instead and
* status icons [+-❤] are updated to match whether one can
* go back/forwards in history/have bookmarked the page.
*
* @param {string} url
*/
updateUrl: function updateUrl(url)
{
if (typeof url == "string")
@@ -1805,7 +2009,7 @@ function StatusLine() //{{{
url = buffer.URL;
// make it even more vim-like
// make it even more Vim-like
if (url == "about:blank")
{
if (!buffer.title)
@@ -1837,6 +2041,13 @@ function StatusLine() //{{{
urlWidget.value = url;
},
/**
* Set the contents of the status line's input buffer
* to the given string.
*
* Used for displaying partial key combinations in
* normal mode.
*/
updateInputBuffer: function updateInputBuffer(buffer)
{
if (!buffer || typeof buffer != "string")
@@ -1845,6 +2056,17 @@ function StatusLine() //{{{
inputBufferWidget.value = buffer;
},
/**
* Update the display of the progress bar.
* If the parameter is a string, it will be
* displayed literally. Otherwise it must be a number
* less than one.
* Negative numbers cause a "Loading..." status,
* Positive (< 1) numbers cause an arrow ==> of length
* proportional to the arrow.
*
* @param {string|number} progress
*/
updateProgress: function updateProgress(progress)
{
if (!progress)
@@ -1872,7 +2094,13 @@ function StatusLine() //{{{
}
},
// you can omit either of the 2 arguments
/**
* Display the correct tabcount (e.g. [1/5]) on the status bar.
* If either parameter is omitted, they will be calculated.
*
* @param {number} currentIndex
* @param {number} totalTabs
*/
updateTabCount: function updateTabCount(currentIndex, totalTabs)
{
if (!liberator.has("tabs"))
@@ -1897,7 +2125,16 @@ function StatusLine() //{{{
tabCountWidget.value = "[" + currentIndex + "/" + totalTabs + "]";
},
// percent is given between 0 and 1
/**
* Display the correct position on the status bar, if the
* percent parameter is omitted it will be calculated.
*
* Negative numbers are set to "All", Zero implies "Top"
* One or above is "Bot", and anything else is multiplied by
* a hundred and displayed as a percentage.
*
* @param {number} percent
*/
updateBufferPosition: function updateBufferPosition(percent)
{
if (!percent || typeof percent != "number")

View File

@@ -57,15 +57,19 @@ const util = { //{{{
},
/**
* Flatten an array, such that all elements of the array are
* Flattens an array, such that all elements of the array are
* joined into a single array:
* [["foo", ["bar"]], ["baz"], "quux"] -> ["foo", ["bar"], "baz", "quux"]
*
* @param {Array} ary
* @returns {Array}
*/
flatten: function flatten(ary) Array.concat.apply([], ary),
/**
* Returns an Iterator for an array's values.
*
* @param {Array} ary
* @returns {Iterator(Object)}
*/
iterator: function iterator(ary)
@@ -76,8 +80,9 @@ const util = { //{{{
},
/**
* Returns an Iterator for the arrays indices and values.
* Returns an Iterator for an array's indices and values.
*
* @param {Array} ary
* @returns {Iterator([{number}, {Object}])}
*/
iterator2: function (ary)
@@ -94,6 +99,7 @@ const util = { //{{{
*
* @param {Array} ary
* @param {boolean} unsorted
* @returns {Array}
*/
uniq: function uniq(ary, unsorted)
{
@@ -135,10 +141,10 @@ const util = { //{{{
/**
* Clips a string to a given length. If the input string is longer
* than <b>length</b>, an elipsis is appended.
* than <b>length</b>, an ellipsis is appended.
*
* @param {string} str
* @param {number} length
* @param {string} str The string to truncate.
* @param {number} length The length of the returned string.
* @returns {string}
*/
clip: function clip(str, length)
@@ -169,6 +175,13 @@ const util = { //{{{
return node.ownerDocument.defaultView.getComputedStyle(node, null);
},
/**
* Copies a string to the system clipboard. If <b>verbose</b> is specified
* the copied string is also echoed to the command-line.
*
* @param {string} str
* @param {boolean} verbose
*/
copyToClipboard: function copyToClipboard(str, verbose)
{
const clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
@@ -178,12 +191,26 @@ const util = { //{{{
liberator.echo("Yanked " + str, commandline.FORCE_SINGLELINE);
},
/**
* Converts any arbitrary string into an URI object.
*
* @param {string} str
* @returns {Object}
*/
// FIXME: newURI needed too?
createURI: function createURI(str)
{
const fixup = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup);
return fixup.createFixupURI(str, fixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP);
},
/**
* Converts HTML special characters in <b>str</b> to the equivalent HTML
* entities.
*
* @param {string} str
* @returns {string}
*/
escapeHTML: function escapeHTML(str)
{
// XXX: the following code is _much_ slower than a simple .replace()
@@ -195,11 +222,26 @@ const util = { //{{{
return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
},
/**
* Escapes Regular Expression special characters in <b>str</b>.
*
* @param {string} str
* @returns {string}
*/
escapeRegex: function escapeRegex(str)
{
return str.replace(/([\\{}()[\].?*+])/g, "\\$1");
},
/**
* Escapes quotes, newline and tab characters in <b>str</b>. The returned
* string is delimited by <b>delimiter</b> or " if <b>delimiter</b> is not
* specified.
*
* @param {string} str
* @param {string} delimiter
* @returns {string}
*/
escapeString: function escapeString(str, delimiter)
{
if (delimiter == undefined)
@@ -207,11 +249,20 @@ const util = { //{{{
return delimiter + str.replace(/([\\'"])/g, "\\$1").replace("\n", "\\n", "g").replace("\t", "\\t", "g") + delimiter;
},
formatBytes: function formatBytes(num, decimalPlaces, humanReadable)
/**
* Converts <b>bytes</b> to a pretty printed data size string.
*
* @param {number} bytes The number of bytes.
* @param {string} decimalPlaces The number of decimal places to use if
* <b>humanReadable</b> is true.
* @param {boolean} humanReadable Use byte multiples.
* @returns {string}
*/
formatBytes: function formatBytes(bytes, decimalPlaces, humanReadable)
{
const unitVal = ["Bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
let unitIndex = 0;
let tmpNum = parseInt(num, 10) || 0;
let tmpNum = parseInt(bytes, 10) || 0;
let strNum = [tmpNum + ""];
if (humanReadable)
@@ -242,33 +293,40 @@ const util = { //{{{
return strNum[0] + " " + unitVal[unitIndex];
},
// generates an Asciidoc help entry, "command" can also be a mapping
generateHelp: function generateHelp(command, extraHelp)
/**
* Generates an Asciidoc help entry.
*
* @param {Object} obj A liberator <b>Command</b>, <b>Mapping</b> or
* <b>Option</b> object
* @param {string} extraHelp Extra help text beyond the description.
* @returns {string}
*/
generateHelp: function generateHelp(obj, extraHelp)
{
let start = "", end = "";
if (command instanceof liberator.Command)
if (obj instanceof Command)
start = ":";
else if (command instanceof liberator.Option)
else if (obj instanceof Option)
start = end = "'";
let ret = "";
let longHelp = false;
if ((command.help && command.description) && (command.help.length + command.description.length) > 50)
if ((obj.help && obj.description) && (obj.help.length + obj.description.length) > 50)
longHelp = true;
// the tags which are printed on the top right
for (let j = command.names.length - 1; j >= 0; j--)
ret += "|" + start + command.names[j] + end + "| ";
for (let j = obj.names.length - 1; j >= 0; j--)
ret += "|" + start + obj.names[j] + end + "| ";
if (longHelp)
ret += "+";
ret += "\n";
// the usage information for the command
let usage = command.names[0];
if (command.specs) // for :commands
usage = command.specs[0];
// the usage information
let usage = obj.names[0];
if (obj.specs) // for :commands
usage = obj.specs[0];
usage = usage.replace(/{/, "\\\\{").replace(/}/, "\\\\}");
usage = usage.replace(/'/, "\\'").replace(/`/, "\\`");
@@ -279,9 +337,9 @@ const util = { //{{{
ret += "\n________________________________________________________________________________\n";
// the actual help text
if (command.description)
if (obj.description)
{
ret += command.description + "."; // the help description
ret += obj.description + "."; // the help description
if (extraHelp)
ret += " +\n" + extraHelp;
}
@@ -294,6 +352,16 @@ const util = { //{{{
return ret;
},
/**
* Sends a synchronous HTTP request to <b>url</b> and returns the
* XMLHttpRequest object. If <b>callback</b> is specified the request is
* asynchronous and the <b>callback</b> is invoked with the object as its
* argument.
*
* @param {string} url
* @param {function} callback
* @returns {Object}
*/
httpGet: function httpGet(url, callback)
{
try
@@ -317,8 +385,21 @@ const util = { //{{{
}
},
/**
* The identity function.
*
* @param {Object} k
* @returns {Object}
*/
identity: function identity(k) k,
/**
* Returns the intersection of two rectangles.
*
* @param {Object} r1
* @param {Object} r2
* @returns {Object}
*/
intersection: function (r1, r2) ({
get width() this.right - this.left,
get height() this.bottom - this.top,
@@ -328,6 +409,14 @@ const util = { //{{{
bottom: Math.min(r1.bottom, r2.bottom)
}),
/**
* Returns the array that results from applying <b>fn</b> to each property
* of <b>obj</b>.
*
* @param {Object} obj
* @param {function} fn
* @returns {Array}
*/
map: function map(obj, fn)
{
let ary = [];
@@ -336,20 +425,32 @@ const util = { //{{{
return ary;
},
newURI: function (url)
/**
* Converts a URI string into an URI object.
*
* @param {string} uri
* @returns {Object}
*/
// FIXME: createURI needed too?
newURI: function (uri)
{
const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
return ioService.newURI(url, null, null);
return services.get("io").newURI(uri, null, null);
},
// if color = true it uses HTML markup to color certain items
/**
* Pretty print a JavaScript object. Use HTML markup to color certain items
* if <b>color</b> is true.
*
* @param {Object} object The object to pretty print.
* @param {boolean} color Whether the output should be colored.
* @returns {string}
*/
objectToString: function objectToString(object, color)
{
/* Use E4X literals so html is automatically quoted
* only when it's asked for. Noone wants to see &lt;
* on their console or :map :foo in their buffer
* when they expect :map <C-f> :foo.
*/
// Use E4X literals so html is automatically quoted
// only when it's asked for. Noone wants to see &lt;
// on their console or :map :foo in their buffer
// when they expect :map <C-f> :foo.
XML.prettyPrinting = false;
XML.ignoreWhitespace = false;
@@ -417,6 +518,15 @@ const util = { //{{{
return color ? string : [s for each (s in string)].join("");
},
/**
* A generator that returns the values between <b>start</b> and <b>end</b>.
* If <b>reverse</b> is true then the values are returned in reverse order.
*
* @param {number} start The interval's start value.
* @param {number} end The interval's end value.
* @param {boolean} reverse Reverse the order in which the values are produced.
* @returns {Iterator(Object)}
*/
range: function range(start, end, reverse)
{
if (!reverse)
@@ -431,7 +541,16 @@ const util = { //{{{
}
},
interruptableRange: function interruptableRange(start, end, time)
/**
* An interruptible generator that returns all values between <b>start</b>
* and <b>end</b>. The thread yields every <b>time</b> milliseconds.
*
* @param {number} start The interval's start value.
* @param {number} end The interval's end value.
* @param {number} time The time in milliseconds between thread yields.
* @returns {Iterator(Object)}
*/
interruptibleRange: function interruptibleRange(start, end, time)
{
let endTime = Date.now() + time;
while (start < end)
@@ -445,15 +564,22 @@ const util = { //{{{
}
},
// same as Firefox's readFromClipboard function, but needed for apps like Thunderbird
/**
* Reads a string from the system clipboard.
*
* This is same as Firefox's readFromClipboard function, but is needed for
* apps like Thunderbird which do not provide it.
*
* @returns {string}
*/
readFromClipboard: function readFromClipboard()
{
let url;
try
{
const clipboard = Cc['@mozilla.org/widget/clipboard;1'].getService(Ci.nsIClipboard);
const transferable = Cc['@mozilla.org/widget/transferable;1'].createInstance(Ci.nsITransferable);
const clipboard = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
const transferable = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
transferable.addDataFlavor("text/unicode");
@@ -478,11 +604,18 @@ const util = { //{{{
return url;
},
// takes a string like 'google bla, www.osnews.com'
// and returns an array ['www.google.com/search?q=bla', 'www.osnews.com']
/**
* Returns an array of URLs parsed from <b>str</b>.
*
* Given a string like 'google bla, www.osnews.com' return an array
* ['www.google.com/search?q=bla', 'www.osnews.com']
*
* @param {string} str
* @returns {Array}
*/
stringToURLArray: function stringToURLArray(str)
{
let urls = str.split(RegExp("\s*" + options["urlseparator"] + "\s*"));
let urls = str.split(RegExp("\\s*" + options["urlseparator"] + "\\s*"));
return urls.map(function (url) {
try
@@ -525,6 +658,14 @@ const util = { //{{{
});
},
/**
* Converts an E4X XML literal to a DOM node.
*
* @param {Node} node
* @param {Document} doc
* @param {Object} nodes
* @returns {Node}
*/
xmlToDom: function xmlToDom(node, doc, nodes)
{
XML.prettyPrinting = false;

View File

@@ -34,6 +34,7 @@ const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
// XXX: does not belong here
function Timer(minInterval, maxInterval, callback)
{
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
@@ -57,7 +58,7 @@ function Timer(minInterval, maxInterval, callback)
};
this.tell = function (arg)
{
if (arg !== undefined)
if (arguments.length > 0)
this.arg = arg;
let now = Date.now();

View File

@@ -31,7 +31,7 @@ const config = { //{{{
name: "Muttator",
hostApplication: "Thunderbird", // TODO: can this be found out otherwise? gBrandBundle.getString("brandShortName");
/*** optional options, there are checked for existance and a fallback provided ***/
/*** optional options, there are checked for existence and a fallback provided ***/
features: ["hints", "mail", "marks", "addressbook", "tabs"],
defaults: { guioptions: "frb" },

View File

@@ -588,14 +588,14 @@ function Mail() //{{{
if (mail.currentFolder.isServer)
return liberator.beep();
mail.currentFolder.markAllMessagesRead();
mail.currentFolder.markAllMessagesRead(msgWindow);
});
mappings.add(myModes, ["<C-t>"],
"Mark all messages as read",
function ()
{
mail.getFolders("", false).forEach(function (folder) { folder.markAllMessagesRead(); });
mail.getFolders("", false).forEach(function (folder) { folder.markAllMessagesRead(msgWindow); });
});
// DISPLAY OPTIONS
@@ -890,12 +890,13 @@ function Mail() //{{{
return false;
},
/*
* general-purpose method to find messages
* @param validatorFunc(msg): return true/false whether msg should be selected or not
* @param canWrap: when true, wraps around folders
* @param openThreads: should we open closed threads?
* @param reverse: change direction of searching
/**
* General-purpose method to find messages
*
* @param {function} validatorFunc(msg): return true/false whether msg should be selected or not
* @param {boolean} canWrap: when true, wraps around folders
* @param {boolean} openThreads: should we open closed threads?
* @param {boolean} reverse: change direction of searching
*/
selectMessage: function (validatorFunc, canWrap, openThreads, reverse, count)
{

View File

@@ -1,3 +1,7 @@
2009:
* Jonathan Austin
* Steven Romanow
2008:
* John Baber
* Mark Orr

View File

@@ -7,8 +7,7 @@
* IMPORTANT: Due to much improved autocompletion, changed default 'complete' option
value to 'sfl', listing intelligent Firefox location bar results. Removed possibility
to use 'h' in 'complete'.
* IMPORTANT: AlwaysHint modes were removed as they didn't make too
much sense with the new hint system
* IMPORTANT: AlwaysHint mode with ;F mode changed the semantics slightly
* IMPORTANT: command actions now take an args object, returned from
commands.parseArgs, as their first argument. This will break any commands
not using the args parser explicitly. The old string value is now

View File

@@ -3,7 +3,6 @@ Priority list:
BUGS:
- add window resize support to hints
- can't reverse tab through the vimperator toolbar
- searching backwards incrementally does not work i.e. with 'incsearch' set
- http://msdn2.microsoft.com/en-us/library/ms535258.aspx does not scroll with j/k/etc.
same for http://forum.mootools.net/topic.php?id=3458 and
@@ -22,7 +21,19 @@ BUGS:
(recent CVS regressions):
- visual caret mode is broken
- BookmarkAdd is fired once for each bookmark periodically i.e. not in response to adding a bookmark
- the message system is a bit of a debacle at the moment but I'm not sure how
it's supposed to work. MST, can you spec it when you have some time?
E.g. :ls | :echomsg "Foobar" doesn't add "Foobar" to the already open MOW.
Obviously I think it should but I'm not sure if it's a bug or not in your
view, thanks. --djk
The spec is easy: echomsg() is used for informational purposes, and should therefore
never need user interaction. Therefore: If the MOW is open, print the message there,
but never open the MOW for an echomsg(). --mst
- While the old :open foo<tab> was broken/annoying, so is the one after 02-01-2008, as
I am often waiting ~20sec or more after doing :open not-cached-things<tab>.
We should probably just abort searching after 5 secs if we already have found some entries.
- :set noflashblock seems broken (= :set fb? afterwards says "fb"), let's see if that's a
plugin or a vimp issue.
FEATURES:
9 finish :help TODOs
@@ -30,6 +41,15 @@ FEATURES:
9 adaptive timeout for auto-completions, :set completions can be updated more often than
:open foo
9 use the storage module for autocommands
8 support 'activate' in buffer.followLink?
Leave this to the bookmarks.tabs.loadInBackground. Hint activation
should be nearly equivalent to the corresponding mouse motion, and that
mouse movement would be governed by the FF pref. However, :tabopen is
something Vimp specific, and so it needs a specific setting (i.e.,
activate). OTOH, I think it would be better if ";t" *always* opens a
new foreground tab and ";b" *always* opensa new background tab. So "F"
should be the only hint mode that changes based on loadInBackground.
--Ted
8 add support for filename special characters such as %
8 :redir and 'verbosefile'
8 middleclick in content == p, and if command line is open, paste there the clipboard buffer
@@ -37,8 +57,10 @@ FEATURES:
8 :addsearch wikpedia http://en.wikipedia.org/wiki/Special:Search?search=%s to allow saving of
quick searches in the RC file.
Why not just add a bookmark? --Kris
7 adaptive learning for tab-completions
(https://bugzilla.mozilla.org/show_bug.cgi?id=395739 could help)
This would require performance tests, how fast it is to add 20 keywords that way, as we need
to search all existing bookmarks to see if the keyword is already defined, and then just update
that bookmark. --mst
8 allow for multiple ex commands separated with |
7 use ctrl-n/p in insert mode for word completion
7 implement QuickFix window based on ItemList
7 [ctrl-o/i] to Go back to a Previous Position (done partly, however currently does not use a per tab jumplist)
@@ -53,9 +75,10 @@ FEATURES:
6 support private mode (and :set [no]private): http://ehsanakhgari.org/blog/2008-11-08/prepare-your-add-private-browsing
6 add [count] support to :b* and :tab* commands where missing
6 registers
6 allow for multiple ex commands separated with |
Here, unlike Vim, y and "*y would be equivalent. That is, the pasteboard would
always be the default register. --Ted
6 check/correct spellings in insert mode with some mappings
6 add more autocommands (TabClose, TabOpen, TabChanged, DownloadPre/Post any more?)
6 add more autocommands (TabClose, TabOpen, TabChanged any more?)
6 jump to the next heading with ]h, next image ]i, previous textbox [t and so on
6 :grep support (needs location list)
6 use '' to jump between marks like vim
@@ -68,12 +91,13 @@ FEATURES:
5 make a command to search within google search results
(http://gadelkareem.com/2007/01/28/using-google-ajax-api-as-an-array/)
maybe impossible, needs a per-site key from google
4 y and Y could maybe changed to, but probably not: Y, yy and yl=yank location, ys=yank selection,
yd=yank domain name, yt=yank title, yw=yank current word, yf=yank filename, (other things to yank?)
4 } { should jump to the next paragraph of the page (maybe impossible)
3 A format for 'guitablabel' and 'statusline'
3 add a command-line window (:help cmdline-window in Vim).
3 Splitting Windows with [:sp :vsp ctrl-w,s ctrl-w,v] and closing with [ctrl-w,q], moving with [ctrl-w,w or tab]
have a look into the split browser extension
1 Add information to liberator/HACKING file about testing and optimization
1 Document remote branches in liberator/HACKING
1 Reformat liberator/HACKING so that git diff can find sections and report changes @ somewhere
- many other ideas are listed in the wiki

View File

@@ -29,7 +29,7 @@ the terms of any one of the MPL, the GPL or the LGPL.
const DEFAULT_FAVICON = "chrome://mozapps/skin/places/defaultFavicon.png";
// Try to import older command line history, quick marks, etc.
liberator.registerObserver("load_options", function () {
liberator.registerObserver("load", function () {
if (!options.getPref("extensions.vimperator.commandline_cmd_history"))
return;
@@ -61,12 +61,20 @@ function Bookmarks() //{{{
const taggingService = PlacesUtils.tagging;
const faviconService = Cc["@mozilla.org/browser/favicon-service;1"].getService(Ci.nsIFaviconService);
// XXX for strange Firefox bug :(
// Error: [Exception... "Component returned failure code: 0x8000ffff (NS_ERROR_UNEXPECTED) [nsIObserverService.addObserver]"
// nsresult: "0x8000ffff (NS_ERROR_UNEXPECTED)"
// location: "JS frame :: file://~firefox/components/nsTaggingService.js :: anonymous :: line 89"
// data: no]
// Source file: file://~firefox/components/nsTaggingService.js
taggingService.getTagsForURI(window.makeURI("http://mysterious.bug"), {});
const Bookmark = new Struct("url", "title", "icon", "keyword", "tags", "id");
const Keyword = new Struct("keyword", "title", "icon", "url");
Bookmark.defaultValue("icon", function () getFavicon(this.url));
Bookmark.prototype.__defineGetter__("extra", function () [
['keyword', this.keyword, "Keyword"],
['tags', this.tags.join(', '), "Tag"]
["keyword", this.keyword, "Keyword"],
["tags", this.tags.join(", "), "Tag"]
].filter(function (item) item[1]));
const storage = modules.storage;
@@ -411,7 +419,7 @@ function Bookmarks() //{{{
get format() ({
anchored: false,
title: ["URL", "Info"],
keys: { text: "url", description: "title", icon: "icon", extra: "extra" },
keys: { text: "url", description: "title", icon: "icon", extra: "extra", tags: "tags" },
process: [template.icon, template.bookmarkDescription]
}),
@@ -692,7 +700,7 @@ function History() //{{{
"Go back in the browser history",
function (args)
{
args = args.string;
let url = args.literalArg;
if (args.bang)
{
@@ -700,12 +708,12 @@ function History() //{{{
}
else
{
if (args)
if (url)
{
let sh = window.getWebNavigation().sessionHistory;
for (let i = sh.index - 1; i >= 0; i--)
for (let i in util.range(sh.index, 0, true))
{
if (sh.getEntryAtIndex(i, false).URI.spec == args)
if (sh.getEntryAtIndex(i, false).URI.spec == url)
{
window.getWebNavigation().gotoIndex(i);
return;
@@ -715,7 +723,7 @@ function History() //{{{
}
else
{
history.stepTo(args.count > 0 ? -1 * args.count : -1);
history.stepTo(-Math.max(args.count, 1));
}
}
},
@@ -738,7 +746,7 @@ function History() //{{{
"Go forward in the browser history",
function (args)
{
args = args.string;
let url = args.literalArg;
if (args.bang)
{
@@ -746,12 +754,12 @@ function History() //{{{
}
else
{
if (args)
if (url)
{
let sh = window.getWebNavigation().sessionHistory;
for (let i in util.range(sh.index + 1, sh.count))
{
if (sh.getEntryAtIndex(i, false).URI.spec == args)
if (sh.getEntryAtIndex(i, false).URI.spec == url)
{
window.getWebNavigation().gotoIndex(i);
return;
@@ -761,7 +769,7 @@ function History() //{{{
}
else
{
history.stepTo(args.count > 0 ? args.count : 1);
history.stepTo(Math.max(args.count, 1));
}
}
},
@@ -837,31 +845,30 @@ function History() //{{{
if (index >= 0 && index < window.getWebNavigation().sessionHistory.count)
window.getWebNavigation().gotoIndex(index);
else
liberator.beep();
liberator.beep(); // XXX: really wanted?
},
goToStart: function goToStart()
{
let index = window.getWebNavigation().sessionHistory.index;
if (index == 0)
{
liberator.beep(); // XXX: really wanted?
return;
}
if (index > 0)
window.getWebNavigation().gotoIndex(0);
else
liberator.beep(); // XXX: really wanted?
},
goToEnd: function goToEnd()
{
let index = window.getWebNavigation().sessionHistory.index;
if (index == window.getWebNavigation().sessionHistory.count - 1)
{
liberator.beep();
return;
}
let sh = window.getWebNavigation().sessionHistory;
let max = sh.count - 1;
if (sh.index < max)
window.getWebNavigation().gotoIndex(max);
else
liberator.beep(); // XXX: really wanted?
},
// if openItems is true, open the matching history items in tabs rather than display

View File

@@ -31,7 +31,7 @@ const config = { //{{{
name: "Vimperator",
hostApplication: "Firefox",
/*** optional options, there are checked for existance and a fallback provided ***/
/*** optional options, there are checked for existence and a fallback provided ***/
features: ["bookmarks", "hints", "history", "marks", "quickmarks", "session", "tabs", "windows"],
defaults: { guioptions: "rb" },
@@ -430,16 +430,12 @@ const config = { //{{{
{
setter: function (value)
{
const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService2);
const ioService = services.get("io");
ioService.offline = !value;
gPrefService.setBoolPref("browser.offline", ioService.offline);
return value;
},
getter: function ()
{
const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService2);
return ioService.offline;
}
getter: function () !services.get("io").offline
});
options.add(["titlestring"],

File diff suppressed because one or more lines are too long

View File

@@ -57,18 +57,18 @@ ________________________________________________________________________________
|:doautoa| |:doautoall|
||:doautoa[ll] {event} [url]|| +
||:doautoa[ll] {event} [a][url][a]|| +
________________________________________________________________________________
Apply the autocommands matching the specified URL to all buffers. If no [url]
is specified use the current URL.
Apply the autocommands matching the specified URL to all buffers. If no
[a][url][a] is specified use the current URL.
________________________________________________________________________________
|:do| |:doautocmd|
||:do[autocmd] {event} [url]|| +
||:do[autocmd] {event} [a][url][a]|| +
________________________________________________________________________________
Apply the autocommands matching the specified URL to the current buffer. If no
[url] is specified use the current URL.
[a][url][a] is specified use the current URL.
________________________________________________________________________________
section:Examples[autocmd-examples]

View File

@@ -30,27 +30,29 @@ ________________________________________________________________________________
section:Opening{nbsp}web{nbsp}pages[opening]
|o| |:o| |:open|
||:o[pen][!] [arg1], [arg2], ...|| +
||:o[pen][!] [a][arg1][a], [a][arg2][a], ...|| +
||o||
________________________________________________________________________________
Open one or more URLs in the current tab.
Multiple URLs can be separated with 'urlseparator' (default: ", " Note that the
space after the comma is required.")
The first URL is opened in the current tab, and all other URLs are
opened in new tabs.
Each token is analyzed and in this order:
1. Opened as a local file if it is an existing relative or absolute filename.
- [c]:open /etc/fstab[c] shows the file system table.
- [c]:open ../other/foo.html[c] in your home directory opens
. Opened as a local file if it is an existing relative or absolute filename.
* [c]:open /etc/fstab[c] shows the file system table.
* [c]:open ../other/foo.html[c] in your home directory opens
[a]/home/other/foo.html[a]
2. Opened with the specified search engine if the token looks like a search
. Opened with the specified search engine if the token looks like a search
string and the first word is the name of a search engine ([c]:open wikipedia
linus torvalds[c] opens the Wikipedia entry for linus torvalds). The short
name of a search engine is automatically guessed from its name. If you want
to set a custom name, you can change it with [c]:dialog searchengines[c].
3. Opened with the default search engine or keyword (specified with the
. Opened with the default search engine or keyword (specified with the
'defsearch' option) if the first word is no search engine ([c]:open linus
torvalds[c] opens a Google search for linux torvalds).
4. Passed directly to Firefox in all other cases ([c]:open www.osnews.com,
. Passed directly to Firefox in all other cases ([c]:open www.osnews.com,
www.slashdot.org[c] opens OSNews in the current, and Slashdot in a new
background tab).
@@ -65,19 +67,18 @@ ________________________________________________________________________________
|t| |:t| |:tabopen| |:tabnew| |:tabe| |:tabedit|
||:tabopen[!] [arg1], [arg2], ...|| +
||:tabopen[!] [a][arg1][a], [a][arg2][a], ...|| +
||t||
________________________________________________________________________________
Just like [c]:open[c], but opens the resulting web page(s)
in a new tab. When used with [!], the 'tabopen' value of the 'activate' option
is negated.
Just like [c]:open[c], but also uses a new tab for the first URL. When
used with [!], the 'tabopen' value of the 'activate' option is negated.
________________________________________________________________________________
|T| +
||T||
________________________________________________________________________________
Open one or more URLs in a new tab, based on current location. Works like
Open one or more URLs in a new tab based on current location. Works like
[m]t[m], but preselects current URL in the [c]:tabopen[c] query.
________________________________________________________________________________
@@ -94,16 +95,15 @@ ________________________________________________________________________________
|O| +
||O||
________________________________________________________________________________
Open one or more URLs in the current tab, based on current location. Works
Open one or more URLs in the current tab based on current location. Works
like [m]o[m], but preselects current URL in the [c]:open[c] query.
________________________________________________________________________________
|:winopen| |:wopen| |:winedit|
||:wino[pen][!] [arg1], [arg2], ...|| +
||:wino[pen][!] [a][arg1][a], [a][arg2][a], ...|| +
________________________________________________________________________________
Just like help::open[browsing.html#opening], but opens the resulting web page(s)
in a new window.
Just like [c]:tabopen[c], but opens the resulting web page(s) in a new window.
________________________________________________________________________________
@@ -274,11 +274,10 @@ ________________________________________________________________________________
section:Writing[writing,save-file]
|:w| |:write| |:sav| |:saveas| +
||:sav[eas][!] [file]||
||:sav[eas][!] [a][file][a]||
________________________________________________________________________________
Save current web page to disk. If [file] is omitted, save to the page's
default filename. Existing documents will only be overwritten if [!] is
given.
Save current web page to disk. If [a][file][a] is omitted, save to the page's
default filename. Existing documents will only be overwritten if [!] is given.
________________________________________________________________________________
section:Quitting[quitting,save-session]

View File

@@ -47,9 +47,9 @@ ________________________________________________________________________________
|:vie| |:viewsource|
||:vie[wsource][!] [url]|| +
||:vie[wsource][!] [a][url][a]|| +
________________________________________________________________________________
View source code of current document. If [url] is specified then view the
View source code of current document. If [a][url][a] is specified then view the
source of that document. When [!] is given, it is opened with the external
editor.
________________________________________________________________________________
@@ -97,24 +97,29 @@ ________________________________________________________________________________
|<Left>| |h| +
||[count]h||
________________________________________________________________________________
Scroll document to the left. Count is supported: [m]10h[m] will move 10 times as much to the left. +
If the document cannot scroll more, a beep is emitted (unless 'visualbell' is set).
Scroll document to the left. If [count] is specified then move [count] times as
much to the left. +
If the document cannot scroll more, a beep is emitted (unless 'visualbell' is
set).
________________________________________________________________________________
|<C-e>| |<Down>| |j| +
||[count]j||
________________________________________________________________________________
Scroll document down. Count is supported: [m]10j[m] will move 10 times as much down. +
If the document cannot scroll more, a beep is emitted (unless 'visualbell' is set).
Scroll document down. If [count] is specified then move [count] times as much
down. +
If the document cannot scroll more, a beep is emitted (unless 'visualbell' is
set).
________________________________________________________________________________
|<C-y>| |<Up>| |k| +
||[count]k||
________________________________________________________________________________
Scroll document up. Count is supported: [m]10k[m] will move 10 times as much up. +
If the document cannot scroll more, a beep is emitted (unless 'visualbell' is set).
Scroll document up. If [count] is specified then move [count] times as much up. +
If the document cannot scroll more, a beep is emitted (unless 'visualbell' is
set).
________________________________________________________________________________
@@ -139,8 +144,10 @@ ________________________________________________________________________________
|<Right>| |l| +
||[count]l||
________________________________________________________________________________
Scroll document to the right. Count is supported: [m]10l[m] will move 10 times as much to the right. +
If the document cannot scroll more, a beep is emitted (unless 'visualbell' is set).
Scroll document to the right. If [count] is specified then move [count] times
as much to the right. +
If the document cannot scroll more, a beep is emitted (unless 'visualbell' is
set).
________________________________________________________________________________
@@ -217,11 +224,11 @@ ________________________________________________________________________________
section:Zooming[zooming,zoom]
The zooming commands are dependent on two properties - a zoom range and a
The zooming commands are dependent on two properties -- a zoom range and a
series of levels within that range.
The absolute value of the page zoom is limited to a value within the configured
zoom range (default: 30% - 300%). The zoom levels are used by
zoom range (default: 30%--300%). The zoom levels are used by
[m]zi[m]/[m]zo[m], and similar commands, to change the zoom value in steps. The
default zoom levels are 30%, 50%, 67%, 80%, 90%, 100%, 110%, 120%, 133%, 150%,
170%, 200%, 240%, 300%.
@@ -306,12 +313,12 @@ ________________________________________________________________________________
|:zo| |:zoom|
||:zo[om][!] [value]|| +
||:zo[om][!] [a][value][a]|| +
||:zo[om][!] +{value} | -{value}|| +
________________________________________________________________________________
Set zoom value of current web page. [value] can be an absolute value between 30
and 300% or a relative value if prefixed with "-" or "+". If [value] is
omitted, zoom is reset to 100%.
Set zoom value of current web page. [a][value][a] can be an absolute value
between 30 and 300% or a relative value if prefixed with "-" or "+". If
[a][value][a] is omitted, zoom is reset to 100%.
Normally this command operates on the text zoom, if used with [!] it operates
on full zoom.
@@ -339,14 +346,14 @@ ________________________________________________________________________________
section:Alternate{nbsp}style{nbsp}sheets[alternate-stylesheet]
Page authors may specify alternate style sheets for an HTML document. Users
can then switch between these various style sheets, selecting their favorite.
Page authors may specify alternate style sheets for an HTML document. Users can
then switch between these various style sheets, selecting their favorite.
|:pagest| |:pagestyle|
||:pagest[yle] [stylesheet]|| +
||:pagest[yle] [a][stylesheet][a]|| +
________________________________________________________________________________
Select the author style sheet to apply. If [stylesheet] is not specified the
page's default style sheet is used.
Select the author style sheet to apply. If [a][stylesheet][a] is not specified
the page's default style sheet is used.
All author styling can be removed by setting the 'usermode' option.
________________________________________________________________________________

View File

@@ -53,10 +53,11 @@ Some notes about the code above:
- The actual help code for this command is embedded in at least 4 underscores
(_). This generates a quoteblock and indents the text so it is more clear
that it belongs to the command.
- Wrap things in *$$[c]$$* and they are drawn like a :command. Also *$$[o]$$*
and *$$[m]$$* are available to show options and mappings.
- Any string within \{...\} and $$[arg]$$, $$[url]$$, $$[count]$$ and $$[!]$$ are
automatically drawn in a blue color.
- Wrap things in *$$[c]$$* and they are drawn like a :command. Also *$$[o]$$*,
*$$[m]$$* and *$$[a]$$* are available to markup options, mappings, and
arguments.
- As a convenience, any string within \{...\} and $$[count]$$ and $$[!]$$ are
automatically marked up as an argument.
There are also some additional asciidoc commands specifically for writing
Vimperator documentation:

View File

@@ -8,10 +8,9 @@ INTRO TO BE WRITTEN...
||:ec[ho] {expr}||
________________________________________________________________________________
Echo the expression. Useful for showing informational messages. Multiple lines
can be separated by \n. {expr} can either be a quoted string, or any
expression which can be fed to eval() like 4+5. You can also view the source
code of objects and functions if the return value of {expr} is an object or
function.
can be separated by \n. {expr} can either be a quoted string, or any expression
which can be fed to eval() like 4+5. You can also view the source code of
objects and functions if the return value of {expr} is an object or function.
________________________________________________________________________________
@@ -43,8 +42,8 @@ ________________________________________________________________________________
|:js| |:javas| |:javascript|
||:javas[cript] \\{cmd\\}|| +
||:javascript <<\\{endpattern\\}\n\\{script\\}\n\\{endpattern\\}|| +
||:javas[cript] {cmd}|| +
||:javascript <<{endpattern}\n{empty}{script}\n{empty}{endpattern} || +
||:javascript[!]||
________________________________________________________________________________
Run any JavaScript command through eval(). Acts as a JavaScript interpreter by

View File

@@ -16,12 +16,9 @@ window.addEventListener("message", function (event) {
}, true);
document.addEventListener("click", function (event) {
let elem = event.target;
if (/^(option|mapping|command)$/.test(elem.className))
var tag = elem.textContent.replace(/\s.*/, "");
if (elem.className == "command")
tag = tag.replace(/\[.*?\]/g, "");
if (tag)
elem.href = "chrome://liberator/content/help.xul?" + encodeURIComponent(tag);
let evt = document.createEvent("UIEvents");
evt.initEvent("liberatorHelpLink", true, true);
event.target.dispatchEvent(evt);
}, true);
// vim: set fdm=marker sw=4 ts=4 et:

View File

@@ -5,7 +5,7 @@ HEADER
INTRO TO BE WRITTEN...
|f| +
||f\\{hint\\}||
||#f#{hint}||
________________________________________________________________________________
Start QuickHint mode. In QuickHint mode, every hintable item (according to the
'hinttags' XPath query) is assigned a unique number. You can now either type
@@ -20,7 +20,7 @@ ________________________________________________________________________________
|F| +
||F\\{hint\\}||
||#F#{hint}||
________________________________________________________________________________
Start QuickHint mode, but open link in a new tab. Like normal QuickHint mode
(activated with [m]f[m]) but opens the link in a new tab.
@@ -30,33 +30,38 @@ ________________________________________________________________________________
|extended-hints| +
|;| +
||;\\{mode\\}\\{hint\\}||
||#;#{mode}{empty}{hint}||
________________________________________________________________________________
Start an extended hint mode. ExtendedHint mode is useful, since in this mode
you can yank link locations, open them in a new window or save images. If
you want to yank the location of hint [a]24[a], press [m];y[m] to start
this hint mode. Then press [a]24[a] to copy the hint location.
{mode} can be either one of: +
{mode} can be one of: +
* [m];[m] to focus a link and hover it with the mouse
* [m]?[m] to show information about the element (incomplete)
* [m]a[m] to save its destination (prompting for save location)
* [m]f[m] to focus a frame
* [m]s[m] to save its destination
* [m]o[m] to open its location in the current tab
* [m]t[m] to open its location in a new tab
* [m]b[m] like [m]t[m] but inverts the option whether the tab is activated
* [m]O[m] to open its location in an [c]:open[c] query
* [m]T[m] to open its location in a [c]:tabopen[c] query
* [m]v[m] to view its destination source
* [m]w[m] to open its destination in a new window
* [m]W[m] to open its location in a [c]:winopen[c] query
* [m]y[m] to yank its destination location
* [m]Y[m] to yank its text description
* |;;| [m];[m] to focus a link and hover it with the mouse
* |;?| [m]?[m] to show information about the element (incomplete)
* |;s| [m]s[m] to save its destination
* |;a| [m]a[m] to save its destination (prompting for save location)
* |;f| [m]f[m] to focus a frame
* |;o| [m]o[m] to open its location in the current tab
* |;t| [m]t[m] to open its location in a new tab
* |;b| [m]b[m] to open its location in a new background tab
* |;w| [m]w[m] to open its destination in a new window
* |;F| [m]F[m] to follow a sequence of [m]<CR>[m]-delimited hints in background tabs
* |;O| [m]O[m] to preselect its location in an [c]:open[c] query
* |;T| [m]T[m] to preselect its location in a [c]:tabopen[c] query
* |;W| [m]W[m] to preselect its location in a [c]:winopen[c] query
* |;v| [m]v[m] to view its destination source
* |;V| [m]V[m] to view its destination source in the external editor
* |;y| [m]y[m] to yank its destination location
* |;Y| [m]Y[m] to yank its text description
Hintable elements for all extended hint modes can be set in the
'extendedhinttags' XPath string.
Note: The behavior of [m];t[m] and [m];b[m] is inverted if the
\'browser.tabs.loadInBackground' Firefox preference is set to false.
________________________________________________________________________________
// vim: set syntax=asciidoc:

View File

@@ -259,7 +259,7 @@ section:Options[option-index]
||'cdpath'|| List of directories searched when executing :cd +
||'complete'|| Items which are completed at the :[tab]open prompt +
||'defsearch'|| Set the default search engine +
||'disabledcssheets'|| Set disabled CSS stylesheets +
||'disabledcssheets'|| Set disabled CSS style sheets +
||'editor'|| Set the external text editor +
||'errorbells'|| Ring the bell when an error message is displayed +
||'eventignore'|| List of autocommand event names which should be ignored +

View File

@@ -38,7 +38,7 @@ more, you can either send me greetings, patches or make a donation:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Of course as a believer in free open source software, only make a donation
if you really like Vimperator and the money doesn't hurt - otherwise just use
if you really like Vimperator and the money doesn't hurt -- otherwise just use
it, recommend it and like it :)
section:Help{nbsp}topics[overview]

View File

@@ -15,7 +15,7 @@ Vimperator supports a number of different marks:
section:Bookmarks[bookmarks]
|a| |:bma| |:bmark|
||:bma[rk][!] [-title=title] [-keyword=kw] [-tags=tag1,tag2] [url]|| +
||:bma[rk][!] [a][-title=title][a] [a][-keyword=kw][a] [a][-tags=tag1,tag2][a] [a][url][a]|| +
||a||
____________________________________________________________________________
Add a bookmark. +
@@ -27,12 +27,12 @@ The following options are interpreted:
- -keyword=keyword (short option: -k)
If [!] is present, a new bookmark is always added. Otherwise, the first
bookmark matching [url] is updated.
bookmark matching [a][url][a] is updated.
When creating a new bookmark, if [a][-title][a] isn't given, either the web
page's title or URL is used. You can omit the optional [url] argument, so just
do [c]:bmark[c] to bookmark the currently loaded web page with a default title
and without any tags.
page's title or URL is used. You can omit the optional [a][url][a] argument, so
just do [c]:bmark[c] to bookmark the currently loaded web page with a default
title and without any tags.
____________________________________________________________________________
@@ -47,10 +47,11 @@ ________________________________________________________________________________
|:bmarks|
||:bmarks[!] [filter]|| +
||:bmarks[!] [a][filter][a]|| +
________________________________________________________________________________
List or open multiple bookmarks. Open the message window at the bottom of the
screen with all bookmarks which match [filter] either in the title or URL.
screen with all bookmarks which match [a][filter][a] either in the title or
URL.
The special version [c]:bmarks![c] works the same as [c]:bmarks[c] except it
opens all the found bookmarks in new tabs.
@@ -62,10 +63,10 @@ ________________________________________________________________________________
|:delbm| |:delbmarks|
||:delbm[arks] [url]|| +
||:delbm[arks] [a][url][a]|| +
________________________________________________________________________________
Delete a bookmark. Deletes *all* bookmarks which match the [url].
If omitted, [url] defaults to the URL of the current buffer. Use [m]<Tab>[m]
Delete a bookmark. Deletes *all* bookmarks which match the [a][url][a]. If
omitted, [a][url][a] defaults to the URL of the current buffer. Use [m]<Tab>[m]
key on a string to complete the URL which you want to delete.
The following options WILL be interpreted in the future:
@@ -94,40 +95,40 @@ ________________________________________________________________________________
|<M-Left>| |<A-Left>| |H| +
||[count]H||
________________________________________________________________________________
Go back in the browser history. Count is supported: [m]3H[m] goes back 3 steps.
Go back in the browser history. If [count] is specified go back [count] pages.
________________________________________________________________________________
|<M-Right>| |<A-Right>| |L| +
||[count]L||
________________________________________________________________________________
Go forward in the browser history. Count is supported: [m]3L[m] goes forward 3 steps.
Go forward in the browser history. If [count] is specified go forward [count]
pages.
________________________________________________________________________________
|:ba| |:back|
||:[count]ba[ck][!] [url]|| +
||:[count]ba[ck][!] [a][url][a]|| +
________________________________________________________________________________
Go back in the browser history. Count is supported, [c]:3back[c] goes back 3
pages in the browser history. +
Go back in the browser history. If [count] is specified go back [count] pages. +
The special version [c]:back![c] goes to the beginning of the browser history.
________________________________________________________________________________
|:fw| |:fo| |:forward|
||:[count]fo[rward][!] [url]|| +
||:[count]fo[rward][!] [a][url][a]|| +
________________________________________________________________________________
Go forward in the browser history. Count is supported, [c]:3forward[c] goes
forward 3 pages in the browser history. The special version [c]:forward![c]
goes to the end of the browser history.
Go forward in the browser history. If [count] is specified go forward [count]
pages. +
The special version [c]:forward![c] goes to the end of the browser history.
________________________________________________________________________________
|:hs| |:hist| |:history|
||:hist[ory][!] [filter]|| +
||:hist[ory][!] [a][filter][a]|| +
________________________________________________________________________________
Show recently visited URLs. Open the message window at the bottom of the
screen with all history items which match [filter] either in the title or URL.
Show recently visited URLs. Open the message window at the bottom of the screen
with all history items which match [a][filter][a] either in the title or URL.
The special version [c]:history![c] works the same as [c]:history[c] except
it opens all the found items in new tabs.
@@ -183,7 +184,7 @@ ________________________________________________________________________________
|:qma| |:qmark|
||:qma[rk] {a-zA-Z0-9} [url]|| +
||:qma[rk] {a-zA-Z0-9} [a][url][a]|| +
________________________________________________________________________________
Mark a URL with a letter for quick access. You can also mark whole groups like this: +
[c]:qmark f \http://forum1.com, \http://forum2.com, imdb some artist[c]
@@ -191,9 +192,10 @@ ________________________________________________________________________________
|:qmarks|
||:qmarks [arg]||
||:qmarks [a][arg][a]||
________________________________________________________________________________
Show all QuickMarks. If [arg] is specified then limit the list to those QuickMarks mentioned.
Show all QuickMarks. If [a][arg][a] is specified then limit the list to those
QuickMarks mentioned.
________________________________________________________________________________
section:Local{nbsp}marks[localmarks]
@@ -237,9 +239,10 @@ ________________________________________________________________________________
|:marks| +
||:marks [arg]||
||:marks [a][arg][a]||
________________________________________________________________________________
Show all location marks of current web page. If [arg] is specified then limit the list to those marks mentioned.
Show all location marks of current web page. If [a][arg][a] is specified then
limit the list to those marks mentioned.
________________________________________________________________________________
// vim: set syntax=asciidoc:

View File

@@ -26,7 +26,7 @@ Show all options. Show all options.
____
|E518| |E519|
||:se[t] {option}*||
||:se[t] {option}?||
____
Show value of {option}.
____
@@ -185,7 +185,7 @@ preferences.
________________________________________________________________________________
|:set-!|
|:set!| |:set-!|
||:se[t]! {preference}={value}|| +
________________________________________________________________________________
Change any Firefox {preference} (those in the about:config window). You can also
@@ -209,8 +209,9 @@ Define when tabs are automatically activated. Available items:
____
|$CDPATH|
|\'cd'| |\'cdpath'|
||'cdpath' 'cd'|| string (default: black)
||'cdpath' 'cd'|| string (default: equivalent to _$CDPATH_ or ",,")
____
List of directories searched when executing the :cd command. This is only used
for relative paths, if an absolute path is specified then the option is
@@ -239,9 +240,9 @@ ____
|\'ds'| |\'defsearch'|
||'defsearch' 'ds'|| string (default: "google")
____
Sets the default search engine.
The default search engine name is used in the [c]:[tab]open [arg][c] command if
[[arg]] neither looks like a URL or like a specified search engine/keyword.
Sets the default search engine. The default search engine name is used in the
[c]:[tab]open [arg][c] command if [a][arg][a] neither looks like a URL or like
a specified search engine/keyword.
This means, it you set 'defsearch' to "youtube", then [c]:open arnold
schwarzenegger[c] will be exactly the same as [c]:open youtube arnold
@@ -249,11 +250,11 @@ schwarzenegger[c]. Therefore, you need to add a keyword or search engine
"youtube" first.
If 'defsearch' is empty, then Firefox will always attempt to open the
raw [[arg]].
raw [a][arg][a].
____
|\'editor'| |i_<Ctrl-i>|
|\'editor'| |i_<C-i>|
||'editor'|| string (default: "gvim -f")
____
Set the external text editor.
@@ -469,7 +470,10 @@ ____
|\'nolpl'| |\'lpl'| |\'noloadplugins'| |\'loadplugins'|
||'loadplugins' 'lpl'|| boolean (default on)
____
Load plugin scripts when starting up.
Load plugin scripts when starting up. When on, yet unloaded plugins are
automatically loaded after the vimperatorrc file has been sourced. To
load plugins earlier, use the [c]:loadplugins[c] command within the
vimperatorrc.
____
@@ -594,7 +598,7 @@ ____
|\'rtp'| |\'runtimepath'|
||'runtimepath' 'rtp'|| stringlist
____
(default: \'$VIMPERATOR_RUNTIME' or Unix, Mac: "\~/.vimperator", Windows: "\~/vimperator")
(default: _$VIMPERATOR_RUNTIME_ or Unix, Mac: "\~/.vimperator", Windows: "\~/vimperator")
List of directories searched for runtime files: +
macros/ +
@@ -603,6 +607,9 @@ plugin/ +
Example: [c]:set runtimepath=\~/myvimperator,\~/.vimperator[c] +
This will search for plugins in both "\~/myvimperator/plugin" and
"\~/.vimperator/plugin"
On startup, if the environment variable _$VIMPERATOR_RUNTIME_ does not
exist, Vimperator will set it to match this value.
____
@@ -618,18 +625,18 @@ ____
|\'shell'| |\'sh'|
||'shell' 'sh'|| string (default: "-c", Win32: "/c")
||'shell' 'sh'|| string (default: _$SHELL_ or "sh", Win32: "cmd.exe")
____
Shell to use for executing :! and :run commands.
____
|\'shellcmdflag'| |\'shcf'|
||'shellcmdflag' 'shcf'|| string (default: $SHELL or "sh", Win32: "cmd.exe")
||'shellcmdflag' 'shcf'|| string (default: "-c", Win32: "/c")
____
Flag passed to shell when executing :! and :run commands.
E.g. bash -c gvim
E.g. "bash -c gvim"
____

View File

@@ -4,8 +4,8 @@ HEADER
Vimperator provides a Vim-like interface to Firefox's standard text search
functionality. There is no support for using regular expressions in search
commands as Firefox does not provide native regexp support. It is unlikely
that this will ever be available.
commands as Firefox does not provide native regexp support. It is unlikely that
this will ever be available.
|/| +
||/\\{pattern\\}[/]<CR>|| +

View File

@@ -16,10 +16,10 @@ ____________________________________________________________________________
|:macros|
||:mac[ros] [args]|| +
||:mac[ros] [a][pat][a]|| +
________________________________________________________________________________
List recorded macros matching the optional regular expression [args]. If no
regexp is given, list all macros.
List recorded macros matching the optional regular expression [a][pat][a]. If
no regexp is given, list all macros.
________________________________________________________________________________
@@ -95,9 +95,11 @@ ________________________________________________________________________________
|:lpl| |:loadplugins|
||:loadplugins|| +
________________________________________________________________________________
Load all unloaded plugins immediately. This is useful both for sourcing new
plugins without restarting vimperator, and making sure that a plugin is loaded
so that you can use its commands from your vimperatorrc.
Load all unloaded plugins immediately. Because plugins are automatically
loaded after vimperatorrc is sourced, this command must be placed early
in the vimperatorrc file if vimperatorrc also includes commands that are
implemented by plugins. Additionally, this command allows for sourcing
new plugins without restarting vimperator.
________________________________________________________________________________

View File

@@ -5,40 +5,46 @@ be documented here.
section:Initialization[initialization,startup]
At startup Vimperator can perform user initialization commands. When one of
the following is successfully located, it is executed, and no further
locations are tried.
At startup, Vimperator completes the following tasks in order.
|$VIMPERATOR_INIT|
1. _$VIMPERATOR_INIT_ - May contain a single ex command, usually
[c]:source {file}[c].
2. [a]\~/_vimperatorrc[a] - Windows only. If this file exists, its contents
are executed.
3. [a]\~/.vimperatorrc[a] - If this file exists, its contents are executed.
. Vimperator can perform user initialization commands. When
one of the following is successfully located, it is executed, and no
further locations are tried.
If 'exrc' is set then any RC file in the current directory is also sourced.
.. |$VIMPERATOR_INIT| _$VIMPERATOR_INIT_ -- May contain a single ex
command (e.g.,
"[c]:source {file}[c]").
.. [a]\~/_vimperatorrc[a] -- Windows only. If this file exists, its
contents are executed.
.. [a]\~/.vimperatorrc[a] -- If this file exists, its contents are
executed.
The plugin directory can be in any of the directories in 'runtimepath'.
. If 'exrc' is set, then any RC file in the current directory is also sourced.
All directories in 'runtimepath' are searched for plugins and they are are all
loaded.
. All directories in 'runtimepath' are searched for a "plugin"
subdirectory and all yet unloaded plugins are loaded. For each
plugin directory, all *.\{js,vimp} files (including those in further
subdirectories) are sourced alphabetically. No plugins will be sourced
if 'noloadplugins' is set. Any particular plugin will not be loaded
if it has already been loaded (e.g., by an earlier [c]:loadplugins[c]
command).
Plugins will not be sourced if 'noloadplugins' is set.
The user's ~ (i.e., "home") directory is determined as follows:
The user's \'$HOME'(~) directory is determined as follows:
* Unix and Mac - _$HOME_ is used.
* Windows - if _%HOME%_ is set then this is used, otherwise _%USERPROFILE%_ or finally
_%HOMEDRIVE%%HOMEPATH%_.
* On Unix and Mac, the environment variable _$HOME_ is used.
* On Windows, Vimperator checks for the existence of _%HOME%_, then
_%USERPROFILE%_, and then _%HOMEDRIVE%%HOMEPATH%_. It uses the first one
it finds.
section:Saving{nbsp}settings[save-settings]
|:mkv| |:mkvimperatorrc|
||:mkv[imperatorrc][!] [file]|| +
||:mkv[imperatorrc][!] [a][file][a]|| +
________________________________________________________________________________
Write current key mappings and changed options to [file]. If no [file] is
specified then _~/.vimperatorrc_ is written unless this file already exists. The
special version [c]:mkvimperatorrc![c] will overwrite [file] if it exists.
Write current key mappings and changed options to [a][file][a]. If no
[a][file][a] is specified then _~/.vimperatorrc_ is written unless this file
already exists. The special version [c]:mkvimperatorrc![c] will overwrite
[a][file][a] if it exists.
Warning: this differs from Vim's behavior which defaults to writing the file
in the current directory.

View File

@@ -92,14 +92,14 @@ ________________________________________________________________________________
|:sty| |:style| +
||:sty[le][!] [-name={name}] [-append] {filter} [{css}]|| +
________________________________________________________________________________
Add CSS styles to the browser or to web pages. {filter} is a
comma separated list of URLs to match. URLs ending with [c]*[c]
are matched as prefixes, URLs not containing any [c]:[c] or
[c]/[c] characters are matched as domains. If {name} (short
option: [c]-n[c]) is provided, any existing style with the same
name is overridden, and the style may later be deleted using
{name}. If -append (short option: -a) is provided along with -name,
{css} and {filter} are appended to its current value.
Add CSS styles to the browser or to web pages. {filter} is a comma
separated list of URLs to match. URLs ending with [c]*[c] are matched as
prefixes, URLs not containing any [c]:[c] or [c]/[c] characters are
matched as domains. If {name} (short option: [c]-n[c]) is provided, any
existing style with the same name is overridden, and the style may later
be deleted using {name}. If -append (short option: [c]-a[c]) is provided
along with [c]-name[c], {css} and {filter} are appended to its current
value.
If {css} isn't provided, matching styles are listed.
________________________________________________________________________________
@@ -112,8 +112,10 @@ the filter are disabled. For instance, a filter [c]mozilla.org[c], given a
style for [c]www.google.com,mozilla.org[c], will result in a style for
[c]www.google.com[c]. The available options are:
- -name: The name provided to [c]:style[c] (short option: -n)
- -index: For unnamed styles, the index listed by [c]:style[c] (short option: -i)
* [c]-name[c]: The name provided to [c]:style[c] (short option:
[c]-n[c])
* [c]-index[c]: For unnamed styles, the index listed by [c]:style[c]
(short option: [c]-i[c])
________________________________________________________________________________
// vim: set syntax=asciidoc:

View File

@@ -3,17 +3,17 @@ HEADER
|tabs| +
Tabs are used to be able to view many web pages at the same time. Each tab
contains exactly one buffer - multiple buffers per tab are not supported. As a
contains exactly one buffer -- multiple buffers per tab are not supported. As a
result many buffer and tab commands are interchangeable.
section:Listing{nbsp}tabs[listing-tabs]
|B| |:tabs| |:ls| |:files| |:buffers|
||:buffers [filter]|| +
||:buffers [a][filter][a]|| +
||B||
________________________________________________________________________________
Show a list of buffers (=tabs) matching [filter]. Without [filter] list all
tabs.
Show a list of buffers (=tabs) matching [a][filter][a]. Without [a][filter][a]
list all tabs.
________________________________________________________________________________
section:Opening{nbsp}tabs[opening-tabs]
@@ -63,7 +63,7 @@ ________________________________________________________________________________
||[count]gt||
________________________________________________________________________________
Go to the next tab. Cycles to the first tab, when the last is selected. +
Count is supported: [m]3gt[m] goes to the third tab.
If [count] is specified go to the [count]th tab.
________________________________________________________________________________
@@ -71,7 +71,7 @@ ________________________________________________________________________________
||[count]gT||
________________________________________________________________________________
Go {count} pages back. Wraps around from the first tab to the last tab. +
Count is supported: [m]3gT[m] goes three tabs back.
If [count] is specified go back [count] tabs.
________________________________________________________________________________
@@ -174,16 +174,15 @@ ________________________________________________________________________________
section:Closing{nbsp}tabs[closing-tabs]
|d| |:tabc| |:tabclose| |:bun| |:bunload| |:bw| |:bwipeout| |:bd| |:bdelete|
||:[count]bd[elete][!] [arg]|| +
||:[count]bd[elete][!] [a][arg][a]|| +
||[count]d||
________________________________________________________________________________
Delete current buffer (=tab). Count is supported, [c]:2bd[c] removes two tabs
and the one to the right is selected. Afterwards, the tab to the right of the
deleted one is selected.
Delete current buffer (=tab). If [count] is specified then [count] tabs are
removed. Afterwards, the tab to the right of the deleted tab(s) is selected.
When used with [arg], remove all tabs which contain [arg] in the hostname.
[!] forces this command to also search for [arg] in the full URL and also
the title of the tab. Use with care.
When used with [a][arg][a], remove all tabs which contain [a][arg][a] in the
hostname. [!] forces this command to also search for [a][arg][a] in the full
URL and also the title of the tab. Use with care.
________________________________________________________________________________
@@ -195,11 +194,11 @@ ________________________________________________________________________________
|u| |:u| |:undo|
||:[count]u[ndo] [url]|| +
||:[count]u[ndo] [a][url][a]|| +
||[count]u||
________________________________________________________________________________
Undo closing of a tab. If a count is given, don't close the last but the
[count]th last tab. With [url] restores the tab matching the URL.
[count]th last tab. With [a][url][a] restores the tab matching the URL.
________________________________________________________________________________

View File

@@ -11,9 +11,9 @@ section:Quick-start{nbsp}tutorial[tutorial]
If you've started using Vimperator from scratch (i.e., without any
customization), you should be looking at this help page in a relatively
bare-looking window. The menubar, navigation bar, and bookmark bars are
hidden. In case you missed the notice in the help:Introduction[intro.html],
you can regain these by issuing the command
bare-looking window. The menubar, navigation bar, and bookmark bars are hidden.
In case you missed the notice in the help:Introduction[intro.html], you can
regain these by issuing the command
:set go+=mTb<CR>
@@ -32,8 +32,8 @@ different meanings depending on which mode the browser is in. Vimperator has
several modes, but the 2 most important are ``normal'' mode and
``command-line'' mode.
When Vimperator starts, it is in normal mode by default. This is probably
where you will spend the majority of your time.
When Vimperator starts, it is in normal mode by default. This is probably where
you will spend the majority of your time.
The other core mode of Vimperator, command-line mode, can be entered from
normal mode by typing a \':' (colon). You will frequently see Vimperator
@@ -45,11 +45,11 @@ Vimperator.
section:Getting{nbsp}help[getting-help]
Vim is a great editor but it's not much of a web browser. So even seasoned
Vim users will probably have to look at Vimperator documentation sooner or
later. Most of the documentation for Vimperator's features are easily found
using the [c]:help[c] command. For example, you can find help on the
[c]:help[c] command by typing
Vim is a great editor but it's not much of a web browser. So even seasoned Vim
users will probably have to look at Vimperator documentation sooner or later.
Most of the documentation for Vimperator's features are easily found using the
[c]:help[c] command. For example, you can find help on the [c]:help[c] command
by typing
:help :help<CR>
@@ -114,10 +114,10 @@ Vimmers.
* [m]d[m] --
close the active tab (delete the buffer)
To open a web page in a new tab, use the [c]:tabopen {url}[c]. To open a URL
in the current tab, use [c]:open[c]. The normal mode
mappings [m]t[m] and [m]o[m], respectively, map to these commands, so the
following pairs sequences are equivalent:
To open a web page in a new tab, use the [c]:tabopen {url}[c]. To open a URL in
the current tab, use [c]:open[c]. The normal mode mappings [m]t[m] and [m]o[m],
respectively, map to these commands, so the following pairs sequences are
equivalent:
:open my.webmail.com<CR>
omy.webmail.com<CR>
@@ -131,14 +131,14 @@ So now you can navigate around in Vimperator. But wait... how do you *open* a
page or tab linked in a web page? How do you ``click'' on all those links
without your tailed friend?
The answer is ``hints''. Activating hints displays a number next to every
link Vimperator can find. To follow the link, simply type the number
corresponding to the hint, a white number inside a red square by default.
The answer is ``hints''. Activating hints displays a number next to every link
Vimperator can find. To follow the link, simply type the number corresponding
to the hint, a white number inside a red square by default.
For text links, there's an additional shortcut; you can type some text
contained in the link and Vimperator will search all the links it can find and
only hint the matching links, further narrowing down the list. If the text
you type uniquely identifies any given link, Vimperator will follow that link
only hint the matching links, further narrowing down the list. If the text you
type uniquely identifies any given link, Vimperator will follow that link
immediately without any further user input.
Whichever way you choose to indicate your target link, once Vimperator has
@@ -171,15 +171,14 @@ following:
section:Saving{nbsp}for{nbsp}posterity{nbsp}-{nbsp}vimperatorrc[vimperatorrc]
Once you get Vimperator set up with your desired options, maps, and
commands, you'll probably want them to be available the next time you
open Vimperator. Continuing the Vim theme, this is done with a
vimperatorrc file.
Once you get Vimperator set up with your desired options, maps, and commands,
you'll probably want them to be available the next time you open Vimperator.
Continuing the Vim theme, this is done with a vimperatorrc file.
To save your current settings and allow them to be loaded automatically
next time you start Vimperator, issue the [c]:mkv[c] command.
This will create the file *$HOME/.vimperatorrc* containing your settings.
This will create the file *_$HOME_/.vimperatorrc* containing your settings.
It is a simple text file, just like a vimrc file and can be easily
edited to suit your preferences.
@@ -196,9 +195,9 @@ Vimperator supports all of Vim's classic methods of exiting.
section:Where{nbsp}did{nbsp}Firefox{nbsp}go?[whither-firefox]
You might feel pretty disoriented now. Don't worry. This is still Firefox
underneath. Here are some ways Vimperator allows Firefox to shine through.
See the [c]:help[c] for these commands and mappings for more information on
how to make the best use of them.
underneath. Here are some ways Vimperator allows Firefox to shine through. See
the [c]:help[c] for these commands and mappings for more information on how to
make the best use of them.
* [c]:dialog[c] --
To access some of Firefox's many dialog windows, you can use the
@@ -239,16 +238,16 @@ as above, with [c]:set go+=m[c], and select *Add-ons* from the *Tools* menu.
section:I'm{nbsp}interested...but{nbsp}lost![support]
Vimperator has an energetic and growing user base. If you've run into a
problem that you can't seem to solve with Vimperator, or if you think you might
have found a bug, please let us know! There is support available on the
Vimperator has an energetic and growing user base. If you've run into a problem
that you can't seem to solve with Vimperator, or if you think you might have
found a bug, please let us know! There is support available on the
http://vimperator.cutup.org/index.php?title=Main_Page[wiki], or in the
#vimperator IRC channel on http://freenode.net/[freenode].
If you have any feature requests or (even better) offers to help, we'd love to
hear from you as well. Developers work on Vimperator whenever possible, but
we are neither infinite nor omnipotent; please bear with us. If you can't
wait for us to get around to it, rest assured patches are welcome! See
the help:Developer[developer.html] page for more information.
hear from you as well. Developers work on Vimperator whenever possible, but we
are neither infinite nor omnipotent; please bear with us. If you can't wait for
us to get around to it, rest assured patches are welcome! See the
help:Developer[developer.html] page for more information.
// vim: set syntax=asciidoc:

View File

@@ -18,6 +18,7 @@ var skipTests = [":bmarks", "gg"];
// Put definitions here which might change due to internal liberator refactoring
/////////////////////////////////////////////////////////////////////////////////////////
var doc; // document where we output status messages
var multilineOutput = document.getElementById("liberator-multiline-output")
var singlelineOutput = document.getElementById("liberator-commandline-command")
@@ -28,10 +29,10 @@ var singlelineOutput = document.getElementById("liberator-commandline-command")
// previous command
/////////////////////////////////////////////////////////////////////////////////////////
// A series of ex commands or mappings, each with a
// A series of Ex commands or mappings, each with a
// function checking whether the command succeeded
// If the string starts with a ":" it is executed as an ex command, otherwise as a mapping
// You can also mix commands mappings
// If the string starts with a ":" it is executed as an Ex command, otherwise as a mapping
// You can also mix commands and mappings
let tests = [
{ cmds: [":!dir"],
verify: function () getMultilineOutput().length > 10 },
@@ -45,6 +46,8 @@ let tests = [
verify: function () getSinglelineOutput() == "test" },
{ cmds: [":qmark V http://test.vimperator.org", ":qmarks"],
verify: function () getMultilineOutput().indexOf("test.vimperator.org") >= 0 },
{ cmds: [":javascript liberator.echo('test', commandline.FORCE_MULTILINE)"],
verify: function () getMultilineOutput() == "test" },
// { cmds: [":echomsg \"testmsg\""],
// verify: function () getOutput() == "testmsg" },
// { cmds: [":echoerr \"testerr\""],
@@ -56,7 +59,7 @@ let tests = [
// testing tab behavior
];
// these functions highly depend on the liberator API, so use ex command tests whenever possible
// these functions highly depend on the liberator API, so use Ex command tests whenever possible
let functions = [
function () { return bookmarks.get("").length > 0 }, // will fail for people without bookmarks :( Might want to add one before
function () { return history.get("").length > 0 }
@@ -64,7 +67,7 @@ let functions = [
/////////////////////////////////////////////////////////////////////////////////////////
// functions below should be as generic as possible, and not require being rewritten
// even after doing major vimperator refactoring
// even after doing major Vimperator refactoring
/////////////////////////////////////////////////////////////////////////////////////////
function resetEnvironment()
@@ -89,15 +92,14 @@ function getBufferPosition()
y: win.scrollMaxY ? win.pageYOffset / win.scrollMaxY : 0 }
};
// TODO: need to find a way to wait for page load
function getLocation() window.content.document.location.href;
var doc;
function echoLine(str, group)
{
if (!doc)
return;
doc.body.appendChild(util.xmlToDom(
<div highlight={group} style="border: 1px solid gray; white-space: pre; height: 1.5em; line-height: 1.5em;">{str}</div>,
doc));
@@ -106,6 +108,7 @@ function echoMulti(str, group)
{
if (!doc)
return;
doc.body.appendChild(util.xmlToDom(<div class="ex-command-output"
style="white-space: nowrap; border: 1px solid black; min-height: 1.5em;"
highlight={group}>{template.maybeXML(str)}</div>,
@@ -120,13 +123,13 @@ commands.addUserCommand(["regr[essions]"],
// TODO: count (better even range) support to just run test 34 of 102
// TODO: bang support to either: a) run commands like deleting bookmarks which
// should only be done in a clean profile or b) run functions and not
// just ex command tests; Yet to be decided
// just Ex command tests; Yet to be decided
let updateOutputHeight = null;
function init()
{
liberator.registerObserver("echoLine", echoLine);
liberator.registerObserver("echoMulti", echoMulti);
liberator.registerObserver("echoMultiline", echoMulti);
liberator.open("chrome://liberator/content/buffer.xhtml", liberator.NEW_TAB);
events.waitForPageLoad();
doc = content.document;
@@ -144,7 +147,7 @@ commands.addUserCommand(["regr[essions]"],
function cleanup()
{
liberator.unregisterObserver("echoLine", echoLine);
liberator.unregisterObserver("echoMulti", echoMulti);
liberator.unregisterObserver("echoMultiline", echoMulti);
commandline.updateOutputHeight = updateOutputHeight;
}
@@ -178,7 +181,7 @@ commands.addUserCommand(["regr[essions]"],
}
};
liberator.echomsg("Running test " + currentTest + " of " + totalTests + ": " + testDescription, 0);
commandline.echo("Running test " + currentTest + " of " + totalTests + ": " + testDescription, "Filter", commandline.APPEND_TO_MESSAGES);
resetEnvironment();
if ("init" in test)
test.init();
@@ -203,7 +206,7 @@ commands.addUserCommand(["regr[essions]"],
if (args.count >= 1 && currentTest != args.count)
continue;
liberator.echomsg("Running test " + currentTest + " of " + totalTests + ": " + util.clip(func.toString().replace(/[\s\n]+/gm, " "), 80));
commandline.echo("Running test " + currentTest + " of " + totalTests + ": " + util.clip(func.toString().replace(/[\s\n]+/gm, " "), 80), "Filter", commandline.APPEND_TO_MESSAGES);
resetEnvironment();
if (!func())

View File

@@ -1,7 +1,7 @@
" Vim syntax file
" Language: VIMperator configuration file
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Last Change: 2008 Dec 07
" Last Change: 2008 Dec 31
if exists("b:current_syntax")
finish
@@ -23,13 +23,13 @@ syn keyword vimperatorCommand ab[breviate] ab[clear] addo[ns] b[uffer] ba[ck] bd
\ cm[ap] cmapc[lear] cno[remap] comc[lear] com[mand] cu[nmap] do[autocmd] doautoa[ll] delbm[arks] delc[ommand] delmac[ros]
\ delm[arks] delqm[arks] dels[tyle] dia[log] dl downl[oads] e[dit] ec[ho] echoe[rr] echom[sg] em[enu] exe[cute] exu[sage]
\ fini[sh] files fo[rward] fw h[elp] ha[rdcopy] hi[ghlight] hist[ory] hs ia[bbrev] iabc[lear] im[ap] imapc[lear] ino[remap]
\ iuna[bbrev] iu[nmap] javas[cript] ju[mps] js let ls macros ma[rk] map mapc[lear] marks mes[sages] mkv[imperatorrc] no[remap]
\ noh[lsearch] norm[al] o[pen] optionu[sage] pa[geinfo] pagest[yle] pc[lose] pl[ay] pref[erences] prefs pw[d] q[uit] qa[ll]
\ qma[rk] qmarks quita[ll] re[draw] re[load] reloada[ll] res[tart] run runt[ime] sty[le] sav[eas] sb[ar] sb[open] sbcl[ose]
\ scrip[tnames] se[t] setg[lobal] setl[ocal] sideb[ar] so[urce] st[op] tN[ext] t[open] tab tabde[tach] tabd[uplicate]
\ tabN[ext] tabc[lose] tabe[dit] tabfir[st] tabl[ast] tabm[ove] tabn[ext] tabnew tabo[nly] tabopen tabp[revious] tabr[ewind]
\ tabs time tn[ext] tp[revious] u[ndo] una[bbreviate] undoa[ll] unl[et] unm[ap] ve[rsion] vie[wsource] viu[sage] w[rite]
\ wc[lose] win[open] winc[lose] wine[dit] wo[pen] wqa[ll] wq xa[ll] zo[om]
\ iuna[bbrev] iu[nmap] javas[cript] ju[mps] js let loadplugins lpl ls macros ma[rk] map mapc[lear] marks mes[sages]
\ mkv[imperatorrc] no[remap] noh[lsearch] norm[al] o[pen] optionu[sage] pa[geinfo] pagest[yle] pc[lose] pl[ay] pref[erences]
\ prefs pw[d] q[uit] qa[ll] qma[rk] qmarks quita[ll] re[draw] re[load] reloada[ll] res[tart] run runt[ime] sty[le] sav[eas]
\ sb[ar] sb[open] sbcl[ose] scrip[tnames] se[t] setg[lobal] setl[ocal] sideb[ar] so[urce] st[op] tN[ext] t[open] tab
\ tabde[tach] tabd[uplicate] tabN[ext] tabc[lose] tabe[dit] tabfir[st] tabl[ast] tabm[ove] tabn[ext] tabnew tabo[nly] tabopen
\ tabp[revious] tabr[ewind] tabs time tn[ext] tp[revious] u[ndo] una[bbreviate] undoa[ll] unl[et] unm[ap] ve[rsion]
\ vie[wsource] viu[sage] w[rite] wc[lose] win[open] winc[lose] wine[dit] wo[pen] wqa[ll] wq xa[ll] zo[om]
\ contained
syn match vimperatorCommand "!" contained
@@ -43,7 +43,7 @@ syn keyword vimperatorAutoEvent BookmarkAdd DOMLoad LocationChange PageLoadPre P
syn match vimperatorAutoEventList "\(\a\+,\)*\a\+" contained contains=vimperatorAutoEvent
syn region vimperatorSet matchgroup=vimperatorCommand start="\%(^\s*:\=\)\@<=\<\%(setl\%[ocal]\|setg\%[lobal]\|set\=\)\=\>"
\ end="$" keepend oneline contains=vimperatorOption,vimperatorComment,vimperatorString
\ end="$" keepend oneline contains=vimperatorOption,vimperatorString
syn keyword vimperatorOption activate act alfc albc cdpath cd complete cpt defsearch ds editor extendedhinttags eht eventignore ei
\ followhints fh guioptions go helpfile hf hintmatching hm hs hinttags ht hinttimeout hto history hi laststatus ls lbc lfc