From 5aa89672c96f1405b6e9d5355e6b351268cfb049 Mon Sep 17 00:00:00 2001 From: Martin Stubenschrott Date: Thu, 7 Jun 2007 23:33:38 +0000 Subject: [PATCH] marks support (thanks viktor) --- ChangeLog | 1 + chrome/content/vimperator/bookmarks.js | 163 ++++++++++++++++- chrome/content/vimperator/commands.js | 89 ++++----- chrome/content/vimperator/find.js | 6 +- chrome/content/vimperator/mappings.js | 233 ++++++++++++++++-------- chrome/content/vimperator/vimperator.js | 151 ++++++++------- 6 files changed, 448 insertions(+), 195 deletions(-) diff --git a/ChangeLog b/ChangeLog index 603ec951..e0d20c7d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@
 2007-05-02:
 	* version ???
+	* added marks support (thanks Viktor Kojouharov)
 	* temporary shortcut Y to yank current selection (for non UNIX-users)
 	* Flashing frame with ]f now works as expected
 	* many help fixes (most of them by Doug Kearns)
diff --git a/chrome/content/vimperator/bookmarks.js b/chrome/content/vimperator/bookmarks.js
index c10f15a4..c04f6bfc 100644
--- a/chrome/content/vimperator/bookmarks.js
+++ b/chrome/content/vimperator/bookmarks.js
@@ -352,7 +352,7 @@ function History()
     logMessage("History initialized");
 }
 
