diff --git a/ChangeLog b/ChangeLog index 54938aac..d7b2bbeb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,544 @@ +2007-09-13 01:49 stubenschrott + + * Donators, chrome/content/vimperator/events.js: allow number input + in command line + +2007-09-12 17:45 stubenschrott + + * NEWS, chrome/content/vimperator/events.js: fixed msn.com + +2007-09-12 17:42 dougkearns + + * vimperator.vim: update Vim syntax highlighting for changed + command names + +2007-09-12 15:41 stubenschrott + + * NEWS, vimperator.vim, chrome/content/vimperator/events.js, + chrome/content/vimperator/mappings.js, + chrome/content/vimperator/options.js: - new 'insertmode' option - + fixed c-u behavior + +2007-09-12 07:43 stubenschrott + + * chrome/content/vimperator/: editor.js, events.js, mappings.js, + vimperator.js, vimperator.xul: removed block cursor, it is just + too unreliable :( Many improvments in textarea mode with support + for motion commands like c or d; initial f,F,t and T support + (only textarea + visual mode, no motion yet); + +2007-09-11 16:01 dougkearns + + * chrome/content/vimperator/options.js: merge new 'popups' option + +2007-09-11 06:14 dougkearns + + * chrome/content/vimperator/: options.js: fix 'cpt' help typo + +2007-09-11 06:09 dougkearns + + * chrome/content/vimperator/: commands.js, mappings.js: fix :map + and :noremap to work with new multi-mode mappings + +2007-09-11 04:03 dougkearns + + * chrome/content/vimperator/: buffers.js, mappings.js, + vimperator.js: move vimperator.getCurrentWord to + vimperator.buffer + +2007-09-10 15:40 dougkearns + + * TODO: add document relationship navigation to pending feature + list + +2007-09-09 12:22 dougkearns + + * chrome/content/vimperator/find.js: fix case sensitivity of search + highlighting - gFindBar.setCaseSensitivity() in FF2 does not set + the preference as _setCaseSensitivity() does in FF3 + +2007-09-08 17:21 stubenschrott + + * chrome/content/vimperator/: editor.js, events.js, mappings.js: a + little better block cursor, broke i and a however a little + +2007-09-08 16:20 stubenschrott + + * chrome/content/vimperator/editor.js: quick'n dirty block cursor, + VERY BUGGY, stay in insert mode of textareas for now + +2007-09-08 14:15 stubenschrott + + * chrome/content/vimperator/editor.js: added forgotten editor.js + +2007-09-08 12:10 dougkearns + + * chrome/content/vimperator/ui.js: fixed multiline input widget + +2007-09-08 12:08 dougkearns + + * chrome/content/vimperator/commands.js: added :w -> :saveas alias, + and changed :w[open] to :wo[pen] + +2007-09-08 12:05 dougkearns + + * chrome/content/vimperator/: events.js, vimperator.js: fixed + saving qmarks + +2007-09-08 12:02 dougkearns + + * chrome/content/vimperator/options.js: merge improved + setTitleString() from MAIN + +2007-09-08 11:58 dougkearns + + * chrome/content/vimperator/options.js: use true as the default + value of 'hlsearch' and 'ignorecase' and store 'hlsearch' as a + preference + +2007-09-08 11:50 dougkearns + + * NEWS, chrome/content/vimperator/default.css, + chrome/content/vimperator/events.js, + chrome/content/vimperator/options.js, + chrome/content/vimperator/vimperator.js, + chrome/content/vimperator/vimperator.xul: added a visual bell and + replaced the 'beep' option with 'visualbell' + +2007-09-08 11:45 dougkearns + + * chrome/content/vimperator/find.js: merge minor Search#find + refactoring from MAIN + +2007-09-08 11:41 dougkearns + + * Makefile: use preX.X for development version numbers + +2007-09-08 06:17 stubenschrott + + * NEWS, chrome/content/vimperator/buffers.js, + chrome/content/vimperator/events.js, + chrome/content/vimperator/mappings.js, + chrome/content/vimperator/ui.js, + chrome/content/vimperator/vimperator.js, + chrome/content/vimperator/vimperator.xul: - TEXTAREA support! Not + working perfectly, but for a one-day-work i am impressed myself, + now just needing to add commands with MOTION like cw or d0. + Visual mode works already quite well. - gi support - BUG: + special keys like home/end in the location bar stoped working by + this dramatic changes + +2007-09-07 14:08 stubenschrott + + * vimperator.vim: updated vimperator.vim + +2007-09-07 10:06 dougkearns + + * chrome/content/vimperator/options.js: minor improvement to + 'popups' help wording + +2007-09-07 02:53 stubenschrott + + * chrome/content/vimperator/commands.js: added :w -> :saveas alias, + and changed :w[open] to :wo[pen] + +2007-09-06 23:36 stubenschrott + + * chrome/content/vimperator/: events.js, vimperator.js: fixed + saving qmarks + +2007-09-06 20:46 stubenschrott + + * vimperator.vim, chrome/content/vimperator/options.js: new + 'popups' option, please test thorougly! + +2007-09-06 19:48 stubenschrott + + * chrome/content/vimperator/options.js: changed some default + options, fixed "hlsearch" + +2007-09-06 19:39 stubenschrott + + * Donators, NEWS, chrome/content/vimperator/events.js, + chrome/content/vimperator/find.js, + chrome/content/vimperator/mappings.js, + chrome/content/vimperator/vimperator.js: * and # support + +2007-09-06 18:10 stubenschrott + + * NEWS, chrome/content/vimperator/events.js, + chrome/content/vimperator/mappings.js: First commit of caret + mode, many things work, some bugs of course, not sure if we can + fix them since we heavily rely on the firefox interface for it. + +2007-09-06 16:24 stubenschrott + + * NEWS, chrome/content/vimperator/events.js, + chrome/content/vimperator/mappings.js, + chrome/content/vimperator/vimperator.js, + chrome/content/vimperator/vimperator.xul: start of a caret mode + +2007-09-06 14:32 stubenschrott + + * NEWS, chrome/content/vimperator/events.js: experimental attempt + to keep you in command mode after loading pages + +2007-09-06 03:19 stubenschrott + + * chrome/content/vimperator/ui.js: fixed multiline input widget + +2007-09-06 02:04 dougkearns + + * NEWS, vimperator.vim, chrome/content/vimperator/find.js, + chrome/content/vimperator/mappings.js, + chrome/content/vimperator/options.js: merge new 'incsearch', + 'ignorecase', 'smartcase', 'hlsearch' options from MAIN + +2007-09-05 22:46 dougkearns + + * chrome/content/vimperator/: default.css, vimperator.js: make the + visual bell solid black and shorten the timeout interval + +2007-09-05 22:39 dougkearns + + * chrome/content/vimperator/help.js: allow the hidden help sections + to be found + +2007-09-05 21:33 stubenschrott + + * Donators: updated Donators once again, thanks so much all the + recent donators! + +2007-09-05 21:33 dougkearns + + * chrome/content/vimperator/vimperator.js: limit the visual bell to + the web page content area + +2007-09-05 21:10 dougkearns + + * chrome/content/vimperator/default.css: remove the border from the + visual bell popup + +2007-09-05 20:49 dougkearns + + * NEWS, vimperator.vim, chrome/content/vimperator/default.css, + chrome/content/vimperator/events.js, + chrome/content/vimperator/options.js, + chrome/content/vimperator/vimperator.js, + chrome/content/vimperator/vimperator.xul: add a visual bell and + replace 'beep' with 'visualbell' + +2007-09-05 15:44 stubenschrott + + * Makefile, NEWS, install.rdf, chrome/content/vimperator/icon.png: + fixed makefile + +2007-09-05 14:51 stubenschrott + + * Donators: updated Donators + +2007-09-05 14:19 dougkearns + + * TODO, chrome/content/vimperator/mappings.js, + chrome/content/vimperator/options.js: document that incremental + searching doesn't search backwards when using ? + +2007-09-05 13:45 dougkearns + + * Makefile: use preX.X for development version numbers + +2007-09-05 13:44 dougkearns + + * NEWS: update NEWS + +2007-09-05 13:32 dougkearns + + * NEWS, vimperator.vim, chrome/content/vimperator/find.js, + chrome/content/vimperator/mappings.js, + chrome/content/vimperator/options.js: add the 'smartcase' option + and support for \c and \C in search patterns + +2007-09-05 10:25 dougkearns + + * chrome/content/vimperator/: default.css: remove some redundant + help page CSS properties + +2007-09-04 13:30 stubenschrott + + * chrome/content/vimperator/options.js: Made all new search options + true by default, sorry Doug. + +2007-09-04 10:08 dougkearns + + * Makefile, chrome/content/vimperator/help.js, + chrome/content/vimperator/logo_white.png: add logo to help page + +2007-09-04 08:21 dougkearns + + * NEWS, chrome/content/vimperator/find.js, + chrome/content/vimperator/options.js: add 'ignorecase' option + +2007-09-04 04:50 dougkearns + + * Makefile, chrome/content/vimperator/vimperator.js: update version + to 0.6dev + +2007-09-04 04:50 dougkearns + + * Makefile, NEWS: update version to 0.5.2dev + +2007-09-04 04:12 dougkearns + + * chrome/content/vimperator/options.js: fix typo in 'scroll' + validator - incorrectly restricting value to 0-2 + +2007-09-04 03:32 stubenschrott + + * chrome/content/vimperator/logo_white.png: made holes in the logo + transparent as well + +2007-09-04 02:13 stubenschrott + + * Donators: updated donators + +2007-09-03 21:45 dougkearns + + * NEWS: update NEWS for 'hlsearch' and 'incsearch' + +2007-09-03 21:43 dougkearns + + * chrome/content/vimperator/: find.js, options.js: add 'incsearch' + option + +2007-09-03 21:10 dougkearns + + * chrome/content/vimperator/: find.js, options.js: add 'hlsearch' + option + +2007-09-03 17:14 dougkearns + + * ChangeLog, NEWS: update NEWS and ChangeLog for release + +2007-09-03 16:48 dougkearns + + * chrome/content/vimperator/vimperator.js: remove CVS from version + string for release + +2007-09-03 16:21 dougkearns + + * vimperator.vim: add highlighting for :nohlsearch + +2007-09-03 16:20 dougkearns + + * chrome/content/vimperator/default.css: remove the help page + tagline's negative top margin + +2007-09-03 16:18 dougkearns + + * chrome/content/vimperator/help.js: remove blank line after logo + in help page + +2007-09-03 14:46 dougkearns + + * chrome/content/vimperator/: mappings.js: add usage and long help + for / and ? mappings + +2007-09-03 12:18 dougkearns + + * chrome/content/vimperator/: help.js: remove extra blank lines + from help page + +2007-09-03 07:26 dougkearns + + * chrome/content/vimperator/options.js: whitespace formatting + improvements + +2007-09-03 07:12 dougkearns + + * NEWS, vimperator.vim, chrome/content/vimperator/commands.js, + chrome/content/vimperator/find.js, + chrome/content/vimperator/mappings.js, + chrome/content/vimperator/options.js, + chrome/content/vimperator/ui.js: merge native / and ? search + +2007-09-02 16:12 stubenschrott + + * chrome/content/vimperator/help.js: added the vimperator logo to + the help file + +2007-09-02 04:27 stubenschrott + + * chrome/content/vimperator/: find.js, ui.js: - Made ? work much + better now - backspacing over the prompt works again + +2007-09-01 20:50 dougkearns + + * chrome/content/vimperator/find.js: search entire page page text - + not just links + +2007-09-01 20:14 stubenschrott + + * NEWS, chrome/content/vimperator/commands.js, + chrome/content/vimperator/default.css, + chrome/content/vimperator/find.js, + chrome/content/vimperator/hints.js, + chrome/content/vimperator/mappings.js, + chrome/content/vimperator/options.js: first commit of native / + and ? search, especially ? is buggy right now + +2007-09-01 17:57 dougkearns + + * chrome/content/vimperator/: buffers.js: use + document.location.href for buffer.URL rather than document.URL + since the latter is undefined for XUL documents + +2007-09-01 13:49 dougkearns + + * vimperatorrc.example: remove outdated :js examples + +2007-09-01 13:39 dougkearns + + * chrome/content/vimperator/: completion.js, help.js: add + initialization section to help + +2007-08-31 08:54 dougkearns + + * chrome/content/vimperator/events.js: comment out currently unused + DOMTitleChanged event handler + +2007-08-31 08:53 dougkearns + + * chrome/content/vimperator/vimperator.js: don't indicate menu mode + when 'smd' is set + +2007-08-29 17:55 dougkearns + + * chrome/content/vimperator/events.js: use gContextMenu and the + menubar events for controlling menu mode + +2007-08-29 15:20 dougkearns + + * chrome/content/vimperator/: events.js, vimperator.js: don't enter + menu mode when tooltip popups are shown + +2007-08-29 00:41 stubenschrott + + * chrome/content/vimperator/: events.js, hints.js, vimperator.js: + Fixed menu mode to be reliable in Linux and made it more sane in + general + +2007-08-28 15:28 stubenschrott + + * chrome/content/vimperator/hints.js: first checkin of the new + FF3-based genElemCoords + +2007-08-28 14:16 dougkearns + + * NEWS: update NEWS + +2007-08-28 14:14 dougkearns + + * chrome/content/vimperator/: commands.js: minor help highlighting + improvments + +2007-08-28 11:55 dougkearns + + * chrome/content/vimperator/vimperator.xul: allow text in the + status line URL field to be selected + +2007-08-28 02:41 stubenschrott + + * chrome/content/vimperator/vimperator.xul: text in the statusline + URL can be selected again, sorry Doug :( + +2007-08-27 19:35 dougkearns + + * chrome/content/vimperator/: events.js: fix typo in + removeEventListener call + +2007-08-27 16:26 dougkearns + + * chrome/content/vimperator/: events.js, vimperator.js: add menu + mode + +2007-08-27 16:19 dougkearns + + * Makefile: update Makefile version to 0.5.1 + +2007-08-27 16:03 dougkearns + + * chrome/content/vimperator/: events.js, vimperator.js: improve + menu mode - track open popup count and menubar activation + +2007-08-27 14:21 dougkearns + + * chrome/content/vimperator/: events.js, vimperator.js: revert + changes to accidentally included files in last commit + +2007-08-27 14:08 dougkearns + + * Makefile, chrome/content/vimperator/events.js, + chrome/content/vimperator/vimperator.js: GNU make 3.80 can't + parse "else ifeq" + +2007-08-27 13:44 dougkearns + + * chrome/content/vimperator/: commands.js: use the coerced boolean + value of args rather than testing for 0 string length when + determining if an arg was passed to an ex command + +2007-08-27 09:07 dougkearns + + * chrome/content/vimperator/: commands.js: if no argument is given + to :winopen open about:blank in the new window + +2007-08-26 17:12 dougkearns + + * chrome/content/vimperator/: completion.js: complete ':set inv' + with boolean options + +2007-08-26 16:27 dougkearns + + * NEWS, chrome/content/vimperator/ui.js: fix commandline history on + Windows - prevent the default cmd_charPrevious action from being + invoked for + +2007-08-26 14:05 dougkearns + + * NEWS: update NEWS + +2007-08-26 13:57 dougkearns + + * chrome/content/vimperator/completion.js: add filename completion + for Windows + +2007-08-26 12:43 dougkearns + + * chrome/content/vimperator/completion.js: add filename completion + for Windows + +2007-08-25 17:48 dougkearns + + * chrome/content/vimperator/bookmarks.js: read the Bookmarks + Toolbar Folder when loading bookmarks - it has previously been + skipped since BookmarksUtils.getAllChildren(root) doesn't read it + +2007-08-24 18:37 dougkearns + + * chrome/content/vimperator/bookmarks.js: make sure search engine + aliases are properly initialized + +2007-08-24 15:55 stubenschrott + + * ChangeLog, NEWS, chrome/content/vimperator/bookmarks.js: fixed :o + foo bla search + 2007-08-24 15:08 stubenschrott * chrome/content/vimperator/bookmarks.js: updated history service diff --git a/NEWS b/NEWS index ccdc7105..aed80af1 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@
 2007-xx-xx:
 	* version 0.6
+	* THIS VERSION ONLY WORKS WITH FIREFOX 3.0
+	* improvements for scrollable -- more -- prompt
+	* changed 'I' key to Ctrl-Q to also work in textboxes
 	* sites like msn.com or yahoo.com don't focus search field anymore on keydown
 	* new gi browser command to focus last used input box
 	* edit TEXTAREAs with many vim commands in a vim and even visual mode if you :set noinsertmode
@@ -12,6 +15,7 @@
 	* added a visual bell and replaced 'beep' with 'visualbell'
 	* added vimperator logo (can be seen in the addons manager)
 	* added 'hlsearch','incsearch', 'ignorecase' and 'smartcase' options
+	* many small bug fixes and enhancments
 
 2007-09-03:
 	* version 0.5.1
diff --git a/TODO b/TODO
index 66951bc0..9bf5a903 100644
--- a/TODO
+++ b/TODO
@@ -24,6 +24,7 @@ FEATURES:
 8 add an interface for navigating document relationships
 8 middleclick in content == p, and if command line is open, paste there the clipboard buffer
 8 it would be nice to have :(undo|back|forward)  w/ tab completion support
+7 use ctrl-n/p in insert mode for word completion
 7 [ctrl-o/i] to Go back to a Previous Position (done partly, however currenty does not use a per tab jumplist)
 7 whereever possible: get rid of dialogs and ask console-like dialog questions or write error prompts directly on the webpage or with :echo()
 7 3d should delete 3 tabs
diff --git a/chrome/content/vimperator/editor.js b/chrome/content/vimperator/editor.js
index cbd3c220..c7a4ccc2 100644
--- a/chrome/content/vimperator/editor.js
+++ b/chrome/content/vimperator/editor.js
@@ -63,8 +63,8 @@ function Editor() //{{{
     this.unselectText = function()
     {
         var elt = window.document.commandDispatcher.focusedElement;
-        elt.selectionEnd = elt.selectionStart;
-        return true;
+        if (elt && elt.selectionEnd)
+            elt.selectionEnd = elt.selectionStart;
     }
 
     this.selectedText = function()
@@ -196,11 +196,11 @@ function Editor() //{{{
             case "d":
                 this.executeCommand("cmd_delete", 1);
                 // need to reset the mode as the visual selection changes it
-                vimperator.setMode(vimperator.modes.TEXTAREA);
+                vimperator.modes.main = vimperator.modes.TEXTAREA;
                 break;
             case "c":
                 this.executeCommand("cmd_delete", 1);
-                this.startInsert();
+                vimperator.modes.set(vimperator.modes.INSERT, vimperator.modes.TEXTAREA);
                 break;
             case "y":
                 this.executeCommand("cmd_copy", 1);
@@ -213,23 +213,6 @@ function Editor() //{{{
         }
         return true;
     }
-    this.startNormal = function()
-    {
-        vimperator.setMode(vimperator.modes.TEXTAREA);
-
-        //var self = this;
-        //editor().addEventListener("mouseclick", function() {
-        //        setTimeout(function() {
-        //            pos =  editor().selectionStart;
-        //            self.moveCaret(pos);
-        //        }, 10);
-        //}, false);
-    }
-
-    this.startInsert = function()
-    {
-        vimperator.setMode(vimperator.modes.INSERT, vimperator.modes.TEXTAREA);
-    }
 
     // This function will move/select up to given "pos"
     // Simple setSelectionRange() would be better, but we want to maintain the correct
diff --git a/chrome/content/vimperator/events.js b/chrome/content/vimperator/events.js
index 5266a3c2..4333bdb7 100644
--- a/chrome/content/vimperator/events.js
+++ b/chrome/content/vimperator/events.js
@@ -46,17 +46,14 @@ function Events() //{{{
     tabcontainer.addEventListener("TabOpen",   function(event) {
         vimperator.statusline.updateTabCount();
         vimperator.buffer.updateBufferList();
-        //vimperator.setMode(); // trick to reshow the mode in the command line
     }, false);
     tabcontainer.addEventListener("TabClose",  function(event) {
         vimperator.statusline.updateTabCount()
         vimperator.buffer.updateBufferList();
-        //vimperator.setMode(); // trick to reshow the mode in the command line
     }, false);
     tabcontainer.addEventListener("TabSelect", function(event) {
         vimperator.statusline.updateTabCount();
         vimperator.buffer.updateBufferList();
-        //vimperator.setMode(); // trick to reshow the mode in the command line
         vimperator.tabs.updateSelectionHistory();
         setTimeout(vimperator.focusContent, 10); // just make sure, that no widget has focus
     }, false);
@@ -69,7 +66,7 @@ function Events() //{{{
     getBrowser().addEventListener("scroll", function (event)
     {
         vimperator.statusline.updateBufferPosition();
-        vimperator.setMode(); // trick to reshow the mode in the command line
+        vimperator.modes.show();
     }, null);
 
 
@@ -81,23 +78,23 @@ function Events() //{{{
         if (event.originalTarget.localName == "tooltip" || event.originalTarget.id == "vimperator-visualbell")
             return;
 
-        vimperator.addMode(null, vimperator.modes.MENU);
+        vimperator.modes.add(vimperator.modes.MENU);
     }
     function exitPopupMode()
     {
         // gContextMenu is set to NULL by firefox, when a context menu is closed
         if (!gContextMenu && !active_menubar)
-            vimperator.removeMode(null, vimperator.modes.MENU);
+            vimperator.modes.remove(vimperator.modes.MENU);
     }
     function enterMenuMode()
     {
         active_menubar = true;
-        vimperator.addMode(null, vimperator.modes.MENU)
+        vimperator.modes.add(vimperator.modes.MENU);
     }
     function exitMenuMode()
     {
         active_menubar = false;
-        vimperator.removeMode(null, vimperator.modes.MENU);
+        vimperator.modes.remove(vimperator.modes.MENU);
     }
     window.addEventListener("popupshown", enterPopupMode, true);
     window.addEventListener("popuphidden", exitPopupMode, true);
@@ -376,102 +373,98 @@ function Events() //{{{
     // access to the real focus target
     this.onFocusChange = function(event)
     {
-        if (vimperator.hasMode(vimperator.modes.COMMAND_LINE))
+        if (vimperator.mode == 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.mode = vimperator.modes.INSERT;
             vimperator.buffer.lastInputField = elem;
         }
         else if (elem && elem instanceof HTMLTextAreaElement)
         {
             if (vimperator.options["insertmode"])
-                vimperator.setMode(vimperator.modes.INSERT, vimperator.modes.TEXTAREA);
+                vimperator.modes.set(vimperator.modes.INSERT, vimperator.modes.TEXTAREA);
             else if (elem.selectionEnd - elem.selectionStart > 0)
-                vimperator.setMode(vimperator.modes.VISUAL, vimperator.modes.TEXTAREA);
+                vimperator.modes.set(vimperator.modes.VISUAL, vimperator.modes.TEXTAREA);
             else
-                vimperator.editor.startNormal();
+                vimperator.modes.main = vimperator.modes.TEXTAREA;
             vimperator.buffer.lastInputField = elem;
         }
-        else if //(vimperator.hasMode(vimperator.modes.VISUAL) ||
-                (vimperator.hasMode(vimperator.modes.INSERT) ||
-                vimperator.hasMode(vimperator.modes.TEXTAREA))
-            vimperator.setMode(vimperator.modes.NORMAL);
+        else if (vimperator.mode == vimperator.modes.INSERT ||
+                 vimperator.mode == vimperator.modes.TEXTAREA ||
+                 vimperator.mode == vimperator.modes.VISUAL)
+            vimperator.modes.reset();
     }
 
     this.onSelectionChange = function(event)
     {
-        vimperator.log("onselection");
         var could_copy = false;
         var controller = document.commandDispatcher.getControllerForCommand("cmd_copy");
         if (controller && controller.isCommandEnabled("cmd_copy"))
             could_copy = true;
 
-        if (could_copy && !vimperator.hasMode(vimperator.modes.VISUAL))
+        if (vimperator.mode != vimperator.modes.VISUAL)
         {
-            if (vimperator.hasMode(vimperator.modes.TEXTAREA) && !vimperator.options["insertmode"])
-                vimperator.setMode(vimperator.modes.VISUAL, vimperator.modes.TEXTAREA);
-            else if (vimperator.hasMode(vimperator.modes.CARET))
-                vimperator.setMode(vimperator.modes.VISUAL, vimperator.modes.CARET);
+            if (could_copy)
+            {
+                if ((vimperator.mode == vimperator.modes.TEXTAREA || (vimperator.modes.extended & vimperator.modes.TEXTAREA))
+                        && !vimperator.options["insertmode"])
+                    vimperator.modes.set(vimperator.modes.VISUAL, vimperator.modes.TEXTAREA);
+                else if (vimperator.mode == vimperator.modes.CARET)
+                    vimperator.modes.set(vimperator.modes.VISUAL, vimperator.modes.CARET);
+            }
         }
-        else if (vimperator.hasMode(vimperator.modes.VISUAL))
+        else
         {
-            if (!could_copy && vimperator.hasMode(vimperator.modes.CARET))
-                vimperator.setMode(vimperator.modes.CARET);
+            if (!could_copy && vimperator.modes.extended & vimperator.modes.CARET)
+                vimperator.mode = vimperator.modes.CARET;
         }
     }
 
     // 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))
+        if (!vimperator.modes.passNextKey)
         {
-            if (vimperator.hasMode(vimperator.modes.VISUAL))
+            if(vimperator.modes.passAllKeys)
             {
-                if (vimperator.hasMode(vimperator.modes.TEXTAREA))
-                {
-                    vimperator.editor.unselectText();
-                    vimperator.setMode(vimperator.modes.TEXTAREA, vimperator.modes.NONE);
-                }
-                else
-                {
+                vimperator.modes.passAllKeys = false;
+                return;
+            }
+
+            switch(vimperator.mode)
+            {
+                case vimperator.modes.VISUAL:
+                    if (vimperator.modes.extended & vimperator.modes.TEXTAREA)
+                        vimperator.mode = vimperator.modes.TEXTAREA;
+                    else if (vimperator.modes.extended & vimperator.modes.CARET)
+                        vimperator.mode = vimperator.modes.CARET;
+                    break;
+
+                case 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);
+                    break;
+
+                case vimperator.modes.INSERT:
+                    if((vimperator.modes.extended & vimperator.modes.TEXTAREA) && !vimperator.options["insertmode"])
+                        vimperator.mode = vimperator.modes.TEXTAREA;
+                    else
+                        vimperator.modes.reset();
+                    break;
+                
+                default:
                     // clear any selection made
                     var selection = window.content.getSelection();
-                    selection.collapseToStart();
-                    if (vimperator.hasMode(vimperator.modes.CARET)) // set as an extended mode
-                        vimperator.setMode(vimperator.modes.CARET);
-                    else
-                        vimperator.setMode(vimperator.modes.NORMAL);
-                }
-            }
-            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.options["insertmode"])
-                    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();
+                    if (selection)
+                        selection.collapseToStart();
+                    vimperator.commandline.clear();
+
+                    vimperator.modes.reset();
             }
         }
     }
