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

made :dialogs generic, moved more commands to vim.js

This commit is contained in:
Martin Stubenschrott
2008-02-28 23:37:35 +00:00
parent e02cc7622c
commit 8c45097170
10 changed files with 670 additions and 629 deletions

2
TODO
View File

@@ -22,6 +22,8 @@ FEATURES:
yd=yank domain name, yt=yank title, yw=yank current word, yf=yank filename, (other things to yank?)
8 all search commands should start searching from the top of the visible viewport
8 :bdelete full_url<cr> and :bdelete! filter<cr> should delete all tabs matching filter or full_url
7 adaptive learning for tab-completions
(https://bugzilla.mozilla.org/show_bug.cgi?id=395739 could help)
7 use ctrl-n/p in insert mode for word completion
7 implement LocationList window, and get rid off/change PreviewWindow to be
a real preview window being able to display html pages

View File

@@ -1318,6 +1318,26 @@ vimperator.Buffer = function () //{{{
if (!retVal)
vimperator.beep();
},
viewSelectionSource: function()
{
// copied (and tuned somebit) from browser.jar -> nsContextMenu.js
var focusedWindow = document.commandDispatcher.focusedWindow;
if (focusedWindow == window)
focusedWindow = content;
var docCharset = null;
if (focusedWindow)
docCharset = "charset=" + focusedWindow.document.characterSet;
var reference = null;
reference = focusedWindow.getSelection();
var docUrl = null;
window.openDialog("chrome://global/content/viewPartialSource.xul",
"_blank", "scrollbars,resizable,chrome,dialog=no",
docUrl, docCharset, reference, "selection");
}
};
//}}}

View File

@@ -588,7 +588,6 @@ vimperator.Commands = function () //{{{
return matches;
}
};
/////////////////////////////////////////////////////////////////////////////}}}
@@ -596,198 +595,7 @@ vimperator.Commands = function () //{{{
/////////////////////////////////////////////////////////////////////////////{{{
// move to vim.js:
commandManager.addUserCommand(new vimperator.Command(["addo[ns]"],
function () { vimperator.open("chrome://mozapps/content/extensions/extensions.xul", vimperator.NEW_TAB); },
{
shortHelp: "Show available Browser Extensions and Themes"
}
));
commandManager.addUserCommand(new vimperator.Command(["beep"],
function () { vimperator.beep(); },
{
shortHelp: "Play a system beep"
}
));
commandManager.addUserCommand(new vimperator.Command(["dia[log]"],
function (args, special)
{
function viewPartialSource()
{
// copied (and tuned somebit) from browser.jar -> nsContextMenu.js
var focusedWindow = document.commandDispatcher.focusedWindow;
if (focusedWindow == window)
focusedWindow = content;
var docCharset = null;
if (focusedWindow)
docCharset = "charset=" + focusedWindow.document.characterSet;
var reference = null;
reference = focusedWindow.getSelection();
var docUrl = null;
window.openDialog("chrome://global/content/viewPartialSource.xul",
"_blank", "scrollbars,resizable,chrome,dialog=no",
docUrl, docCharset, reference, "selection");
}
try
{
switch (args)
{
case "about": openDialog("chrome://browser/content/aboutDialog.xul", "_blank", "chrome,dialog,modal,centerscreen"); break;
case "addbookmark": PlacesCommandHook.bookmarkCurrentPage(true, PlacesUtils.bookmarksRootId); break;
case "addons": BrowserOpenAddonsMgr(); break;
case "bookmarks": openDialog("chrome://browser/content/bookmarks/bookmarksPanel.xul", "Bookmarks", "dialog,centerscreen,width=600,height=600"); break;
case "checkupdates": checkForUpdates(); break;
case "cleardata": Cc[GLUE_CID].getService(Ci.nsIBrowserGlue).sanitize(window || null); break;
case "console": toJavaScriptConsole(); break;
case "customizetoolbar": BrowserCustomizeToolbar(); break;
case "dominspector": inspectDOMDocument(content.document); break;
case "downloads": toOpenWindowByType('Download:Manager', 'chrome://mozapps/content/downloads/downloads.xul', 'chrome,dialog=no,resizable'); break;
case "history": openDialog("chrome://browser/content/history/history-panel.xul", "History", "dialog,centerscreen,width=600,height=600"); break;
case "import": BrowserImport(); break;
case "openfile": BrowserOpenFileWindow(); break;
case "pageinfo": BrowserPageInfo(); break;
case "pagesource": BrowserViewSourceOfDocument(content.document); break;
case "places": PlacesCommandHook.showPlacesOrganizer(ORGANIZER_ROOT_BOOKMARKS); break;
case "preferences": openPreferences(); break;
case "printpreview": PrintUtils.printPreview(onEnterPrintPreview, onExitPrintPreview); break;
case "print": PrintUtils.print(); break;
case "printsetup": PrintUtils.showPageSetup(); break;
case "saveframe": saveFrameDocument(); break;
case "savepage": saveDocument(window.content.document); break;
case "searchengines": openDialog("chrome://browser/content/search/engineManager.xul", "_blank", "chrome,dialog,modal,centerscreen"); break;
case "selectionsource": viewPartialSource(); break;
case "": vimperator.echoerr("E474: Invalid argument"); break;
default: vimperator.echoerr("Dialog '" + args + "' not available");
}
}
catch (e)
{
vimperator.echoerr("Error opening '" + args + "': " + e);
}
},
{
shortHelp: "Open a Firefox dialog",
completer: function (filter) { return vimperator.completion.dialog(filter); }
}
));
commandManager.addUserCommand(new vimperator.Command(["exe[cute]"],
function (args)
{
vimperator.execute(args);
},
{
shortHelp: "Execute the string that results from the evaluation of {expr1} as an Ex command."
}
));
commandManager.addUserCommand(new vimperator.Command(["exu[sage]"],
function (args, special, count, modifiers)
{
var usage = "<table>";
for (let command in vimperator.commands)
{
usage += "<tr><td style='color: magenta; padding-right: 20px'> :" +
vimperator.util.escapeHTML(command.name) + "</td><td>" +
vimperator.util.escapeHTML(command.shortHelp) + "</td></tr>";
}
usage += "</table>";
vimperator.echo(usage, vimperator.commandline.FORCE_MULTILINE);
},
{
shortHelp: "Show help for Ex commands"
}
));
commandManager.addUserCommand(new vimperator.Command(["h[elp]"],
function (args, special, count, modifiers)
{
function jumpToTag(file, tag)
{
vimperator.open("chrome://" + vimperator.config.name.toLowerCase() + "/locale/" + file);
setTimeout(function() {
var elem = vimperator.buffer.getElement('@class="tag" and text()="' + tag + '"');
if (elem)
window.content.scrollTo(0, elem.getBoundingClientRect().top - 10); // 10px context
else
dump('no element: ' + '@class="tag" and text()="' + tag + '"\n' );
}, 200);
}
if (!args)
{
vimperator.open("chrome://" + vimperator.config.name.toLowerCase() + "/locale/intro.html");
return;
}
var [, items] = vimperator.completion.help(args);
var partialMatch = -1;
for (var i = 0; i < items.length; i++)
{
if (items[i][0] == args)
{
jumpToTag(items[i][1], items[i][0]);
return;
}
else if (partialMatch == -1 && items[i][0].indexOf(args) > -1)
{
partialMatch = i;
}
}
if (partialMatch > -1)
jumpToTag(items[partialMatch][1], items[partialMatch][0]);
else
vimperator.echoerr("E149: Sorry, no help for " + args);
},
{
shortHelp: "Display help",
completer: function (filter) { return vimperator.completion.help(filter); }
}
));
commandManager.addUserCommand(new vimperator.Command(["javas[cript]", "js"],
function (args, special)
{
if (special) // open javascript console
vimperator.open("chrome://global/content/console.xul", vimperator.NEW_TAB);
else
{
// check for a heredoc
var matches = args.match(/(.*)<<\s*([^\s]+)$/);
if (matches && matches[2])
{
vimperator.commandline.inputMultiline(new RegExp("^" + matches[2] + "$", "m"),
function (code)
{
try
{
eval(matches[1] + "\n" + code);
}
catch (e)
{
vimperator.echoerr(e.name + ": " + e.message);
}
});
}
else // single line javascript code
{
try
{
eval("with(vimperator){" + args + "}");
}
catch (e)
{
vimperator.echoerr(e.name + ": " + e.message);
}
}
}
},
{
shortHelp: "Run any JavaScript command through eval()",
completer: function (filter) { return vimperator.completion.javascript(filter); }
}
));
commandManager.addUserCommand(new vimperator.Command(["let"],
function (args)
{
@@ -1041,133 +849,6 @@ vimperator.Commands = function () //{{{
));
// move to io.js:
commandManager.addUserCommand(new vimperator.Command(["cd", "chd[ir]"],
function (args)
{
if (!args)
args = "~";
if (vimperator.io.setCurrentDirectory(args))
vimperator.echo(vimperator.io.getCurrentDirectory());
},
{
shortHelp: "Change the current directory",
completer: function (filter) { return vimperator.completion.file(filter, true); }
}
));
commandManager.addUserCommand(new vimperator.Command(["pw[d]"],
function (args)
{
if (args)
vimperator.echoerr("E488: Trailing characters");
else
vimperator.echo(vimperator.io.getCurrentDirectory());
},
{
shortHelp: "Print the current directory name"
}
));
commandManager.addUserCommand(new vimperator.Command(["mkv[imperatorrc]"],
function (args, special)
{
// TODO: "E172: Only one file name allowed"
var filename;
if (args)
filename = args;
else
filename = (navigator.platform == "Win32") ? "~/_vimperatorrc" : "~/.vimperatorrc";
var file = vimperator.io.getFile(filename);
if (file.exists() && !special)
{
vimperator.echoerr("E189: \".vimperatorrc\" exists (add ! to override)");
return;
}
var line = "\" " + vimperator.version + "\n";
line += "\" Mappings\n";
var mode = [[[vimperator.modes.NORMAL], ""], [[vimperator.modes.COMMAND_LINE], "c"],
[[vimperator.modes.INSERT, vimperator.modes.TEXTAREA], "i"]];
for (var y = 0; y < mode.length; y++)
{
// NOTE: names.length is always 1 on user maps. If that changes, also fix getUserIterator and v.m.list
for (var map in vimperator.mappings.getUserIterator(mode[y][0]))
line += mode[y][1] + (map.noremap ? "nore" : "") + "map " + map.names[0] + " " + map.rhs + "\n";
}
line += "\n\" Options\n";
for (var option in vimperator.options)
{
// TODO: options should be queried for this info
// TODO: string/list options might need escaping in future
if (!/fullscreen|usermode/.test(option.name) && option.value != option.defaultValue)
{
if (option.type == "boolean")
line += "set " + (option.value ? option.name : "no" + option.name) + "\n";
else
line += "set " + option.name + "=" + option.value + "\n";
}
}
// :mkvimrc doesn't save autocommands, so we don't either - remove this code at some point
// line += "\n\" Auto-Commands\n";
// for (var item in vimperator.autocommands)
// line += "autocmd " + item + "\n";
line += "\n\" Abbreviations\n";
for (var abbrCmd in vimperator.editor.abbreviations)
line += abbrCmd;
// if (vimperator.events.getMapLeader() != "\\")
// line += "\nlet mapleader = \"" + vimperator.events.getMapLeader() + "\"\n";
// source a user .vimperatorrc file
line += "\nsource! " + filename + ".local\n";
line += "\n\" vim: set ft=vimperator:";
vimperator.io.writeFile(file, line);
},
{
shortHelp: "Write current key mappings and changed options to [file]"
}
));
commandManager.addUserCommand(new vimperator.Command(["so[urce]"],
function (args, special)
{
// FIXME: implement proper filename quoting
//if (/[^\\]\s/.test(args))
//{
// vimperator.echoerr("E172: Only one file name allowed");
// return;
//}
vimperator.io.source(args, special);
},
{
shortHelp: "Read Ex commands from {file}",
completer: function (filter) { return vimperator.completion.file(filter, true); }
}
));
commandManager.addUserCommand(new vimperator.Command(["!", "run"],
function (args, special)
{
// :!! needs to be treated specially as the command parser sets the special flag but removes the ! from args
if (special)
args = "!" + (args || "");
// TODO: better escaping of ! to also substitute \\! correctly
args = args.replace(/(^|[^\\])!/g, "$1" + lastRunCommand);
lastRunCommand = args;
var output = vimperator.io.system(args);
if (output)
vimperator.echo(vimperator.util.escapeHTML(output));
},
{
shortHelp: "Run a command"
}
));
// TODO: move where? (commands.js would be fine, but timing issue)
commandManager.addUserCommand(new vimperator.Command(["com[mand]"],
@@ -1615,293 +1296,12 @@ vimperator.Commands = function () //{{{
{ shortHelp: "Close preview window on bottom of screen" }
));
// move where?
commandManager.addUserCommand(new vimperator.Command(["pref[erences]", "prefs"],
function (args, special, count, modifiers)
{
if (!args)
{
// TODO: copy these snippets to more function which should work with :tab xxx
if (modifiers && modifiers.inTab)
{
vimperator.open(special ? "about:config" :
"chrome://browser/content/preferences/preferences.xul", vimperator.NEW_TAB);
}
else
{
if (special) // open firefox settings gui dialog
vimperator.open("about:config", vimperator.CURRENT_TAB);
else
openPreferences();
}
}
else
{
vimperator.echoerr("E488: Trailing characters");
}
},
{
shortHelp: "Show Browser Preferences"
}
));
// move to tabs.js
commandManager.addUserCommand(new vimperator.Command(["reloada[ll]"],
function (args, special) { vimperator.tabs.reloadAll(special); },
{ shortHelp: "Reload all pages" }
));
// move where?
commandManager.addUserCommand(new vimperator.Command(["se[t]"],
// TODO: support setting multiple options at once
function (args, special, count, modifiers)
{
if (special)
{
var onlyNonDefault = false;
if (!args)
{
args = "all";
onlyNonDefault = true;
}
// 1 2 3 4 5
var matches = args.match(/^\s*?([a-zA-Z0-9\.\-_{}]+)([?&!])?\s*(([+-^]?)=(.*))?\s*$/);
var name = matches[1];
var reset = false;
var invertBoolean = false;
if (matches[2] == "&")
reset = true;
else if (matches[2] == "!")
invertBoolean = true;
if (name == "all" && reset)
vimperator.echoerr("You can't reset all the firefox options, it could make your browser unusable.");
else if (name == "all")
vimperator.options.listPrefs(onlyNonDefault, "");
else if (reset)
vimperator.options.resetPref(name);
else if (invertBoolean)
vimperator.options.invertPref(name);
else if (matches[3])
{
var value = matches[5];
switch (value)
{
case undefined:
value = "";
break;
case "true":
value = true;
break;
case "false":
value = false;
break;
default:
var valueInt = parseInt(value, 10);
if (!isNaN(valueInt))
value = valueInt;
}
vimperator.options.setPref(name, value);
}
else
{
vimperator.options.listPrefs(onlyNonDefault, name);
}
return;
}
var onlyNonDefault = false; // used for :set to print non-default options
if (!args)
{
args = "all";
onlyNonDefault = true;
}
// 1 2 3 4 5 6
var matches = args.match(/^\s*(no|inv)?([a-z]+)([?&!])?\s*(([+-^]?)=(.*))?\s*$/);
if (!matches)
{
vimperator.echoerr("E518: Unknown option: " + args);
return;
}
var unsetBoolean = false;
if (matches[1] == "no")
unsetBoolean = true;
var name = matches[2];
var all = false;
if (name == "all")
all = true;
var option = vimperator.options.get(name);
if (!option && !all)
{
vimperator.echoerr("E518: Unknown option: " + args);
return;
}
var valueGiven = !!matches[4];
var get = false;
if (all || matches[3] == "?" || (option.type != "boolean" && !valueGiven))
get = true;
var reset = false;
if (matches[3] == "&")
reset = true;
var invertBoolean = false;
if (matches[1] == "inv" || matches[3] == "!")
invertBoolean = true;
var operator = matches[5];
var value = matches[6];
if (value === undefined)
value = "";
// reset a variable to its default value
if (reset)
{
if (all)
{
for (let option in vimperator.options)
option.reset();
}
else
{
option.reset();
}
}
// read access
else if (get)
{
if (all)
{
vimperator.options.list(onlyNonDefault);
}
else
{
if (option.type == "boolean")
vimperator.echo((option.value ? " " : "no") + option.name);
else
vimperator.echo(" " + option.name + "=" + option.value);
}
}
// write access
// NOTE: the behaviour is generally Vim compatible but could be
// improved. i.e. Vim's behaviour is pretty sloppy to no real
// benefit
else
{
var currentValue = option.value;
var newValue;
switch (option.type)
{
case "boolean":
if (valueGiven)
{
vimperator.echoerr("E474: Invalid argument: " + args);
return;
}
if (invertBoolean)
newValue = !option.value;
else
newValue = !unsetBoolean;
break;
case "number":
value = parseInt(value);
if (isNaN(value))
{
vimperator.echoerr("E521: Number required after =: " + args);
return;
}
if (operator == "+")
newValue = currentValue + value;
else if (operator == "-")
newValue = currentValue - value;
else if (operator == "^")
newValue = currentValue * value;
else
newValue = value;
break;
case "charlist":
if (operator == "+")
newValue = currentValue.replace(new RegExp("[" + value + "]", "g"), "") + value;
else if (operator == "-")
newValue = currentValue.replace(value, "");
else if (operator == "^")
// NOTE: Vim doesn't prepend if there's a match in the current value
newValue = value + currentValue.replace(new RegExp("[" + value + "]", "g"), "");
else
newValue = value;
break;
case "stringlist":
if (operator == "+")
{
if (!currentValue.match(value))
newValue = (currentValue ? currentValue + "," : "") + value;
else
newValue = currentValue;
}
else if (operator == "-")
{
newValue = currentValue.replace(new RegExp("^" + value + ",?|," + value), "");
}
else if (operator == "^")
{
if (!currentValue.match(value))
newValue = value + (currentValue ? "," : "") + currentValue;
else
newValue = currentValue;
}
else
{
newValue = value;
}
break;
case "string":
if (operator == "+")
newValue = currentValue + value;
else if (operator == "-")
newValue = currentValue.replace(value, "");
else if (operator == "^")
newValue = value + currentValue;
else
newValue = value;
break;
default:
vimperator.echoerr("E685: Internal error: option type `" + option.type + "' not supported");
}
if (option.isValidValue(newValue))
option.value = newValue;
else
// FIXME: need to be able to specify more specific errors
vimperator.echoerr("E474: Invalid argument: " + args);
}
},
{
shortHelp: "Set an option",
completer: function (filter, special) { return vimperator.completion.option(filter, special); }
}
));
// TODO: check for v.has("windows")
commandManager.addUserCommand(new vimperator.Command(["winc[lose]", "wc[lose]"],
function (args) { window.close(); },

View File

@@ -150,32 +150,7 @@ vimperator.Completion = function () //{{{
dialog: function (filter)
{
substrings = [];
var nodes = [
["about", "About Firefox"],
["addbookmark", "Add bookmarks for the current page"],
["addons", "Manage Add-ons"],
["bookmarks", "List your bookmarks"],
["checkupdates", "Check for updates"],
["cleardata", "Clear private data"],
["console", "JavaScript console"],
["customizetoolbar", "Customize the Toolbar"],
["dominspector", "DOM Inspector"],
["downloads", "Manage Downloads"],
["history", "List your history"],
["import", "Import Preferences, Bookmarks, History, etc. from other browsers"],
["openfile", "Open the file selector dialog"],
["pageinfo", "Show information about the current page"],
["pagesource", "View page source"],
["places", "Places Organizer: Manage your bookmarks and history"],
["preferences", "Show Firefox preferences dialog"],
["printpreview", "Preview the page before printing"],
["printsetup", "Setup the page size and orientation before printing"],
["print", "Show print dialog"],
["saveframe", "Save frame to disk"],
["savepage", "Save page to disk"],
["searchengines", "Manage installed search engines"],
["selectionsource", "View selection source"]
];
var nodes = vimperator.config.dialogs || [];
if (!filter)
return [0, nodes];
@@ -186,6 +161,7 @@ vimperator.Completion = function () //{{{
return [0, buildLongestCommonSubstring(mapped, filter)];
},
macros: function (filter)
{
var macros = [];

View File

@@ -38,6 +38,137 @@ vimperator.IO = function () //{{{
const WINDOWS = navigator.platform == "Win32";
var cwd = null, oldcwd = null;
var extname = vimperator.config.name.toLowerCase(); // "vimperator" or "muttator"
/////////////////////////////////////////////////////////////////////////////}}}
////////////////////// COMMANDS ////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
vimperator.commands.add(["cd", "chd[ir]"],
"Change the current directory",
function (args)
{
if (!args)
args = "~";
if (vimperator.io.setCurrentDirectory(args))
vimperator.echo(vimperator.io.getCurrentDirectory());
},
{
completer: function (filter) { return vimperator.completion.file(filter, true); }
});
vimperator.commands.add(["pw[d]"],
"Print the current directory name",
function (args)
{
if (args)
vimperator.echoerr("E488: Trailing characters");
else
vimperator.echo(vimperator.io.getCurrentDirectory());
});
// mkv[imperatorrc] or mkm[uttatorrc]
vimperator.commands.add(["mk" + extname.substr(0,1) + "[" + extname.substr(1) + "rc]"],
"Write current key mappings and changed options to the config file",
function (args, special)
{
// TODO: "E172: Only one file name allowed"
var filename;
if (args)
filename = args;
else
{
filename = (navigator.platform == "Win32") ? "~/_" : "~/.";
filename += extname+ "rc";
}
var file = vimperator.io.getFile(filename);
if (file.exists() && !special)
{
vimperator.echoerr("E189: \"" + filename + "\" exists (add ! to override)");
return;
}
var line = "\" " + vimperator.version + "\n";
line += "\" Mappings\n";
var mode = [[[vimperator.modes.NORMAL], ""], [[vimperator.modes.COMMAND_LINE], "c"],
[[vimperator.modes.INSERT, vimperator.modes.TEXTAREA], "i"]];
for (var y = 0; y < mode.length; y++)
{
// NOTE: names.length is always 1 on user maps. If that changes, also fix getUserIterator and v.m.list
for (var map in vimperator.mappings.getUserIterator(mode[y][0]))
line += mode[y][1] + (map.noremap ? "nore" : "") + "map " + map.names[0] + " " + map.rhs + "\n";
}
line += "\n\" Options\n";
for (var option in vimperator.options)
{
// TODO: options should be queried for this info
// TODO: string/list options might need escaping in future
if (!/fullscreen|usermode/.test(option.name) && option.value != option.defaultValue)
{
if (option.type == "boolean")
line += "set " + (option.value ? option.name : "no" + option.name) + "\n";
else
line += "set " + option.name + "=" + option.value + "\n";
}
}
// :mkvimrc doesn't save autocommands, so we don't either - remove this code at some point
// line += "\n\" Auto-Commands\n";
// for (var item in vimperator.autocommands)
// line += "autocmd " + item + "\n";
line += "\n\" Abbreviations\n";
for (var abbrCmd in vimperator.editor.abbreviations)
line += abbrCmd;
// if (vimperator.events.getMapLeader() != "\\")
// line += "\nlet mapleader = \"" + vimperator.events.getMapLeader() + "\"\n";
// source a user .vimperatorrc file
line += "\nsource! " + filename + ".local\n";
line += "\n\" vim: set ft=vimperator:";
vimperator.io.writeFile(file, line);
});
vimperator.commands.add(["so[urce]"],
"Read Ex commands from a file",
function (args, special)
{
// FIXME: implement proper filename quoting
//if (/[^\\]\s/.test(args))
//{
// vimperator.echoerr("E172: Only one file name allowed");
// return;
//}
vimperator.io.source(args, special);
},
{
completer: function (filter) { return vimperator.completion.file(filter, true); }
});
vimperator.commands.add(["!", "run"],
"Run a command",
function (args, special)
{
// :!! needs to be treated specially as the command parser sets the
// special flag but removes the ! from args
if (special)
args = "!" + (args || "");
// TODO: better escaping of ! to also substitute \\! correctly
args = args.replace(/(^|[^\\])!/g, "$1" + lastRunCommand);
lastRunCommand = args;
var output = vimperator.io.system(args);
if (output)
vimperator.echo(vimperator.util.escapeHTML(output));
});
/////////////////////////////////////////////////////////////////////////////}}}
////////////////////// PUBLIC SECTION //////////////////////////////////////////

View File

@@ -76,6 +76,10 @@ vimperator.Mail = function ()
"Reply to sender",
function () { goDoCommand("cmd_reply"); });
vimperator.mappings.add(modes, ["gm"],
"Get new messages",
function () { goDoCommand("cmd_getNewMessages"); });
/////////////////////////////////////////////////////////////////////////////}}}
////////////////////// PUBLIC SECTION //////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{

View File

@@ -36,8 +36,49 @@ vimperator.config = {
get browserModes() { return [vimperator.modes.MESSAGE]; },
get mainWidget() { return GetThreadTree(); }, // focusContent() focuses this widget
mainWindowID: "messengerWindow", // used for :set titlestring
dialogs: [],
guioptions: { m: ["mail-toolbar-menubar2"], T: ["mail-bar2"], f: ["folderPaneBox", "folderpane_splitter"], F: ["folderPaneHeader"] },
dialogs: [
/*["about", "About Firefox",
function() { openDialog("chrome://browser/content/aboutDialog.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
["addons", "Manage Add-ons",
function() { BrowserOpenAddonsMgr(); }],*/
["checkupdates", "Check for updates",
function() { checkForUpdates(); }],
/*["cleardata", "Clear private data",
function() { Cc[GLUE_CID].getService(Ci.nsIBrowserGlue).sanitize(window || null); }],*/
["console", "JavaScript console",
function() { toJavaScriptConsole(); }],
/*["customizetoolbar", "Customize the Toolbar",
function() { BrowserCustomizeToolbar(); }],*/
["dominspector", "DOM Inspector",
function() { inspectDOMDocument(content.document); }],
["downloads", "Manage Downloads",
function() { toOpenWindowByType('Download:Manager', 'chrome://mozapps/content/downloads/downloads.xul', 'chrome,dialog=no,resizable'); }],
/*["import", "Import Preferences, Bookmarks, History, etc. from other browsers",
function() { BrowserImport(); }],
["openfile", "Open the file selector dialog",
function() { BrowserOpenFileWindow(); }],
["pageinfo", "Show information about the current page",
function() { BrowserPageInfo(); }],
["pagesource", "View page source",
function() { BrowserViewSourceOfDocument(content.document); }],
["preferences", "Show Firefox preferences dialog",
function() { openPreferences(); }],
["printpreview", "Preview the page before printing",
function() { PrintUtils.printPreview(onEnterPrintPreview, onExitPrintPreview); }],*/
["printsetup", "Setup the page size and orientation before printing",
function() { PrintUtils.showPageSetup(); }],
["print", "Show print dialog",
function() { PrintUtils.print(); }],
["saveframe", "Save frame to disk",
function() { saveFrameDocument(); }],
["savepage", "Save page to disk",
function() { saveDocument(window.content.document); }],
/*["searchengines", "Manage installed search engines",
function() { openDialog("chrome://browser/content/search/engineManager.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
["selectionsource", "View selection source",
function() { vimperator.buffer.viewSelectionSource(); }]*/
],
init: function()
{

View File

@@ -196,6 +196,286 @@ vimperator.Options = function () //{{{
// start with saved session
storePreference("browser.startup.page", 3);
/////////////////////////////////////////////////////////////////////////////}}}
////////////////////// COMMANDS ////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
vimperator.commands.add(["pref[erences]", "prefs"],
"Show " + vimperator.config.appName + " Preferences",
function (args, special, count, modifiers)
{
if (!args)
{
// TODO: copy these snippets to more function which should work with :tab xxx
if (modifiers && modifiers.inTab)
{
vimperator.open(special ? "about:config" :
"chrome://browser/content/preferences/preferences.xul", vimperator.NEW_TAB);
}
else
{
if (special) // open firefox settings gui dialog
vimperator.open("about:config", vimperator.CURRENT_TAB);
else
openPreferences();
}
}
else
{
vimperator.echoerr("E488: Trailing characters");
}
});
// TODO: support setting multiple options at once
vimperator.commands.add(["se[t]"],
"Set an option",
function (args, special, count, modifiers)
{
if (special)
{
var onlyNonDefault = false;
if (!args)
{
args = "all";
onlyNonDefault = true;
}
// 1 2 3 4 5
var matches = args.match(/^\s*?([a-zA-Z0-9\.\-_{}]+)([?&!])?\s*(([+-^]?)=(.*))?\s*$/);
var name = matches[1];
var reset = false;
var invertBoolean = false;
if (matches[2] == "&")
reset = true;
else if (matches[2] == "!")
invertBoolean = true;
if (name == "all" && reset)
vimperator.echoerr("You can't reset all the firefox options, it could make your browser unusable.");
else if (name == "all")
vimperator.options.listPrefs(onlyNonDefault, "");
else if (reset)
vimperator.options.resetPref(name);
else if (invertBoolean)
vimperator.options.invertPref(name);
else if (matches[3])
{
var value = matches[5];
switch (value)
{
case undefined:
value = "";
break;
case "true":
value = true;
break;
case "false":
value = false;
break;
default:
var valueInt = parseInt(value, 10);
if (!isNaN(valueInt))
value = valueInt;
}
vimperator.options.setPref(name, value);
}
else
{
vimperator.options.listPrefs(onlyNonDefault, name);
}
return;
}
var onlyNonDefault = false; // used for :set to print non-default options
if (!args)
{
args = "all";
onlyNonDefault = true;
}
// 1 2 3 4 5 6
var matches = args.match(/^\s*(no|inv)?([a-z]+)([?&!])?\s*(([+-^]?)=(.*))?\s*$/);
if (!matches)
{
vimperator.echoerr("E518: Unknown option: " + args);
return;
}
var unsetBoolean = false;
if (matches[1] == "no")
unsetBoolean = true;
var name = matches[2];
var all = false;
if (name == "all")
all = true;
var option = vimperator.options.get(name);
if (!option && !all)
{
vimperator.echoerr("E518: Unknown option: " + args);
return;
}
var valueGiven = !!matches[4];
var get = false;
if (all || matches[3] == "?" || (option.type != "boolean" && !valueGiven))
get = true;
var reset = false;
if (matches[3] == "&")
reset = true;
var invertBoolean = false;
if (matches[1] == "inv" || matches[3] == "!")
invertBoolean = true;
var operator = matches[5];
var value = matches[6];
if (value === undefined)
value = "";
// reset a variable to its default value
if (reset)
{
if (all)
{
for (let option in vimperator.options)
option.reset();
}
else
{
option.reset();
}
}
// read access
else if (get)
{
if (all)
{
vimperator.options.list(onlyNonDefault);
}
else
{
if (option.type == "boolean")
vimperator.echo((option.value ? " " : "no") + option.name);
else
vimperator.echo(" " + option.name + "=" + option.value);
}
}
// write access
// NOTE: the behaviour is generally Vim compatible but could be
// improved. i.e. Vim's behaviour is pretty sloppy to no real
// benefit
else
{
var currentValue = option.value;
var newValue;
switch (option.type)
{
case "boolean":
if (valueGiven)
{
vimperator.echoerr("E474: Invalid argument: " + args);
return;
}
if (invertBoolean)
newValue = !option.value;
else
newValue = !unsetBoolean;
break;
case "number":
value = parseInt(value);
if (isNaN(value))
{
vimperator.echoerr("E521: Number required after =: " + args);
return;
}
if (operator == "+")
newValue = currentValue + value;
else if (operator == "-")
newValue = currentValue - value;
else if (operator == "^")
newValue = currentValue * value;
else
newValue = value;
break;
case "charlist":
if (operator == "+")
newValue = currentValue.replace(new RegExp("[" + value + "]", "g"), "") + value;
else if (operator == "-")
newValue = currentValue.replace(value, "");
else if (operator == "^")
// NOTE: Vim doesn't prepend if there's a match in the current value
newValue = value + currentValue.replace(new RegExp("[" + value + "]", "g"), "");
else
newValue = value;
break;
case "stringlist":
if (operator == "+")
{
if (!currentValue.match(value))
newValue = (currentValue ? currentValue + "," : "") + value;
else
newValue = currentValue;
}
else if (operator == "-")
{
newValue = currentValue.replace(new RegExp("^" + value + ",?|," + value), "");
}
else if (operator == "^")
{
if (!currentValue.match(value))
newValue = value + (currentValue ? "," : "") + currentValue;
else
newValue = currentValue;
}
else
{
newValue = value;
}
break;
case "string":
if (operator == "+")
newValue = currentValue + value;
else if (operator == "-")
newValue = currentValue.replace(value, "");
else if (operator == "^")
newValue = value + currentValue;
else
newValue = value;
break;
default:
vimperator.echoerr("E685: Internal error: option type `" + option.type + "' not supported");
}
if (option.isValidValue(newValue))
option.value = newValue;
else
// FIXME: need to be able to specify more specific errors
vimperator.echoerr("E474: Invalid argument: " + args);
}
},
{
completer: function (filter, special) { return vimperator.completion.option(filter, special); }
});
/////////////////////////////////////////////////////////////////////////////}}}
////////////////////// PUBLIC SECTION //////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{

View File

@@ -116,7 +116,144 @@ const vimperator = (function () //{{{
function addCommands()
{
vimperator.commands.add(["addo[ns]"],
"Manage available Extensions and Themes",
function () { vimperator.open("chrome://mozapps/content/extensions/extensions.xul", vimperator.NEW_TAB); });
vimperator.commands.add(["beep"],
"Play a system beep",
function () { vimperator.beep(); });
vimperator.commands.add(["dia[log]"],
"Open a " + vimperator.config.appName + " dialog",
function (args, special)
{
try
{
var dialogs = vimperator.config.dialogs || [];
for (let i = 0; i < dialogs.length; i++)
{
if (dialogs[i][0] == args)
return dialogs[i][2]();
}
vimperator.echoerr(args ? "Dialog \"" + args + "\" not available" : "E474: Invalid argument");
}
catch (e)
{
vimperator.echoerr("Error opening '" + args + "': " + e);
}
},
{
completer: function (filter) { return vimperator.completion.dialog(filter); }
});
vimperator.commands.add(["exe[cute]"],
"Execute the argument as an Ex command",
function (args) { vimperator.execute(args); });
vimperator.commands.add(["exu[sage]"],
"List all Ex commands with a short description",
function ()
{
var usage = "<table>";
for (let command in vimperator.commands)
{
usage += "<tr><td style='color: magenta; padding-right: 20px'> :" +
vimperator.util.escapeHTML(command.name) + "</td><td>" +
vimperator.util.escapeHTML(command.shortHelp) + "</td></tr>";
}
usage += "</table>";
vimperator.echo(usage, vimperator.commandline.FORCE_MULTILINE);
});
vimperator.commands.add(["h[elp]"],
"Display help",
function (args, special, count, modifiers)
{
function jumpToTag(file, tag)
{
vimperator.open("chrome://" + vimperator.config.name.toLowerCase() + "/locale/" + file);
setTimeout(function() {
var elem = vimperator.buffer.getElement('@class="tag" and text()="' + tag + '"');
if (elem)
window.content.scrollTo(0, elem.getBoundingClientRect().top - 10); // 10px context
else
dump('no element: ' + '@class="tag" and text()="' + tag + '"\n' );
}, 200);
}
if (!args)
{
vimperator.open("chrome://" + vimperator.config.name.toLowerCase() + "/locale/intro.html");
return;
}
var [, items] = vimperator.completion.help(args);
var partialMatch = -1;
for (var i = 0; i < items.length; i++)
{
if (items[i][0] == args)
{
jumpToTag(items[i][1], items[i][0]);
return;
}
else if (partialMatch == -1 && items[i][0].indexOf(args) > -1)
{
partialMatch = i;
}
}
if (partialMatch > -1)
jumpToTag(items[partialMatch][1], items[partialMatch][0]);
else
vimperator.echoerr("E149: Sorry, no help for " + args);
},
{
completer: function (filter) { return vimperator.completion.help(filter); }
});
vimperator.commands.add(["javas[cript]", "js"],
"Run a JavaScript command through eval()",
function (args, special)
{
if (special) // open javascript console
vimperator.open("chrome://global/content/console.xul", vimperator.NEW_TAB);
else
{
// check for a heredoc
var matches = args.match(/(.*)<<\s*([^\s]+)$/);
if (matches && matches[2])
{
vimperator.commandline.inputMultiline(new RegExp("^" + matches[2] + "$", "m"),
function (code)
{
try
{
eval(matches[1] + "\n" + code);
}
catch (e)
{
vimperator.echoerr(e.name + ": " + e.message);
}
});
}
else // single line javascript code
{
try
{
eval("with(vimperator){" + args + "}");
}
catch (e)
{
vimperator.echoerr(e.name + ": " + e.message);
}
}
}
},
{
completer: function (filter) { return vimperator.completion.javascript(filter); }
});
}
// initially hide all GUI, it is later restored unless the user has :set go= or something
@@ -487,8 +624,9 @@ const vimperator = (function () //{{{
function log(module) { vimperator.log("Loading module " + module + "...", 3); };
vimperator.log("Initializing vimperator object...", 1);
// commands must always be the first module to be initialized
log("commands"); vimperator.commands = vimperator.Commands(); addCommands();
log("options"); vimperator.options = vimperator.Options(); addOptions();
log("commands"); vimperator.commands = vimperator.Commands();
log("mappings"); vimperator.mappings = vimperator.Mappings(); addMappings();
log("events"); vimperator.events = vimperator.Events();
log("commandline"); vimperator.commandline = vimperator.CommandLine();

View File

@@ -33,8 +33,57 @@ vimperator.config = {
/*** optional options, there are checked for existance and a fallback provided ***/
features: ["bookmarks", "history", "marks", "quickmarks", "hints", "tabs", "windows"],
dialogs: [],
guioptions: { m: ["toolbar-menubar"], T: ["nav-bar"], b: ["PersonalToolbar"] },
dialogs: [
["about", "About Firefox",
function() { openDialog("chrome://browser/content/aboutDialog.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
["addbookmark", "Add bookmark for the current page",
function() { PlacesCommandHook.bookmarkCurrentPage(true, PlacesUtils.bookmarksRootId); }],
["addons", "Manage Add-ons",
function() { BrowserOpenAddonsMgr(); }],
["bookmarks", "List your bookmarks",
function() { openDialog("chrome://browser/content/bookmarks/bookmarksPanel.xul", "Bookmarks", "dialog,centerscreen,width=600,height=600"); }],
["checkupdates", "Check for updates",
function() { checkForUpdates(); }],
["cleardata", "Clear private data",
function() { Cc[GLUE_CID].getService(Ci.nsIBrowserGlue).sanitize(window || null); }],
["console", "JavaScript console",
function() { toJavaScriptConsole(); }],
["customizetoolbar", "Customize the Toolbar",
function() { BrowserCustomizeToolbar(); }],
["dominspector", "DOM Inspector",
function() { inspectDOMDocument(content.document); }],
["downloads", "Manage Downloads",
function() { toOpenWindowByType('Download:Manager', 'chrome://mozapps/content/downloads/downloads.xul', 'chrome,dialog=no,resizable'); }],
["history", "List your history",
function() { openDialog("chrome://browser/content/history/history-panel.xul", "History", "dialog,centerscreen,width=600,height=600"); }],
["import", "Import Preferences, Bookmarks, History, etc. from other browsers",
function() { BrowserImport(); }],
["openfile", "Open the file selector dialog",
function() { BrowserOpenFileWindow(); }],
["pageinfo", "Show information about the current page",
function() { BrowserPageInfo(); }],
["pagesource", "View page source",
function() { BrowserViewSourceOfDocument(content.document); }],
["places", "Places Organizer: Manage your bookmarks and history",
function() { PlacesCommandHook.showPlacesOrganizer(ORGANIZER_ROOT_BOOKMARKS); }],
["preferences", "Show Firefox preferences dialog",
function() { openPreferences(); }],
["printpreview", "Preview the page before printing",
function() { PrintUtils.printPreview(onEnterPrintPreview, onExitPrintPreview); }],
["printsetup", "Setup the page size and orientation before printing",
function() { PrintUtils.showPageSetup(); }],
["print", "Show print dialog",
function() { PrintUtils.print(); }],
["saveframe", "Save frame to disk",
function() { saveFrameDocument(); }],
["savepage", "Save page to disk",
function() { saveDocument(window.content.document); }],
["searchengines", "Manage installed search engines",
function() { openDialog("chrome://browser/content/search/engineManager.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
["selectionsource", "View selection source",
function() { vimperator.buffer.viewSelectionSource(); }]
],
init: function()
{