-Vimperator.prototype.quickmarks = new function()
+/*Vimperator.prototype.quickmarks = new function()
 {
     //logObject(vimperator);
     //setTimeout(function() {logObject(vimperator)}, 1000);
@@ -375,8 +375,165 @@ function QM()
     this.zoom = function() { vimperator.zoom_to(200); logObject(vimperator)};
 
     logMessage("QM initialized.");
+}*/
+
+function Marks()
+{
+    var marks = {};
+
+    function remove(mark)
+    {
+        var ok = false;
+        if (mark.match(/^[A-Z0-9]$/))
+        {
+            if (mark in marks)
+            {
+                delete marks[mark];
+                ok = true;
+            }
+        }
+        else if (mark.match(/^[a-z]$/))
+        {
+            if (mark in marks)
+            {
+                var win = vimperator.getCurrentBuffer(), length = marks[mark].length;
+                for (var i = 0; i < length; i++)
+                {
+                    if (marks[mark][i].location == win.location.href)
+                    {
+                        marks[mark].splice(i, 1);
+                        ok = true;
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (!ok)
+        {
+            vimperator.echoerr("E20: Mark not set");
+            return false;
+        }
+        return ok;
+    }
+    
+    this.add = function(mark)
+    {
+        var win = vimperator.getCurrentBuffer();
+        var x = win.scrollMaxX ? win.pageXOffset / win.scrollMaxX : 0;
+        var y = win.scrollMaxY ? win.pageYOffset / win.scrollMaxY : 0;
+        var position = { x: x, y: y };
+        if (mark.match(/^[A-Z0-9]$/))
+            marks[mark] = { location: win.location.href, position: position, tab: vimperator.tabs.getTab() };
+        else if (mark.match(/^[a-z]$/))
+        {
+            if (!marks[mark])
+                marks[mark] = [];
+            marks[mark].push({ location: win.location.href, position: position });
+        }
+        else
+            return false;
+
+        return this;
+    }
+
+    // TODO: add support for mark ranges (p-z)
+    this.remove = function(marks_str, special)
+    {
+        if (special)
+        {
+            var win = vimperator.getCurrentBuffer();
+            for (var i in marks)
+            {
+                if (i.match(/^[A-Z0-9]$/))
+                    continue;
+
+                var length = marks[i].length;
+                for (var j = 0; j < length; j++)
+                {
+                    if (marks[i][j].location == win.location.href)
+                    {
+                        marks[i].splice(j, 1);
+                        ok = true;
+                        break;
+                    }
+                }
+            }
+            return this;
+        }
+        marks_str.split(/ /).forEach(function(mark)
+        {
+            if (mark.length == 1)
+                remove(mark);
+            else
+                for (var i = 0; i < mark.length; i++)
+                {
+                    remove(mark.substr(i, 1));
+                }
+        });
+        return this;
+    }
+
+    this.jumpTo = function(mark)
+    {
+        var ok = false;
+        if (mark.match(/^[A-Z0-9]$/))
+        {
+            var slice = marks[mark];
+            if (slice && slice.tab && slice.tab.linkedBrowser)
+            {
+                vimperator.tabs.select(vimperator.tabs.index(slice.tab));
+                if (!slice.tab.parentNode)
+                {
+                    /* FIXME: this doesn't work
+                    setTimeout(function()
+                        {
+                            vimperator.getCurrentBuffer().addEventListener('load', function()
+                                {
+                                    this.scrollTo(slice.position.x, slice.position.y);
+                                }, false);
+                        }, 100);
+                    */
+                    openURLsInNewTab(slice.location);
+                    return;
+                }
+                var win = slice.tab.linkedBrowser.contentWindow;
+                if (win.location.href != slice.location)
+                {
+                    win.location.href = slice.location;
+                    return;
+                }
+                win.scrollTo(slice.position.x * win.scrollMaxX, slice.position.y * win.scrollMaxY);
+                ok = true;
+            }
+        }
+        else if (mark.match(/^[a-z]$/))
+        {
+            var win = vimperator.getCurrentBuffer();
+            var slice = marks[mark] || [];
+            for (var i = 0; i < slice.length; i++)
+            {
+                if (win.location.href == slice[i].location)
+                {
+                    win.scrollTo(slice[i].position.x * win.scrollMaxX, slice[i].position.y * win.scrollMaxY);
+                    ok = true;
+                }
+            }
+        }
+
+        if (!ok)
+        {
+            vimperator.echoerr("E20: Mark not set");
+            return false;
+        }
+        return this;
+    }
+    
+    // TODO: show marks like vim does (when the multiline echo impl is done) or in the preview windwo right now
+    this.list = function()
+    {
+        return this;
+    }
 }
 
-
-
 // vim: set fdm=marker sw=4 ts=4 et:
diff --git a/chrome/content/vimperator/commands.js b/chrome/content/vimperator/commands.js
index ca353244..efba3b2d 100644
--- a/chrome/content/vimperator/commands.js
+++ b/chrome/content/vimperator/commands.js
@@ -31,16 +31,6 @@ const USAGE = 1;
 const SHORTHELP = 2;
 const HELP = 3;
 
-
-// var g_insert_mappings = [ /*{{{*/
-//     ["xxx", "todo"],
-//     ["", "delete word"],
-//     ["", "delete beginning"],
-//     ["", "go beginning"],
-//     ["", "go end"],
-//     ["", "cancel"]
-// ]; /*}}}*/
-
 /* [command, action, cancel_hint_mode, always_active] */
 var g_hint_mappings = [ /*{{{*/
     /* hint action keys */
@@ -269,7 +259,13 @@ function Commands()//{{{
         }
     ));
     addDefaultCommand(new Command(["ba[ck]"],
-        function(args, special, count) { if(special) historyGoToBeginning(); else stepInHistory(count > 0 ? -1 * count : -1); },
+        function(args, special, count)
+        {
+            if(special)
+                historyGoToBeginning();
+            else
+                stepInHistory(count > 0 ? -1 * count : -1);
+        },
         {
             usage: ["{count}ba[ck][!]"],
             short_help: "Go back in the browser history",
@@ -286,7 +282,7 @@ function Commands()//{{{
         }
     ));
     addDefaultCommand(new Command(["beep"],
-        function() { /*vimperator.*/beep(); },
+        /*vimperator.*/beep,
         {
             usage: ["beep"],
             short_help: "Play a system beep"
@@ -346,6 +342,17 @@ function Commands()//{{{
             help: "If the list is already shown, close the preview window."
         }
     ));
+    addDefaultCommand(new Command(["delm[arks]"],
+        function(marks, special) { vimperator.marks.remove(marks, special); },
+        {
+            usage: ["delm[arks]! {marks}"],
+            short_help: "Delete the specified marks {a-zA-Z}",
+            help: "Marks are presented as a list. Example:
" + + ":delmarks Aa b p will delete marks A, a, b and p
" + + ":delmarks! will delete all marks for the current buffer", + } + + )); addDefaultCommand(new Command(["downl[oads]", "dl"], function() { openURLsInNewTab("chrome://mozapps/content/downloads/downloads.xul", true); }, { @@ -387,7 +394,13 @@ function Commands()//{{{ } )); addDefaultCommand(new Command(["fo[rward]", "fw"], - function(args, special, count) { if(special) historyGoToEnd(); else stepInHistory(count > 0 ? count : 1); }, + function(args, special, count) + { + if(special) + historyGoToEnd(); + else + stepInHistory(count > 0 ? count : 1); + }, { usage: ["{count}fo[rward][!]"], short_help: "Go forward in the browser history", @@ -451,19 +464,17 @@ function Commands()//{{{ } )); addDefaultCommand(new Command(["ma[rk]"], - set_location_mark, + function(mark) { vimperator.marks.add(mark) }, { usage: ["ma[rk] {arg}"], short_help: "Mark current location within the webpage", - help: "Not implemented yet" } )); addDefaultCommand(new Command(["marks"], - set_location_mark, + function(mark) { vimperator.marks.list(mark) }, { usage: ["marks {arg}"], short_help: "Show all location marks of current webpage", - help: "Not implemented yet" } )); addDefaultCommand(new Command(["o[pen]", "e[dit]"], @@ -645,7 +656,13 @@ function Commands()//{{{ } )); addDefaultCommand(new Command(["tabopen", "t[open]", "tabnew", "tabe[dit]"], - function (args, special) { if (args.length > 0) openURLsInNewTab(args, !special); else openURLsInNewTab("about:blank", true); }, + function (args, special) + { + if (args.length > 0) + openURLsInNewTab(args, !special); + else + openURLsInNewTab("about:blank", true); + }, { usage: ["tabopen [url] [| url]"], short_help: "Open one or more URLs in a new tab", @@ -704,7 +721,13 @@ function Commands()//{{{ } )); addDefaultCommand(new Command(["ve[rsion]"], - function (args, special) { if (special) openURLs("about:"); else vimperator.echo("Vimperator version: " + vimperator.ver); }, + function (args, special) + { + if (special) + openURLs("about:"); + else + vimperator.echo("Vimperator version: " + vimperator.ver); + }, { usage: ["ve[rsion][!]"], short_help: "Show version information", @@ -1204,22 +1227,6 @@ function show_url_marks(mark) } -//////////////////////////////////////////////////////////////////////// -// location marks functions /////////////////////////////////////// {{{1 -//////////////////////////////////////////////////////////////////////// -/* vimperator has a concept of location marks - * these provide quick access to a location within a webpage - */ -function set_location_mark(mark) -{ - -} - -function show_location_marks(mark) -{ - -} - //////////////////////////////////////////////////////////////////////// // tab/buffer related functions /////////////////////////////////// {{{1 //////////////////////////////////////////////////////////////////////// @@ -1270,8 +1277,8 @@ function updateBufferList() function scrollBufferRelative(right, down) { var win = document.commandDispatcher.focusedWindow; - if (g_count < 1) - g_count = 1; + if (vimperator.input.count < 1) + vimperator.input.count = 1; // beep if we can't go there if (down > 0) @@ -1292,7 +1299,7 @@ function scrollBufferRelative(right, down) if (win.scrollX == 0) beep(); } - win.scrollBy(g_count * right * 20, g_count * down * 20); + win.scrollBy(vimperator.input.count * right * 20, vimperator.input.count * down * 20); } /* both values are given in percent, -1 means no change */ @@ -1321,8 +1328,8 @@ function scrollBufferAbsolute(horizontal, vertical) /* also used to zoom out, when factor is negative */ function zoom_in(factor) { - if (g_count < 1) - g_count = 1; + if (vimperator.input.count < 1) + vimperator.input.count = 1; //ZoomManager.prototype.getInstance().enlarge(); var zoomMgr = ZoomManager.prototype.getInstance(); @@ -1338,7 +1345,7 @@ function zoom_in(factor) } else { - var value = zoomMgr.textZoom + factor*g_count*25; + var value = zoomMgr.textZoom + factor*vimperator.input.count*25; if (value < 25) value = 25; if (value > 500) value = 500; diff --git a/chrome/content/vimperator/find.js b/chrome/content/vimperator/find.js index a9347ff0..38f14a6c 100644 --- a/chrome/content/vimperator/find.js +++ b/chrome/content/vimperator/find.js @@ -58,6 +58,7 @@ function clearSelection() { var selctrl = vimperator.search.gSelCtrl; var sel = selctrl.getSelection(Components.interfaces.nsISelectionController.SELECTION_NORMAL); sel.removeAllRanges(); + gFindBar.highlightDoc(); } // Sets what is currently selected @@ -183,6 +184,7 @@ function highlightFind(str, color, wrapped, dir, pt) function clearHighlight() { + gFindBar.highlightDoc(); var win = window._content; var doc = win.document; if (!document) @@ -319,7 +321,8 @@ function Search() // Called when the user types a key in the search dialog. Triggers a find attempt this.searchKeyPressed = function(command) { if (command != "") { - this.find(vimperator.commandline.getCommand(), true, this.lastFindState()["point"]); + var str = vimperator.commandline.getCommand(); + this.find(str, true, this.lastFindState()["point"]); this.resumeFindState(this.lastFindState()); } else { @@ -438,6 +441,7 @@ function Search() wrapped = true; point = null; } + gFindBar.highlightDoc('yellow', 'black', str); matchRange = highlightFind(str, "lightblue", wrapped, dir, point); if (matchRange == null) { // No more matches in this direction. So add the state and then find diff --git a/chrome/content/vimperator/mappings.js b/chrome/content/vimperator/mappings.js index b975db89..a11845a5 100644 --- a/chrome/content/vimperator/mappings.js +++ b/chrome/content/vimperator/mappings.js @@ -10,17 +10,17 @@ function Map(mode, cmds, act, extra_info) //{{{ if (extra_info) { - var flags = extra_info.flags || 0; + this.flags = extra_info.flags || 0; if (extra_info.usage) this.usage = extra_info.usage; else { this.usage = ""; - if (flags & Mappings.flags.COUNT) + if (this.flags & Mappings.flags.COUNT) this.usage = "{count}"; this.usage += this.commands[0]; // only the first command name - if (flags & Mappings.flags.ARGUMENT) + if (this.flags & Mappings.flags.ARGUMENT) this.usage += " {arg}"; } @@ -38,21 +38,28 @@ function Map(mode, cmds, act, extra_info) //{{{ } // Since we will add many Map-objects, we add some functions as prototypes // this will ensure we only have one copy of each function, not one for each object -Map.prototype.execute = function(count) +Map.prototype.execute = function(motion, count, argument) { - this.action.call(this, count); + var args = []; + if (this.flags & Mappings.flags.MOTION) + args.push(motion); + if (this.flags & Mappings.flags.COUNT) + args.push(count); + if (this.flags & Mappings.flags.ARGUMENT) + args.push(argument); + this.action.apply(this, args); } Map.prototype.toString = function() { // FIXME: -- djk return "Map {" + - "\nmode: " + this.mode + - "\ncommands: " + this.commands + - "\naction: " + this.action + - "\nusage: " + this.usage + - "\nshort_help: " + this.short_help + - "\nhelp: " + this.help + + "\n\tmode: " + this.mode + + "\n\tcommands: " + this.commands + + "\n\taction: " + this.action + + "\n\tusage: " + this.usage + + "\n\tshort_help: " + this.short_help + + "\n\thelp: " + this.help + "\n}" } //}}} @@ -111,7 +118,6 @@ function Mappings()//{{{ ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - // TODO: change to Mappings.MOTION etc? -- djk Mappings.flags = { MOTION: 1 << 0, COUNT: 1 << 1, @@ -188,186 +194,224 @@ function Mappings()//{{{ /* * Normal mode */ - addDefaultMap(new Map(vimperator.modes.NORMAL, ["]f"], focusNextFrame, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["'", "`"], + function (mark) { vimperator.marks.jumpTo(mark) }, + { + short_help: "Jump to the mark in the current buffer", + usage: "'{a-zA-Z0-9}", + help: "Marks a-z are local to the buffer, whereas A-Z and 0-9 are valid between buffers.", + flags: Mappings.flags.ARGUMENT + } + )); + addDefaultMap(new Map(vimperator.modes.NORMAL, ["]f"], + focusNextFrame, { short_help: "Focus next frame", help: "Flashes the next frame in order with a red color, to quickly show where keyboard focus is.
" + "This may not work correctly for frames with lots of CSS code." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["b"], function (args) { vimperator.commandline.open(":", "buffer ", vimperator.modes.EX); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["b"], + function (args) { vimperator.commandline.open(":", "buffer ", vimperator.modes.EX); }, { short_help: "Open a prompt to switch buffers", help: "Typing the corresponding number opens switches to this buffer." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["B"], toggleBufferList, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["B"], + toggleBufferList, { short_help: "Toggle buffer list", help: "Toggles the display of the buffer list which shows all opened tabs." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["d"], function(count) { vimperator.tabs.remove(getBrowser().mCurrentTab, count, false, 0); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["d"], + function(count) { vimperator.tabs.remove(getBrowser().mCurrentTab, count, false, 0); }, { short_help: "Delete current buffer (=tab)", help: "Count WILL be supported in future releases, then 2d removes two tabs and the one the right is selected.", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["D"], function(count) { vimperator.tabs.remove(getBrowser().mCurrentTab, count, true, 0); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["D"], + function(count) { vimperator.tabs.remove(getBrowser().mCurrentTab, count, true, 0); }, { short_help: "Delete current buffer (=tab)", help: "Count WILL be supported in future releases, then 2d removes two tabs and the one the right is selected.", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gh"], BrowserHome, + 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"], BrowserHome, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["gH"], + BrowserHome, { short_help: "Go home in a new tab", help: "Opens the homepage in a new tab." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gP"], function(count) { openURLsInNewTab(readFromClipboard(), false); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["gP"], + function(count) { openURLsInNewTab(readFromClipboard(), false); }, { short_help: "Open (put) an URL based on the current clipboard contents in a new buffer", help: "Works like P, but inverts the 'activate' option." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gt", "", ""], function(count) { vimperator.tabs.select(count > 0 ? count -1: "+1", count > 0 ? false : true); }, + 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", help: "Cycles to the first tab, when the last is selected.
Count is supported, 3gt goes to the third tab.", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gT", "", ""], function(count) { vimperator.tabs.select(count > 0 ? count -1: "-1", count > 0 ? false : true); }, + 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", help: "Cycles to the last tab, when the first is selected.
Count is supported, 3gT goes to the third tab.", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["m"], set_location_mark, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["m"], + function(mark) { vimperator.marks.add(mark) }, { short_help: "Set mark at the cursor position", - usage: "m{a-zA-Z}", - help: "Marks a-z are local to the buffer, whereas A-Z are valid between buffers.", + usage: "m{a-zA-Z0-9}", + help: "Marks a-z are local to the buffer, whereas A-Z and 0-9 are valid between buffers.", flags: Mappings.flags.ARGUMENT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["o"], function(count) { vimperator.commandline.open(":", "open ", vimperator.modes.EX); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["o"], + function(count) { 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"], function(count) { vimperator.commandline.open(":", "open " + getCurrentLocation(), vimperator.modes.EX); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["O"], + function(count) { vimperator.commandline.open(":", "open " + getCurrentLocation(), 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", ""], function(count) { openURLs(readFromClipboard()); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["p", ""], + function(count) { openURLs(readFromClipboard()); }, { short_help: "Open (put) an URL based on the current clipboard contents in the current buffer", help: "You can also just select some non-URL text, and search for it with the default search engine or keyword (specified by the 'defsearch' option) with p." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["P"], function(count) { openURLsInNewTab(readFromClipboard(), true); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["P"], + function(count) { openURLsInNewTab(readFromClipboard(), true); }, { short_help: "Open (put) an URL based on the current clipboard contents in a new buffer", help: "Works like p, but opens a new tab.
" + "Whether the new buffer is activated, depends on the 'activate' option." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["r"], function(count) { reload(getBrowser().mCurrentTab, false); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["r"], + function(count) { reload(getBrowser().mCurrentTab, false); }, { short_help: "Reload", help: "Forces reloading of the current page." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["R"], function(count) { reload(getBrowser().mCurrentTab, true); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["R"], + function(count) { 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"], function(count) { vimperator.commandline.open(":", "tabopen ", vimperator.modes.EX); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["t"], + function(count) { vimperator.commandline.open(":", "tabopen ", vimperator.modes.EX); }, { short_help: "Open one or more URLs in a new tab", help: "Like o but open URLs in a new tab.
" + "See :tabopen for more details." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["T"], function(count) { vimperator.commandline.open(":", "tabopen " + getCurrentLocation(), vimperator.modes.EX); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["T"], + function(count) { vimperator.commandline.open(":", "tabopen " + getCurrentLocation(), vimperator.modes.EX); }, { short_help: "Open one ore more URLs in a new tab, based on current location", help: "Works like t, but preselects current URL in the :tabopen query." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["u"], function(count) { execute_command(count, 'undo', false, ''); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["u"], + function(count) { execute_command(count, 'undo', false, ''); }, { short_help: "Undo closing of a tab", help: "If a count is given, don't close the last but the n'th last tab.", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["y"], yankCurrentLocation, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["y"], + yankCurrentLocation, { short_help: "Yank current location to the clipboard", help: "Under UNIX the location is also put into the selection, which can be pasted with the middle mouse button." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["Y"], yankCurrentSelection, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["Y"], + yankCurrentSelection, { short_help: "Copy selected text", help: "The currently selected text is copied to the system clipboard." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["zi", "+"], function(count) { zoom_in(1); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["zi", "+"], + function(count) { zoom_in(1); }, { short_help: "Zoom in current web page by 25%", help: "Currently no count supported." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["zI"], function(count) { zoom_in(4); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["zI"], + function(count) { zoom_in(4); }, { short_help: "Zoom in current web page by 100%", help: "Currently no count supported." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["zo", "-"], function(count) { zoom_in(-1); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["zo", "-"], + function(count) { zoom_in(-1); }, { short_help: "Zoom out current web page by 25%", help: "Currently no count supported." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["zO"], function(count) { zoom_in(-4); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["zO"], + function(count) { zoom_in(-4); }, { short_help: "Zoom out current web page by 100%", help: "Currently no count supported." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["zz"], zoom_to, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["zz"], + zoom_to, { short_help: "Set zoom value of the webpage", help: "Zoom value can be between 25 and 500%. If it is omitted, zoom is reset to 100%.", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["ZQ"], function(count) { quit(false); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["ZQ"], + function(count) { quit(false); }, { short_help: "Quit and don't save the session", help: "Works like :qall." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["ZZ"], function(count) { quit(true); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["ZZ"], + function(count) { quit(true); }, { short_help: "Quit and save the session", help: "Quit Vimperator, no matter how many tabs/windows are open. The session is stored.
" + @@ -376,33 +420,38 @@ function Mappings()//{{{ )); /* scrolling commands */ - addDefaultMap(new Map(vimperator.modes.NORMAL, ["0", "^"], function(count) { scrollBufferAbsolute(0, -1); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["0", "^"], + function(count) { scrollBufferAbsolute(0, -1); }, { 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, ["$"], function(count) { scrollBufferAbsolute(100, -1); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["$"], + function(count) { scrollBufferAbsolute(100, -1); }, { short_help: "Scroll to the absolute right of the document", help: null } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gg", ""], function(count) { scrollBufferAbsolute(-1, count > 0 ? count : 0); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["gg", ""], + function(count) { scrollBufferAbsolute(-1, count > 0 ? count : 0); }, { short_help: "Goto the top of the document", help: "Count is supported, 35gg vertically goes to 35% of the document.", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["G", ""], function(count) { scrollBufferAbsolute(-1, count >= 0 ? count : 100); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["G", ""], + function(count) { scrollBufferAbsolute(-1, count >= 0 ? count : 100); }, { short_help: "Goto the end of the document", help: "Count is supported, 35G vertically goes to 35% of the document.", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["h", ""], function(count) { scrollBufferRelative(-1, 0); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["h", ""], + function(count) { scrollBufferRelative(-1, 0); }, { short_help: "Scroll document to the left", help: "Count is supported: 10h will move 10 times as much to the left.
" + @@ -410,7 +459,8 @@ function Mappings()//{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["j", "", ""], function(count) { scrollBufferRelative(0, 1); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["j", "", ""], + function(count) { scrollBufferRelative(0, 1); }, { short_help: "Scroll document down", help: "Count is supported: 10j will move 10 times as much down.
" + @@ -418,7 +468,8 @@ function Mappings()//{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["k", "", ""], function(count) { scrollBufferRelative(0, -1); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["k", "", ""], + function(count) { scrollBufferRelative(0, -1); }, { short_help: "Scroll document up", help: "Count is supported: 10k will move 10 times as much up.
" + @@ -426,7 +477,8 @@ function Mappings()//{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["l", ""], function(count) { scrollBufferRelative(1, 0); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["l", ""], + function(count) { scrollBufferRelative(1, 0); }, { short_help: "Scroll document to the right", help: "Count is supported: 10l will move 10 times as much to the right.
" + @@ -434,13 +486,15 @@ function Mappings()//{{{ flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["", "", "", ""], function(count) { goDoCommand('cmd_scrollPageUp'); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["", "", "", ""], + function(count) { goDoCommand('cmd_scrollPageUp'); }, { short_help: "Scroll up a full page of the current document", help: "No count support for now." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["", "", "", ""], function(count) { goDoCommand('cmd_scrollPageDown'); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["", "", "", ""], + function(count) { goDoCommand('cmd_scrollPageDown'); }, { short_help: "Scroll down a full page of the current document", help: "No count support for now." @@ -448,42 +502,48 @@ function Mappings()//{{{ )); /* history manipulation and jumplist */ - addDefaultMap(new Map(vimperator.modes.NORMAL, [""], function(count) { stepInHistory(count > 0 ? -1 * count : -1); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, [""], + function(count) { stepInHistory(count > 0 ? -1 * count : -1); }, { short_help: "Go to an older position in the jump list", help: "The jump list is just the browser history for now.", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, [""], function(count) { stepInHistory(count > 0 ? count : 1); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, [""], + function(count) { stepInHistory(count > 0 ? count : 1); }, { short_help: "Go to a newer position in the jump list", help: "The jump list is just the browser history for now.", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["H", "", ""], function(count) { stepInHistory(count > 0 ? -1 * count : -1); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["H", "", ""], + function(count) { stepInHistory(count > 0 ? -1 * count : -1); }, { short_help: "Go back in the browser history", help: "Count is supported, 3H goes back 3 steps.", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["L", "", ""], function(count) { stepInHistory(count > 0 ? count : 1); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["L", "", ""], + function(count) { stepInHistory(count > 0 ? count : 1); }, { short_help: "Go forward in the browser history", help: "Count is supported, 3L goes forward 3 steps.", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gu", ""], goUp, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["gu", ""], + goUp, { short_help: "Go to parent directory", help: "Count is supported, 2gu on http://www.example.com/dir1/dir2/file.htm would open http://www.example.com/dir1/.", flags: Mappings.flags.COUNT } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["gU", ""], function(count) { openURLs("..."); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["gU", ""], + function(count) { openURLs("..."); }, { short_help: "Go to the root of the website", help: "gU on http://www.example.com/dir1/dir2/file.htm opens http://www.example.com/.
" + @@ -492,7 +552,8 @@ function Mappings()//{{{ )); /* hint managment */ - addDefaultMap(new Map(vimperator.modes.NORMAL, ["f"], function(count) { hah.enableHahMode(vimperator.modes.QUICK_HINT); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["f"], + function(count) { hah.enableHahMode(vimperator.modes.QUICK_HINT); }, { short_help: "Start QuickHint mode", help: "In QuickHint mode, every hintable item (according to the 'hinttags' XPath query) is assigned a label.
" + @@ -500,7 +561,8 @@ function Mappings()//{{{ "If you write the hint in ALLCAPS, the hint is followed in a background tab." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["F"], function(count) { hah.enableHahMode(vimperator.modes.ALWAYS_HINT); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["F"], + function(count) { hah.enableHahMode(vimperator.modes.ALWAYS_HINT); }, { short_help: "Start AlwaysHint mode", help: "In AlwaysHint mode, every hintable item (according to the 'hinttags' XPath query) is assigned a label.
" + @@ -509,7 +571,8 @@ function Mappings()//{{{ "Also, most Ctrl-prefixed shortcut keys are available in this mode for navigation." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, [";"], function(count) { hah.enableHahMode(vimperator.modes.EXTENDED_HINT); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, [";"], + function(count) { hah.enableHahMode(vimperator.modes.EXTENDED_HINT); }, { short_help: "Start ExtendedHint mode", help: "ExtendedHint mode is useful, since in this mode you can yank link locations, or open them in a new window.
" + @@ -532,19 +595,22 @@ function Mappings()//{{{ )); /* search managment */ - addDefaultMap(new Map(vimperator.modes.NORMAL, ["g/"], function(count) { vimperator.search.openSearchDialog(); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["g/"], + function(count) { vimperator.search.openSearchDialog(); }, { short_help: "Search forward for a pattern", - help: "" + help: "Buggy on many sites, use / if you want a reliable search!" } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["n"], function(count) { vimperator.search.findNext(); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["n"], + function(count) { vimperator.search.findNext(); }, { short_help: "Find next", help: "Repeat the last \"/\" 1 time (until count is supported)." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, ["N"], function(count) { vimperator.search.findPrevious(); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["N"], + function(count) { vimperator.search.findPrevious(); }, { short_help: "Find previous", help: "Repeat the last \"/\" 1 time (until count is supported) in the opposite direction." @@ -552,19 +618,22 @@ function Mappings()//{{{ )); /* vimperator managment */ - addDefaultMap(new Map(vimperator.modes.NORMAL, [""], function(count) { help(null); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, [""], + function(count) { help(null); }, { short_help: "Open help window", help: "The default section is shown, if you need help for a specific topic, try :help <F1> (jumping to a specific section not implemented yet)." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, [":"], function(count) { vimperator.commandline.open(":", "", vimperator.modes.EX); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, [":"], + function(count) { 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"], function(count) { vimperator.addMode(null, vimperator.modes.ESCAPE_ALL_KEYS);}, + addDefaultMap(new Map(vimperator.modes.NORMAL, ["I"], + function(count) { vimperator.addMode(null, vimperator.modes.ESCAPE_ALL_KEYS); }, { short_help: "Disable vimperator keys", help: "Starts an 'ignorekeys' mode, where all keys except <Esc> are passed to the next event handler.
" + @@ -573,8 +642,8 @@ function Mappings()//{{{ "in this mode to the webpage, prepend it with <C-v>." } )); - // if you ever add/remove keys here, also check them in the onVimperatorKeypress() function - addDefaultMap(new Map(vimperator.modes.NORMAL, [""], function(count) { vimperator.addMode(null, vimperator.modes.ESCAPE_ONE_KEY); }, + addDefaultMap(new Map(vimperator.modes.NORMAL, [""], + function(count) { vimperator.addMode(null, vimperator.modes.ESCAPE_ONE_KEY); }, { 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>.
" + @@ -582,14 +651,16 @@ function Mappings()//{{{ "When in 'ignorekeys' mode (activated by <I>), <C-v> will pass the next key to Vimperator instead of the webpage." } )); - addDefaultMap(new Map(vimperator.modes.NORMAL, [""], BrowserStop, + addDefaultMap(new Map(vimperator.modes.NORMAL, [""], + BrowserStop, { short_help: "Stop loading", help: "Stops loading the current webpage." } )); - // if you ever add/remove keys here, also check them in the onVimperatorKeypress() - addDefaultMap(new Map(vimperator.modes.NORMAL, ["", ""], onEscape, + // if you ever add/remove keys here, also check them in the vimperaotr.onEvent() + addDefaultMap(new Map(vimperator.modes.NORMAL, ["", ""], + onEscape, { short_help: "Cancel any operation", help: "Exits any command line or hint mode and returns to browser mode.
" + @@ -597,6 +668,8 @@ function Mappings()//{{{ } )); //}}} + + // TODO: Convert these to the new mappings model var hint_maps = [ /* hint action keys */ ["o", "hah.openHints(false, false);", true, false], @@ -605,7 +678,7 @@ function Mappings()//{{{ ["s", "vimperator.echoerr('Saving of links not yet implemented');", true, false], ["y", "hah.yankUrlHints();", true, false], ["Y", "hah.yankTextHints();", true, false], - [",", "g_inputbuffer+=','; hah.setCurrentState(0);", false, true], + [",", "vimperator.input.count+=','; hah.setCurrentState(0);", false, true], [":", "vimperator.commandline.open(':', '', vimperator.modes.EX);", false, true], /* movement keys */ ["", "scrollBufferRelative(0, 1);", false, true], @@ -624,11 +697,11 @@ function Mappings()//{{{ ["", "vimperator.tabs.select('+1', true)", true, true], // same as gt, but no count supported ["", "vimperator.tabs.select('-1', true)", true, true], /* navigation */ - ["", "stepInHistory(g_count > 0 ? -1 * g_count : -1);", false, true], - ["", "stepInHistory(g_count > 0 ? g_count : 1);", false, true], - ["", "stepInHistory(g_count > 0 ? -1 * g_count : -1);", false, true], - ["", "stepInHistory(g_count > 0 ? g_count : 1);", false, true], - ["", "vimperator.tabs.remove(getBrowser().mCurrentTab, g_count, false, 0);", true, true], + ["", "stepInHistory(vimperator.input.count > 0 ? -1 * vimperator.input.count : -1);", false, true], + ["", "stepInHistory(vimperator.input.count > 0 ? vimperator.input.count : 1);", false, true], + ["", "stepInHistory(vimperator.input.count > 0 ? -1 * vimperator.input.count : -1);", false, true], + ["", "stepInHistory(vimperator.input.count > 0 ? vimperator.input.count : 1);", false, true], + ["", "vimperator.tabs.remove(getBrowser().mCurrentTab, vimperator.input.count, false, 0);", true, true], /* cancel hint mode keys */ ["", "", true, true], ["", "", true, true], diff --git a/chrome/content/vimperator/vimperator.js b/chrome/content/vimperator/vimperator.js index d5656b39..ea4e08f6 100644 --- a/chrome/content/vimperator/vimperator.js +++ b/chrome/content/vimperator/vimperator.js @@ -31,9 +31,6 @@ var vimperator = null; var popup_allowed_events; // need to change and reset this firefox pref -var g_inputbuffer = ""; // here we store partial commands (e.g. 'g' if you want to type 'gg') -var g_count = -1; // the parsed integer of g_inputbuffer, or -1 if no count was given - // handles multi-line commands var prev_match = new Array(5); var heredoc = ''; @@ -173,16 +170,20 @@ function init() Vimperator.prototype.commands = new Commands; Vimperator.prototype.bookmarks = new Bookmarks; Vimperator.prototype.history = new History; - Vimperator.prototype.qm = new QM; // Vimperator.prototype.commandline = new CommandLine; Vimperator.prototype.search = new Search; Vimperator.prototype.previewwindow = new InformationList("vimperator-previewwindow", { incremental_fill: false, max_items: 10 }); Vimperator.prototype.bufferwindow = new InformationList("vimperator-bufferwindow", { incremental_fill: false, max_items: 10 }); - Vimperator.prototype.statusline = new StatusLine(); - Vimperator.prototype.tabs = new Tabs(); - Vimperator.prototype.mappings = new Mappings(); - + Vimperator.prototype.statusline = new StatusLine; + Vimperator.prototype.tabs = new Tabs; + Vimperator.prototype.mappings = new Mappings; + Vimperator.prototype.marks = new Marks; + vimperator.input = { + buffer: "", // partial command storage + pendingMap: null, // pending map storage + count: -1, // parsed count from the input buffer + }; // XXX: move elsewhere vimperator.registerCallback("submit", vimperator.modes.EX, function(command) { /*vimperator.*/execute(command); } ); vimperator.registerCallback("complete", vimperator.modes.EX, function(str) { return exTabCompletion(str); } ); @@ -680,7 +681,7 @@ function Vimperator() } this.triggerCallback = function(type, data) { - for (i in callbacks) + for (var i in callbacks) { var [thistype, thismode, thisfunc] = callbacks[i]; if (vimperator.hasMode(thismode) && type == thistype) @@ -820,7 +821,6 @@ function Vimperator() // if Hit-a-hint mode is on, special handling of keys is required // g_hint_mappings is used // FIXME: total mess - //if (hah.hintsVisible()) if (vimperator.hasMode(vimperator.modes.HINTS)) { // never propagate this key to firefox, when hints are visible @@ -838,7 +838,7 @@ function Vimperator() if (g_hint_mappings[i][2] == true) // stop processing this event { hah.disableHahMode(); - g_inputbuffer = ""; + vimperator.input.buffer = ""; vimperator.statusline.updateInputBuffer(""); return false; } @@ -846,7 +846,7 @@ function Vimperator() { // FIXME: make sure that YOU update the statusbar message yourself // first in g_hint_mappings when in this mode! - vimperator.statusline.updateInputBuffer(g_inputbuffer); + vimperator.statusline.updateInputBuffer(vimperator.input.buffer); return false; } } @@ -858,8 +858,8 @@ function Vimperator() { beep(); hah.disableHahMode(); - g_inputbuffer = ""; - vimperator.statusline.updateInputBuffer(g_inputbuffer); + vimperator.input.buffer = ""; + vimperator.statusline.updateInputBuffer(vimperator.input.buffer); return true; } @@ -874,16 +874,16 @@ function Vimperator() hah.disableHahMode(); else // ALWAYS mode hah.resetHintedElements(); - g_inputbuffer = ""; + vimperator.input.buffer = ""; } //else if (res == 0 || hah.currentMode() == HINT_MODE_EXTENDED) // key processed, part of a larger hint else if (res == 0 || vimperator.hasMode(vimperator.modes.EXTENDED_HINT)) // key processed, part of a larger hint - g_inputbuffer += key; + vimperator.input.buffer += key; else // this key completed a quick hint { // if the hint is all in UPPERCASE, open it in new tab - g_inputbuffer += key; - if (g_inputbuffer.toUpperCase() == g_inputbuffer) + vimperator.input.buffer += key; + if (vimperator.input.buffer.toUpperCase() == vimperator.input.buffer) hah.openHints(true, false); else // open in current window hah.openHints(false, false); @@ -894,72 +894,74 @@ function Vimperator() else // ALWAYS mode hah.resetHintedElements(); - g_inputbuffer = ""; + vimperator.input.buffer = ""; } - vimperator.statusline.updateInputBuffer(g_inputbuffer); + vimperator.statusline.updateInputBuffer(vimperator.input.buffer); return true; } - var count_str = g_inputbuffer.match(/^[0-9]*/)[0]; - - // counts must be at the start of a complete mapping (10j -> go 10 lines down) - if (event.charCode >= 48 && event.charCode <= 57 && !(event.ctrlKey || event.altKey)) + if (vimperator.hasMode(vimperator.modes.NORMAL)) { - if (g_inputbuffer.search(/[^0-9]/) != -1) + var count_str = vimperator.input.buffer.match(/^[0-9]*/)[0]; + var candidate_command = (vimperator.input.buffer + key).replace(count_str, ''); + var map; + + // counts must be at the start of a complete mapping (10j -> go 10 lines down) + if ((vimperator.input.buffer + key).match(/^[1-9][0-9]*$/)) { - g_inputbuffer = ""; - beep(); - vimperator.statusline.updateInputBuffer(g_inputbuffer); + vimperator.input.buffer += key; + vimperator.statusline.updateInputBuffer(vimperator.input.buffer); return true; } + + if (vimperator.input.pendingMap) + { + vimperator.input.pendingMap.execute(null, vimperator.input.count, key); + vimperator.input.pendingMap = null; + vimperator.input.buffer = ""; + } + else if (map = vimperator.mappings.get(vimperator.modes.NORMAL, candidate_command)) + { + vimperator.input.count = parseInt(count_str, 10); + if (isNaN(vimperator.input.count)) + vimperator.input.count = -1; + if (map.flags & Mappings.flags.ARGUMENT) + { + vimperator.input.pendingMap = map; + vimperator.input.buffer += key; + } + else + { + map.execute(null, vimperator.input.count); + vimperator.input.buffer = ""; + } + + event.preventDefault(); + event.stopPropagation(); + } + else if (vimperator.mappings.getCandidates(vimperator.modes.NORMAL, candidate_command).length > 0) + { + vimperator.input.buffer += key; + event.preventDefault(); + event.stopPropagation(); + } else { - // handle '0' specially to allow binding of 0 - if (g_inputbuffer != "" || key != "0") - { - g_inputbuffer += key; - vimperator.statusline.updateInputBuffer(g_inputbuffer); - return true; - } - // else let the flow continue, and check if 0 is a mapping + vimperator.input.buffer = ""; + vimperator.input.pendingMap = null; + beep(); } } - - var candidate_command = (g_inputbuffer + key).replace(count_str, ''); - - if (map = vimperator.mappings.get(vimperator.modes.NORMAL, candidate_command)) - { - g_count = parseInt(count_str, 10); - if (isNaN(g_count)) - g_count = -1; - - // FIXME: allow null (= no operation) mappings. No longer applicable? -- djk - map.execute(g_count); - - // command executed, reset input buffer - g_inputbuffer = ""; - vimperator.statusline.updateInputBuffer(g_inputbuffer); - event.preventDefault(); - event.stopPropagation(); - return false; - } - else if (vimperator.mappings.getCandidates(vimperator.modes.NORMAL, candidate_command).length > 0) - { - g_inputbuffer += key; - event.preventDefault(); - event.stopPropagation(); - } - else - { - g_inputbuffer = ""; - beep(); - } - - vimperator.statusline.updateInputBuffer(g_inputbuffer); + vimperator.statusline.updateInputBuffer(vimperator.input.buffer); return false; }/*}}}*/ + this.getCurrentBuffer = function() + { + return document.commandDispatcher.focusedWindow; + } + // FIXME: is not called for onLocationChange etc, find the reason this.browserStatusHandler = function() { this.init(); } @@ -1079,8 +1081,9 @@ function Vimperator() // alert('end'); } -// XXX: move where? // provides functions for working with tabs +// XXX: ATTENTION: We are planning to move to the FUEL API once we switch to +// Firefox 3.0, then this class should go away and their tab methods should be used function Tabs() { //////////////////////////////////////////////////////////////////////////////// @@ -1168,6 +1171,14 @@ function Tabs() return buffers; } + this.getTab = function(index) + { + if (index) + return getBrowser().mTabs[index]; + + return getBrowser().tabContainer.selectedItem; + } + /* spec == "" moves the tab to the last position as per Vim * wrap causes the movement to wrap around the start and end of the tab list * NOTE: position is a 0 based index @@ -1214,7 +1225,6 @@ function Tabs() getBrowser().mTabContainer.selectedIndex = index; } - /* XXX: disabled until we find a better way where to update the titles, right now * it has O(n^2) complexity on firefox start when we load 50 tabs * (c) by hrist @@ -1251,4 +1261,5 @@ function Tabs() } */ } + // vim: set fdm=marker sw=4 ts=4 et: