diff --git a/NEWS b/NEWS index 74165c02..bd3ec241 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@
 2007-xx-xx:
 	* version 0.6
+	* new gi browser command to focus last used input box
+	* edit TEXTAREAs with many vim commands in a vim and even visual mode
+	* support for emacs/bash-like ctrl-e/a/u/k/h keys in single line text fields
 	* support for * and # mappings to search for the text selection or the text under the cursor
 	* Escape finally clears any selection made in the document
 	* initial start of caret mode. Start with 'i', stop with Escape;
diff --git a/chrome/content/vimperator/buffers.js b/chrome/content/vimperator/buffers.js
index bdb68bc9..5394f72b 100644
--- a/chrome/content/vimperator/buffers.js
+++ b/chrome/content/vimperator/buffers.js
@@ -140,6 +140,8 @@ function Buffer() //{{{
         return window.content.document.title;
     });
 
+    this.lastInputField = null; // used to keep track of the right field for "gi"
+
     // returns an XPathResult object
     this.evaluateXPath = function(expression, doc, ordered)
     {
diff --git a/chrome/content/vimperator/events.js b/chrome/content/vimperator/events.js
index 233a6739..5dd0c423 100644
--- a/chrome/content/vimperator/events.js
+++ b/chrome/content/vimperator/events.js
@@ -64,6 +64,9 @@ function Events() //{{{
     // this adds an event which is is called on each page load, even if the
     // page is loaded in a background tab
     getBrowser().addEventListener("load", onPageLoad, true);
+    // to keep track if we are in a text field
+    //getBrowser().addEventListener("focus", onFocus, true);
+    //getBrowser().addEventListener("focus", onFocus, true);
 
     // called when the active document is scrolled
     getBrowser().addEventListener("scroll", function (event)
@@ -378,71 +381,96 @@ function Events() //{{{
         return (key == "" || key == "" || key == "");
     }
 
+    // event is delibarately not used, as i don't seem to have access to the really focus target
+    this.onFocusChange = function(event)
+    {
+        if (vimperator.hasMode(vimperator.modes.COMMAND_LINE))
+            return;
+
+        var elem = window.document.commandDispatcher.focusedElement;
+        if (elem && elem instanceof HTMLInputElement &&
+                (elem.type.toLowerCase() == "text" || elem.type.toLowerCase() == "password"))
+        {
+            vimperator.setMode(vimperator.modes.INSERT);
+            vimperator.buffer.lastInputField = elem;
+        }
+        else if (elem && elem instanceof HTMLTextAreaElement)
+        {
+            if (elem.selectionEnd - elem.selectionStart > 0)
+                vimperator.setMode(vimperator.modes.VISUAL, vimperator.modes.TEXTAREA);
+            else
+                vimperator.setMode(vimperator.modes.TEXTAREA);
+            vimperator.buffer.lastInputField = elem;
+        }
+        else
+        {
+            if (vimperator.hasMode(vimperator.modes.INSERT) ||
+                vimperator.hasMode(vimperator.modes.TEXTAREA))
+                    vimperator.setMode(vimperator.modes.NORMAL); // FIXME: remember previous mode
+        }
+    }
+
+    // global escape handler, is called in ALL modes
+    // XXX: split up and move to mappings.js as closures?
     this.onEscape = function()
     {
         if (!vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY))
         {
-            // setting this option will trigger an observer which will care about all other details
-            if (vimperator.hasMode(vimperator.modes.CARET))
-                Options.setFirefoxPref("accessibility.browsewithcaret", false);
-
             // clear any selection made
+            // FIXME: need to make more general to allow caret/visual mode also for text fields
             var selection = window.content.getSelection();
             selection.collapseToStart();
 
-            vimperator.setMode(vimperator.modes.NORMAL);
-            vimperator.commandline.clear();
-            vimperator.hints.disableHahMode();
-            vimperator.statusline.updateUrl();
-            vimperator.focusContent();
+            if (vimperator.hasMode(vimperator.modes.VISUAL))
+            {
+                if (vimperator.hasMode(vimperator.modes.TEXTAREA))
+                    vimperator.editor.unselectText();
+                vimperator.setMode(vimperator.getMode()[1], vimperator.modes.NONE);
+            }
+            else if (vimperator.hasMode(vimperator.modes.CARET))
+            {
+                // setting this option will trigger an observer which will care about all other details
+                // like setting the NORMAL mode
+                Options.setFirefoxPref("accessibility.browsewithcaret", false);
+            }
+            else if (vimperator.hasMode(vimperator.modes.INSERT))
+            {
+                if(vimperator.hasMode(vimperator.modes.TEXTAREA))
+                    vimperator.setMode(vimperator.modes.TEXTAREA);
+                else
+                {
+                    vimperator.editor.unselectText();
+                    vimperator.setMode(vimperator.modes.NORMAL);
+                    vimperator.focusContent();
+                }
+            }
+            else
+            {
+                vimperator.setMode(vimperator.modes.NORMAL);
+                vimperator.commandline.clear();
+                vimperator.hints.disableHahMode();
+                vimperator.statusline.updateUrl();
+                vimperator.focusContent();
+            }
+
+
         }
     }
 
+    // this keypress handler gets always called first, even if e.g.
+    // the commandline has focus
     this.onKeyPress = function(event)
     {
         var key = vimperator.events.toString(event);
         if (!key)
              return false;
-        // sometimes the non-content area has focus, making our keys not work
-        //    if (event.target.id == "main-window")
-        //        alert("focusContent();");
 
+        var stop = true; // set to false if we should NOT consume this event but let also firefox handle it
+
+        // menus have their own command handlers
         if (vimperator.hasMode(vimperator.modes.MENU))
             return false;
 
-        // XXX: ugly hack for now pass certain keys to firefox as they are without beeping
-        // also fixes key navigation in menus, etc.
-        if (key == "" || key == "" || key == "" || key == "" || key == "")
-            return false;
-
-
-        // XXX: for now only, later: input mappings if form element focused
-        if (isFormElemFocused())
-        {
-            if (key == "")
-            {
-                var elt = window.document.commandDispatcher.focusedElement;
-
-                if (elt.setSelectionRange && readFromClipboard())
-                    // readFromClipboard would return 'undefined' if not checked
-                    // dunno about .setSelectionRange
-                {
-                    var rangeStart = elt.selectionStart; // caret position
-                    var rangeEnd = elt.selectionEnd;
-                    var tempStr1 = elt.value.substring(0,rangeStart);
-                    var tempStr2 = readFromClipboard();
-                    var tempStr3 = elt.value.substring(rangeEnd);
-                    elt.value = tempStr1 + tempStr2  + tempStr3;
-                    elt.selectionStart = rangeStart + tempStr2.length;
-                    elt.selectionEnd = elt.selectionStart;
-                    // prevent additional firefox-clipboard pasting
-                    event.preventDefault();
-                }
-            }
-            return false;
-            //vimperator.setMode(vimperator.modes.CARET); // FOR TESTING ONLY
-        }
-
         // handle Escape-one-key mode (Ctrl-v)
         if (vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY) && !vimperator.hasMode(vimperator.modes.ESCAPE_ALL_KEYS))
         {
@@ -455,11 +483,23 @@ function Events() //{{{
             if (vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY))
                 vimperator.removeMode(null, vimperator.modes.ESCAPE_ONE_KEY); // and then let flow continue
             else if (key == "" || key == "" || key == "")
-                ; // let flow continue to handle these keys
+                ; // let flow continue to handle these keys to cancel escape-all-keys mode
             else
                 return false;
         }
 
+        // FIXME: proper way is to have a better onFocus handler which also handles events for the XUL
+        if (!vimperator.hasMode(vimperator.modes.TEXTAREA) &&
+            !vimperator.hasMode(vimperator.modes.INSERT) &&
+            isFormElemFocused()) // non insert mode, but e.g. the location bar has focus
+                return false;
+
+        // XXX: ugly hack for now pass certain keys to firefox as they are without beeping
+        // also fixes key navigation in combo boxes, etc.
+        if (key == "" || key == "")// || key == "" || key == "" || key == "" || key == "")
+            return false;
+
+
     //  // FIXME: handle middle click in content area {{{
     //  //     alert(event.target.id);
     //  if (/*event.type == 'mousedown' && */event.button == 1 && event.target.id == 'content')
@@ -486,8 +526,8 @@ function Events() //{{{
         if (vimperator.hasMode(vimperator.modes.HINTS))
         {
             // never propagate this key to firefox, when hints are visible
-            event.preventDefault();
-            event.stopPropagation();
+            //event.preventDefault();
+            //event.stopPropagation();
 
             var map = vimperator.mappings.get(vimperator.modes.HINTS, key);
             if (map)
@@ -568,11 +608,8 @@ function Events() //{{{
         if ((vimperator.input.buffer + key).match(/^[1-9][0-9]*$/))
         {
             vimperator.input.buffer += key;
-            vimperator.statusline.updateInputBuffer(vimperator.input.buffer);
-            return true;
         }
-
-        if (vimperator.input.pendingMap)
+        else if (vimperator.input.pendingMap)
         {
             vimperator.input.buffer = "";
 
@@ -580,8 +617,6 @@ function Events() //{{{
                 vimperator.input.pendingMap.execute(null, vimperator.input.count, key);
 
             vimperator.input.pendingMap = null;
-            event.preventDefault();
-            event.stopPropagation();
         }
         else if (map = vimperator.mappings.get(mode, candidate_command))
         {
@@ -596,23 +631,30 @@ function Events() //{{{
             else
             {
                 vimperator.input.buffer = "";
+                // vimperator.log("executed: " + candidate_command + " in mode: " + mode, 8);
                 map.execute(null, vimperator.input.count);
             }
-
-            event.preventDefault();
-            event.stopPropagation();
         }
         else if (vimperator.mappings.getCandidates(mode, candidate_command).length > 0)
         {
             vimperator.input.buffer += key;
-            event.preventDefault();
-            event.stopPropagation();
         }
         else
         {
             vimperator.input.buffer = "";
             vimperator.input.pendingMap = null;
-            vimperator.beep();
+
+            if (vimperator.hasMode(vimperator.modes.INSERT) ||
+                vimperator.hasMode(vimperator.modes.COMMAND_LINE))
+                    stop = false; // command was not a vimperator command, maybe it is a firefox command
+            else
+                vimperator.beep();
+        }
+
+        if (stop)
+        {
+            event.preventDefault();
+            event.stopPropagation();
         }
 
         vimperator.statusline.updateInputBuffer(vimperator.input.buffer);
diff --git a/chrome/content/vimperator/mappings.js b/chrome/content/vimperator/mappings.js
index 6bef5310..beb484c3 100644
--- a/chrome/content/vimperator/mappings.js
+++ b/chrome/content/vimperator/mappings.js
@@ -26,12 +26,12 @@ the provisions above, a recipient may use your version of this file under
 the terms of any one of the MPL, the GPL or the LGPL.
 }}} ***** END LICENSE BLOCK *****/
 
-function Map(mode, cmds, action, extra_info) //{{{
+function Map(modes, cmds, action, extra_info) //{{{
 {
-    if (!mode || (!cmds || !cmds.length) || !action)
+    if (!modes || (!cmds || !cmds.length) || !action)
         return null;
 
-    this.mode = mode;
+    this.modes = modes;
     this.names = cmds;
     this.action = action;
 
@@ -108,10 +108,14 @@ function Mappings() //{{{
 
     function addDefaultMap(map)
     {
-        if (!main[map.mode])
-            main[map.mode] = [];
+        for (var i = 0; i < map.modes.length; i++)
+        {
+            var mode = map.modes[i];
+            if (!main[mode])
+                main[mode] = [];
 
-        main[map.mode].push(map);
+            main[mode].push(map);
+        }
     }
 
     function getMap(mode, cmd, stack)
@@ -206,7 +210,10 @@ function Mappings() //{{{
     this.add = function(map)
     {
         for (var i = 0; i < map.names.length; i++)
-            removeMap(map.mode, map.names[i]);
+        {
+            for (var j = 0; j < map.modes.length; j++)
+                removeMap(map.modes[0], map.names[i]);
+        }
 
         user[map.mode].push(map);
     }
@@ -290,26 +297,46 @@ function Mappings() //{{{
     /////////////////////////////////////////////////////////////////////////////}}}
     ////////////////////// DEFAULT MAPPINGS ////////////////////////////////////////
     /////////////////////////////////////////////////////////////////////////////{{{
+    var anymode = [vimperator.modes.NORMAL,
+                   vimperator.modes.INSERT,
+                   vimperator.modes.VISUAL,
+                   vimperator.modes.HINTS,
+                   //vimperator.modes.COMMAND_LINE,
+                   vimperator.modes.CARET,
+                   vimperator.modes.TEXTAREA];
+    var any_non_insertmode = [vimperator.modes.NORMAL,
+                   vimperator.modes.VISUAL,
+                   vimperator.modes.HINTS,
+                   vimperator.modes.CARET,
+                   vimperator.modes.TEXTAREA];
 
     //
     // Normal mode
     // {{{
     // vimperator management
-    addDefaultMap(new Map(vimperator.modes.NORMAL, [""],
+    addDefaultMap(new Map(anymode, [""],
         function() { vimperator.help(null); },
         {
             short_help: "Open help window",
             help: "The default section is shown, if you need help for a specific topic, try :help <F1>."
         }
     ));
-    addDefaultMap(new Map(vimperator.modes.NORMAL, [":"],
+    addDefaultMap(new Map(anymode, ["", ""],
+        vimperator.events.onEscape,
+        {
+            short_help: "Focus content",
+            help: "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." + } + )); + addDefaultMap(new Map(any_non_insertmode, [":"], function() { vimperator.commandline.open(":", "", vimperator.modes.EX); }, { short_help: "Start command line mode", help: "In command line mode, you can perform extended commands, which may require arguments." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["i"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["i"], function() { Options.setFirefoxPref("accessibility.browsewithcaret", true); @@ -321,7 +348,7 @@ function Mappings() //{{{ "NOTE: Movement keys are not really working for the moment." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["I"], + addDefaultMap(new Map([vimperator.modes.NORMAL, vimperator.modes.HINTS], ["I"], // XXX: I is bad, needs to change function() { vimperator.addMode(null, vimperator.modes.ESCAPE_ALL_KEYS); }, { short_help: "Disable Vimperator keys", @@ -331,7 +358,7 @@ function Mappings() //{{{ "in this mode to the web page, prepend it with <C-v>." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, [""], + addDefaultMap(new Map(anymode, [""], function() { vimperator.addMode(null, vimperator.modes.ESCAPE_ONE_KEY); }, { short_help: "Escape next key", @@ -340,14 +367,14 @@ function Mappings() //{{{ "When in 'ignorekeys' mode (activated by <I>), <C-v> will pass the next key to Vimperator instead of the web page." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, [""], + addDefaultMap(new Map([vimperator.modes.NORMAL], [""], BrowserStop, { short_help: "Stop loading", help: "Stops loading the current web page." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, [""], + addDefaultMap(new Map(anymode, [""], function() { return; }, { short_help: "Do nothing", @@ -355,16 +382,8 @@ function Mappings() //{{{ ":map <C-n> <Nop> will prevent <C-n> from doing anything." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["", ""], - vimperator.events.onEscape, - { - short_help: "Focus content", - help: "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." - } - )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["]f"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["]f"], function(count) { vimperator.buffer.shiftFrameFocus(count > 1 ? count : 1, true); }, { short_help: "Focus next frame", @@ -372,7 +391,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["[f"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["[f"], function(count) { vimperator.buffer.shiftFrameFocus(count > 1 ? count : 1, false); }, { short_help: "Focus previous frame", @@ -380,14 +399,14 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["b"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["b"], function() { vimperator.commandline.open(":", "buffer ", vimperator.modes.EX); }, { short_help: "Open a prompt to switch buffers", help: "Typing the corresponding number switches to this buffer." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["B"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["B"], function() { vimperator.buffer.list(true); }, { short_help: "Toggle buffer list", @@ -395,7 +414,7 @@ function Mappings() //{{{ "WARNING: This mapping may be removed/changed in future." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["d"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["d"], function(count) { vimperator.tabs.remove(getBrowser().mCurrentTab, count, false, 0); }, { short_help: "Delete current buffer (=tab)", @@ -403,7 +422,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["D"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["D"], function(count) { vimperator.tabs.remove(getBrowser().mCurrentTab, count, true, 0); }, { short_help: "Delete current buffer (=tab)", @@ -411,14 +430,14 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gh"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["gh"], BrowserHome, { short_help: "Go home", help: "Opens the homepage in the current tab." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gH"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["gH"], function() { var homepages = gHomeButton.getHomePage(); @@ -431,7 +450,20 @@ function Mappings() //{{{ "Whether the new tab is activated or not depends on the 'activate' option.
" } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["go"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["gi"], + function() + { + if (vimperator.buffer.lastInputField) + vimperator.buffer.lastInputField.focus(); + else // TODO: Focus first input field on page, or beep if none found + vimperator.beep(); + }, + { + short_help: "Focus last used input field", + help: "TODO" + } + )); + addDefaultMap(new Map([vimperator.modes.NORMAL], ["go"], function(arg) { vimperator.quickmarks.jumpTo(arg, vimperator.CURRENT_TAB) }, { short_help: "Jump to a QuickMark in the current tab", @@ -441,7 +473,7 @@ function Mappings() //{{{ flags: Mappings.flags.ARGUMENT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gn"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["gn"], function(arg) { vimperator.quickmarks.jumpTo(arg, @@ -457,7 +489,7 @@ function Mappings() //{{{ flags: Mappings.flags.ARGUMENT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gP"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["gP"], function() { vimperator.open(readFromClipboard(), @@ -469,7 +501,7 @@ function Mappings() //{{{ help: "Works like P, but inverts the 'activate' option." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gt", "", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["gt", "", ""], function(count) { vimperator.tabs.select(count > 0 ? count -1: "+1", count > 0 ? false : true); }, { short_help: "Go to the next tab", @@ -477,7 +509,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gT", "", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["gT", "", ""], function(count) { vimperator.tabs.select(count > 0 ? count -1: "-1", count > 0 ? false : true); }, { short_help: "Go to the previous tab", @@ -485,7 +517,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ['', ''], + addDefaultMap(new Map([vimperator.modes.NORMAL], ['', ''], function() { if (vimperator.tabs.getTab() == vimperator.tabs.alternate) @@ -512,7 +544,7 @@ function Mappings() //{{{ help: "The alternate tab is the last selected tab. This provides a quick method of toggling between two tabs." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["m"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["m"], function(arg) { if (/[^a-zA-Z]/.test(arg)) @@ -530,7 +562,7 @@ function Mappings() //{{{ flags: Mappings.flags.ARGUMENT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["'", "`"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["'", "`"], function(arg) { vimperator.marks.jumpTo(arg) }, { short_help: "Jump to the mark in the current buffer", @@ -539,7 +571,7 @@ function Mappings() //{{{ flags: Mappings.flags.ARGUMENT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["M"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["M"], function(arg) { if (/[^a-zA-Z0-9]/.test(arg)) @@ -558,28 +590,28 @@ function Mappings() //{{{ flags: Mappings.flags.ARGUMENT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["o"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["o"], function() { vimperator.commandline.open(":", "open ", vimperator.modes.EX); }, { short_help: "Open one or more URLs in the current tab", help: "See :open for more details." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["O"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["O"], function() { vimperator.commandline.open(":", "open " + vimperator.buffer.URL, vimperator.modes.EX); }, { short_help: "Open one or more URLs in the current tab, based on current location", help: "Works like o, but preselects current URL in the :open query." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["p", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["p", ""], function() { vimperator.open(readFromClipboard()); }, { short_help: "Open (put) a URL based on the current clipboard contents in the current buffer", help: "You can also just select (for non-X11 users: copy) some non-URL text, and search for it with the default search engine or keyword (specified by the 'defsearch' option) with p." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["P"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["P"], function() { vimperator.open(readFromClipboard(), @@ -592,21 +624,21 @@ function Mappings() //{{{ "Whether the new buffer is activated, depends on the 'activate' option." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["r"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["r"], function() { vimperator.tabs.reload(getBrowser().mCurrentTab, false); }, { short_help: "Reload", help: "Forces reloading of the current page." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["R"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["R"], function() { vimperator.tabs.reload(getBrowser().mCurrentTab, true); }, { short_help: "Reload while skipping the cache", help: "Forces reloading of the current page skipping the cache." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["t"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["t"], function() { vimperator.commandline.open(":", "tabopen ", vimperator.modes.EX); }, { short_help: "Open one or more URLs in a new tab", @@ -614,14 +646,14 @@ function Mappings() //{{{ "See :tabopen for more details." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["T"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["T"], function() { vimperator.commandline.open(":", "tabopen " + vimperator.buffer.URL, vimperator.modes.EX); }, { short_help: "Open one or more URLs in a new tab, based on current location", help: "Works like t, but preselects current URL in the :tabopen query." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["u"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["u"], function(count) { vimperator.commands.undo("", false, count); }, { short_help: "Undo closing of a tab", @@ -629,7 +661,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["y"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["y"], function() { var url = vimperator.buffer.URL; @@ -641,7 +673,7 @@ function Mappings() //{{{ help: "When running in X11 the location is also put into the selection, which can be pasted with the middle mouse button." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["Y"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["Y"], function() { var sel = window.content.document.getSelection(); @@ -652,35 +684,35 @@ function Mappings() //{{{ help: "The currently selected text is copied to the system clipboard." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["zi", "+"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["zi", "+"], function(count) { vimperator.buffer.zoomIn(count > 1 ? count : 1); }, { short_help: "Zoom in current web page by 25%", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["zI"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["zI"], function(count) { vimperator.buffer.zoomIn((count > 1 ? count : 1) * 4); }, { short_help: "Zoom in current web page by 100%", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["zo", "-"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["zo", "-"], function(count) { vimperator.buffer.zoomOut(count > 1 ? count : 1); }, { short_help: "Zoom out current web page by 25%", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["zO"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["zO"], function(count) { vimperator.buffer.zoomOut((count > 1 ? count : 1) * 4); }, { short_help: "Zoom out current web page by 100%", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["zz"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["zz"], function(count) { vimperator.buffer.textZoom = count > 1 ? count : 100; }, { short_help: "Set zoom value of the web page", @@ -688,14 +720,14 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["ZQ"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["ZQ"], function() { vimperator.quit(false); }, { short_help: "Quit and don't save the session", help: "Works like :qall." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["ZZ"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["ZZ"], function() { vimperator.quit(true); }, { short_help: "Quit and save the session", @@ -705,20 +737,20 @@ function Mappings() //{{{ )); // scrolling commands - addDefaultMap(new Map(vimperator.modes.NORMAL, ["0", "^"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["0", "^"], function() { vimperator.buffer.scrollStart(); }, { short_help: "Scroll to the absolute left of the document", help: "Unlike in Vim, 0 and ^ work exactly the same way." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["$"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["$"], function() { vimperator.buffer.scrollEnd(); }, { short_help: "Scroll to the absolute right of the document" } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gg", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["gg", ""], function(count) { vimperator.buffer.scrollToPercentile(count > 0 ? count : 0); }, { short_help: "Goto the top of the document", @@ -726,7 +758,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["G", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["G", ""], function(count) { vimperator.buffer.scrollToPercentile(count >= 0 ? count : 100); }, { short_help: "Goto the end of the document", @@ -734,7 +766,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["h", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["h", ""], function(count) { vimperator.buffer.scrollColumns(-(count > 1 ? count : 1)); }, { short_help: "Scroll document to the left", @@ -743,7 +775,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["j", "", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["j", "", ""], function(count) { vimperator.buffer.scrollLines(count > 1 ? count : 1); }, { short_help: "Scroll document down", @@ -752,7 +784,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["k", "", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["k", "", ""], function(count) { vimperator.buffer.scrollLines(-(count > 1 ? count : 1)); }, { short_help: "Scroll document up", @@ -777,7 +809,7 @@ function Mappings() //{{{ win.scrollBy(0, vimperator.buffer.pageHeight / 2 * direction); } } - addDefaultMap(new Map(vimperator.modes.NORMAL, [""], + addDefaultMap(new Map([vimperator.modes.NORMAL], [""], function(count) { scrollByScrollSize(count, 1); }, { short_help: "Scroll window downwards in the buffer", @@ -786,7 +818,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, [""], + addDefaultMap(new Map([vimperator.modes.NORMAL], [""], function(count) { scrollByScrollSize(count, -1); }, { short_help: "Scroll window upwards in the buffer", @@ -795,7 +827,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["l", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["l", ""], function(count) { vimperator.buffer.scrollColumns(count > 1 ? count : 1); }, { short_help: "Scroll document to the right", @@ -804,7 +836,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["", "", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["", "", ""], function(count) { vimperator.buffer.scrollPages(-(count > 1 ? count : 1)); }, { short_help: "Scroll up a full page", @@ -812,7 +844,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["", "", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["", "", ""], function(count) { vimperator.buffer.scrollPages(count > 1 ? count : 1); }, { short_help: "Scroll down a full page", @@ -822,7 +854,7 @@ function Mappings() //{{{ )); // history manipulation and jumplist - addDefaultMap(new Map(vimperator.modes.NORMAL, [""], + addDefaultMap(new Map([vimperator.modes.NORMAL], [""], function(count) { vimperator.history.stepTo(-(count > 1 ? count : 1)); }, { short_help: "Go to an older position in the jump list", @@ -830,7 +862,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, [""], + addDefaultMap(new Map([vimperator.modes.NORMAL], [""], function(count) { vimperator.history.stepTo(count > 1 ? count : 1); }, { short_help: "Go to a newer position in the jump list", @@ -838,7 +870,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["H", "", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["H", "", ""], function(count) { vimperator.history.stepTo(-(count > 1 ? count : 1)); }, { short_help: "Go back in the browser history", @@ -846,7 +878,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["L", "", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["L", "", ""], function(count) { vimperator.history.stepTo(count > 1 ? count : 1); }, { short_help: "Go forward in the browser history", @@ -874,7 +906,7 @@ function Mappings() //{{{ else return false; } - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gu", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["gu", ""], function(count) { var gocmd = ""; @@ -897,7 +929,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gU", ""], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["gU", ""], function() { vimperator.open("..."); }, { short_help: "Go to the root of the website", @@ -907,7 +939,7 @@ function Mappings() //{{{ )); // hint managment - addDefaultMap(new Map(vimperator.modes.NORMAL, ["f"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["f"], function() { vimperator.hints.enableHahMode(vimperator.modes.QUICK_HINT); }, { short_help: "Start QuickHint mode", @@ -916,7 +948,7 @@ function Mappings() //{{{ "If you write the hint in ALLCAPS, the hint is followed in a background tab." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["F"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["F"], function() { vimperator.hints.enableHahMode(vimperator.modes.ALWAYS_HINT); }, { short_help: "Start AlwaysHint mode", @@ -926,7 +958,7 @@ function Mappings() //{{{ "Also, most Ctrl-prefixed shortcut keys are available in this mode for navigation." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, [";"], + addDefaultMap(new Map([vimperator.modes.NORMAL], [";"], function() { vimperator.hints.enableHahMode(vimperator.modes.EXTENDED_HINT); }, { short_help: "Start ExtendedHint mode", @@ -950,7 +982,7 @@ function Mappings() //{{{ )); // search management - addDefaultMap(new Map(vimperator.modes.NORMAL, ["/"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["/"], function() { vimperator.search.openSearchDialog(vimperator.modes.SEARCH_FORWARD); }, { short_help: "Search forward for a pattern", @@ -960,7 +992,7 @@ function Mappings() //{{{ "\"\\C\" forces case-sensitive matching for the whole pattern." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["?"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["?"], function() { vimperator.search.openSearchDialog(vimperator.modes.SEARCH_BACKWARD); }, { short_help: "Search backwards for a pattern", @@ -971,14 +1003,14 @@ function Mappings() //{{{ "NOTE: incremental searching currenly only works in the forward direction." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["n"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["n"], function() { vimperator.search.findAgain(false); }, { short_help: "Find next", help: "Repeat the last search 1 time (until count is supported)." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["N"], + addDefaultMap(new Map([vimperator.modes.NORMAL], ["N"], function() { vimperator.search.findAgain(true); }, { short_help: "Find previous", @@ -992,56 +1024,56 @@ function Mappings() //{{{ // {{{ // action keys - addDefaultMap(new Map(vimperator.modes.HINTS, ["o"], + addDefaultMap(new Map([vimperator.modes.HINTS], ["o"], function() { vimperator.hints.openHints(false, false); }, { cancel_mode: true, always_active: false } )); - addDefaultMap(new Map(vimperator.modes.HINTS, ["t"], + addDefaultMap(new Map([vimperator.modes.HINTS], ["t"], function() { vimperator.hints.openHints(true, false); }, { cancel_mode: true, always_active: false } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function() { vimperator.hints.openHints(false, true ); }, { cancel_mode: true, always_active: false } )); - addDefaultMap(new Map(vimperator.modes.HINTS, ["s"], + addDefaultMap(new Map([vimperator.modes.HINTS], ["s"], function() { vimperator.echoerr('Saving of links not yet implemented'); }, { cancel_mode: true, always_active: false } )); - addDefaultMap(new Map(vimperator.modes.HINTS, ["y"], + addDefaultMap(new Map([vimperator.modes.HINTS], ["y"], function() { vimperator.hints.yankUrlHints(); }, { cancel_mode: true, always_active: false } )); - addDefaultMap(new Map(vimperator.modes.HINTS, ["Y"], + addDefaultMap(new Map([vimperator.modes.HINTS], ["Y"], function() { vimperator.hints.yankTextHints(); }, { cancel_mode: true, always_active: false } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [","], + addDefaultMap(new Map([vimperator.modes.HINTS], [","], function() { vimperator.input.buffer += ','; vimperator.hints.setCurrentState(0); }, { cancel_mode: false, always_active: true } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [":"], + addDefaultMap(new Map([vimperator.modes.HINTS], [":"], function() { vimperator.commandline.open(':', '', vimperator.modes.EX); }, { cancel_mode: false, @@ -1050,7 +1082,7 @@ function Mappings() //{{{ )); // movement keys - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function(count) { vimperator.buffer.scrollLines(count > 1 ? count : 1); }, { cancel_mode: false, @@ -1058,7 +1090,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function(count) { vimperator.buffer.scrollLines(-(count > 1 ? count : 1)); }, { cancel_mode: false, @@ -1066,21 +1098,21 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function() { vimperator.buffer.scrollTop(); }, { cancel_mode: false, always_active: true } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function() { vimperator.buffer.scrollBottom(); }, { cancel_mode: false, always_active: true } )); - addDefaultMap(new Map(vimperator.modes.HINTS, ["", ""], + addDefaultMap(new Map([vimperator.modes.HINTS], ["", ""], function(count) { vimperator.buffer.scrollPages(-(count > 1 ? count : 1)); }, { cancel_mode: false, @@ -1088,7 +1120,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.HINTS, ["", ""], + addDefaultMap(new Map([vimperator.modes.HINTS], ["", ""], function(count) { vimperator.buffer.scrollPages(count > 1 ? count : 1); }, { cancel_mode: false, @@ -1096,7 +1128,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function() { vimperator.buffer.scrollColumns(-(count > 1 ? count : 1)); }, { cancel_mode: false, @@ -1104,7 +1136,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function() { vimperator.buffer.scrollLines(count > 1 ? count : 1); }, { cancel_mode: false, @@ -1112,7 +1144,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function() { vimperator.buffer.scrollLines(-(count > 1 ? count : 1)); }, { cancel_mode: false, @@ -1120,7 +1152,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function() { vimperator.buffer.scrollColumns(count > 1 ? count : 1); }, { cancel_mode: false, @@ -1130,14 +1162,14 @@ function Mappings() //{{{ )); // tab management - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function() { vimperator.tabs.select('+1', true); }, { cancel_mode: true, always_active: true } )); // same as gt, but no count supported - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function() { vimperator.tabs.select('-1', true); }, { cancel_mode: true, @@ -1146,7 +1178,7 @@ function Mappings() //{{{ )); // navigation - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function(count) { vimperator.history.stepTo(count > 0 ? -count : -1); }, { cancel_mode: false, @@ -1154,7 +1186,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function(count) { vimperator.history.stepTo(count > 1 ? count : 1); }, { cancel_mode: false, @@ -1162,7 +1194,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function(count) { vimperator.history.stepTo(count > 0 ? -count : -1); }, { cancel_mode: false, @@ -1170,7 +1202,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function(count) { vimperator.history.stepTo(count > 1 ? count : 1); }, { cancel_mode: false, @@ -1178,7 +1210,7 @@ function Mappings() //{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function() { vimperator.tabs.remove(getBrowser().mCurrentTab, vimperator.input.count, false, 0); }, { cancel_mode: true, @@ -1187,49 +1219,49 @@ function Mappings() //{{{ )); // cancel_mode hint mode keys - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function() { ; }, { cancel_mode: true, always_active: true } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function() { ; }, { cancel_mode: true, always_active: true } )); - addDefaultMap(new Map(vimperator.modes.HINTS, [""], + addDefaultMap(new Map([vimperator.modes.HINTS], [""], function() { ; }, { cancel_mode: true, always_active: true } )); - addDefaultMap(new Map(vimperator.modes.HINTS, ["", "", ""], + /*addDefaultMap(new Map([vimperator.modes.HINTS], ["", "", ""], function() { ; }, { cancel_mode: true, always_active: true } - )); - //}}} - //}}} + ));*/ - + // }}} // Caret mode + // {{{ + function getSelectionController() { - return getBrowser().docShell - .QueryInterface(Components.interfaces.nsIInterfaceRequestor) - .getInterface(Components.interfaces.nsISelectionDisplay) - .QueryInterface(Components.interfaces.nsISelectionController); + return getBrowser().docShell + .QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsISelectionDisplay) + .QueryInterface(Components.interfaces.nsISelectionController); } // prevent beeping on esc, should unify - addDefaultMap(new Map(vimperator.modes.CARET, ["", "", ""], + /*addDefaultMap(new Map([vimperator.modes.CARET], ["", "", ""], function() { if (!vimperator.hasMode(vimperator.modes.VISUAL)) @@ -1244,142 +1276,109 @@ function Mappings() //{{{ } }, { } - )); - addDefaultMap(new Map(vimperator.modes.CARET, ["v"], - function(count) - { - vimperator.addMode(null, vimperator.modes.VISUAL); - }, + ));*/ + + addDefaultMap(new Map([vimperator.modes.CARET, vimperator.modes.TEXTAREA], ["v"], + function(count) { vimperator.setMode(vimperator.modes.VISUAL, vimperator.getMode()[0]); }, { short_help: "Start visual mode", - help: "Must be in caret mode for now, later also for text fields" + help: "Works for caret mode and textarea mode." } )); - addDefaultMap(new Map(vimperator.modes.CARET, ["j", ""], + addDefaultMap(new Map([vimperator.modes.CARET], ["j", ""], function(count) { if (count < 1) count = 1; while(count--) - getSelectionController().lineMove(true, vimperator.hasMode(vimperator.modes.VISUAL)); + getSelectionController().lineMove(true, false); }, - { - flags: Mappings.flags.COUNT - } + { flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.CARET, ["k", ""], + addDefaultMap(new Map([vimperator.modes.CARET], ["k", ""], function(count) { if (count < 1) count = 1; while(count--) - getSelectionController().lineMove(false, vimperator.hasMode(vimperator.modes.VISUAL)); + getSelectionController().lineMove(false, false); }, - { - flags: Mappings.flags.COUNT - } + { flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.CARET, ["h", ""], + addDefaultMap(new Map([vimperator.modes.CARET], ["h", ""], function(count) { if (count < 1) count = 1; while(count--) - getSelectionController().characterMove(false, vimperator.hasMode(vimperator.modes.VISUAL)); + getSelectionController().characterMove(false, false); }, - { - flags: Mappings.flags.COUNT - } + { flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.CARET, ["l", ""], + addDefaultMap(new Map([vimperator.modes.CARET], ["l", ""], function(count) { if (count < 1) count = 1; while(count--) - getSelectionController().characterMove(true, vimperator.hasMode(vimperator.modes.VISUAL)); + getSelectionController().characterMove(true, false); }, - { - flags: Mappings.flags.COUNT - } + { flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.CARET, ["b", "B"], + addDefaultMap(new Map([vimperator.modes.CARET], ["b", "B", ""], function(count) { if (count < 1) count = 1; while(count--) - getSelectionController().wordMove(false, vimperator.hasMode(vimperator.modes.VISUAL)); + getSelectionController().wordMove(false, false); }, - { - flags: Mappings.flags.COUNT - } + { flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.CARET, ["w", "W"], + addDefaultMap(new Map([vimperator.modes.CARET], ["w", "W", ""], function(count) { if (count < 1) count = 1; while(count--) - getSelectionController().wordMove(true, vimperator.hasMode(vimperator.modes.VISUAL)); + getSelectionController().wordMove(true, false); }, - { - flags: Mappings.flags.COUNT - } + { flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.CARET, ["", ""], + addDefaultMap(new Map([vimperator.modes.CARET], ["", ""], function(count) { if (count < 1) count = 1; while(count--) - getSelectionController().pageMove(true, vimperator.hasMode(vimperator.modes.VISUAL)); + getSelectionController().pageMove(true, false); }, - { - flags: Mappings.flags.COUNT - } + { flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.CARET, ["", ""], + addDefaultMap(new Map([vimperator.modes.CARET], ["", ""], function(count) { if (count < 1) count = 1; while(count--) - getSelectionController().pageMove(false, vimperator.hasMode(vimperator.modes.VISUAL)); - + getSelectionController().pageMove(false, false); }, - { - flags: Mappings.flags.COUNT - } + { flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.CARET, ["gg", ""], - function(count) - { - getSelectionController().completeMove(false, vimperator.hasMode(vimperator.modes.VISUAL)); - }, + addDefaultMap(new Map([vimperator.modes.CARET], ["gg", ""], + function(count) { getSelectionController().completeMove(false, false); }, { } )); - addDefaultMap(new Map(vimperator.modes.CARET, ["G", ""], - function(count) - { - // no count support for now - getSelectionController().completeMove(true, vimperator.hasMode(vimperator.modes.VISUAL)); - }, + addDefaultMap(new Map([vimperator.modes.CARET], ["G", ""], + function(count) { getSelectionController().completeMove(true, false); }, { } )); - addDefaultMap(new Map(vimperator.modes.CARET, ["0", "^"], - function(count) - { - getSelectionController().intraLineMove(false, vimperator.hasMode(vimperator.modes.VISUAL)); - }, + addDefaultMap(new Map([vimperator.modes.CARET], ["0", "^", ""], + function(count) { getSelectionController().intraLineMove(false, false); }, { } )); - addDefaultMap(new Map(vimperator.modes.CARET, ["$"], - function(count) - { - getSelectionController().intraLineMove(true, vimperator.hasMode(vimperator.modes.VISUAL)); - }, + addDefaultMap(new Map([vimperator.modes.CARET], ["$", ""], + function(count) { getSelectionController().intraLineMove(true, false); }, { } )); - // BIG FIXME: unify event handling to allow keys to be valid in more than one mode!! - addDefaultMap(new Map(vimperator.modes.CARET, ["*"], + addDefaultMap(new Map([vimperator.modes.NORMAL, vimperator.modes.CARET, vimperator.modes.TEXTAREA], ["*"], function(count) { vimperator.search.searchSubmitted(vimperator.getCurrentWord(), false); @@ -1387,15 +1386,7 @@ function Mappings() //{{{ }, { } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["*"], - function(count) - { - vimperator.search.searchSubmitted(vimperator.getCurrentWord(), false); - vimperator.search.findAgain(); - }, - { } - )); - addDefaultMap(new Map(vimperator.modes.CARET, ["#"], + addDefaultMap(new Map([vimperator.modes.NORMAL, vimperator.modes.CARET, vimperator.modes.TEXTAREA], ["#"], function(count) { vimperator.search.searchSubmitted(vimperator.getCurrentWord(), true); @@ -1403,14 +1394,369 @@ function Mappings() //{{{ }, { } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["#"], + + // }}} + // VISUAL mode + // {{{ + + addDefaultMap(new Map([vimperator.modes.VISUAL], ["j", ""], function(count) { - vimperator.search.searchSubmitted(vimperator.getCurrentWord(), true); - vimperator.search.findAgain(); + if (count < 1) count = 1; + while(count--) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + getSelectionController().lineMove(true, true); + else + vimperator.editor.executeCommand("cmd_selectLineNext"); + } + }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["k", ""], + function(count) + { + if (count < 1) count = 1; + while(count--) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + getSelectionController().lineMove(false, true); + else + vimperator.editor.executeCommand("cmd_selectLinePrevious"); + } + }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["h", ""], + function(count) + { + if (count < 1) count = 1; + while(count--) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + getSelectionController().characterMove(false, true); + else + vimperator.editor.executeCommand("cmd_selectCharPrevious"); + } + }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["l", ""], + function(count) + { + if (count < 1) count = 1; + while(count--) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + getSelectionController().characterMove(true, true); + else + vimperator.editor.executeCommand("cmd_selectCharNext"); + } + }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["b", "B"], + function(count) + { + if (count < 1) count = 1; + while(count--) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + getSelectionController().wordMove(false, true); + else + vimperator.editor.executeCommand("cmd_selectWordPrevious"); + } + }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["w", "W"], + function(count) + { + if (count < 1) count = 1; + while(count--) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + getSelectionController().wordMove(true, true); + else + vimperator.editor.executeCommand("cmd_selectWordNext"); + } + }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["", ""], + function(count) + { + if (count < 1) count = 1; + while(count--) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + getSelectionController().pageMove(true, true); + else + ;//vimperator.editor.executeCommand("cmd_selectWordNext"); + } + }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["", ""], + function(count) + { + if (count < 1) count = 1; + while(count--) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + getSelectionController().pageMove(false, true); + else + ;//vimperator.editor.executeCommand("cmd_selectWordNext"); + } + }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["gg", ""], + function(count) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + getSelectionController().completeMove(false, true); + else + vimperator.editor.executeCommand("cmd_selectTop"); }, { } )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["G", ""], + function(count) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + getSelectionController().completeMove(true, true); + else + vimperator.editor.executeCommand("cmd_selectBottom"); + }, + { } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["0", "^", ""], + function(count) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + getSelectionController().intraLineMove(false, true); + else + vimperator.editor.executeCommand("cmd_selectBeginLine"); + }, + { } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["$", ""], + function(count) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + getSelectionController().intraLineMove(true, true); + else + vimperator.editor.executeCommand("cmd_selectEndLine"); + }, + { } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["c", "s"], + function(count) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + vimperator.beep(); + else + { + vimperator.editor.executeCommand("cmd_cut"); + vimperator.setMode(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); + } + }, + { } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["d"], + function(count) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + vimperator.beep(); + else + { + vimperator.editor.executeCommand("cmd_cut"); + vimperator.setMode(vimperator.modes.TEXTAREA); + } + }, + { } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL], ["y"], + function(count) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + vimperator.beep(); // TODO: yanking is possible for caret mode + else + { + vimperator.editor.executeCommand("cmd_copy"); + vimperator.editor.unselectText(); + vimperator.setMode(vimperator.modes.TEXTAREA); + } + }, + { } + )); + addDefaultMap(new Map([vimperator.modes.VISUAL, vimperator.modes.TEXTAREA], ["p"], + function(count) + { + if (vimperator.hasMode(vimperator.modes.CARET)) + vimperator.beep(); // TODO: yanking is possible for caret mode + else + { + vimperator.editor.executeCommand("cmd_paste"); + vimperator.setMode(vimperator.modes.TEXTAREA); + } + }, + { } + )); + + + // }}} + // Textarea mode + // {{{ + + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["i"], + function(count) { vimperator.setMode(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); }, + { } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["a"], + function(count) + { + vimperator.editor.executeCommand("cmd_charNext", 1); + vimperator.setMode(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); + }, + { } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["I", "gI"], + function(count) + { + vimperator.editor.executeCommand("cmd_beginLine", 1); + vimperator.setMode(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); + }, + { } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["A"], + function(count) + { + vimperator.editor.executeCommand("cmd_endLine", 1); + vimperator.setMode(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); + }, + { } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["s"], + function(count) + { + vimperator.editor.executeCommand("cmd_deleteCharForward", 1); + vimperator.setMode(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); + }, + { } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["S"], + function(count) + { + vimperator.editor.executeCommand("cmd_deleteToEndOfLine", 1); + vimperator.editor.executeCommand("cmd_deleteToBeginningOfLine", 1); + vimperator.setMode(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); + }, + { } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["C"], + function(count) + { + vimperator.editor.executeCommand("cmd_deleteToEndOfLine", 1); + vimperator.setMode(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); + }, + { } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["v"], + function(count) { vimperator.setMode(vimperator.modes.VISUAL, vimperator.modes.TEXTAREA); }, + { } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["u"], + function(count) { vimperator.editor.executeCommand("cmd_undo", count); }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], [""], + function(count) { vimperator.editor.executeCommand("cmd_redo", count); }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["j", "", ""], + function(count) { vimperator.editor.executeCommand("cmd_lineNext", count); }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["k", ""], + function(count) { vimperator.editor.executeCommand("cmd_linePrevious", count); }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["h", "", ""], + function(count) { vimperator.editor.executeCommand("cmd_charPrevious", count); }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["l", "", ""], + function(count) { vimperator.editor.executeCommand("cmd_charNext", count); }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["w", "W", ""], + function(count) { vimperator.editor.executeCommand("cmd_wordNext", count); }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["b", "B", ""], + function(count) { vimperator.editor.executeCommand("cmd_wordPrevious", 1); }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["gg", ""], + function(count) { vimperator.editor.executeCommand("cmd_moveTop", 1); }, + { } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["G", ""], + function(count) { vimperator.editor.executeCommand("cmd_moveBottom", 1); }, + { } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["0", "^", ""], + function(count) { vimperator.editor.executeCommand("cmd_beginLine", 1); }, + { } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["$", ""], + function(count) { vimperator.editor.executeCommand("cmd_endLine", 1); }, + { } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["", ""], + function(count) { vimperator.editor.executeCommand("cmd_movePageDown", count); }, + { flags: Mappings.flags.COUNT } + )); + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["", ""], + function(count) { vimperator.editor.executeCommand("cmd_movePageUp", count); }, + { flags: Mappings.flags.COUNT } + )); + + // }}} + // INSERT mode + // {{{ + addDefaultMap(new Map([vimperator.modes.INSERT, vimperator.modes.COMMAND_LINE], [""], + function() { vimperator.editor.executeCommand("cmd_deleteWordBackward", 1); }, + { } + )); + addDefaultMap(new Map([vimperator.modes.INSERT, vimperator.modes.COMMAND_LINE], [""], + function() { vimperator.editor.executeCommand("cmd_deleteToBeginningOfLine", 1); }, + { } + )); + addDefaultMap(new Map([vimperator.modes.INSERT, vimperator.modes.COMMAND_LINE], [""], + function() { vimperator.editor.executeCommand("cmd_deleteToEndOfLine", 1); }, + { } + )); + addDefaultMap(new Map([vimperator.modes.INSERT, vimperator.modes.COMMAND_LINE], ["", ""], + function() { vimperator.editor.executeCommand("cmd_beginLine", 1); }, + { } + )); + addDefaultMap(new Map([vimperator.modes.INSERT, vimperator.modes.COMMAND_LINE], ["", ""], + function() { vimperator.editor.executeCommand("cmd_endLine", 1); }, + { } + )); + addDefaultMap(new Map([vimperator.modes.INSERT, vimperator.modes.COMMAND_LINE], ["", ""], + function() { vimperator.editor.executeCommand("cmd_deleteCharBackward", 1); }, + { } + )); + addDefaultMap(new Map([vimperator.modes.INSERT, vimperator.modes.COMMAND_LINE], [""], + function() { vimperator.editor.pasteClipboard(); }, + { } + )); + + //}}} } //}}} diff --git a/chrome/content/vimperator/ui.js b/chrome/content/vimperator/ui.js index ea634ac8..ff9327ea 100644 --- a/chrome/content/vimperator/ui.js +++ b/chrome/content/vimperator/ui.js @@ -226,7 +226,7 @@ function CommandLine() //{{{ this.echo = function(str, flags) { var focused = document.commandDispatcher.focusedElement; - if (/*!echo_allowed && focused && */focused == command_widget.inputField) + if (focused && focused == command_widget.inputField || focused == multiline_input_widget.inputField) return false; if (typeof str != "string") @@ -249,7 +249,7 @@ function CommandLine() //{{{ this.echoErr = function(str) { var focused = document.commandDispatcher.focusedElement; - if (/*!echo_allowed && focused && */focused == command_widget.inputField) + if (focused && focused == command_widget.inputField || focused == multiline_input_widget.inputField) return false; setErrorStyle(); @@ -296,6 +296,7 @@ function CommandLine() //{{{ { multiline_input_widget.collapsed = true; multiline_output_widget.collapsed = true; + completionlist.hide(); setPrompt(" "); // looks faster than an empty string as most prompts are 1 char long setCommand(""); @@ -326,6 +327,9 @@ function CommandLine() //{{{ } else if (event.type == "keypress") { + if (!cur_extended_mode) + return; + var key = vimperator.events.toString(event); /* user pressed ENTER to carry out a command */ @@ -550,7 +554,6 @@ function CommandLine() //{{{ var key = vimperator.events.toString(event); if (vimperator.events.isAcceptKey(key)) { - //var lines = multiline_input_widget.value.substr(0, multiline_input_widget.selectionStart).split(/\n/); var text = multiline_input_widget.value.substr(0, multiline_input_widget.selectionStart); if (text.match(multiline_regexp)) { diff --git a/chrome/content/vimperator/vimperator.js b/chrome/content/vimperator/vimperator.js index 17d57e22..6bbfd4fe 100644 --- a/chrome/content/vimperator/vimperator.js +++ b/chrome/content/vimperator/vimperator.js @@ -41,6 +41,7 @@ const vimperator = (function() //{{{ HINTS: 1 << 3, COMMAND_LINE: 1 << 4, CARET: 1 << 5, // text cursor is visible + TEXTAREA: 1 << 6, // text cursor is in a HTMLTextAreaElement // extended modes EX: 1 << 10, READ_MULTILINE: 1 << 11, @@ -60,6 +61,7 @@ const vimperator = (function() //{{{ mode_messages[modes.VISUAL] = "VISUAL"; mode_messages[modes.HINTS] = "HINTS"; mode_messages[modes.CARET] = "CARET"; // XXX: not a perfect name + mode_messages[modes.TEXTAREA] = "TEXTAREA"; // XXX: not a perfect name mode_messages[modes.ESCAPE_ONE_KEY] = "escape one key"; mode_messages[modes.ESCAPE_ALL_KEYS] = "escape all keys"; mode_messages[modes.ESCAPE_ONE_KEY | modes.ESCAPE_ALL_KEYS] = "pass one key"; @@ -90,7 +92,7 @@ const vimperator = (function() //{{{ var str_extended = mode_messages[extended_mode]; if (!str_mode && !str_extended) { - vimperator.echo(""); + vimperator.commandline.echo(""); return; } @@ -99,7 +101,7 @@ const vimperator = (function() //{{{ else str_extended = ""; - vimperator.echo("-- " + str_mode + str_extended + " --"); + vimperator.commandline.echo("-- " + str_mode.toUpperCase() + str_extended.toLowerCase() + " --"); } function expandPath(path) @@ -218,6 +220,7 @@ const vimperator = (function() //{{{ triggerCallback: function(type, mode, data) { + // dump("type: " + type + " mode: " + mode + "data: " + data + "\n"); for (var i in callbacks) { var [thistype, thismode, thisfunc] = callbacks[i]; @@ -292,6 +295,7 @@ const vimperator = (function() //{{{ popup.height = box.height; popup.width = box.width; + //popup.style.backgroundColor = "black"; ////popup.showPopup(win, box.screenX, box.screenY, "popup"); //popup.showPopup(win, -1, -1, "popup", "topleft", "topleft"); @@ -383,7 +387,7 @@ const vimperator = (function() //{{{ console_service.logStringMessage('vimperator: ' + msg); }, - // logs an object to the javascript error console also prints all + // log an object to the javascript error console and print all // properties of the object logObject: function(object, level) { @@ -619,6 +623,8 @@ const vimperator = (function() //{{{ vimperator.statusline = new StatusLine(); vimperator.log("Loading module buffer...", 3); vimperator.buffer = new Buffer(); + vimperator.log("Loading module editor...", 3); + vimperator.editor = new Editor(); vimperator.log("Loading module tabs...", 3); vimperator.tabs = new Tabs(); vimperator.log("Loading module marks...", 3); diff --git a/chrome/content/vimperator/vimperator.xul b/chrome/content/vimperator/vimperator.xul index baac399d..8d9b959a 100644 --- a/chrome/content/vimperator/vimperator.xul +++ b/chrome/content/vimperator/vimperator.xul @@ -44,6 +44,7 @@ the terms of any one of the MPL, the GPL or the LGPL.