diff --git a/chrome/content/vimperator/mappings.js b/chrome/content/vimperator/mappings.js new file mode 100644 index 00000000..3457f752 --- /dev/null +++ b/chrome/content/vimperator/mappings.js @@ -0,0 +1,542 @@ +function Map(mode, cmd, action, extra_info) +{ + if (!mode || (!cmd || !cmd.length) || !action) return; + if (!extra_info) extra_info = {}; + this.mode = mode; + this.cmd = cmd; + this.action = action; + this.flags = extra_info.flags || 0; + + if (extra_info.usage) + this.usage = extra_info.usage; + else + { + var usage = ""; + if (flags & vimperator.mappings.flags.COUNT) + usage = "{count}"; + + usage += cmd; + if (flags & vimperator.mappings.flags.ARGUMENT) + usage += " {arg}"; + } + + if (extra_info.help) + this.help = extra_info.help; + if (extra_info.short) + this.short = extra_info.short; + + this.execute: function() { + this.cmd.call(this); + } +} + +function Mappings() +{ + this.main = []; + this.user = []; + this.flags = { + MOTION: 1 << 1; + COUNT: 1 << 2; + ARGUMENT: 1 << 3; + }; + + this.add: function(map) + { + if (!map) return; + if (!this.user[map.mode]) + this.user[map.mode] = []; + + this.user[map.mode].push(map); + return this; + } + + this.remove: function(map) + { + var index; + + if (!map || !(index = this.user[map.mode].indexOf(map))) + return; + + this.user[map.mode].splice(index, 1); + return this; + } + + this.get: function(mode, cmd) + { + if (!mode || !cmd) return; + var map = getFrom(mode, cmd, this.user); + if (!map) map = getFrom(mode, cmd, this.main); + return map; + } + + function addDefaults(map) + { + if (!map) return; + if (!this.main[map.mode]) + this.main[map.mode] = []; + + this.main[map.mode].push(map); + return this; + } + + function getFrom(mode, cmd, stack) + { + if (!stack || !stack[mode] || !stack[mode].length) + return; + + var substack = stack[mode]; + var stack_length = substack.length; + for (var i = 0; i < stack_length; i++) + { + for (var j = 0; j < substack[i].cmd.length; j++) + if (substack[i].cmd[j] == cmd) + return substack[i]; + } + } + + /* Default mappings + * Normal mode + * */ + addDefaults(new Map(vimperator.mode.NORMAL, ["]f"], focusNextFrame, {short: "Focus next frame", help: + "Flashes the next frame in order with a red color, to quickly show where keyboard focus is.
"+ + "This may not work correctly for frames with lots of CSS code." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["b"], function (args) { vimperator.commandline.open(":", "buffer ", vimperator.modes.EX); }, { + short: "Open a prompt to switch buffers", help: + "Typing the corresponding number opens switches to this buffer." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["B"], toggleBufferList, {short: "Toggle buffer list", help: + "Toggles the display of the buffer list which shows all opened tabs." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["d"], function(count) { vimperator.tabs.remove(getBrowser().mCurrentTab, count, false, 0); }, { + short: "Delete current buffer (=tab)", flags: this.flags.COUNT, help: + "Count WILL be supported in future releases, then 2d removes two tabs and the one the right is selected." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["D"], function(count) { vimperator.tabs.remove(getBrowser().mCurrentTab, count, true, 0); }, { + short: "Delete current buffer (=tab)", flags: this.flags.COUNT, help: + "Count WILL be supported in future releases, then 2d removes two tabs and the one the right is selected." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["gh"], BrowserHome, {short: "Go home", help: + "Opens the homepage in the current tab." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["gH"], BrowserHome, {short: "Go home in a new tab", help: + "Opens the homepage in a new tab." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["gP"], function(count) { openURLsInNewTab(readFromClipboard(), false); }, { + short: "Open (put) an URL based on the current clipboard contents in a new buffer", + help: "Works like P, but inverts the 'activate' setting." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["gt", "", ""], + function(count) { vimperator.tabs.select(count > 0 ? count -1: "+1", count > 0 ? false : true); }, { + short: "Go to the next tab", flags: this.flags.COUNT, + help: "Cycles to the first tab, when the last is selected.
Count is supported, 3gt goes to the third tab." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["gT", "", ""], + function(count) { vimperator.tabs.select(count > 0 ? count -1: "-1", count > 0 ? false : true); }, { + short: "Go to the previous tab", flags: this.flags.COUNT, + help: "Cycles to the last tab, when the first is selected.
Count is supported, 3gT goes to the third tab." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["m"], set_location_mark, {short: "Set mark at the cursor position", usage: "m{a-zA-Z}", + help: "Marks a-z are local to the buffer, whereas A-Z are valid between buffers", flags: this.flags.ARGUMENT + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["o"], function(count) { vimperator.commandline.open(":", "open ", vimperator.modes.EX) }, { + short: "Open one or more URLs in the current tab", + help: "See :open for more details." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["O"], + function(count) { vimperator.commandline.open(":", "open " + getCurrentLocation(), vimperator.modes.EX); }, { + short: "Open one ore more URLs in the current tab, based on current location", + help: "Works like o, but preselects current URL in the :open query." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["p", ""], + function(count) { openURLs(readFromClipboard()); }, { + short: "Open (put) an URL based on the current clipboard contents in the current buffer", + help: "You can also just select some non-URL text, and search for it with the default search engine or keyword (specified by the 'defsearch' setting) with p." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["P"], + function(count) { openURLsInNewTab(readFromClipboard(), true); }, { + short: "Open (put) an URL based on the current clipboard contents in a new buffer", + help: "Works like p, but opens a new tab.
" + + "Whether the new buffer is activated, depends on the 'activate' setting." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["r"], function(count) { reload(getBrowser().mCurrentTab, false); }, { + short: "Reload", help: "Forces reloading of the current page." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["R"], function(count) { reload(getBrowser().mCurrentTab, true); }, { + short: "Reload while skipping the cache", help: "Forces reloading of the current page skipping the cache." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["t"], function(count) { vimperator.commandline.open(":", "tabopen ", vimperator.modes.EX); }, { + short: "Open one or more URLs in a new tab", + help: "Like o but open URLs in a new tab.
"+ + "See :tabopen for more details." + })); + addDefaults(new Map(vimperator.mode.NORMAL, ["T"], + function(count) { vimperator.commandline.open(":", "tabopen " + getCurrentLocation(), vimperator.modes.EX); }, { + short: "Open one ore more URLs in a new tab, based on current location", + help: "Works like t, but preselects current URL in the :tabopen query.", + })); + + var normal_maps = [ + [ + ["u"], + ["{count}u"], + "Undo closing of a tab", + "If a count is given, don't close the last but the n'th last tab.", + function(count) { execute_command(count, 'undo', false, ''); }, + this.flags.COUNT + ], + [ + ["y"], + ["y"], + "Yank current location to the clipboard", + "Under UNIX the location is also put into the selection, which can be pasted with the middle mouse button.", + yankCurrentLocation + ], + [ + ["Y"], + ["Y"], + "Copy selected text", + "The currently selected text is copied to the system clipboard.", + yankCurrentSelection, + null + ], + [ + ["zi", "+"], + ["zi", "+"], + "Zoom in current web page by 25%", + "Currently no count supported.", + function(count) { zoom_in(1); } + ], + [ + ["zI"], + ["zI"], + "Zoom in current web page by 100%", + "Currently no count supported.", + function(count) { zoom_in(4); } + ], + [ + ["zo", "-"], + ["zo", "-"], + "Zoom out current web page by 25%", + "Currently no count supported.", + function(count) { zoom_in(-1); } + ], + [ + ["zO"], + ["zO"], + "Zoom out current web page by 100%", + "Currently no count supported.", + function(count) { zoom_in(-4); } + ], + [ + ["zz"], + ["{count}zz"], + "Set zoom value of the webpage", + "Zoom value can be between 25 and 500%. If it is omitted, zoom is reset to 100%.", + zoom_to, + this.flags.COUNT + ], + [ + ["ZQ"], + ["ZQ"], + "Quit and don't save the session", + "Works like :qall.", + function(count) { quit(false); } + ], + [ + ["ZZ"], + ["ZZ"], + "Quit and save the session", + "Quit Vimperator, no matter how many tabs/windows are open. The session is stored.
" + + "Works like :xall.", + function(count) { quit(true); } + ], + + /* scrolling commands */ + [ + ["0", "^"], + ["0", "^"], + "Scroll to the absolute left of the document", + "Unlike in vim, 0 and ^ work exactly the same way.", + function(count) { scrollBufferAbsolute(0, -1); } + ], + [ + ["$"], + ["$"], + "Scroll to the absolute right of the document", + null, + function(count) { scrollBufferAbsolute(100, -1); } + ], + [ + ["gg", ""], + ["{count}gg", "{count}"], + "Goto the top of the document", + "Count is supported, 35gg vertically goes to 35% of the document.", + function(count) { scrollBufferAbsolute(-1, count > 0 ? count : 0); }, + this.flags.COUNT + ], + [ + ["G", ""], + ["{count}G", "{count}"], + "Goto the end of the document", + "Count is supported, 35G vertically goes to 35% of the document.", + function(count) { scrollBufferAbsolute(-1, count >= 0 ? count : 100); }, + this.flags.COUNT + ], + [ + ["h", ""], + ["{count}h", "{count}"], + "Scroll document to the left", + "Count is supported: 10h will move 10 times as much to the left.
"+ + "If the document cannot scroll more, a beep is emmited (unless 'beep' is turned off).", + function(count) { scrollBufferRelative(-1, 0); }, + this.flags.COUNT + ], + [ + ["j", "", ""], + ["{count}j", "{count}", "{count}"], + "Scroll document down", + "Count is supported: 10j will move 10 times as much down.
"+ + "If the document cannot scroll more, a beep is emmited (unless 'beep' is turned off).", + function(count) { scrollBufferRelative(0, 1); }, + this.flags.COUNT + ], + [ + ["k", "", ""], + ["{count}k", "{count}", "{count}"], + "Scroll document up", + "Count is supported: 10k will move 10 times as much up.
"+ + "If the document cannot scroll more, a beep is emmited (unless 'beep' is turned off).", + function(count) { scrollBufferRelative(0, -1); }, + this.flags.COUNT + ], + [ + ["l", ""], + ["{count}l", "{count}"], + "Scroll document to the right", + "Count is supported: 10l will move 10 times as much to the right.
"+ + "If the document cannot scroll more, a beep is emmited (unless 'beep' is turned off).", + function(count) { scrollBufferRelative(1, 0); }, + this.flags.COUNT + ], + [ + ["", "", "", ""], + [""], + "Scroll up a full page of the current document", + "No count support for now.", + function(count) { goDoCommand('cmd_scrollPageUp'); } + ], + [ + ["", "", "", ""], + [""], + "Scroll down a full page of the current document", + "No count support for now,", + function(count) { goDoCommand('cmd_scrollPageDown'); } + ], + + /* history manipulation and jumplist */ + [ + [""], + ["{count}"], + "Go to an older position in the jump list", + "The jump list is just the browser history for now", + function(count) { stepInHistory(count > 0 ? -1 * count : -1); }, + this.flags.COUNT + ], + [ + [""], + ["{count}"], + "Go to a newer position in the jump list", + "The jump list is just the browser history for now", + function(count) { stepInHistory(count > 0 ? count : 1); }, + this.flags.COUNT + ], + [ + ["H", "", ""], + ["{count}H", "{count}", "{count}"], + "Go back in the browser history", + "Count is supported, 3H goes back 3 steps.", + function(count) { stepInHistory(count > 0 ? -1 * count : -1); }, + this.flags.COUNT + ], + [ + ["L", "", ""], + ["{count}L", "{count}", "{count}"], + "Go forward in the browser history", + "Count is supported, 3L goes forward 3 steps.", + function(count) { stepInHistory(count > 0 ? count : 1); }, + this.flags.COUNT + ], + [ + ["gu", ""], + ["{count}gu", "{count}"], + "Go to parent directory", + "Count is supported, 2gu on http://www.example.com/dir1/dir2/file.htm would open http://www.example.com/dir1/.", + goUp, + this.flags.COUNT + ], + [ + ["gU", ""], + ["gU", ""], + "Go to the root of the website", + "gU on http://www.example.com/dir1/dir2/file.htm opens http://www.example.com/.
"+ + "When browsing a local directory, it goes to the root document.", + function(count) { openURLs("..."); } + ], + + /* hint managment */ + [ + ["f"], + ["f"], + "Start QuickHint mode", + "In QuickHint mode, every hintable item (according to the 'hinttags' XPath query) is assigned a label.
"+ + "If you then press the keys for a label, it is followed as soon as it can be uniquely identified and this mode is stopped. Or press <Esc> to stop this mode.
"+ + "If you write the hint in ALLCAPS, the hint is followed in a background tab.", + function(count) { hah.enableHahMode(vimperator.modes.QUICK_HINT); } + ], + [ + ["F"], + ["F"], + "Start AlwaysHint mode", + "In AlwaysHint mode, every hintable item (according to the 'hinttags' XPath query) is assigned a label.
"+ + "If you then press the keys for a label, it is followed as soon as it can be uniquely identified. Labels stay active after following a hint in this mode, press <Esc> to stop this mode.
"+ + "This hint mode is especially useful for browsing large sites like Forums as hints are automatically regenerated when switching to a new document.
"+ + "Also, most Ctrl-prefixed shortcut keys are available in this mode for navigation.", + function(count) { hah.enableHahMode(vimperator.modes.ALWAYS_HINT); } + ], + [ + [";"], + [";"], + "Start ExtendedHint mode", + "ExtendedHint mode is useful, since in this mode you can yank link locations, or open them in a new window.
"+ + "E.g., if you want to yank the location of hint AB, press ; to start this hint mode.
"+ + "Then press AB to select the hint. Now press y to yank its location.
"+ + "Actions for selected hints in ExtendedHint mode are:
"+ + "
  • y to yank its location
  • "+ + "
  • Y to yank its text description
  • "+ + "
  • o to open its location in the current tab
  • "+ + "
  • t to open its location in a new tab
  • "+ + "
  • O to open its location in an :open query (not implemented yet)
  • "+ + "
  • T to open its location in an :tabopen query (not implemented yet)
  • "+ + "
  • s to save its destination (not implemented yet)
  • "+ + "
  • <C-w> to open its destination in a new window
  • "+ + "
"+ + "Multiple hints can be seperated by commas where it makes sense. ;ab,ac,adt opens AB, AC and AD in a new tab.
"+ + "Hintable elements for this mode can be set in the 'extendedhinttags' XPath string.", + function(count) { hah.enableHahMode(vimperator.modes.EXTENDED_HINT); } + ], + + /* search managment */ + [ + ["g/"], + ["g/"], + "Search forward for a pattern", + "", + function(count) { vimperator.search.openSearchDialog(); } + ], + [ + ["n"], + ["n"], + "Find next", + "Repeat the last \"/\" 1 time (until count is supported).", + function(count) { vimperator.search.findNext(); } + ], + [ + ["N"], + ["N"], + "Find previous", + "Repeat the last \"/\" 1 time (until count is supported) in the opposite direction.", + function(count) { vimperator.search.findPrevious(); } + ], + + /* vimperator managment */ + [ + [""], + [""], + "Open help window", + "The default section is shown, if you need help for a specific topic, try :help <F1> (jumping to a specific section not implemented yet).", + function(count) { help(null); } + ], + [ + [":"], + [":"], + "Start command line mode", + "In command line mode, you can perform extended commands, which may require arguments.", + function(count) { vimperator.commandline.open(":", "", vimperator.modes.EX); } + ], + [ + ["I"], + ["I"], + "Disable vimperator keys", + "Starts an 'ignorekeys' mode, where all keys except <Esc> are passed to the next event handler.
"+ + "This is especially useful, if JavaScript controlled forms like the RichEdit form fields of GMail don't work anymore.
" + + "To exit this mode, press <Esc>. If you also need to pass <Esc>"+ + "in this mode to the webpage, prepend it with <C-v>.", + function(count) { vimperator.addMode(null, vimperator.modes.ESCAPE_ALL_KEYS);} + ], + [ + [""], // if you ever add/remove keys here, also check them in the onVimperatorKeypress() function + [""], + "Escape next key", + "If you need to pass a certain key to a javascript form field or another extension prefix the key with <C-v>.
"+ + "Also works to unshadow Firefox shortcuts like <C-o> which are otherwise hidden in Vimperator.
"+ + "When in 'ignorekeys' mode (activated by <I>), <C-v> will pass the next key to Vimperator instead of the webpage.", + function(count) { vimperator.addMode(null, vimperator.modes.ESCAPE_ONE_KEY); } + ], + [ + [""], + [""], + "Stop loading", + "Stops loading the current webpage.", + BrowserStop + ], + [ + ["", ""], // if you ever add/remove keys here, also check them in the onVimperatorKeypress() function + ["", ""], + "Cancel any operation", + "Exits any command line or hint mode and returns to browser mode.
"+ + "Also focuses the web page, in case a form field has focus and eats our key presses.", + onEscape + ] + ]; + var hint_maps = [ + /* hint action keys */ + ["o", "hah.openHints(false, false);", true, false], + ["t", "hah.openHints(true, false);", true, false], + ["", "hah.openHints(false, true );", true, false], + ["s", "vimperator.echoerr('Saving of links not yet implemented');", true, false], + ["y", "hah.yankUrlHints();", true, false], + ["Y", "hah.yankTextHints();", true, false], + [",", "g_inputbuffer+=','; hah.setCurrentState(0);", false, true], + [":", "vimperator.commandline.open(':', '', vimperator.modes.EX);", false, true], + /* movement keys */ + ["", "scrollBufferRelative(0, 1);", false, true], + ["", "scrollBufferRelative(0, -1);", false, true], + ["", "scrollBufferAbsolute(-1, 0);", false, true], + ["", "scrollBufferAbsolute(-1, 100);", false, true], + ["", "goDoCommand('cmd_scrollPageUp');", false, true], + ["", "goDoCommand('cmd_scrollPageUp');", false, true], + ["", "goDoCommand('cmd_scrollPageDown');", false, true], + ["", "goDoCommand('cmd_scrollPageDown');", false, true], + ["", "scrollBufferRelative(-1, 0);", false, true], + ["", "scrollBufferRelative(0, 1);", false, true], + ["", "scrollBufferRelative(0, -1);", false, true], + ["", "scrollBufferRelative(1, 0);", false, true], + /* tab managment */ + ["", "vimperator.tabs.select('+1', true)", true, true], // same as gt, but no count supported + ["", "vimperator.tabs.select('-1', true)", true, true], + /* navigation */ + ["", "stepInHistory(g_count > 0 ? -1 * g_count : -1);", false, true], + ["", "stepInHistory(g_count > 0 ? g_count : 1);", false, true], + ["", "stepInHistory(g_count > 0 ? -1 * g_count : -1);", false, true], + ["", "stepInHistory(g_count > 0 ? g_count : 1);", false, true], + ["", "vimperator.tabs.remove(getBrowser().mCurrentTab, g_count, false, 0);", true, true], + /* cancel hint mode keys */ + ["", "", true, true], + ["", "", true, true], + ["", "", true, true], + ["", "", true, true] + ]; +} + +// vim: set fdm=marker sw=4 ts=4 et: