From 7af9664ac06654ccab61fd551e55470b5b279ebb Mon Sep 17 00:00:00 2001 From: Martin Stubenschrott Date: Tue, 12 Jun 2007 10:48:35 +0000 Subject: [PATCH] - fixed commandline focus/blur behavior - could be buggy, so please report any bugs - text selection is not possible anymore for :echo'ed things, should come later when holding shift - cleared commandline on scroll events --- ChangeLog | 1 + TODO | 4 - chrome/content/vimperator/find.js | 7 +- chrome/content/vimperator/ui.js | 127 ++++++++++++++++++----- chrome/content/vimperator/vimperator.js | 19 ++-- chrome/content/vimperator/vimperator.xul | 4 +- 6 files changed, 120 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index 28a0b617..64463e22 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@
 2007-05-02:
 	* version ???
+	* Command line is now cleared on most redraws like in vim
     * The RSS feed button in the address bar works again
     * reload/stop buttons update enabled state again
 	* added marks support (thanks Viktor Kojouharov)
diff --git a/TODO b/TODO
index 465ebd3e..2d349e5a 100644
--- a/TODO
+++ b/TODO
@@ -14,7 +14,6 @@ BUGS:
      webpage, saving  only the html works just fine..
 -  key closes :addons and other XUL windows
 
-
 FEATURES:
 9 :map commands to keys
 9 :command for new commands
@@ -56,9 +55,6 @@ RANDOM IDEAS:
 * 16:06:04       bartman| maxauthority: feature idea: what if :n and :N searched the 
                         page and if they found a unique .*next.* or .*prev.* they would follow that link?
-* 20:12:26         skaar| so, I think get_history_completion effectively will put the oldest 
-                        history entry at the top of the completion list
-  20:12:48         skaar| since you're counting down in the for loop
 * hide scrollbars: http://rafb.net/p/YHRhEe47.html (window.content.document.body.style.overflow = "hidden")
 
 
diff --git a/chrome/content/vimperator/find.js b/chrome/content/vimperator/find.js index 38f14a6c..c4965e85 100644 --- a/chrome/content/vimperator/find.js +++ b/chrome/content/vimperator/find.js @@ -461,14 +461,11 @@ function Search() logMessage("Search initialized"); } -// @todo nicer way to register commands? +// @TODO should be moved into commands.js vimperator.commands.add(new Command(["noh[lsearch]"], clearSelection, { - usage: ["noh[lsearch]"], - short_help: "Clear the current selection", - help: null, - completer: null + short_help: "Clear the current selection" } )); diff --git a/chrome/content/vimperator/ui.js b/chrome/content/vimperator/ui.js index 8caa429e..436b76bf 100644 --- a/chrome/content/vimperator/ui.js +++ b/chrome/content/vimperator/ui.js @@ -63,7 +63,7 @@ function CommandLine () var history_index = UNINITIALIZED; var history_start = ""; - // for the example command "open sometext| othertext" (| is the cursor pos) + // for the example command "open sometext| othertext" (| is the cursor pos): var completion_start_index = 0; // will be 5 because we want to complete arguments for the :open command var completion_prefix = "" // will be: "open sometext" var completion_postfix = ""; // will be: " othertext" @@ -76,14 +76,32 @@ function CommandLine () // The command bar which contains the current command var command_widget = document.getElementById('vimperator-commandline-command'); - // load the history + // we need to save the mode which were in before opening the command line + // this is then used if we focus the command line again without the "official" + // way of calling "open" + var cur_extended_mode = null; // the extended mode which we last openend the command line for + var cur_prompt = null; + var cur_command = null; + var old_mode = null; // when we leave the command prompt this mode is restored + var old_extended_mode = null; + + // an ugly hack that we allow the :echo(err) commands after hitting enter + // and before the blur() event gets fired + var echo_allowed = false; + + // load the commandline history var hist = get_pref("commandline_history", ""); history = hist.split("\n"); + // TODO: these styles should be moved to the .css file function setNormalStyle() { command_widget.inputField.setAttribute("style","font-family: monospace;"); } + function setMessageStyle() + { + command_widget.inputField.setAttribute("style", "font-family: monospace; color:magenta; font-weight: bold"); + } function setErrorStyle() { command_widget.inputField.setAttribute("style", "font-family: monospace; color:white; background-color:red; font-weight: bold"); @@ -118,13 +136,16 @@ function CommandLine () function addToHistory(str) { + if(str.length < 1) + return; + // first remove all old history elements which have this string history = history.filter(function(elem) { return elem != str; }); // add string to the command line history - if (str.length >= 1 && history.push(str) > HISTORY_SIZE) - history.shift(); + if (history.push(str) > HISTORY_SIZE) //remove the first 10% of the history + history = history.slice(HISTORY_SIZE / 10); } //////////////////////////////////////////////////////////////////////////////// @@ -137,47 +158,64 @@ function CommandLine () }; /** - * All arguments can be ommited and will be defaulted to "" + * All arguments can be ommited and will be defaulted to "" or null */ - this.open = function(prompt, cmd, minor_mode) + this.open = function(prompt, cmd, ext_mode) { - if (!prompt) - prompt = ""; - if (!cmd) - cmd = ""; - //if (minor_mode) - vimperator.setMode(vimperator.modes.COMMAND_LINE, minor_mode); + // save the current prompts, we need it later if the command widget + // receives focus without calling the this.open() method + cur_prompt = prompt || ""; + cur_command = cmd || ""; + cur_extended_mode = ext_mode || null; setNormalStyle(); - setPrompt(prompt); - setCommand(cmd); history_index = UNINITIALIZED; completion_index = UNINITIALIZED; + + // the command_widget.focus() method calls setPrompt() and setCommand() + // this is done, because for follow-mouse window managers, we receive + // blur and focus events once the user leaves the Firefox window with the mouse command_widget.focus(); }; this.echo = function(str) { var focused = document.commandDispatcher.focusedElement; - if (focused && focused == command_widget.inputField) - return; + if (!echo_allowed && focused && focused == command_widget.inputField) + return false; setNormalStyle(); setPrompt(""); setCommand(str); + cur_extended_mode = null; + return true; }; this.echoErr = function(str) { var focused = document.commandDispatcher.focusedElement; - if (focused && focused == command_widget.inputField) - return; + if (!echo_allowed && focused && focused == command_widget.inputField) + return false; setErrorStyle(); setPrompt(""); setCommand(str); + cur_extended_mode = null; + return true; }; + // this will prompt the user for a string + // vimperator.commandline.input("(s)ave or (o)pen the file?") + this.input = function(str) + { + // TODO: unfinished, need to find out how/if we can block the execution of code + // to make this code synchronous + setPrompt(""); + setMessageStyle(); + setCommand(str); + return "not implemented"; + } + this.clear = function() { setPrompt(" "); // looks faster than an empty string @@ -188,20 +226,55 @@ function CommandLine () this.onEvent = function(event) { - //var end = false; var command = this.getCommand(); if(event.type == "blur") { + logMessage("blur"); // when we do a command_widget.focus() we get a blur event immediately, // so check if the target is the actualy input field if (event.target == command_widget.inputField) { - addToHistory(command); + var silent = false; + if (old_mode == vimperator.modes.NORMAL) + silent = true; + vimperator.setMode(old_mode || vimperator.modes.NORMAL, old_extended_mode || null, silent); + cur_command = command; + + // don't add the echoed command to the history, on pressing , the + // command is saved right into the kepress handler + if(!echo_allowed) + addToHistory(command); + completionlist.hide(); vimperator.statusline.updateProgress(""); // we may have a "match x of y" visible } } + else if(event.type == "focus") + { + // if we manually click into the command line, don't open it + if (event.target == command_widget.inputField && cur_extended_mode != null) + { + // save the mode, because we need to restore it on blur() + [old_mode, old_extended_mode] = vimperator.getMode(); + vimperator.setMode(vimperator.modes.COMMAND_LINE, cur_extended_mode); + + setPrompt(cur_prompt); + setCommand(cur_command); + } + else + { + //event.stopPropagation(); // XXX: doesnt seem to work + //event.preventDefault(); // so we need to use the hack + + // NOTE: echo_allowed is a misleading name here, actually this flag is set + // so that we don't save a history entry if the user clicks into the text field + echo_allowed = true; + event.target.blur(); + echo_allowed = false; + return false; + } + } else if(event.type == "input") { vimperator.triggerCallback("change", command); @@ -213,6 +286,7 @@ function CommandLine () if (key == "" || key == "" || key == "") { // FIXME: move to execute() in commands.js + // var end = false; // try { // [prev_match, heredoc, end] = multiliner(command, prev_match, heredoc); // } catch(e) { @@ -225,19 +299,20 @@ function CommandLine () // if (!end) // command_line.value = ""; - // NOTE: the command is saved to the history in the blur() handler - vimperator.focusContent(); + echo_allowed = true; + addToHistory(command); var res = vimperator.triggerCallback("submit", command); - vimperator.setMode(vimperator.modes.NORMAL, null, true); + vimperator.focusContent(); + echo_allowed = false; return res; } /* user pressed ESCAPE to cancel this prompt */ else if (key == "" || key == "" || key == "") { var res = vimperator.triggerCallback("cancel"); - addToHistory(command); - this.clear(); + // the command history item is saved in the blur() handler vimperator.focusContent(); + this.clear(); return res; } @@ -423,7 +498,7 @@ function CommandLine () } // it would be better if we had a destructor in javascript ... - this.saveHistory = function() + this.destroy = function() { set_pref("commandline_history", history.join("\n")); } diff --git a/chrome/content/vimperator/vimperator.js b/chrome/content/vimperator/vimperator.js index 6830ec26..d2d2e47b 100644 --- a/chrome/content/vimperator/vimperator.js +++ b/chrome/content/vimperator/vimperator.js @@ -64,20 +64,17 @@ function init() Vimperator.prototype.mappings = new Mappings; Vimperator.prototype.marks = new Marks; + // XXX: move into Vimperator() ? 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); } ); - // this function adds all our required listeners to react on events - // also stuff like window.onScroll is handled there. - //addEventListeners(); - //vimperator.events(); - set_showtabline(get_pref("showtabline")); set_guioptions(get_pref("guioptions")); set_titlestring(); @@ -121,7 +118,7 @@ function init() function unload() { /*** save our preferences ***/ - vimperator.commandline.saveHistory(); + vimperator.commandline.destroy(); vimperator.events.destroy(); @@ -233,6 +230,12 @@ function Vimperator() //{{{1 this.echo = this.commandline.echo; this.echoerr = this.commandline.echoErr; + + this.getMode = function() + { + return [mode, extended_mode]; + } + // set current mode // use "null" if you only want to set one of those modes this.setMode = function(main, extended, silent) @@ -314,14 +317,17 @@ function Events() //{{{1 tabcontainer.addEventListener("TabOpen", function(event) { vimperator.statusline.updateTabCount(); updateBufferList(); + vimperator.setMode(); // trick to reshow the mode in the command line }, false); tabcontainer.addEventListener("TabClose", function(event) { vimperator.statusline.updateTabCount() updateBufferList(); + vimperator.setMode(); // trick to reshow the mode in the command line }, false); tabcontainer.addEventListener("TabSelect", function(event) { vimperator.statusline.updateTabCount(); updateBufferList(); + vimperator.setMode(); // trick to reshow the mode in the command line }, false); // this adds an event which is is called on each page load, even if the @@ -332,6 +338,7 @@ function Events() //{{{1 window.onscroll = function (event) { vimperator.statusline.updateBufferPosition(); + vimperator.setMode(); // trick to reshow the mode in the command line }; window.document.addEventListener("DOMTitleChanged", function(event) diff --git a/chrome/content/vimperator/vimperator.xul b/chrome/content/vimperator/vimperator.xul index 55827350..26093e47 100644 --- a/chrome/content/vimperator/vimperator.xul +++ b/chrome/content/vimperator/vimperator.xul @@ -97,7 +97,9 @@ the terms of any one of the MPL, the GPL or the LGPL.