@@ -482,37 +475,45 @@ function Events() //{{{
     {
         var key = vimperator.events.toString(event);
         if (!key)
-             return false;
+             return true;
 
         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;
+        if (vimperator.modes.extended & vimperator.modes.MENU)
+            return true;
 
         // handle Escape-one-key mode (Ctrl-v)
-        if (vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY) && !vimperator.hasMode(vimperator.modes.ESCAPE_ALL_KEYS))
+        if (vimperator.modes.passNextKey && !vimperator.modes.passAllKeys)
         {
-            vimperator.removeMode(null, vimperator.modes.ESCAPE_ONE_KEY);
-            return false;
+            vimperator.modes.passNextKey = false;
+            return true;
         }
-        // handle Escape-all-keys mode (I)
-        if (vimperator.hasMode(vimperator.modes.ESCAPE_ALL_KEYS))
+        // handle Escape-all-keys mode (Ctrl-q)
+        if (vimperator.modes.passAllKeys)
         {
-            if (vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY))
-                vimperator.removeMode(null, vimperator.modes.ESCAPE_ONE_KEY); // and then let flow continue
+            if (vimperator.modes.passNextKey)
+                vimperator.modes.passNextKey = false; // and then let flow continue
             else if (key == "" || key == "" || key == "")
                 ; // let flow continue to handle these keys to cancel escape-all-keys mode
             else
-                return false;
+                return true;
         }
 
         // 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) &&
-            !vimperator.hasMode(vimperator.modes.COMMAND_LINE) &&
+        if (!vimperator.mode == vimperator.modes.TEXTAREA &&
+            !vimperator.mode == vimperator.modes.INSERT &&
+            !vimperator.mode == vimperator.modes.COMMAND_LINE &&
                     isFormElemFocused()) // non insert mode, but e.g. the location bar has focus
-                return false;
+                return true;
+
+        if (vimperator.mode == vimperator.modes.COMMAND_LINE &&
+            (vimperator.modes.extended & vimperator.modes.OUTPUT_MULTILINE))
+        {
+            vimperator.commandline.onMultilineOutputEvent(event);
+            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.
@@ -543,7 +544,7 @@ function Events() //{{{
 
         // if Hit-a-hint mode is on, special handling of keys is required
         // FIXME: total mess
-        if (vimperator.hasMode(vimperator.modes.HINTS))
+        if (vimperator.mode == vimperator.modes.HINTS)
         {
             // never propagate this key to firefox, when hints are visible
             //event.preventDefault();
@@ -588,13 +589,13 @@ function Events() //{{{
             if (res < 0) // error occured processing this key
             {
                 vimperator.beep();
-                if (vimperator.hasMode(vimperator.modes.QUICK_HINT))
+                if (vimperator.modes.extended & vimperator.modes.QUICK_HINT)
                     vimperator.hints.disableHahMode();
                 else // ALWAYS mode
                     vimperator.hints.resetHintedElements();
                 vimperator.input.buffer = "";
             }
-            else if (res == 0 || vimperator.hasMode(vimperator.modes.EXTENDED_HINT)) // key processed, part of a larger hint
+            else if (res == 0 || vimperator.modes.extended & vimperator.modes.EXTENDED_HINT) // key processed, part of a larger hint
                 vimperator.input.buffer += key;
             else // this key completed a quick hint
             {
@@ -605,8 +606,7 @@ function Events() //{{{
                 else // open in current window
                     vimperator.hints.openHints(false, false);
 
-                //if (vimperator.hints.currentMode() == HINT_MODE_QUICK)
-                if (vimperator.hasMode(vimperator.modes.QUICK_HINT))
+                if (vimperator.modes.extended & vimperator.modes.QUICK_HINT)
                     vimperator.hints.disableHahMode();
                 else // ALWAYS mode
                     vimperator.hints.resetHintedElements();
@@ -619,7 +619,6 @@ function Events() //{{{
         }
 
 
-        var [mode, extended_mode] = vimperator.getMode();
         var count_str = vimperator.input.buffer.match(/^[0-9]*/)[0];
         var candidate_command = (vimperator.input.buffer + key).replace(count_str, '');
         var map;
@@ -628,9 +627,8 @@ function Events() //{{{
         if ((vimperator.input.buffer + key).match(/^[1-9][0-9]*$/))
         {
             // no count for insert mode mappings
-            if (vimperator.hasMode(vimperator.modes.INSERT) ||
-                vimperator.hasMode(vimperator.modes.COMMAND_LINE))
-                    stop = false;
+            if (vimperator.mode == vimperator.modes.INSERT || vimperator.mode == vimperator.modes.COMMAND_LINE)
+                stop = false;
             else
                 vimperator.input.buffer += key;
         }
@@ -643,7 +641,7 @@ function Events() //{{{
 
             vimperator.input.pendingArgMap = null;
         }
-        else if (map = vimperator.mappings.get(mode, candidate_command))
+        else if (map = vimperator.mappings.get(vimperator.mode, candidate_command))
         {
             vimperator.input.count = parseInt(count_str, 10);
             if (isNaN(vimperator.input.count))
@@ -675,7 +673,7 @@ function Events() //{{{
                 map.execute(null, vimperator.input.count);
             }
         }
-        else if (vimperator.mappings.getCandidates(mode, candidate_command).length > 0)
+        else if (vimperator.mappings.getCandidates(vimperator.mode, candidate_command).length > 0)
         {
             vimperator.input.buffer += key;
         }
@@ -685,9 +683,8 @@ function Events() //{{{
             vimperator.input.pendingArgMap = null;
             vimperator.input.pendingMotionMap = null;
 
-            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
+            if (vimperator.mode == vimperator.modes.INSERT || vimperator.mode == vimperator.modes.COMMAND_LINE)
+                stop = false; // command was not a vimperator command, maybe it is a firefox command
             else
                 vimperator.beep();
         }
@@ -707,10 +704,8 @@ function Events() //{{{
     // this is need for sites like msn.com which focus the input field on keydown
     this.onKeyDown = function(event)
     {
-        if ((vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY) && !vimperator.hasMode(vimperator.modes.ESCAPE_ALL_KEYS)) ||
-            (vimperator.hasMode(vimperator.modes.ESCAPE_ALL_KEYS) && !vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY)) ||
-            isFormElemFocused())
-                return true;
+        if (vimperator.modes.passNextKey ^ vimperator.modes.passAllKeys || isFormElemFocused())
+            return true;
 
         event.preventDefault();
         event.stopPropagation();
@@ -769,13 +764,10 @@ function Events() //{{{
         // happens when the users switches tabs
         onLocationChange: function()
         {
-            // if (vimperator.hasMode(vimperator.modes.HINTS) && !vimperator.hasMode(vimperator.modes.ALWAYS_HINT))
-            //     vimperator.hints.disableHahMode();
-
             vimperator.statusline.updateUrl();
             vimperator.statusline.updateProgress();
 
-            // if this is not delayed we get the wrong position of the old buffer
+            // if this is not delayed we get the position of the old buffer
             setTimeout(function() { vimperator.statusline.updateBufferPosition(); }, 100);
         },
         // called at the very end of a page load
@@ -799,7 +791,7 @@ function Events() //{{{
                 if (ssli == 1)
                     vimperator.statusline.updateUrl();
                 else if (ssli == 2)
-                    vimperator.setMode(); // trick to reshow the mode in the command line
+                    vimperator.modes.show();
             }
         },
 
@@ -846,7 +838,7 @@ function Events() //{{{
             {
                 case "accessibility.browsewithcaret":
                     var value = Options.getFirefoxPref("accessibility.browsewithcaret", false);
-                    vimperator.setMode(value ? vimperator.modes.CARET : vimperator.modes.NORMAL, null);
+                    vimperator.mode = value ? vimperator.modes.CARET : vimperator.modes.NORMAL;
                     break;
             }
          }
diff --git a/chrome/content/vimperator/find.js b/chrome/content/vimperator/find.js
index bfe7746a..f6b68342 100644
--- a/chrome/content/vimperator/find.js
+++ b/chrome/content/vimperator/find.js
@@ -128,6 +128,9 @@ function Search() //{{{
             this.highlight(lastsearch);
         }
 
+        var leader = lastsearch_backwards ? "?" : "/";
+        vimperator.commandline.echo(leader + lastsearch);
+
         var up = reverse ? !lastsearch_backwards : lastsearch_backwards;
         var result = getBrowser().fastFind.findAgain(up, false);
 
@@ -180,18 +183,15 @@ function Search() //{{{
         lastsearch_backwards = backwards;
         lastsearch = command;
 
-        vimperator.setMode(vimperator.modes.NORMAL);
-        vimperator.focusContent();
+        vimperator.modes.set(vimperator.modes.NORMAL, null, true);
     }
 
     // Called when the search is cancelled - for example if someone presses
     // escape while typing a search
     this.searchCanceled = function()
     {
-        //removeMode(MODE_SEARCH);
-        vimperator.setMode(vimperator.modes.NORMAL);
+        vimperator.modes.reset();
         this.clear();
-        vimperator.focusContent();
     }
 
     this.highlight = function(word)
diff --git a/chrome/content/vimperator/hints.js b/chrome/content/vimperator/hints.js
index 6c3ddeb6..2ffa692c 100644
--- a/chrome/content/vimperator/hints.js
+++ b/chrome/content/vimperator/hints.js
@@ -217,12 +217,12 @@ function Hints() //{{{
         if (!win)
             win = window.content;
 
-        if (linkCount == 0 && !vimperator.hasMode(vimperator.modes.ALWAYS_HINT))
+        if (linkCount == 0 && !(vimperator.modes.extended & vimperator.modes.ALWAYS_HINT))
         {
             vimperator.beep();
+            vimperator.modes.reset();
 
-            // FIXME: this.disableHahMode(win);
-            vimperator.setMode(vimperator.modes.NORMAL);
+            // XXX: move to mode handling
             isHahModeEnabled = false;
             linkNumString = '';
             hintedElems = [];
@@ -400,10 +400,10 @@ function Hints() //{{{
      * @param event that caused the mode to change
      * @return -1 if already enabled
      */
-    //function enableHahMode(event, mode)
+    // XXX: move to mode handling
     this.enableHahMode = function(mode)
     {
-        vimperator.setMode(vimperator.modes.HINTS, mode);
+        vimperator.modes.set(vimperator.modes.HINTS, mode);
         state = 0;
         linkCount = 0;
         linkNumString = '';
@@ -424,13 +424,14 @@ function Hints() //{{{
      *                 false if cancel
      * @return -1 if already disabled
      */
-    //function disableHahMode(event)
+    // XXX: move to mode handling
     this.disableHahMode = function(win)
     {
         if (!isHahModeEnabled)
             return;
 
-        vimperator.setMode(vimperator.modes.NORMAL);
+        vimperator.modes.reset();
+
         isHahModeEnabled = false;
         linkNumString = '';
         hintedElems = [];
@@ -675,7 +676,7 @@ function Hints() //{{{
 
         startCoordLoader(doc);
 
-        if (vimperator.hasMode(vimperator.modes.ALWAYS_HINT))
+        if (vimperator.modes.extended & vimperator.modes.ALWAYS_HINT)
         {
             state = 0;
             linkCount = 0;
diff --git a/chrome/content/vimperator/mappings.js b/chrome/content/vimperator/mappings.js
index aa166c3b..46c8a54f 100644
--- a/chrome/content/vimperator/mappings.js
+++ b/chrome/content/vimperator/mappings.js
@@ -259,7 +259,11 @@ function Mappings() //{{{
             for (var j = 0; j < map.names.length; j++)
             {
                 if (map.names[j].indexOf(cmd) == 0)
-                    matches.push(map)
+                {
+                    // for < only return a candidate if it doesn't seem like a  mapping
+                    if (cmd != "<" || !/^<.+>/.test(map.names[j]))
+                        matches.push(map)
+                }
             }
         }
 
@@ -337,20 +341,21 @@ function Mappings() //{{{
             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()
         {
+            // setting this option triggers an observer
+            // which takes care of the mode setting
             Options.setFirefoxPref("accessibility.browsewithcaret", true);
-            vimperator.setMode(vimperator.modes.CARET, null);
         },
         {
             short_help: "Start caret mode",
             help: "This mode resembles the vim normal mode where you see a text cursor and can move around. " +
-            "NOTE: Movement keys are not really working for the moment."
+            "If you want to select text in this mode, press v to start its Visual mode."
         }
     ));
-    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); },
+    addDefaultMap(new Map(anymode, [""],
+        function() { vimperator.modes.passAllKeys = true; },
         {
             short_help: "Disable Vimperator keys",
             help: "Starts an 'ignorekeys' mode, where all keys except <Esc> are passed to the next event handler.
" + @@ -360,7 +365,7 @@ function Mappings() //{{{ } )); addDefaultMap(new Map(anymode, [""], - function() { vimperator.addMode(null, vimperator.modes.ESCAPE_ONE_KEY); }, + function() { vimperator.modes.passNextKey = true; }, { short_help: "Escape next key", help: "If you need to pass a certain key to a JavaScript form field or another extension prefix the key with <C-v>.
" + @@ -1261,26 +1266,8 @@ function Mappings() //{{{ .QueryInterface(Components.interfaces.nsISelectionController); } - // prevent beeping on esc, should unify - /*addDefaultMap(new Map([vimperator.modes.CARET], ["", "", ""], - function() - { - if (!vimperator.hasMode(vimperator.modes.VISUAL)) - vimperator.onEscape(); - else - { - vimperator.removeMode(null, vimperator.modes.VISUAL); - // 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(); - } - }, - { } - ));*/ - addDefaultMap(new Map([vimperator.modes.CARET, vimperator.modes.TEXTAREA], ["v"], - function(count) { vimperator.setMode(vimperator.modes.VISUAL, vimperator.getMode()[0]); }, + function(count) { vimperator.modes.set(vimperator.modes.VISUAL, vimperator.mode); }, { short_help: "Start visual mode", help: "Works for caret mode and textarea mode." @@ -1406,10 +1393,10 @@ function Mappings() //{{{ if (count < 1) count = 1; while(count--) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) { vimperator.editor.executeCommand("cmd_selectLineNext"); - if (vimperator.hasMode(vimperator.modes.LINE) && !vimperator.editor.selectedText()) + if ((vimperator.modes.extended & vimperator.modes.LINE) && !vimperator.editor.selectedText()) vimperator.editor.executeCommand("cmd_selectLineNext"); } else @@ -1424,10 +1411,10 @@ function Mappings() //{{{ if (count < 1) count = 1; while(count--) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) { vimperator.editor.executeCommand("cmd_selectLinePrevious"); - if (vimperator.hasMode(vimperator.modes.LINE) && !vimperator.editor.selectedText()) + if ((vimperator.modes.extended & vimperator.modes.LINE) && !vimperator.editor.selectedText()) vimperator.editor.executeCommand("cmd_selectLinePrevious"); } else @@ -1442,7 +1429,7 @@ function Mappings() //{{{ if (count < 1) count = 1; while(count--) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) vimperator.editor.executeCommand("cmd_selectCharPrevious"); else getSelectionController().characterMove(false, true); @@ -1456,7 +1443,7 @@ function Mappings() //{{{ if (count < 1) count = 1; while(count--) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) vimperator.editor.executeCommand("cmd_selectCharNext"); else getSelectionController().characterMove(true, true); @@ -1470,7 +1457,7 @@ function Mappings() //{{{ if (count < 1) count = 1; while(count--) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) vimperator.editor.executeCommand("cmd_selectWordPrevious"); else getSelectionController().wordMove(false, true); @@ -1484,7 +1471,7 @@ function Mappings() //{{{ if (count < 1) count = 1; while(count--) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) vimperator.editor.executeCommand("cmd_selectWordNext"); else getSelectionController().wordMove(true, true); @@ -1498,7 +1485,7 @@ function Mappings() //{{{ if (count < 1) count = 1; while(count--) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) ;//vimperator.editor.executeCommand("cmd_selectPageNext"); else getSelectionController().pageMove(true, true); @@ -1512,7 +1499,7 @@ function Mappings() //{{{ if (count < 1) count = 1; while(count--) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) ;//vimperator.editor.executeCommand("cmd_selectWordNext"); else getSelectionController().pageMove(false, true); @@ -1523,7 +1510,7 @@ function Mappings() //{{{ addDefaultMap(new Map([vimperator.modes.VISUAL], ["gg", ""], function(count) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) vimperator.editor.executeCommand("cmd_selectTop"); else getSelectionController().completeMove(false, true); @@ -1533,7 +1520,7 @@ function Mappings() //{{{ addDefaultMap(new Map([vimperator.modes.VISUAL], ["G", ""], function(count) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) vimperator.editor.executeCommand("cmd_selectBottom"); else getSelectionController().completeMove(true, true); @@ -1543,7 +1530,7 @@ function Mappings() //{{{ addDefaultMap(new Map([vimperator.modes.VISUAL], ["0", "^", ""], function(count) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) vimperator.editor.executeCommand("cmd_selectBeginLine"); else getSelectionController().intraLineMove(false, true); @@ -1553,7 +1540,7 @@ function Mappings() //{{{ addDefaultMap(new Map([vimperator.modes.VISUAL], ["$", ""], function(count) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) vimperator.editor.executeCommand("cmd_selectEndLine"); else getSelectionController().intraLineMove(true, true); @@ -1563,10 +1550,10 @@ function Mappings() //{{{ addDefaultMap(new Map([vimperator.modes.VISUAL], ["c", "s"], function(count) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) { vimperator.editor.executeCommand("cmd_cut"); - vimperator.setMode(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); + vimperator.modes.set(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); } else vimperator.beep(); @@ -1576,10 +1563,10 @@ function Mappings() //{{{ addDefaultMap(new Map([vimperator.modes.VISUAL], ["d"], function(count) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) { vimperator.editor.executeCommand("cmd_cut"); - vimperator.setMode(vimperator.modes.TEXTAREA); + vimperator.modes.set(vimperator.modes.TEXTAREA); } else vimperator.beep(); @@ -1589,11 +1576,11 @@ function Mappings() //{{{ addDefaultMap(new Map([vimperator.modes.VISUAL], ["y"], function(count) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (vimperator.modes.extended & vimperator.modes.TEXTAREA) { vimperator.editor.executeCommand("cmd_copy"); // vimperator.editor.unselectText(); - vimperator.setMode(vimperator.modes.TEXTAREA); + vimperator.modes.set(vimperator.modes.TEXTAREA); } else vimperator.beep(); // TODO: yanking is possible for caret mode @@ -1603,12 +1590,12 @@ function Mappings() //{{{ addDefaultMap(new Map([vimperator.modes.VISUAL, vimperator.modes.TEXTAREA], ["p"], function(count) { - if (vimperator.hasMode(vimperator.modes.TEXTAREA)) + if (!(vimperator.modes.extended & vimperator.modes.CARET)) { if (!count) count = 1; while (count--) vimperator.editor.executeCommand("cmd_paste"); - vimperator.setMode(vimperator.modes.TEXTAREA); + vimperator.mode = vimperator.modes.TEXTAREA; } else vimperator.beep(); @@ -1621,15 +1608,15 @@ function Mappings() //{{{ // Textarea mode // {{{ - addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["i"], - function(count) { vimperator.editor.startInsert(); }, + addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["i", ""], + function(count) { vimperator.modes.set(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); }, { } )); addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["a"], function(count) { vimperator.editor.executeCommand("cmd_charNext", 1); - vimperator.editor.startInsert(); + vimperator.modes.set(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); }, { } )); @@ -1637,7 +1624,7 @@ function Mappings() //{{{ function(count) { vimperator.editor.executeCommand("cmd_beginLine", 1); - vimperator.editor.startInsert(); + vimperator.modes.set(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); }, { } )); @@ -1645,7 +1632,7 @@ function Mappings() //{{{ function(count) { vimperator.editor.executeCommand("cmd_endLine", 1); - vimperator.editor.startInsert(); + vimperator.modes.set(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); }, { } )); @@ -1653,7 +1640,7 @@ function Mappings() //{{{ function(count) { vimperator.editor.executeCommand("cmd_deleteCharForward", 1); - vimperator.editor.startInsert(); + vimperator.modes.set(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); }, { } )); @@ -1662,7 +1649,7 @@ function Mappings() //{{{ { vimperator.editor.executeCommand("cmd_deleteToEndOfLine", 1); vimperator.editor.executeCommand("cmd_deleteToBeginningOfLine", 1); - vimperator.editor.startInsert(); + vimperator.modes.set(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); }, { } )); @@ -1670,29 +1657,29 @@ function Mappings() //{{{ function(count) { vimperator.editor.executeCommand("cmd_deleteToEndOfLine", 1); - vimperator.editor.startInsert(); + vimperator.modes.set(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); }, { } )); addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["v"], - function(count) { vimperator.setMode(vimperator.modes.VISUAL, vimperator.modes.TEXTAREA); }, + function(count) { vimperator.modes.set(vimperator.modes.VISUAL, vimperator.modes.TEXTAREA); }, { } )); addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["V"], function(count) { + vimperator.modes.set(vimperator.modes.VISUAL, vimperator.modes.TEXTAREA | vimperator.modes.LINE); vimperator.editor.executeCommand("cmd_beginLine", 1); vimperator.editor.executeCommand("cmd_selectLineNext", 1); - vimperator.setMode(vimperator.modes.VISUAL, vimperator.modes.TEXTAREA | vimperator.modes.LINE); }, { } )); addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["u"], - function(count) { vimperator.editor.executeCommand("cmd_undo", count); vimperator.setMode(vimperator.modes.TEXTAREA); }, + function(count) { vimperator.editor.executeCommand("cmd_undo", count); vimperator.mode = vimperator.modes.TEXTAREA; }, { flags: Mappings.flags.COUNT } )); addDefaultMap(new Map([vimperator.modes.TEXTAREA], [""], - function(count) { vimperator.editor.executeCommand("cmd_redo", count); vimperator.setMode(vimperator.modes.TEXTAREA); }, + function(count) { vimperator.editor.executeCommand("cmd_redo", count); vimperator.mode = vimperator.modes.TEXTAREA; }, { flags: Mappings.flags.COUNT } )); addDefaultMap(new Map([vimperator.modes.TEXTAREA], ["j", "", ""], @@ -1747,7 +1734,7 @@ function Mappings() //{{{ function(count) { vimperator.editor.executeCommand("cmd_endLine", 1); - vimperator.editor.startInsert(); + vimperator.modes.set(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); vimperator.events.feedkeys(""); }, { } @@ -1756,7 +1743,7 @@ function Mappings() //{{{ function(count) { vimperator.editor.executeCommand("cmd_beginLine", 1); - vimperator.editor.startInsert(); + vimperator.modes.set(vimperator.modes.INSERT, vimperator.modes.TEXTAREA); vimperator.events.feedkeys(""); vimperator.editor.executeCommand("cmd_linePrevious", 1); }, @@ -1769,7 +1756,7 @@ function Mappings() //{{{ { var pos = vimperator.editor.findCharForward(arg, count); if (pos >= 0) - vimperator.editor.moveToPosition(pos, true, vimperator.hasMode(vimperator.modes.VISUAL)); + vimperator.editor.moveToPosition(pos, true, vimperator.mode == vimperator.modes.VISUAL); }, { flags: Mappings.flags.ARGUMENT | Mappings.flags.COUNT} )); @@ -1778,7 +1765,7 @@ function Mappings() //{{{ { var pos = vimperator.editor.findCharBackward(arg, count); if (pos >= 0) - vimperator.editor.moveToPosition(pos, false, vimperator.hasMode(vimperator.modes.VISUAL)); + vimperator.editor.moveToPosition(pos, false, vimperator.mode == vimperator.modes.VISUAL); }, { flags: Mappings.flags.ARGUMENT | Mappings.flags.COUNT} )); @@ -1787,7 +1774,7 @@ function Mappings() //{{{ { var pos = vimperator.editor.findCharForward(arg, count); if (pos >= 0) - vimperator.editor.moveToPosition(pos - 1, true, vimperator.hasMode(vimperator.modes.VISUAL)); + vimperator.editor.moveToPosition(pos - 1, true, vimperator.mode = vimperator.modes.VISUAL); }, { flags: Mappings.flags.ARGUMENT | Mappings.flags.COUNT} )); @@ -1796,7 +1783,7 @@ function Mappings() //{{{ { var pos = vimperator.editor.findCharBackward(arg, count); if (pos >= 0) - vimperator.editor.moveToPosition(pos + 1, false, vimperator.hasMode(vimperator.modes.VISUAL)); + vimperator.editor.moveToPosition(pos + 1, false, vimperator.mode = vimperator.modes.VISUAL); }, { flags: Mappings.flags.ARGUMENT | Mappings.flags.COUNT} )); @@ -1805,7 +1792,7 @@ function Mappings() //{{{ // { // var pos = vimperator.editor.findCharBackward(null, count); // if (pos >= 0) - // vimperator.editor.moveToPosition(pos + 1, false, vimperator.hasMode(vimperator.modes.VISUAL)); + // vimperator.editor.moveToPosition(pos + 1, false, vimperator.mode = vimperator.modes.VISUAL); // }, // { flags: Mappings.flags.ARGUMENT | Mappings.flags.COUNT} // )); @@ -1853,7 +1840,7 @@ function Mappings() //{{{ function() { vimperator.editor.executeCommand("cmd_endLine", 1); }, { } )); - addDefaultMap(new Map([vimperator.modes.INSERT, vimperator.modes.COMMAND_LINE], ["", ""], + addDefaultMap(new Map([vimperator.modes.INSERT, vimperator.modes.COMMAND_LINE], [""], // let firefox handle function() { vimperator.editor.executeCommand("cmd_deleteCharBackward", 1); }, { } )); diff --git a/chrome/content/vimperator/modes.js b/chrome/content/vimperator/modes.js new file mode 100644 index 00000000..9b55b259 --- /dev/null +++ b/chrome/content/vimperator/modes.js @@ -0,0 +1,214 @@ +/***** BEGIN LICENSE BLOCK ***** {{{ +Version: MPL 1.1/GPL 2.0/LGPL 2.1 + +The contents of this file are subject to the Mozilla Public License Version +1.1 (the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at +http://www.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the +License. + +(c) 2006-2007: Martin Stubenschrott + +Alternatively, the contents of this file may be used under the terms of +either the GNU General Public License Version 2 or later (the "GPL"), or +the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +in which case the provisions of the GPL or the LGPL are applicable instead +of those above. If you wish to allow use of your version of this file only +under the terms of either the GPL or the LGPL, and not to allow others to +use your version of this file under the terms of the MPL, indicate your +decision by deleting the provisions above and replace them with the notice +and other provisions required by the GPL or the LGPL. If you do not delete +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 *****/ + +vimperator.modes = (function() +{ + var main = 1; // NORMAL + var extended = 0; // NONE + + var passNextKey = false; + var passAllKeys = false; + + function getModeMessage() + { + if (passNextKey && !passAllKeys) + return "PASS THROUGH (next)"; + else if (passAllKeys && !passNextKey) + return "PASS THROUGH"; + + var ext = ""; + switch (extended) + { + case vimperator.modes.QUICK_HINT: + ext = " (quick)"; break; + case vimperator.modes.EXTENDED_HINT: + ext = " (extended)"; break; + case vimperator.modes.ALWAYS_HINT: + ext = " (always)"; break; + case vimperator.modes.MENU: // TODO: desirable? + ext = " (menu)"; break; + } + + switch (main) + { + case vimperator.modes.INSERT: + return "INSERT" + ext; + case vimperator.modes.VISUAL: + return (extended & vimperator.modes.LINE) ? "VISUAL LINE" + ext : "VISUAL" + ext; + case vimperator.modes.HINTS: + return "HINTS" + ext; + case vimperator.modes.CARET: + return "CARET" + ext; + case vimperator.modes.TEXTAREA: + return "TEXTAREA" + ext; + default: + return null; + } + } + + function handleModeChange(oldmode, newmode) + { + vimperator.log("switching from mode " + oldmode + " to mode " + newmode, 7); + + switch (oldmode) + { + case vimperator.modes.TEXTAREA: + case vimperator.modes.INSERT: + vimperator.editor.unselectText(); + break; + + case vimperator.modes.VISUAL: + if (newmode == vimperator.modes.CARET) + { + // clear any selection made + var selection = window.content.getSelection(); + if (selection) + selection.collapseToStart(); + } + else + vimperator.editor.unselectText(); + break; + + case vimperator.modes.HINTS: + // XXX: for now this does not work, but later it should be here + // vimperator.hints.disableHahMode(); + break; + } + + if (newmode == vimperator.modes.NORMAL) + { + var value = Options.getFirefoxPref("accessibility.browsewithcaret", false); + if (value) + Options.setFirefoxPref("accessibility.browsewithcaret", false); + + vimperator.statusline.updateUrl(); + vimperator.focusContent(); + } + } + + return { + // main modes, only one should ever be active + NONE: 0, + NORMAL: 1 << 0, + INSERT: 1 << 1, + VISUAL: 1 << 2, + 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, can include multiple modes, and even main modes + EX: 1 << 10, + INPUT_MULTILINE: 1 << 11, + OUTPUT_MULTILINE: 1 << 12, + SEARCH_FORWARD: 1 << 13, + SEARCH_BACKWARD: 1 << 14, + QUICK_HINT: 1 << 15, + EXTENDED_HINT: 1 << 16, + ALWAYS_HINT: 1 << 17, + MENU: 1 << 18, // a popupmenu is active + LINE: 1 << 19, // linewise visual mode + + reset: function() + { + this.set(vimperator.modes.NORMAL, vimperator.modes.NONE); + }, + + show: function() + { + if (!vimperator.options["showmode"]) + return; + + // never show mode messages if we are in command line mode + if (main == vimperator.modes.COMMAND_LINE) + return; + + var msg = getModeMessage(); + if (msg) + vimperator.commandline.echo("-- " + getModeMessage() + " --"); + else + vimperator.commandline.echo(""); + }, + + // helper function to set both modes in one go + set: function(main_mode, extended_mode, silent) + { + // if a main mode is set, the extended is always cleared + if (typeof main_mode === "number") + { + if (main_mode != main) + handleModeChange(main, main_mode); + + main = main_mode; + if (!extended_mode) + extended = vimperator.modes.NONE; + + } + if (typeof extended_mode === "number") + extended = extended_mode; + + if (!silent) + this.show(); + }, + + // add/remove always work on the extended mode only + add: function(mode) + { + extended |= mode; + this.show(); + }, + remove: function(mode) + { + extended = (extended | mode) ^ mode; + this.show(); + }, + + get passNextKey() { return passNextKey; }, + set passNextKey(value) { passNextKey = value; this.show(); }, + + get passAllKeys() { return passAllKeys; }, + set passAllKeys(value) { passAllKeys = value; this.show(); }, + + get main() { return main; }, + set main(value) { + if (value != main) + handleModeChange(main, value); + + main = value; + // setting the main mode always resets any extended mode + extended = vimperator.modes.NONE; + this.show(); + }, + + get extended() { return extended; }, + set extended(value) { + extended = value; this.show(); + } + } +})(); + + diff --git a/chrome/content/vimperator/options.js b/chrome/content/vimperator/options.js index 398bd0e7..96758d39 100644 --- a/chrome/content/vimperator/options.js +++ b/chrome/content/vimperator/options.js @@ -143,16 +143,15 @@ function Options() //{{{ function loadPreference(name, forced_default, vimperator_branch) { - var pref = null; - var default_value = ""; + var default_value = null; + if (forced_default != null) // this argument sets defaults for non-user settable options (like comp_history) + default_value = forced_default; if (vimperator_branch) { branch = vimperator_prefs; - if (forced_default) // this argument sets defaults for non-user settable options (like comp_history) - default_value = forced_default; - else + if (!forced_default) // this argument sets defaults for non-user settable options (like comp_history) { for (var i = 0; i < options.length; i++) { @@ -171,21 +170,22 @@ function Options() //{{{ try { - if (typeof default_value == "string") - pref = branch.getCharPref(name); - else if (typeof default_value == "number") - pref = branch.getIntPref(name); - else if (typeof default_value == "boolean") - pref = branch.getBoolPref(name); - else - pref = default_value; + switch (typeof default_value) + { + case "string": + return branch.getCharPref(name); + case "number": + return branch.getIntPref(name); + case "boolean": + return branch.getBoolPref(name); + default: + return default_value; + } } catch (e) { - //alert("error: " + e); - pref = default_value; + return default_value; } - return pref; } function setGuiOptions(value) diff --git a/chrome/content/vimperator/ui.js b/chrome/content/vimperator/ui.js index ff9327ea..b08cc866 100644 --- a/chrome/content/vimperator/ui.js +++ b/chrome/content/vimperator/ui.js @@ -154,9 +154,11 @@ function CommandLine() //{{{ //multiline_output_widget.style.height = height + "px"; multiline_output_widget.height = height + "px"; multiline_output_widget.collapsed = false; - //vimperator.log(content_height); - multiline_output_widget.contentWindow.scrollTo(0, content_height); // scroll to the end when 'nomore' is set + //multiline_output_widget.contentWindow.scrollTo(0, content_height); // scroll to the end when 'nomore' is set + multiline_output_widget.contentWindow.scrollTo(0, 0); // scroll to the end when 'nomore' is set multiline_output_widget.contentWindow.focus(); + + vimperator.modes.set(vimperator.modes.COMMAND_LINE, vimperator.modes.OUTPUT_MULTILINE); } function autosizeMultilineInputWidget() @@ -214,8 +216,9 @@ function CommandLine() //{{{ completion_index = UNINITIALIZED; // save the mode, because we need to restore it - [old_mode, old_extended_mode] = vimperator.getMode(); - vimperator.setMode(vimperator.modes.COMMAND_LINE, cur_extended_mode, true); + old_mode = vimperator.mode; + old_extended_mode = vimperator.mode.extended; + vimperator.modes.set(vimperator.modes.COMMAND_LINE, cur_extended_mode); setPrompt(cur_prompt); setCommand(cur_command); @@ -275,9 +278,10 @@ function CommandLine() //{{{ // @param until_regexp this.inputMultiline = function(until_regexp, callback_func) { - // save the mode, because we need to restore it on blur() - [old_mode, old_extended_mode] = vimperator.getMode(); - vimperator.setMode(vimperator.modes.COMMAND_LINE, vimperator.modes.READ_MULTILINE, true); + // save the mode, because we need to restore it + old_mode = vimperator.mode; + old_extended_mode = vimperator.mode.extended; + vimperator.modes.set(vimperator.modes.COMMAND_LINE, vimperator.modes.INPUT_MULTILINE); // save the arguments, they are needed in the event handler onEvent multiline_regexp = until_regexp; @@ -311,14 +315,15 @@ function CommandLine() //{{{ { // prevent losing focus, there should be a better way, but it just didn't work otherwise setTimeout(function() { - if (vimperator.hasMode(vimperator.modes.COMMAND_LINE) && - !vimperator.hasMode(vimperator.modes.READ_MULTILINE)) - command_widget.inputField.focus(); + if (vimperator.mode == vimperator.modes.COMMAND_LINE && + !(vimperator.modes.extended & vimperator.modes.INPUT_MULTILINE) && + !(vimperator.modes.extended & vimperator.modes.OUTPUT_MULTILINE)) + command_widget.inputField.focus(); }, 0); } else if (event.type == "focus") { - if (!cur_extended_mode) + if (!cur_extended_mode && event.target == command_widget.inputField) event.target.blur(); } else if (event.type == "input") @@ -337,8 +342,9 @@ function CommandLine() //{{{ { var mode = cur_extended_mode; // save it here, as setMode() resets it addToHistory(command); - vimperator.setMode(old_mode, old_extended_mode); - vimperator.focusContent(); + vimperator.modes.reset(); //FIXME: use mode stack + //vimperator.modes.set(old_mode, old_extended_mode, true); + //vimperator.focusContent(); completionlist.hide(); vimperator.statusline.updateProgress(""); // we may have a "match x of y" visible return vimperator.triggerCallback("submit", mode, command); @@ -349,8 +355,8 @@ function CommandLine() //{{{ { var res = vimperator.triggerCallback("cancel", cur_extended_mode); addToHistory(command); - vimperator.setMode(old_mode, old_extended_mode); - vimperator.focusContent(); + vimperator.modes.set(old_mode, old_extended_mode); + //vimperator.focusContent(); completionlist.hide(); vimperator.statusline.updateProgress(""); // we may have a "match x of y" visible this.clear(); @@ -534,9 +540,7 @@ function CommandLine() //{{{ if (command.length == 0) { vimperator.triggerCallback("cancel", cur_extended_mode); - vimperator.setMode(old_mode, old_extended_mode); - vimperator.focusContent(); - this.clear(); + vimperator.modes.reset(); // FIXME: use mode stack } } else // any other key @@ -558,20 +562,20 @@ function CommandLine() //{{{ if (text.match(multiline_regexp)) { text = text.replace(multiline_regexp, ""); - vimperator.setMode(old_mode, old_extended_mode); + vimperator.modes.set(old_mode, old_extended_mode); multiline_input_widget.collapsed = true; multiline_callback.call(this, text); } } else if (vimperator.events.isCancelKey(key)) { - vimperator.setMode(old_mode, old_extended_mode); + vimperator.modes.set(old_mode, old_extended_mode); multiline_input_widget.collapsed = true; } } else if (event.type == "blur") { - if (vimperator.hasMode(vimperator.modes.READ_MULTILINE)) + if (vimperator.modes.extended & vimperator.modes.INPUT_MULTILINE) setTimeout(function() { multiline_input_widget.inputField.focus(); }, 0); } else if (event.type == "input") @@ -580,13 +584,80 @@ function CommandLine() //{{{ } } + // TODO: differentiate between scrollable and not scrollable this.onMultilineOutputEvent = function(event) { - var key = vimperator.events.toString(event); - if (vimperator.events.isAcceptKey(key) || vimperator.events.isCancelKey(key)) + // return 0 if window can never scroll + // 1 if window can scroll, but is at the end + // 2 if window can scroll + function canScroll() + { + var win = multiline_output_widget.contentWindow; + var percent = win.scrollMaxY == 0 ? -1 : win.scrollY / win.scrollMaxY; + if (percent < 0) + return 0; + else if (percent >= 1) + return 1; + else + return 2; + } + + function hide() { multiline_output_widget.collapsed = true; - vimperator.focusContent(); + // FIXME: use mode stack + vimperator.modes.reset(); + } + + var key = vimperator.events.toString(event); + switch (key) + { + case ":": + vimperator.commandline.open(":", "", vimperator.modes.EX); + break; + + case "j": + case "": + case "": + if (canScroll() == 2) + multiline_output_widget.contentWindow.scrollByLines(1); + else + hide(); + break; + case "k": + case "": + case "": + if (canScroll() >= 1) + multiline_output_widget.contentWindow.scrollByLines(-1); + else + hide(); + break; + case "f": + if (canScroll() == 2) + multiline_output_widget.contentWindow.scrollByPages(1); + else + hide(); + break; + case "b": + if (canScroll() >= 1) + multiline_output_widget.contentWindow.scrollByPages(-1); + else + hide(); + break; + case "g": + multiline_output_widget.contentWindow.scrollTo(0, 0); + break; + case "G": + multiline_output_widget.contentWindow.scrollTo(0, multiline_output_widget.contentWindow.scrollMaxY); + break; + + default: + if (canScroll() == 0 || vimperator.events.isCancelKey(key)) + hide(); + else if (canScroll() == 1 && vimperator.events.isAcceptKey(key)) + hide(); + else + ; // show a more help inline like in vim } } diff --git a/chrome/content/vimperator/vimperator.js b/chrome/content/vimperator/vimperator.js index 0f85f5b2..5bc5bd54 100644 --- a/chrome/content/vimperator/vimperator.js +++ b/chrome/content/vimperator/vimperator.js @@ -32,51 +32,6 @@ const vimperator = (function() //{{{ ////////////////////// PRIVATE SECTION ///////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - var modes = { - // main modes - NONE: 0, - NORMAL: 1 << 0, - INSERT: 1 << 1, - VISUAL: 1 << 2, - 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, - SEARCH_FORWARD: 1 << 12, - SEARCH_BACKWARD: 1 << 13, - ESCAPE_ONE_KEY: 1 << 14, - ESCAPE_ALL_KEYS: 1 << 15, - QUICK_HINT: 1 << 16, - EXTENDED_HINT: 1 << 17, - ALWAYS_HINT: 1 << 18, - MENU: 1 << 19, // a popupmenu is active - LINE: 1 << 20 // linewise visual mode - } - - var mode_messages = {}; - mode_messages[modes.NORMAL] = ""; - mode_messages[modes.INSERT] = "INSERT"; - mode_messages[modes.VISUAL] = "VISUAL"; - mode_messages[modes.HINTS] = "HINTS"; - mode_messages[modes.CARET] = "CARET"; - mode_messages[modes.TEXTAREA] = "TEXTAREA"; - mode_messages[modes.TEXTAREA | modes.LINE] = "line"; // used in visual mode - 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"; - mode_messages[modes.QUICK_HINT] = "quick"; - mode_messages[modes.EXTENDED_HINT] = "extended"; - mode_messages[modes.ALWAYS_HINT] = "always"; - mode_messages[modes.MENU] = "menu"; // TODO: desirable? -> now that it seems to work reliable -> NO (--mst) - - var mode = modes.NORMAL; - var extended_mode = modes.NONE; - - var callbacks = []; - // our services var sound_service = Components.classes['@mozilla.org/sound;1'] .getService(Components.interfaces.nsISound); @@ -85,26 +40,8 @@ const vimperator = (function() //{{{ var environment_service = Components.classes["@mozilla.org/process/environment;1"] .getService(Components.interfaces.nsIEnvironment); - function showMode() - { - if (!vimperator.options["showmode"]) - return; + var callbacks = []; - var str_mode = mode_messages[mode]; - var str_extended = mode_messages[extended_mode]; - if (!str_mode && !str_extended) - { - vimperator.commandline.echo(""); - return; - } - - if (str_extended) - str_extended = " (" + str_extended + ")"; - else - str_extended = ""; - - vimperator.commandline.echo("-- " + str_mode.toUpperCase() + str_extended.toLowerCase() + " --"); - } function expandPath(path) { @@ -189,15 +126,14 @@ const vimperator = (function() //{{{ /////////////////////////////////////////////////////////////////////////////{{{ return { + get mode() { return vimperator.modes.main; }, + set mode(value) { vimperator.modes.main = value; }, - modes: modes, - - //openflags: { // XXX: maybe move these consts in a subnamespace? + // Global contants CURRENT_TAB: 1, NEW_TAB: 2, NEW_BACKGROUND_TAB: 3, NEW_WINDOW: 4, - //}, // ###VERSION### and ###DATE### are replaced by the Makefile version: "###VERSION### (created: ###DATE###)", @@ -233,64 +169,6 @@ const vimperator = (function() //{{{ return false; }, - getMode: function() - { - return [mode, extended_mode]; - }, - - // set current mode - // use "null" if you only want to set one of those modes - setMode: function(main, extended, silent) - { - // if a main mode is set, the extended is always cleared - if (main) - { - mode = main; - extended_mode = vimperator.modes.NONE; - - // TODO: also fix the other modes!! - switch (main) - { - case vimperator.modes.TEXTAREA: - vimperator.editor.unselectText(); - break; - } - } - if (typeof extended === "number") - extended_mode = extended; - - if (!silent) - showMode(); - }, - - // returns true if "whichmode" is found in either the main or - // extended mode - hasMode: function(whichmode) - { - return ((mode & whichmode) || (extended_mode & whichmode) > 0) ? true : false; - }, - - addMode: function(main, extended) - { - if (main) - mode |= main; - if (extended) - extended_mode |= extended; - - showMode(); - }, - - // always show the new mode in the statusline - removeMode: function(main, extended) - { - if (main) - mode = (mode | main) ^ main; - if (extended) - extended_mode = (extended_mode | extended) ^ extended; - - showMode(); - }, - beep: function() { if (!vimperator.options["visualbell"]) @@ -640,8 +518,12 @@ const vimperator = (function() //{{{ }, 1000); } - //gURLBar.blur(); // TODO: needed anymore? - vimperator.focusContent(); + // disable caret browsing initially + //Options.setFirefoxPref("accessibility.browsewithcaret", false); + //vimperator.focusContent(); + + // always start in normal mode + vimperator.modes.reset(); // finally, read a ~/.vimperatorrc // make sourcing asynchronous, otherwise commands that open new tabs won't work diff --git a/chrome/content/vimperator/vimperator.xul b/chrome/content/vimperator/vimperator.xul index b057bc7c..783ad251 100644 --- a/chrome/content/vimperator/vimperator.xul +++ b/chrome/content/vimperator/vimperator.xul @@ -51,6 +51,7 @@ the terms of any one of the MPL, the GPL or the LGPL.